From b2a3c12b7442247c440f7083d48ef05716753ec1 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 19 May 2010 15:57:42 -0400 Subject: 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 Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100519195742.2885.5344.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-finder.c | 48 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) (limited to 'tools/perf/util/probe-finder.c') 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, return -ENOENT; } + pr_debug("%s type is %s.\n", + dwarf_diename(vr_die), dwarf_diename(&type)); + if (cast && strcmp(cast, "string") == 0) { /* String type */ ret = dwarf_tag(&type); if (ret != DW_TAG_pointer_type && @@ -553,16 +556,44 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, struct kprobe_trace_arg_ref *ref = *ref_ptr; Dwarf_Die type; Dwarf_Word offs; - int ret; + int ret, tag; pr_debug("converting %s in %s\n", field->name, varname); if (die_get_real_type(vr_die, &type) == NULL) { pr_warning("Failed to get the type of %s.\n", varname); return -ENOENT; } - - /* Check the pointer and dereference */ - if (dwarf_tag(&type) == DW_TAG_pointer_type) { + pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); + tag = dwarf_tag(&type); + + if (field->name[0] == '[' && + (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { + if (field->next) + /* Save original type for next field */ + memcpy(die_mem, &type, sizeof(*die_mem)); + /* Get the type of this array */ + if (die_get_real_type(&type, &type) == NULL) { + pr_warning("Failed to get the type of %s.\n", varname); + return -ENOENT; + } + pr_debug2("Array real type: (%x)\n", + (unsigned)dwarf_dieoffset(&type)); + if (tag == DW_TAG_pointer_type) { + ref = zalloc(sizeof(struct kprobe_trace_arg_ref)); + if (ref == NULL) + return -ENOMEM; + if (*ref_ptr) + (*ref_ptr)->next = ref; + else + *ref_ptr = ref; + } + ref->offset += die_get_byte_size(&type) * field->index; + if (!field->next) + /* Save vr_die for converting types */ + memcpy(die_mem, vr_die, sizeof(*die_mem)); + goto next; + } else if (tag == DW_TAG_pointer_type) { + /* Check the pointer and dereference */ if (!field->ref) { pr_err("Semantic error: %s must be referred by '->'\n", field->name); @@ -588,10 +619,15 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, *ref_ptr = ref; } else { /* Verify it is a data structure */ - if (dwarf_tag(&type) != DW_TAG_structure_type) { + if (tag != DW_TAG_structure_type) { pr_warning("%s is not a data structure.\n", varname); return -EINVAL; } + if (field->name[0] == '[') { + pr_err("Semantic error: %s is not a pointor nor array.", + varname); + return -EINVAL; + } if (field->ref) { pr_err("Semantic error: %s must be referred by '.'\n", field->name); @@ -618,6 +654,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, } ref->offset += (long)offs; +next: /* Converting next field */ if (field->next) return convert_variable_fields(die_mem, field->name, @@ -667,7 +704,6 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) char buf[32], *ptr; int ret; - /* TODO: Support arrays */ if (pf->pvar->name) pf->tvar->name = strdup(pf->pvar->name); else { -- cgit v1.2.2