aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@kernel.org>2018-03-17 08:52:25 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2018-03-19 12:51:53 -0400
commitd0461794a1dcaf552b507e23788777f718b736a1 (patch)
tree3b11b356462ccadfc2b64b974f2af8cb6bb93ed0
parent4c9cb2c2b4b5530717f74b2252f8cc4c45b2a918 (diff)
perf probe: Use right type to access array elements
Current 'perf probe' converts the type of array-elements incorrectly. It always converts the types as a pointer of array. This passes the "array" type DIE to the type converter so that it can get correct "element of array" type DIE from it. E.g. ==== $ cat hello.c #include <stdio.h> void foo(int a[]) { printf("%d\n", a[1]); } void main() { int a[3] = {4, 5, 6}; printf("%d\n", a[0]); foo(a); } $ gcc -g hello.c -o hello $ perf probe -x ./hello -D "foo a[1]" ==== Without this fix, above outputs ==== p:probe_hello/foo /tmp/hello:0x4d3 a=+4(-8(%bp)):u64 ==== The "u64" means "int *", but a[1] is "int". With this, ==== p:probe_hello/foo /tmp/hello:0x4d3 a=+4(-8(%bp)):s32 ==== So, "int" correctly converted to "s32" Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Tom Zanussi <tom.zanussi@linux.intel.com> Cc: linux-kselftest@vger.kernel.org Cc: linux-trace-users@vger.kernel.org Fixes: b2a3c12b7442 ("perf probe: Support tracing an entry of array") Link: http://lkml.kernel.org/r/152129114502.31874.2474068470011496356.stgit@devbox Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/probe-finder.c13
1 files changed, 5 insertions, 8 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index a5731de0e5eb..c37fbef1711d 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -423,20 +423,20 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
423 pr_warning("Failed to get the type of %s.\n", varname); 423 pr_warning("Failed to get the type of %s.\n", varname);
424 return -ENOENT; 424 return -ENOENT;
425 } 425 }
426 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); 426 pr_debug2("Var real type: %s (%x)\n", dwarf_diename(&type),
427 (unsigned)dwarf_dieoffset(&type));
427 tag = dwarf_tag(&type); 428 tag = dwarf_tag(&type);
428 429
429 if (field->name[0] == '[' && 430 if (field->name[0] == '[' &&
430 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { 431 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
431 if (field->next) 432 /* Save original type for next field or type */
432 /* Save original type for next field */ 433 memcpy(die_mem, &type, sizeof(*die_mem));
433 memcpy(die_mem, &type, sizeof(*die_mem));
434 /* Get the type of this array */ 434 /* Get the type of this array */
435 if (die_get_real_type(&type, &type) == NULL) { 435 if (die_get_real_type(&type, &type) == NULL) {
436 pr_warning("Failed to get the type of %s.\n", varname); 436 pr_warning("Failed to get the type of %s.\n", varname);
437 return -ENOENT; 437 return -ENOENT;
438 } 438 }
439 pr_debug2("Array real type: (%x)\n", 439 pr_debug2("Array real type: %s (%x)\n", dwarf_diename(&type),
440 (unsigned)dwarf_dieoffset(&type)); 440 (unsigned)dwarf_dieoffset(&type));
441 if (tag == DW_TAG_pointer_type) { 441 if (tag == DW_TAG_pointer_type) {
442 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 442 ref = zalloc(sizeof(struct probe_trace_arg_ref));
@@ -448,9 +448,6 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
448 *ref_ptr = ref; 448 *ref_ptr = ref;
449 } 449 }
450 ref->offset += dwarf_bytesize(&type) * field->index; 450 ref->offset += dwarf_bytesize(&type) * field->index;
451 if (!field->next)
452 /* Save vr_die for converting types */
453 memcpy(die_mem, vr_die, sizeof(*die_mem));
454 goto next; 451 goto next;
455 } else if (tag == DW_TAG_pointer_type) { 452 } else if (tag == DW_TAG_pointer_type) {
456 /* Check the pointer and dereference */ 453 /* Check the pointer and dereference */