From d5a00296a63fdd049273f86d0a0cdef6b230f8e6 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Sat, 24 Sep 2016 00:35:31 +0900 Subject: [PATCH] perf probe: Match linkage name with mangled name 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 Signed-off-by: Masami Hiramatsu Tested-by: Arnaldo Carvalho de Melo Tested-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/147464493162.29804.16715053505069382443.stgit@devbox Signed-off-by: Arnaldo Carvalho de Melo --- 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 @@ -129,6 +129,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 @@ -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);