[PATCH v1 1/2] perf libdw: Pass dso_name explicitly to properly anchor split-debug builds

Ian Rogers <[email protected]>
Newsgroups org.kernel.vger.linux-kernel,org.kernel.vger.linux-perf-users
Message-ID <[email protected]>
When resolving source lines via get_srcline(), srcline_dso_name()
explicitly checks for and returns the split-debug file path
(dso__symsrc_filename, which is cached during dso__load()) rather than
the default executable path (dso__long_name). Because libdw__addr2line
defaulted to dso__long_name without accepting a passed dso_name, the
Dwfl_Module was hardcoded to initialize against the stripped
executable instead of the intended split debug file.

By explicitly passing the successfully resolved dso_name down the call
path from addr2line() to dso__libdw_dwfl(), libdw accurately anchors to
the dynamically discovered split-debug file, fixing dwarf resolution for
these binaries.

Assisted-by: Antigravity:gemini-3.6-flash
Signed-off-by: Ian Rogers <[email protected]>
---
 tools/perf/arch/powerpc/util/skip-callchain-idx.c |  2 +-
 tools/perf/util/dso.h                             |  5 +++--
 tools/perf/util/libdw.c                           | 10 +++++-----
 tools/perf/util/libdw.h                           |  5 +++--
 tools/perf/util/srcline.c                         |  2 +-
 5 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index e57f10798fa6..f7dd27faaec2 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -152,7 +152,7 @@ static int check_return_addr(struct dso *dso, Dwarf_Addr mapped_pc)
 	Dwarf_Addr	end = mapped_pc;
 	bool		signalp;
 
-	dwfl = dso__libdw_dwfl(dso);
+	dwfl = dso__libdw_dwfl(dso, NULL);
 	if (!dwfl)
 		return -1;
 
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 55c4aaa53c38..3271e1ecaa9e 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -380,9 +380,10 @@ static inline void dso__set_libdw(struct dso *dso, void *val)
 
 struct Dwfl;
 #ifdef HAVE_LIBDW_SUPPORT
-struct Dwfl *dso__libdw_dwfl(struct dso *dso);
+struct Dwfl *dso__libdw_dwfl(struct dso *dso, const char *dso_name);
 #else
-static inline struct Dwfl *dso__libdw_dwfl(struct dso *dso __maybe_unused)
+static inline struct Dwfl *dso__libdw_dwfl(struct dso *dso __maybe_unused,
+					   const char *dso_name __maybe_unused)
 {
 	return NULL;
 }
diff --git a/tools/perf/util/libdw.c b/tools/perf/util/libdw.c
index 4ca7e7e4fbe9..f53caee980b0 100644
--- a/tools/perf/util/libdw.c
+++ b/tools/perf/util/libdw.c
@@ -25,17 +25,17 @@ void dso__free_libdw(struct dso *dso)
 	}
 }
 
-struct Dwfl *dso__libdw_dwfl(struct dso *dso)
+struct Dwfl *dso__libdw_dwfl(struct dso *dso, const char *dso_name)
 {
 	Dwfl *dwfl = dso__libdw(dso);
-	const char *dso_name;
 	Dwfl_Module *mod;
 	int fd;
 
 	if (dwfl)
 		return dwfl;
 
-	dso_name = dso__long_name(dso);
+	if (!dso_name)
+		dso_name = dso__long_name(dso);
 	/*
 	 * Initialize Dwfl session.
 	 * We need to open the DSO file to report it to libdw.
@@ -163,11 +163,11 @@ static int libdw_a2l_cb(Dwarf_Die *die, void *_args)
 	return DWARF_CB_ABORT;
 }
 
-int libdw__addr2line(u64 addr, char **file, unsigned int *line_nr,
+int libdw__addr2line(const char *dso_name, u64 addr, char **file, unsigned int *line_nr,
 		     struct dso *dso, bool unwind_inlines,
 		     struct inline_node *node, struct symbol *sym)
 {
-	Dwfl *dwfl = dso__libdw_dwfl(dso);
+	Dwfl *dwfl = dso__libdw_dwfl(dso, dso_name);
 	Dwfl_Module *mod;
 	Dwfl_Line *dwline;
 	Dwarf_Addr bias;
diff --git a/tools/perf/util/libdw.h b/tools/perf/util/libdw.h
index b12094737415..4bdd28d44e25 100644
--- a/tools/perf/util/libdw.h
+++ b/tools/perf/util/libdw.h
@@ -25,7 +25,7 @@ struct symbol;
  *
  * Returns 1 on success (found), 0 on failure (not found).
  */
-int libdw__addr2line(u64 addr, char **file,
+int libdw__addr2line(const char *dso_name, u64 addr, char **file,
 		     unsigned int *line_nr, struct dso *dso,
 		     bool unwind_inlines, struct inline_node *node,
 		     struct symbol *sym);
@@ -40,7 +40,8 @@ void dso__free_libdw(struct dso *dso);
 
 #else /* HAVE_LIBDW_SUPPORT */
 
-static inline int libdw__addr2line(u64 addr __maybe_unused, char **file __maybe_unused,
+static inline int libdw__addr2line(const char *dso_name, u64 addr __maybe_unused,
+				   char **file __maybe_unused,
 				   unsigned int *line_nr __maybe_unused,
 				   struct dso *dso __maybe_unused,
 				   bool unwind_inlines __maybe_unused,
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index b082178c279b..8e954f0c860a 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -155,7 +155,7 @@ static int addr2line(const char *dso_name, u64 addr, char **file, unsigned int *
 	for (size_t i = 0; i < ARRAY_SIZE(symbol_conf.addr2line_style); i++) {
 		switch (symbol_conf.addr2line_style[i]) {
 		case A2L_STYLE_LIBDW:
-			ret = libdw__addr2line(addr, file, line_nr, dso, unwind_inlines,
+			ret = libdw__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines,
 					       node, sym);
 			break;
 		case A2L_STYLE_LLVM:
-- 
2.55.0.766.g2966f0265a-goog
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.