Commit d0461794 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Arnaldo Carvalho de Melo

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: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Tested-by: default avatarArnaldo 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: b2a3c12b ("perf probe: Support tracing an entry of array")
Link: http://lkml.kernel.org/r/152129114502.31874.2474068470011496356.stgit@devboxSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 4c9cb2c2
...@@ -423,20 +423,20 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, ...@@ -423,20 +423,20 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
pr_warning("Failed to get the type of %s.\n", varname); pr_warning("Failed to get the type of %s.\n", varname);
return -ENOENT; return -ENOENT;
} }
pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); pr_debug2("Var real type: %s (%x)\n", dwarf_diename(&type),
(unsigned)dwarf_dieoffset(&type));
tag = dwarf_tag(&type); tag = dwarf_tag(&type);
if (field->name[0] == '[' && if (field->name[0] == '[' &&
(tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
if (field->next) /* Save original type for next field or type */
/* Save original type for next field */ memcpy(die_mem, &type, sizeof(*die_mem));
memcpy(die_mem, &type, sizeof(*die_mem));
/* Get the type of this array */ /* Get the type of this array */
if (die_get_real_type(&type, &type) == NULL) { if (die_get_real_type(&type, &type) == NULL) {
pr_warning("Failed to get the type of %s.\n", varname); pr_warning("Failed to get the type of %s.\n", varname);
return -ENOENT; return -ENOENT;
} }
pr_debug2("Array real type: (%x)\n", pr_debug2("Array real type: %s (%x)\n", dwarf_diename(&type),
(unsigned)dwarf_dieoffset(&type)); (unsigned)dwarf_dieoffset(&type));
if (tag == DW_TAG_pointer_type) { if (tag == DW_TAG_pointer_type) {
ref = zalloc(sizeof(struct probe_trace_arg_ref)); 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,9 +448,6 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
*ref_ptr = ref; *ref_ptr = ref;
} }
ref->offset += dwarf_bytesize(&type) * field->index; ref->offset += dwarf_bytesize(&type) * field->index;
if (!field->next)
/* Save vr_die for converting types */
memcpy(die_mem, vr_die, sizeof(*die_mem));
goto next; goto next;
} else if (tag == DW_TAG_pointer_type) { } else if (tag == DW_TAG_pointer_type) {
/* Check the pointer and dereference */ /* Check the pointer and dereference */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment