Commit-ID:  d0461794a1dcaf552b507e23788777f718b736a1
Gitweb:     https://git.kernel.org/tip/d0461794a1dcaf552b507e23788777f718b736a1
Author:     Masami Hiramatsu <mhira...@kernel.org>
AuthorDate: Sat, 17 Mar 2018 21:52:25 +0900
Committer:  Arnaldo Carvalho de Melo <a...@redhat.com>
CommitDate: Mon, 19 Mar 2018 13:51:53 -0300

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 <mhira...@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <a...@redhat.com>
Cc: Namhyung Kim <namhy...@kernel.org>
Cc: Ravi Bangoria <ravi.bango...@linux.vnet.ibm.com>
Cc: Shuah Khan <sh...@kernel.org>
Cc: Steven Rostedt <rost...@goodmis.org>
Cc: Tom Zanussi <tom.zanu...@linux.intel.com>
Cc: linux-kselft...@vger.kernel.org
Cc: linux-trace-us...@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 <a...@redhat.com>
---
 tools/perf/util/probe-finder.c | 13 +++++--------
 1 file 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,
                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 */

Reply via email to