diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2010-04-12 13:17:22 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-04-14 16:28:09 -0400 |
commit | 11a1ca3554b377d2a8a318a3cbf8ce10a7a2a8e4 (patch) | |
tree | 36483c56ee6b7148247ef6fbe349b09ee8cfcb25 /tools/perf/util | |
parent | 4984912eb23113a4007940cd09c8351c0623ea5f (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/perf/util')
-rw-r--r-- | tools/perf/util/probe-event.c | 23 | ||||
-rw-r--r-- | tools/perf/util/probe-event.h | 1 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 10 |
3 files changed, 31 insertions, 3 deletions
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 */ |
438 | static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg) | 438 | static 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; |
607 | error: | 624 | error: |
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 { | |||
57 | struct perf_probe_arg { | 57 | struct 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 ; |
553 | error: | 556 | error: |
@@ -560,13 +563,16 @@ error: | |||
560 | static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) | 563 | static 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 | ||