diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2010-05-19 15:57:42 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-07-05 17:50:27 -0400 |
commit | b2a3c12b7442247c440f7083d48ef05716753ec1 (patch) | |
tree | c3a3d0bb442e285979b0dbeecfbf0c04a8b3743e /tools/perf/util/probe-finder.c | |
parent | 73317b954041031249e8968d2e9023ff4e960d99 (diff) |
perf probe: Support tracing an entry of array
Add array-entry tracing support to perf probe. This enables to trace an entry
of array which is indexed by constant value, e.g. array[0].
For example:
$ perf probe -a 'bio_split bi->bi_io_vec[0]'
Cc: Paul Mackerras <paulus@samba.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20100519195742.2885.5344.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 | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index aaea16b1c60b..308664deb857 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -485,6 +485,9 @@ static int convert_variable_type(Dwarf_Die *vr_die, | |||
485 | return -ENOENT; | 485 | return -ENOENT; |
486 | } | 486 | } |
487 | 487 | ||
488 | pr_debug("%s type is %s.\n", | ||
489 | dwarf_diename(vr_die), dwarf_diename(&type)); | ||
490 | |||
488 | if (cast && strcmp(cast, "string") == 0) { /* String type */ | 491 | if (cast && strcmp(cast, "string") == 0) { /* String type */ |
489 | ret = dwarf_tag(&type); | 492 | ret = dwarf_tag(&type); |
490 | if (ret != DW_TAG_pointer_type && | 493 | if (ret != DW_TAG_pointer_type && |
@@ -553,16 +556,44 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
553 | struct kprobe_trace_arg_ref *ref = *ref_ptr; | 556 | struct kprobe_trace_arg_ref *ref = *ref_ptr; |
554 | Dwarf_Die type; | 557 | Dwarf_Die type; |
555 | Dwarf_Word offs; | 558 | Dwarf_Word offs; |
556 | int ret; | 559 | int ret, tag; |
557 | 560 | ||
558 | pr_debug("converting %s in %s\n", field->name, varname); | 561 | pr_debug("converting %s in %s\n", field->name, varname); |
559 | if (die_get_real_type(vr_die, &type) == NULL) { | 562 | if (die_get_real_type(vr_die, &type) == NULL) { |
560 | pr_warning("Failed to get the type of %s.\n", varname); | 563 | pr_warning("Failed to get the type of %s.\n", varname); |
561 | return -ENOENT; | 564 | return -ENOENT; |
562 | } | 565 | } |
563 | 566 | pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); | |
564 | /* Check the pointer and dereference */ | 567 | tag = dwarf_tag(&type); |
565 | if (dwarf_tag(&type) == DW_TAG_pointer_type) { | 568 | |
569 | if (field->name[0] == '[' && | ||
570 | (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { | ||
571 | if (field->next) | ||
572 | /* Save original type for next field */ | ||
573 | memcpy(die_mem, &type, sizeof(*die_mem)); | ||
574 | /* Get the type of this array */ | ||
575 | if (die_get_real_type(&type, &type) == NULL) { | ||
576 | pr_warning("Failed to get the type of %s.\n", varname); | ||
577 | return -ENOENT; | ||
578 | } | ||
579 | pr_debug2("Array real type: (%x)\n", | ||
580 | (unsigned)dwarf_dieoffset(&type)); | ||
581 | if (tag == DW_TAG_pointer_type) { | ||
582 | ref = zalloc(sizeof(struct kprobe_trace_arg_ref)); | ||
583 | if (ref == NULL) | ||
584 | return -ENOMEM; | ||
585 | if (*ref_ptr) | ||
586 | (*ref_ptr)->next = ref; | ||
587 | else | ||
588 | *ref_ptr = ref; | ||
589 | } | ||
590 | ref->offset += die_get_byte_size(&type) * field->index; | ||
591 | if (!field->next) | ||
592 | /* Save vr_die for converting types */ | ||
593 | memcpy(die_mem, vr_die, sizeof(*die_mem)); | ||
594 | goto next; | ||
595 | } else if (tag == DW_TAG_pointer_type) { | ||
596 | /* Check the pointer and dereference */ | ||
566 | if (!field->ref) { | 597 | if (!field->ref) { |
567 | pr_err("Semantic error: %s must be referred by '->'\n", | 598 | pr_err("Semantic error: %s must be referred by '->'\n", |
568 | field->name); | 599 | field->name); |
@@ -588,10 +619,15 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
588 | *ref_ptr = ref; | 619 | *ref_ptr = ref; |
589 | } else { | 620 | } else { |
590 | /* Verify it is a data structure */ | 621 | /* Verify it is a data structure */ |
591 | if (dwarf_tag(&type) != DW_TAG_structure_type) { | 622 | if (tag != DW_TAG_structure_type) { |
592 | pr_warning("%s is not a data structure.\n", varname); | 623 | pr_warning("%s is not a data structure.\n", varname); |
593 | return -EINVAL; | 624 | return -EINVAL; |
594 | } | 625 | } |
626 | if (field->name[0] == '[') { | ||
627 | pr_err("Semantic error: %s is not a pointor nor array.", | ||
628 | varname); | ||
629 | return -EINVAL; | ||
630 | } | ||
595 | if (field->ref) { | 631 | if (field->ref) { |
596 | pr_err("Semantic error: %s must be referred by '.'\n", | 632 | pr_err("Semantic error: %s must be referred by '.'\n", |
597 | field->name); | 633 | field->name); |
@@ -618,6 +654,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
618 | } | 654 | } |
619 | ref->offset += (long)offs; | 655 | ref->offset += (long)offs; |
620 | 656 | ||
657 | next: | ||
621 | /* Converting next field */ | 658 | /* Converting next field */ |
622 | if (field->next) | 659 | if (field->next) |
623 | return convert_variable_fields(die_mem, field->name, | 660 | return convert_variable_fields(die_mem, field->name, |
@@ -667,7 +704,6 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) | |||
667 | char buf[32], *ptr; | 704 | char buf[32], *ptr; |
668 | int ret; | 705 | int ret; |
669 | 706 | ||
670 | /* TODO: Support arrays */ | ||
671 | if (pf->pvar->name) | 707 | if (pf->pvar->name) |
672 | pf->tvar->name = strdup(pf->pvar->name); | 708 | pf->tvar->name = strdup(pf->pvar->name); |
673 | else { | 709 | else { |