From: Masami Hiramatsu <mhira...@kernel.org>

Match linkage name with mangled name if exists. The linkage_name is used
for storing mangled name of the object.

Thus, this allows 'perf probe' to find appropriate probe point from
mangled symbol as below.

E.g. without this fix:
  ----
  $ perf probe -x /usr/lib64/libstdc++.so.6 \
    -D _ZNKSt15basic_fstreamXXIwSt11char_traitsIwEE7is_openEv
  Probe point '_ZNKSt15basic_fstreamXXIwSt11char_traitsIwEE7is_openEv'
  not found.
    Error: Failed to add events.
  ----

With this fix, perf probe can find the correct one.
  ----
  $ perf probe -x /usr/lib64/libstdc++.so.6 \
    -D _ZNKSt15basic_fstreamXXIwSt11char_traitsIwEE7is_openEv
  p:probe_libstdc/_ZNKSt15basic_fstreamXXIwSt11char_traitsIwEE7is_openEv
  /usr/lib64/libstdc++.so.6.0.22:0x8ca60
  ----

Committer notes:

After the fix, setting it for real (no -D/--definition, that amounts to
a --dry-run):

  # perf probe -x /usr/lib64/libstdc++.so.6 
_ZNKSt15basic_fstreamXXIwSt11char_traitsIwEE7is_openEv
  Added new event:
    probe_libstdc:_ZNKSt15basic_fstreamXXIwSt11char_traitsIwEE7is_openEv (on 
_ZNKSt15basic_fstreamXXIwSt11char_traitsIwEE7is_openEv in 
/usr/lib64/libstdc++.so.6.0.22)

  You can now use it in all perf tools, such as:

        perf record -e 
probe_libstdc:_ZNKSt15basic_fstreamXXIwSt11char_traitsIwEE7is_openEv -aR sleep 1

  # perf probe -l probe_libstdc:*
    probe_libstdc:_ZNKSt15basic_fstreamXXIwSt11char_traitsIwEE7is_openEv (on 
is_open@libstdc++-v3/include/fstream in /usr/lib64/libstdc++.so.6.0.22)
  #

Reported-by: Thomas Gleixner <t...@linutronix.de>
Signed-off-by: Masami Hiramatsu <mhira...@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <a...@redhat.com>
Tested-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsah...@gmail.com>
Cc: Namhyung Kim <namhy...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Link: 
http://lkml.kernel.org/r/147464493162.29804.16715053505069382443.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 tools/perf/util/dwarf-aux.c | 28 ++++++++++++++++++++++++++--
 tools/perf/util/dwarf-aux.h |  3 +++
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index faec899435f2..41e068e94349 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -130,6 +130,22 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr 
addr,
 }
 
 /**
+ * die_get_linkage_name - Get the linkage name of the object
+ * @dw_die: A DIE of the object
+ *
+ * Get the linkage name attiribute of given @dw_die.
+ * For C++ binary, the linkage name will be the mangled symbol.
+ */
+const char *die_get_linkage_name(Dwarf_Die *dw_die)
+{
+       Dwarf_Attribute attr;
+
+       if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
+               return NULL;
+       return dwarf_formstring(&attr);
+}
+
+/**
  * die_compare_name - Compare diename and tname
  * @dw_die: a DIE
  * @tname: a string of target name
@@ -145,18 +161,26 @@ bool die_compare_name(Dwarf_Die *dw_die, const char 
*tname)
 }
 
 /**
- * die_match_name - Match diename and glob
+ * die_match_name - Match diename/linkage name and glob
  * @dw_die: a DIE
  * @glob: a string of target glob pattern
  *
  * Glob matching the name of @dw_die and @glob. Return false if matching fail.
+ * This also match linkage name.
  */
 bool die_match_name(Dwarf_Die *dw_die, const char *glob)
 {
        const char *name;
 
        name = dwarf_diename(dw_die);
-       return name ? strglobmatch(name, glob) : false;
+       if (name && strglobmatch(name, glob))
+               return true;
+       /* fall back to check linkage name */
+       name = die_get_linkage_name(dw_die);
+       if (name && strglobmatch(name, glob))
+               return true;
+
+       return false;
 }
 
 /**
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index 8b6d2f83af02..8ac53bf1ec4e 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -38,6 +38,9 @@ int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
 int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
                         int (*callback)(Dwarf_Die *, void *), void *data);
 
+/* Get DW_AT_linkage_name (should be NULL for C binary) */
+const char *die_get_linkage_name(Dwarf_Die *dw_die);
+
 /* Ensure that this DIE is a subprogram and definition (not declaration) */
 bool die_is_func_def(Dwarf_Die *dw_die);
 
-- 
2.7.4

Reply via email to