diff options
author | Masami Hiramatsu <mhiramat@kernel.org> | 2018-03-17 08:52:25 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2018-03-19 12:51:53 -0400 |
commit | d0461794a1dcaf552b507e23788777f718b736a1 (patch) | |
tree | 3b11b356462ccadfc2b64b974f2af8cb6bb93ed0 | |
parent | 4c9cb2c2b4b5530717f74b2252f8cc4c45b2a918 (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.c | 13 |
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 */ |