]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
perf probe: Use right type to access array elements
authorMasami Hiramatsu <mhiramat@kernel.org>
Sat, 17 Mar 2018 12:52:25 +0000 (21:52 +0900)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 19 Mar 2018 16:51:53 +0000 (13:51 -0300)
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>
tools/perf/util/probe-finder.c

index a5731de0e5ebc73ed3fbc35dd1b334e664f20b69..c37fbef1711dd70df81d6b0d82556121fa4a1bc1 100644 (file)
@@ -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);
                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);
 
        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));
+               /* Save original type for next field or type */
+               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",
+               pr_debug2("Array real type: %s (%x)\n", dwarf_diename(&type),
                         (unsigned)dwarf_dieoffset(&type));
                if (tag == DW_TAG_pointer_type) {
                        ref = zalloc(sizeof(struct probe_trace_arg_ref));
@@ -448,9 +448,6 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
                                *ref_ptr = ref;
                }
                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;
        } else if (tag == DW_TAG_pointer_type) {
                /* Check the pointer and dereference */