[PATCH v4 3/3] perf libbfd: Report success when an address is found
From: Ian Rogers
Date: Thu Sep 17 2026 - 01:05:31 EST
libbfd__addr2line() only reports success when the caller asked for a file
name. addr2inlines() passes a NULL file as it just wants the inline_node
populating, so libbfd__addr2line() returns 0 for it unless
bfd_find_inliner_info() happened to find an inline frame. addr2line() in
srcline.c treats 0 as a failure and tries the next addr2line
implementation, which appends its own frames to the inline_node libbfd
already appended to. Every frame that isn't inlined is then reported
twice, which happens by default when perf is built with libbfd but
without libdw as the fallback order is then libbfd followed by the
addr2line command:
$ perf record --call-graph dwarf -- perf test -w inlineloop 1
$ perf script --fields +srcline
...
56051a994f8e parent+0x2e (perf)
inlineloop.c:32
56051a99503a inlineloop+0x8a (perf)
inlineloop.c:47
56051a99503a inlineloop+0x8a (perf)
inlineloop.c:47
56051a95841a cmd_test+0xb7a (perf)
??:0
56051a95841a cmd_test+0xb7a (perf)
??:0
...
Report success whenever the address is found, like libdw__addr2line()
does, and clear the frames appended so far when appending fails so that a
following implementation starts from an empty node.
Fixes: 257046a36750 ("perf srcline: Fallback between addr2line implementations")
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
Assisted-by: Antigravity:gemini-3.1-pro
---
tools/perf/util/libbfd.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/libbfd.c b/tools/perf/util/libbfd.c
index d87242d88525..a907d7c1ac94 100644
--- a/tools/perf/util/libbfd.c
+++ b/tools/perf/util/libbfd.c
@@ -287,6 +287,7 @@ int libbfd__addr2line(const char *dso_name, u64 addr,
int cnt = 0;
if (node && inline_list__append_dso_a2l(dso, node, sym)) {
+ inline_node__clear_frames(node);
ret = 0;
goto out;
}
@@ -300,23 +301,32 @@ int libbfd__addr2line(const char *dso_name, u64 addr,
if (node != NULL) {
if (inline_list__append_dso_a2l(dso, node, sym)) {
+ inline_node__clear_frames(node);
ret = 0;
goto out;
}
- // found at least one inline frame
- ret = 1;
}
}
}
if (file) {
*file = a2l->filename ? strdup(a2l->filename) : NULL;
- ret = *file ? 1 : 0;
+ if (!*file) {
+ /* Leave ret as 0 so that another addr2line is tried. */
+ goto out;
+ }
}
if (line)
*line = a2l->line;
+ /*
+ * The address was found, report success so that the caller doesn't try
+ * another addr2line implementation that would append the inline frames
+ * above a second time.
+ */
+ ret = 1;
+
out:
mutex_unlock(dso__lock(dso));
return ret;
--
2.55.0.1082.g2b9226bbc0-goog