aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-04-12 13:16:53 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-04-14 16:26:04 -0400
commit48481938b02471d505296d7557ed296eb093d496 (patch)
tree7549d861d76621d1e3d2ddd75eae4575901f1fd0 /tools/perf/util
parentfcd1498405c2c88ac632e7c3c3fce3213d9196db (diff)
perf probe: Support argument name
Set given names to event arguments. The syntax is same as kprobe-tracer, you can add 'NAME=' right before each argument. e.g. ./perf probe vfs_read foo=file then, 'foo' is set to the argument name as below. ./perf probe -l probe:vfs_read (on vfs_read@linux-2.6-tip/fs/read_write.c with foo) Cc: Ingo Molnar <mingo@elte.hu> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20100412171653.3790.74624.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/probe-event.c34
-rw-r--r--tools/perf/util/probe-event.h1
-rw-r--r--tools/perf/util/probe-finder.c27
3 files changed, 41 insertions, 21 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3fc0be741b8e..ab6f53deabad 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -437,22 +437,28 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
437/* Parse perf-probe event argument */ 437/* Parse perf-probe event argument */
438static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg) 438static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg)
439{ 439{
440 const char *tmp; 440 char *tmp;
441 struct perf_probe_arg_field **fieldp; 441 struct perf_probe_arg_field **fieldp;
442 442
443 pr_debug("parsing arg: %s into ", str); 443 pr_debug("parsing arg: %s into ", str);
444 444
445 tmp = strchr(str, '=');
446 if (tmp) {
447 arg->name = xstrndup(str, tmp - str);
448 str = tmp + 1;
449 }
450
445 tmp = strpbrk(str, "-."); 451 tmp = strpbrk(str, "-.");
446 if (!is_c_varname(str) || !tmp) { 452 if (!is_c_varname(str) || !tmp) {
447 /* A variable, register, symbol or special value */ 453 /* A variable, register, symbol or special value */
448 arg->name = xstrdup(str); 454 arg->var = xstrdup(str);
449 pr_debug("%s\n", arg->name); 455 pr_debug("%s\n", arg->var);
450 return; 456 return;
451 } 457 }
452 458
453 /* Structure fields */ 459 /* Structure fields */
454 arg->name = xstrndup(str, tmp - str); 460 arg->var = xstrndup(str, tmp - str);
455 pr_debug("%s, ", arg->name); 461 pr_debug("%s, ", arg->var);
456 fieldp = &arg->field; 462 fieldp = &arg->field;
457 463
458 do { 464 do {
@@ -497,7 +503,7 @@ void parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
497 pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); 503 pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs);
498 for (i = 0; i < pev->nargs; i++) { 504 for (i = 0; i < pev->nargs; i++) {
499 parse_perf_probe_arg(argv[i + 1], &pev->args[i]); 505 parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
500 if (is_c_varname(pev->args[i].name) && pev->point.retprobe) 506 if (is_c_varname(pev->args[i].var) && pev->point.retprobe)
501 semantic_error("You can't specify local variable for" 507 semantic_error("You can't specify local variable for"
502 " kretprobe"); 508 " kretprobe");
503 } 509 }
@@ -514,7 +520,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
514 return true; 520 return true;
515 521
516 for (i = 0; i < pev->nargs; i++) 522 for (i = 0; i < pev->nargs; i++)
517 if (is_c_varname(pev->args[i].name)) 523 if (is_c_varname(pev->args[i].var))
518 return true; 524 return true;
519 525
520 return false; 526 return false;
@@ -575,7 +581,10 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
575 int ret; 581 int ret;
576 char *tmp = buf; 582 char *tmp = buf;
577 583
578 ret = e_snprintf(tmp, len, "%s", pa->name); 584 if (pa->name && pa->var)
585 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
586 else
587 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
579 if (ret <= 0) 588 if (ret <= 0)
580 goto error; 589 goto error;
581 tmp += ret; 590 tmp += ret;
@@ -803,6 +812,8 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
803 for (i = 0; i < pev->nargs; i++) { 812 for (i = 0; i < pev->nargs; i++) {
804 if (pev->args[i].name) 813 if (pev->args[i].name)
805 free(pev->args[i].name); 814 free(pev->args[i].name);
815 if (pev->args[i].var)
816 free(pev->args[i].var);
806 field = pev->args[i].field; 817 field = pev->args[i].field;
807 while (field) { 818 while (field) {
808 next = field->next; 819 next = field->next;
@@ -1117,8 +1128,11 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
1117 if (tev->nargs) { 1128 if (tev->nargs) {
1118 tev->args = xzalloc(sizeof(struct kprobe_trace_arg) 1129 tev->args = xzalloc(sizeof(struct kprobe_trace_arg)
1119 * tev->nargs); 1130 * tev->nargs);
1120 for (i = 0; i < tev->nargs; i++) 1131 for (i = 0; i < tev->nargs; i++) {
1121 tev->args[i].value = xstrdup(pev->args[i].name); 1132 if (pev->args[i].name)
1133 tev->args[i].name = xstrdup(pev->args[i].name);
1134 tev->args[i].value = xstrdup(pev->args[i].var);
1135 }
1122 } 1136 }
1123 1137
1124 /* Currently just checking function name from symbol map */ 1138 /* Currently just checking function name from symbol map */
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 9d99fc24c4fc..10411f596321 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -55,6 +55,7 @@ struct perf_probe_arg_field {
55/* Perf probe probing argument */ 55/* Perf probe probing argument */
56struct perf_probe_arg { 56struct perf_probe_arg {
57 char *name; /* Argument name */ 57 char *name; /* Argument name */
58 char *var; /* Variable name */
58 struct perf_probe_arg_field *field; /* Structure fields */ 59 struct perf_probe_arg_field *field; /* Structure fields */
59}; 60};
60 61
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index a8513772df08..105e95c95eeb 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -484,35 +484,40 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
484 convert_location(expr, pf); 484 convert_location(expr, pf);
485 485
486 if (pf->pvar->field) 486 if (pf->pvar->field)
487 convert_variable_fields(vr_die, pf->pvar->name, 487 convert_variable_fields(vr_die, pf->pvar->var,
488 pf->pvar->field, &pf->tvar->ref); 488 pf->pvar->field, &pf->tvar->ref);
489 /* *expr will be cached in libdw. Don't free it. */ 489 /* *expr will be cached in libdw. Don't free it. */
490 return ; 490 return ;
491error: 491error:
492 /* TODO: Support const_value */ 492 /* TODO: Support const_value */
493 die("Failed to find the location of %s at this address.\n" 493 die("Failed to find the location of %s at this address.\n"
494 " Perhaps, it has been optimized out.", pf->pvar->name); 494 " Perhaps, it has been optimized out.", pf->pvar->var);
495} 495}
496 496
497/* Find a variable in a subprogram die */ 497/* Find a variable in a subprogram die */
498static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) 498static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
499{ 499{
500 Dwarf_Die vr_die; 500 Dwarf_Die vr_die;
501 char buf[128]; 501 char buf[32];
502 502
503 /* TODO: Support struct members and arrays */ 503 /* TODO: Support arrays */
504 if (!is_c_varname(pf->pvar->name)) { 504 if (pf->pvar->name)
505 pf->tvar->name = xstrdup(pf->pvar->name);
506 else {
507 synthesize_perf_probe_arg(pf->pvar, buf, 32);
508 pf->tvar->name = xstrdup(buf);
509 }
510
511 if (!is_c_varname(pf->pvar->var)) {
505 /* Copy raw parameters */ 512 /* Copy raw parameters */
506 pf->tvar->value = xstrdup(pf->pvar->name); 513 pf->tvar->value = xstrdup(pf->pvar->var);
507 } else { 514 } else {
508 synthesize_perf_probe_arg(pf->pvar, buf, 128);
509 pf->tvar->name = xstrdup(buf);
510 pr_debug("Searching '%s' variable in context.\n", 515 pr_debug("Searching '%s' variable in context.\n",
511 pf->pvar->name); 516 pf->pvar->var);
512 /* Search child die for local variables and parameters. */ 517 /* Search child die for local variables and parameters. */
513 if (!die_find_variable(sp_die, pf->pvar->name, &vr_die)) 518 if (!die_find_variable(sp_die, pf->pvar->var, &vr_die))
514 die("Failed to find '%s' in this function.", 519 die("Failed to find '%s' in this function.",
515 pf->pvar->name); 520 pf->pvar->var);
516 convert_variable(&vr_die, pf); 521 convert_variable(&vr_die, pf);
517 } 522 }
518} 523}