diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2010-05-19 15:57:35 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-07-05 17:47:28 -0400 |
commit | 73317b954041031249e8968d2e9023ff4e960d99 (patch) | |
tree | 44768b7724bacbb15c54057710c70accce1cd8c3 /tools/perf/util/probe-finder.c | |
parent | e09c8614b32915c16f68e039ac7040e602d73e35 (diff) |
perf probe: Support "string" type
Support string type casting to event argument. If perf-probe finds an argument
casted as string, it ensures the target variable is "(unsigned/signed) char
*(or []). perf-probe also adds dereference if the target is a pointer.
So, both of 'char buf[10];' and 'char *buf;' can be accessed by 'buf:string'
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: <20100519195734.2885.1666.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/probe-finder.c')
-rw-r--r-- | tools/perf/util/probe-finder.c | 59 |
1 files changed, 48 insertions, 11 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index baf66538349..aaea16b1c60 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -464,18 +464,61 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf) | |||
464 | } | 464 | } |
465 | 465 | ||
466 | static int convert_variable_type(Dwarf_Die *vr_die, | 466 | static int convert_variable_type(Dwarf_Die *vr_die, |
467 | struct kprobe_trace_arg *targ) | 467 | struct kprobe_trace_arg *tvar, |
468 | const char *cast) | ||
468 | { | 469 | { |
470 | struct kprobe_trace_arg_ref **ref_ptr = &tvar->ref; | ||
469 | Dwarf_Die type; | 471 | Dwarf_Die type; |
470 | char buf[16]; | 472 | char buf[16]; |
471 | int ret; | 473 | int ret; |
472 | 474 | ||
475 | /* TODO: check all types */ | ||
476 | if (cast && strcmp(cast, "string") != 0) { | ||
477 | /* Non string type is OK */ | ||
478 | tvar->type = strdup(cast); | ||
479 | return (tvar->type == NULL) ? -ENOMEM : 0; | ||
480 | } | ||
481 | |||
473 | if (die_get_real_type(vr_die, &type) == NULL) { | 482 | if (die_get_real_type(vr_die, &type) == NULL) { |
474 | pr_warning("Failed to get a type information of %s.\n", | 483 | pr_warning("Failed to get a type information of %s.\n", |
475 | dwarf_diename(vr_die)); | 484 | dwarf_diename(vr_die)); |
476 | return -ENOENT; | 485 | return -ENOENT; |
477 | } | 486 | } |
478 | 487 | ||
488 | if (cast && strcmp(cast, "string") == 0) { /* String type */ | ||
489 | ret = dwarf_tag(&type); | ||
490 | if (ret != DW_TAG_pointer_type && | ||
491 | ret != DW_TAG_array_type) { | ||
492 | pr_warning("Failed to cast into string: " | ||
493 | "%s(%s) is not a pointer nor array.", | ||
494 | dwarf_diename(vr_die), dwarf_diename(&type)); | ||
495 | return -EINVAL; | ||
496 | } | ||
497 | if (ret == DW_TAG_pointer_type) { | ||
498 | if (die_get_real_type(&type, &type) == NULL) { | ||
499 | pr_warning("Failed to get a type information."); | ||
500 | return -ENOENT; | ||
501 | } | ||
502 | while (*ref_ptr) | ||
503 | ref_ptr = &(*ref_ptr)->next; | ||
504 | /* Add new reference with offset +0 */ | ||
505 | *ref_ptr = zalloc(sizeof(struct kprobe_trace_arg_ref)); | ||
506 | if (*ref_ptr == NULL) { | ||
507 | pr_warning("Out of memory error\n"); | ||
508 | return -ENOMEM; | ||
509 | } | ||
510 | } | ||
511 | if (die_compare_name(&type, "char") != 0 && | ||
512 | die_compare_name(&type, "unsigned char") != 0) { | ||
513 | pr_warning("Failed to cast into string: " | ||
514 | "%s is not (unsigned) char *.", | ||
515 | dwarf_diename(vr_die)); | ||
516 | return -EINVAL; | ||
517 | } | ||
518 | tvar->type = strdup(cast); | ||
519 | return (tvar->type == NULL) ? -ENOMEM : 0; | ||
520 | } | ||
521 | |||
479 | ret = die_get_byte_size(&type) * 8; | 522 | ret = die_get_byte_size(&type) * 8; |
480 | if (ret) { | 523 | if (ret) { |
481 | /* Check the bitwidth */ | 524 | /* Check the bitwidth */ |
@@ -495,8 +538,8 @@ static int convert_variable_type(Dwarf_Die *vr_die, | |||
495 | strerror(-ret)); | 538 | strerror(-ret)); |
496 | return ret; | 539 | return ret; |
497 | } | 540 | } |
498 | targ->type = strdup(buf); | 541 | tvar->type = strdup(buf); |
499 | if (targ->type == NULL) | 542 | if (tvar->type == NULL) |
500 | return -ENOMEM; | 543 | return -ENOMEM; |
501 | } | 544 | } |
502 | return 0; | 545 | return 0; |
@@ -606,14 +649,8 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) | |||
606 | &die_mem); | 649 | &die_mem); |
607 | vr_die = &die_mem; | 650 | vr_die = &die_mem; |
608 | } | 651 | } |
609 | if (ret == 0) { | 652 | if (ret == 0) |
610 | if (pf->pvar->type) { | 653 | ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type); |
611 | pf->tvar->type = strdup(pf->pvar->type); | ||
612 | if (pf->tvar->type == NULL) | ||
613 | ret = -ENOMEM; | ||
614 | } else | ||
615 | ret = convert_variable_type(vr_die, pf->tvar); | ||
616 | } | ||
617 | /* *expr will be cached in libdw. Don't free it. */ | 654 | /* *expr will be cached in libdw. Don't free it. */ |
618 | return ret; | 655 | return ret; |
619 | error: | 656 | error: |