From: Holger Hans Peter Freyther <holgar+ker...@google.com> If die_match_name does not match, attempt to demangle the linkage name. To use the generic demangling API we require to have a struct dso. Store it inside the debuginfo and pass it to the relevant callbacks.
./perf probe -x ./foo -L \ "std::vector<int, std::allocator<int> >::at:2-3" <...::at@/usr/include/c++/5/bits/stl_vector.h:2> 2 _M_range_check(__n); 3 return (*this)[__n]; Signed-off-by: Holger Hans Peter Freyther <holgar+ker...@google.com> --- tools/perf/util/probe-finder.c | 55 ++++++++++++++++++++++++++++++++++-------- tools/perf/util/probe-finder.h | 3 +++ 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index c37fbef..c73dccc 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -96,7 +96,7 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, return -ENOENT; } -static struct debuginfo *__debuginfo__new(const char *path) +static struct debuginfo *__debuginfo__new(const char *path, struct dso *dso) { struct debuginfo *dbg = zalloc(sizeof(*dbg)); if (!dbg) @@ -104,8 +104,10 @@ static struct debuginfo *__debuginfo__new(const char *path) if (debuginfo__init_offline_dwarf(dbg, path) < 0) zfree(&dbg); - if (dbg) + if (dbg) { pr_debug("Open Debuginfo file: %s\n", path); + dbg->dso = dso__get(dso); + } return dbg; } @@ -135,13 +137,15 @@ struct debuginfo *debuginfo__new(const char *path) if (dso__read_binary_type_filename(dso, *type, &nil, buf, PATH_MAX) < 0) continue; - dinfo = __debuginfo__new(buf); + dinfo = __debuginfo__new(buf, dso); } - dso__put(dso); out: /* if failed to open all distro debuginfo, open given binary */ - return dinfo ? : __debuginfo__new(path); + if (!dinfo) + dinfo = __debuginfo__new(path, dso); + dso__put(dso); + return dinfo; } void debuginfo__delete(struct debuginfo *dbg) @@ -149,6 +153,7 @@ void debuginfo__delete(struct debuginfo *dbg) if (dbg) { if (dbg->dwfl) dwfl_end(dbg->dwfl); + dso__put(dbg->dso); free(dbg); } } @@ -167,6 +172,32 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs) } /* + * Check if the the demangled linkage_name matches the function. E.g. the + * linkage name of _ZNKSt6vectorIiSaIiEE4sizeEv matching the c++ function name + * of std::vector<int, std::allocator<int> >::size() const. + */ +static bool matches_demangled(struct debuginfo *dbg, Dwarf_Die *dw_die, + const char *function) +{ + const char *name; + char *demangled; + bool res; + + name = die_get_linkage_name(dw_die); + if (!name) + return false; + + demangled = dso__demangle_sym(dbg->dso, 0, name); + if (!demangled) + return false; + + res = strglobmatch(demangled, function); + free(demangled); + return res; +} + + +/* * Convert a location into trace_arg. * If tvar == NULL, this just checks variable can be converted. * If fentry == true and vr_die is a parameter, do huristic search @@ -975,6 +1006,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) struct dwarf_callback_param { void *data; int retval; + struct debuginfo *dbg; }; /* Search function from function name */ @@ -1721,7 +1753,8 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) return DWARF_CB_OK; if (die_is_func_def(sp_die) && - die_match_name(sp_die, lr->function)) { + (die_match_name(sp_die, lr->function) || + matches_demangled(param->dbg, sp_die, lr->function))) { lf->fname = dwarf_decl_file(sp_die); dwarf_decl_line(sp_die, &lr->offset); pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); @@ -1744,9 +1777,11 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) return DWARF_CB_OK; } -static int find_line_range_by_func(struct line_finder *lf) +static int find_line_range_by_func(struct debuginfo *dbg, + struct line_finder *lf) { - struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; + struct dwarf_callback_param param = { + .data = (void *)lf, .retval = 0, .dbg = dbg}; dwarf_getfuncs(&lf->cu_die, line_range_search_cb, ¶m, 0); return param.retval; } @@ -1766,7 +1801,7 @@ int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr) .function = lr->function, .file = lr->file, .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0}; struct dwarf_callback_param line_range_param = { - .data = (void *)&lf, .retval = 0}; + .data = (void *)&lf, .retval = 0, .dbg = dbg}; dwarf_getpubnames(dbg->dbg, pubname_search_cb, &pubname_param, 0); @@ -1796,7 +1831,7 @@ int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr) if (!lr->file || lf.fname) { if (lr->function) - ret = find_line_range_by_func(&lf); + ret = find_line_range_by_func(dbg, &lf); else { lf.lno_s = lr->start; lf.lno_e = lr->end; diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 1625298..e28acbd 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -14,6 +14,8 @@ #define PROBE_ARG_VARS "$vars" #define PROBE_ARG_PARAMS "$params" +struct dso; + static inline int is_c_varname(const char *name) { /* TODO */ @@ -32,6 +34,7 @@ struct debuginfo { Dwfl_Module *mod; Dwfl *dwfl; Dwarf_Addr bias; + struct dso *dso; }; /* This also tries to open distro debuginfo */ -- 2.7.4