aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--tools/perf/Documentation/perf-probe.txt10
-rw-r--r--tools/perf/builtin-probe.c4
-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
5 files changed, 52 insertions, 24 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index bb671b346774..e36ed4dd3868 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -79,7 +79,15 @@ Probe points are defined by following syntax.
79'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'. 79'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'.
80'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function. 80'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function.
81It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern. 81It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern.
82'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc). 82'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT).
83
84PROBE ARGUMENT
85--------------
86Each probe argument follows below syntax.
87
88 [NAME=]LOCALVAR|$retval|%REG|@SYMBOL
89
90'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), or kprobe-tracer argument format (e.g. $retval, %ax, etc).
83 91
84LINE SYNTAX 92LINE SYNTAX
85----------- 93-----------
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index bfc47fff9c59..daf4668d2de0 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -142,9 +142,9 @@ static const struct option options[] = {
142 OPT_CALLBACK('a', "add", NULL, 142 OPT_CALLBACK('a', "add", NULL,
143#ifdef DWARF_SUPPORT 143#ifdef DWARF_SUPPORT
144 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" 144 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
145 " [ARG ...]", 145 " [[NAME=]ARG ...]",
146#else 146#else
147 "[EVENT=]FUNC[+OFF|%return] [ARG ...]", 147 "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
148#endif 148#endif
149 "probe point definition, where\n" 149 "probe point definition, where\n"
150 "\t\tGROUP:\tGroup name (optional)\n" 150 "\t\tGROUP:\tGroup name (optional)\n"
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}