diff options
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/util/probe-finder.c | 56 |
1 files changed, 48 insertions, 8 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 508c017f566a..69215bff17e9 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -280,6 +280,19 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) return name ? (strcmp(tname, name) == 0) : false; } +/* Get callsite line number of inline-function instance */ +static int die_get_call_lineno(Dwarf_Die *in_die) +{ + Dwarf_Attribute attr; + Dwarf_Word ret; + + if (!dwarf_attr(in_die, DW_AT_call_line, &attr)) + return -ENOENT; + + dwarf_formudata(&attr, &ret); + return (int)ret; +} + /* Get type die */ static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) { @@ -463,27 +476,54 @@ typedef int (* line_walk_handler_t) (const char *fname, int lineno, Dwarf_Addr addr, void *data); struct __line_walk_param { + const char *fname; line_walk_handler_t handler; void *data; int retval; }; -/* Walk on decl lines in given DIE */ +static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) +{ + struct __line_walk_param *lw = data; + Dwarf_Addr addr; + int lineno; + + if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) { + lineno = die_get_call_lineno(in_die); + if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) { + lw->retval = lw->handler(lw->fname, lineno, addr, + lw->data); + if (lw->retval != 0) + return DIE_FIND_CB_FOUND; + } + } + return DIE_FIND_CB_SIBLING; +} + +/* Walk on lines of blocks included in given DIE */ static int __die_walk_funclines(Dwarf_Die *sp_die, line_walk_handler_t handler, void *data) { - const char *fname; + struct __line_walk_param lw = { + .handler = handler, + .data = data, + .retval = 0, + }; + Dwarf_Die die_mem; Dwarf_Addr addr; - int lineno, ret = 0; + int lineno; /* Handle function declaration line */ - fname = dwarf_decl_file(sp_die); - if (fname && dwarf_decl_line(sp_die, &lineno) == 0 && + lw.fname = dwarf_decl_file(sp_die); + if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 && dwarf_entrypc(sp_die, &addr) == 0) { - ret = handler(fname, lineno, addr, data); + lw.retval = handler(lw.fname, lineno, addr, data); + if (lw.retval != 0) + goto done; } - - return ret; + die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem); +done: + return lw.retval; } static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data) |