summaryrefslogtreecommitdiff
path: root/tools/perf/util/probe-finder.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r--tools/perf/util/probe-finder.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 371476cb8ddc..c09e0a9fdf4c 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1327,8 +1327,8 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
struct perf_probe_point *ppt)
{
Dwarf_Die cudie, spdie, indie;
- Dwarf_Addr _addr, baseaddr;
- const char *fname = NULL, *func = NULL, *tmp;
+ Dwarf_Addr _addr = 0, baseaddr = 0;
+ const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
int baseline = 0, lineno = 0, ret = 0;
/* Adjust address with bias */
@@ -1349,27 +1349,36 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
/* Find a corresponding function (name, baseline and baseaddr) */
if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
/* Get function entry information */
- tmp = dwarf_diename(&spdie);
- if (!tmp ||
+ func = basefunc = dwarf_diename(&spdie);
+ if (!func ||
dwarf_entrypc(&spdie, &baseaddr) != 0 ||
- dwarf_decl_line(&spdie, &baseline) != 0)
+ dwarf_decl_line(&spdie, &baseline) != 0) {
+ lineno = 0;
goto post;
- func = tmp;
+ }
- if (addr == (unsigned long)baseaddr)
+ if (addr == (unsigned long)baseaddr) {
/* Function entry - Relative line number is 0 */
lineno = baseline;
- else if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
- &indie)) {
+ fname = dwarf_decl_file(&spdie);
+ goto post;
+ }
+
+ /* Track down the inline functions step by step */
+ while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr,
+ &indie)) {
+ /* There is an inline function */
if (dwarf_entrypc(&indie, &_addr) == 0 &&
- _addr == addr)
+ _addr == addr) {
/*
* addr is at an inline function entry.
* In this case, lineno should be the call-site
- * line number.
+ * line number. (overwrite lineinfo)
*/
lineno = die_get_call_lineno(&indie);
- else {
+ fname = die_get_call_file(&indie);
+ break;
+ } else {
/*
* addr is in an inline function body.
* Since lineno points one of the lines
@@ -1377,19 +1386,27 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
* be the entry line of the inline function.
*/
tmp = dwarf_diename(&indie);
- if (tmp &&
- dwarf_decl_line(&spdie, &baseline) == 0)
- func = tmp;
+ if (!tmp ||
+ dwarf_decl_line(&indie, &baseline) != 0)
+ break;
+ func = tmp;
+ spdie = indie;
}
}
+ /* Verify the lineno and baseline are in a same file */
+ tmp = dwarf_decl_file(&spdie);
+ if (!tmp || strcmp(tmp, fname) != 0)
+ lineno = 0;
}
post:
/* Make a relative line number or an offset */
if (lineno)
ppt->line = lineno - baseline;
- else if (func)
+ else if (basefunc) {
ppt->offset = addr - (unsigned long)baseaddr;
+ func = basefunc;
+ }
/* Duplicate strings */
if (func) {