aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-04-12 13:17:22 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-04-14 16:28:09 -0400
commit11a1ca3554b377d2a8a318a3cbf8ce10a7a2a8e4 (patch)
tree36483c56ee6b7148247ef6fbe349b09ee8cfcb25 /tools
parent4984912eb23113a4007940cd09c8351c0623ea5f (diff)
perf probe: Support basic type casting
Add basic type casting for arguments to perf probe. This allows users to specify the actual type of arguments. Of course, if user sets invalid types, kprobe-tracer rejects that. 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: <20100412171722.3790.50372.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')
-rw-r--r--tools/perf/Documentation/perf-probe.txt3
-rw-r--r--tools/perf/util/probe-event.c23
-rw-r--r--tools/perf/util/probe-event.h1
-rw-r--r--tools/perf/util/probe-finder.c10
4 files changed, 33 insertions, 4 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 441324f2615d..63c25d304880 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -85,9 +85,10 @@ PROBE ARGUMENT
85-------------- 85--------------
86Each probe argument follows below syntax. 86Each probe argument follows below syntax.
87 87
88 [NAME=]LOCALVAR|$retval|%REG|@SYMBOL 88 [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE]
89 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). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.) 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). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
91'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo.
91 92
92LINE SYNTAX 93LINE SYNTAX
93----------- 94-----------
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 05ca4a959e60..bef280527e60 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -435,7 +435,7 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
435} 435}
436 436
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(char *str, struct perf_probe_arg *arg)
439{ 439{
440 char *tmp; 440 char *tmp;
441 struct perf_probe_arg_field **fieldp; 441 struct perf_probe_arg_field **fieldp;
@@ -445,9 +445,17 @@ static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg)
445 tmp = strchr(str, '='); 445 tmp = strchr(str, '=');
446 if (tmp) { 446 if (tmp) {
447 arg->name = xstrndup(str, tmp - str); 447 arg->name = xstrndup(str, tmp - str);
448 pr_debug("name:%s ", arg->name);
448 str = tmp + 1; 449 str = tmp + 1;
449 } 450 }
450 451
452 tmp = strchr(str, ':');
453 if (tmp) { /* Type setting */
454 *tmp = '\0';
455 arg->type = xstrdup(tmp + 1);
456 pr_debug("type:%s ", arg->type);
457 }
458
451 tmp = strpbrk(str, "-."); 459 tmp = strpbrk(str, "-.");
452 if (!is_c_varname(str) || !tmp) { 460 if (!is_c_varname(str) || !tmp) {
453 /* A variable, register, symbol or special value */ 461 /* A variable, register, symbol or special value */
@@ -603,6 +611,15 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
603 len -= ret; 611 len -= ret;
604 field = field->next; 612 field = field->next;
605 } 613 }
614
615 if (pa->type) {
616 ret = e_snprintf(tmp, len, ":%s", pa->type);
617 if (ret <= 0)
618 goto error;
619 tmp += ret;
620 len -= ret;
621 }
622
606 return tmp - buf; 623 return tmp - buf;
607error: 624error:
608 die("Failed to synthesize perf probe argument: %s", strerror(-ret)); 625 die("Failed to synthesize perf probe argument: %s", strerror(-ret));
@@ -825,6 +842,8 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
825 free(pev->args[i].name); 842 free(pev->args[i].name);
826 if (pev->args[i].var) 843 if (pev->args[i].var)
827 free(pev->args[i].var); 844 free(pev->args[i].var);
845 if (pev->args[i].type)
846 free(pev->args[i].type);
828 field = pev->args[i].field; 847 field = pev->args[i].field;
829 while (field) { 848 while (field) {
830 next = field->next; 849 next = field->next;
@@ -1145,6 +1164,8 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
1145 if (pev->args[i].name) 1164 if (pev->args[i].name)
1146 tev->args[i].name = xstrdup(pev->args[i].name); 1165 tev->args[i].name = xstrdup(pev->args[i].name);
1147 tev->args[i].value = xstrdup(pev->args[i].var); 1166 tev->args[i].value = xstrdup(pev->args[i].var);
1167 if (pev->args[i].type)
1168 tev->args[i].type = xstrdup(pev->args[i].type);
1148 } 1169 }
1149 } 1170 }
1150 1171
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index a393a3f87cd0..ff2f26b1822c 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -57,6 +57,7 @@ struct perf_probe_arg_field {
57struct perf_probe_arg { 57struct perf_probe_arg {
58 char *name; /* Argument name */ 58 char *name; /* Argument name */
59 char *var; /* Variable name */ 59 char *var; /* Variable name */
60 char *type; /* Type name */
60 struct perf_probe_arg_field *field; /* Structure fields */ 61 struct perf_probe_arg_field *field; /* Structure fields */
61}; 62};
62 63
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ebeb413ac473..ab476736cbe7 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -547,7 +547,10 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
547 &die_mem); 547 &die_mem);
548 vr_die = &die_mem; 548 vr_die = &die_mem;
549 } 549 }
550 convert_variable_type(vr_die, pf->tvar); 550 if (pf->pvar->type)
551 pf->tvar->type = xstrdup(pf->pvar->type);
552 else
553 convert_variable_type(vr_die, pf->tvar);
551 /* *expr will be cached in libdw. Don't free it. */ 554 /* *expr will be cached in libdw. Don't free it. */
552 return ; 555 return ;
553error: 556error:
@@ -560,13 +563,16 @@ error:
560static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) 563static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
561{ 564{
562 Dwarf_Die vr_die; 565 Dwarf_Die vr_die;
563 char buf[32]; 566 char buf[32], *ptr;
564 567
565 /* TODO: Support arrays */ 568 /* TODO: Support arrays */
566 if (pf->pvar->name) 569 if (pf->pvar->name)
567 pf->tvar->name = xstrdup(pf->pvar->name); 570 pf->tvar->name = xstrdup(pf->pvar->name);
568 else { 571 else {
569 synthesize_perf_probe_arg(pf->pvar, buf, 32); 572 synthesize_perf_probe_arg(pf->pvar, buf, 32);
573 ptr = strchr(buf, ':'); /* Change type separator to _ */
574 if (ptr)
575 *ptr = '_';
570 pf->tvar->name = xstrdup(buf); 576 pf->tvar->name = xstrdup(buf);
571 } 577 }
572 578