Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Masami Hiramatsu and committed by
Arnaldo Carvalho de Melo
d0461794 4c9cb2c2

+5 -8
+5 -8
tools/perf/util/probe-finder.c
··· 423 423 pr_warning("Failed to get the type of %s.\n", varname); 424 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 428 tag = dwarf_tag(&type); 428 429 429 430 if (field->name[0] == '[' && 430 431 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { 431 - if (field->next) 432 - /* Save original type for next field */ 433 - memcpy(die_mem, &type, sizeof(*die_mem)); 432 + /* Save original type for next field or type */ 433 + memcpy(die_mem, &type, sizeof(*die_mem)); 434 434 /* Get the type of this array */ 435 435 if (die_get_real_type(&type, &type) == NULL) { 436 436 pr_warning("Failed to get the type of %s.\n", varname); 437 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 440 (unsigned)dwarf_dieoffset(&type)); 441 441 if (tag == DW_TAG_pointer_type) { 442 442 ref = zalloc(sizeof(struct probe_trace_arg_ref)); ··· 448 448 *ref_ptr = ref; 449 449 } 450 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 451 goto next; 455 452 } else if (tag == DW_TAG_pointer_type) { 456 453 /* Check the pointer and dereference */