aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-finder.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-05-19 15:57:42 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-07-05 17:50:27 -0400
commitb2a3c12b7442247c440f7083d48ef05716753ec1 (patch)
treec3a3d0bb442e285979b0dbeecfbf0c04a8b3743e /tools/perf/util/probe-finder.c
parent73317b954041031249e8968d2e9023ff4e960d99 (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.c48
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
657next:
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 {