From: Namhyung Kim <namhyung@kernel.org>
To: James Clark <james.clark@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
Jakub Brnak <jbrnak@redhat.com>, Leo Yan <leo.yan@arm.com>,
Arnaldo Carvalho de Melo <acme@redhat.com>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 1/4] perf libdw: Find the CU by iterating all CUs when aranges are missing
Date: Sun, 8 Nov 2026 20:51:14 -0800 [thread overview]
Message-ID: <avFRQh8EL_Ab9Qcs@z2> (raw)
In-Reply-To: <20261106-james-perf-test-fixes-v2-1-9a912662f822@linaro.org>
Hello James,
On Fri, Nov 06, 2026 at 10:48:07AM +0000, James Clark wrote:
> libdw__addr2line() finds the CU with dwfl_module_getsrc() and
> dwfl_module_addrdie(), which use dwarf_getaranges(). In elfutils 0.190
> this only reads .debug_aranges, which can be partial. For example, when
> Perf is built with LLVM=1, clang doesn't emit .debug_aranges by default
> so the lookup then fails and no source lines are found for most of the
> Perf binary.
>
> This used to be hidden by falling back to the next addr2line style, but
> now missing information stops the fallback since commit (62d7cdc8d587
> "perf libdw: Optimize fallback logic for missing DWARF").
>
> find_cu_die() in annotate-data.c already handles partial aranges by
> iterating all CUs in .debug_info and checking them with dwarf_haspc().
> Move it to dwarf-aux.c, then look up the line in that CU with
> dwarf_getsrc_die() and use the same CU for unwinding inlines. While
> moving it, don't treat a dwarf_haspc() error as a match.
>
> This fixes the "test addr2line inline unwinding" test when Perf is built
> with LLVM:
>
> $ perf test -vvv "test addr2line inline unwinding"
> ...
> Inline unwinding fp verification test [Failed missing inlined functions]
> ...
> Inline unwinding dwarf verification test [Failed missing inlined functions]
> ...
> Inline unwinding lbr verification test [Failed missing inlined functions]
> ---- end(-1) ----
> 79: test addr2line inline unwinding : FAILED!
>
> Fixes: 88c51002d06f ("perf addr2line: Add a libdw implementation")
> Signed-off-by: James Clark <james.clark@linaro.org>
Can you please rebase this one again? It seems to clash with the recent
C++ data type profiling support. I'm processing other patches as they
are independent fixes.
Thanks,
Namhyung
> ---
> tools/perf/util/annotate-data.c | 27 +--------------------------
> tools/perf/util/dwarf-aux.c | 37 +++++++++++++++++++++++++++++++++++++
> tools/perf/util/dwarf-aux.h | 3 +++
> tools/perf/util/libdw.c | 19 ++++++++++---------
> 4 files changed, 51 insertions(+), 35 deletions(-)
>
> diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
> index 25e3169ea8ad..8092ef9d2045 100644
> --- a/tools/perf/util/annotate-data.c
> +++ b/tools/perf/util/annotate-data.c
> @@ -523,31 +523,6 @@ static struct annotated_data_type *dso__findnew_data_type(struct dso *dso,
> return result;
> }
>
> -static bool find_cu_die(struct debuginfo *di, u64 pc, Dwarf_Die *cu_die)
> -{
> - Dwarf_Off off, next_off;
> - size_t header_size;
> -
> - if (dwarf_addrdie(di->dbg, pc, cu_die) != NULL)
> - return cu_die;
> -
> - /*
> - * There are some kernels don't have full aranges and contain only a few
> - * aranges entries. Fallback to iterate all CU entries in .debug_info
> - * in case it's missing.
> - */
> - off = 0;
> - while (dwarf_nextcu(di->dbg, off, &next_off, &header_size,
> - NULL, NULL, NULL) == 0) {
> - if (dwarf_offdie(di->dbg, off + header_size, cu_die) &&
> - dwarf_haspc(cu_die, pc))
> - return true;
> -
> - off = next_off;
> - }
> - return false;
> -}
> -
> enum type_match_result {
> PERF_TMR_UNKNOWN = 0,
> PERF_TMR_OK,
> @@ -1827,7 +1802,7 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die)
> pc = map__rip_2objdump(dloc->ms->map, dloc->ip);
>
> /* Get a compile_unit for this address */
> - if (!find_cu_die(dloc->di, pc, &cu_die)) {
> + if (!cu_find_by_addr(dloc->di->dbg, pc, &cu_die)) {
> pr_debug_dtp("cannot find CU for address %"PRIx64"\n", pc);
> ann_data_stat.no_cuinfo++;
> return -1;
> diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
> index 54f8b5ec74a2..742fccba5376 100644
> --- a/tools/perf/util/dwarf-aux.c
> +++ b/tools/perf/util/dwarf-aux.c
> @@ -106,6 +106,43 @@ static Dwarf_Line *cu_getsrc_die(Dwarf_Die *cu_die, Dwarf_Addr addr)
> return line;
> }
>
> +/**
> + * cu_find_by_addr - Find the CU DIE that contains an address
> + * @dbg: a Dwarf handle
> + * @addr: An address
> + * @cu_die: a buffer to store the found CU DIE
> + *
> + * Find the CU DIE whose ranges contain @addr. dwarf_addrdie() uses
> + * dwarf_getaranges() which didn't work until elfutils 0.191. Release notes:
> + *
> + * * NEWS *
> + * libdw: dwarf_addrdie now supports binaries lacking a .debug_aranges
> + * section.
> + *
> + * Clang doesn't emit them by default, so fall back to iterating all CUs in
> + * case it's missing.
> + *
> + * Return @cu_die if found, otherwise NULL.
> + */
> +Dwarf_Die *cu_find_by_addr(Dwarf *dbg, Dwarf_Addr addr, Dwarf_Die *cu_die)
> +{
> + Dwarf_Off off = 0, next_off;
> + size_t header_size;
> +
> + if (dwarf_addrdie(dbg, addr, cu_die) && dwarf_haspc(cu_die, addr) == 1)
> + return cu_die;
> +
> + while (dwarf_nextcu(dbg, off, &next_off, &header_size,
> + NULL, NULL, NULL) == 0) {
> + if (dwarf_offdie(dbg, off + header_size, cu_die) &&
> + dwarf_haspc(cu_die, addr) == 1)
> + return cu_die;
> +
> + off = next_off;
> + }
> + return NULL;
> +}
> +
> /**
> * cu_find_lineinfo - Get a line number and file name for given address
> * @cu_die: a CU DIE
> diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
> index 6f9145510adc..cc3fd61374c4 100644
> --- a/tools/perf/util/dwarf-aux.h
> +++ b/tools/perf/util/dwarf-aux.h
> @@ -23,6 +23,9 @@ const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname);
> /* Get DW_AT_comp_dir (should be NULL with older gcc) */
> const char *cu_get_comp_dir(Dwarf_Die *cu_die);
>
> +/* Find the CU DIE that contains the given address */
> +Dwarf_Die *cu_find_by_addr(Dwarf *dbg, Dwarf_Addr addr, Dwarf_Die *cu_die);
> +
> /* Get a line number and file name for given address */
> int cu_find_lineinfo(Dwarf_Die *cudie, Dwarf_Addr addr,
> const char **fname, int *lineno);
> diff --git a/tools/perf/util/libdw.c b/tools/perf/util/libdw.c
> index e660623338d5..90767361f485 100644
> --- a/tools/perf/util/libdw.c
> +++ b/tools/perf/util/libdw.c
> @@ -170,7 +170,9 @@ int libdw__addr2line(u64 addr, char **file, unsigned int *line_nr,
> {
> Dwfl *dwfl;
> Dwfl_Module *mod;
> - Dwfl_Line *dwline;
> + Dwarf_Line *dwline;
> + Dwarf_Die cu_mem, *cudie;
> + Dwarf *dw;
> Dwarf_Addr bias;
> const char *src;
> int lineno = 0;
> @@ -197,7 +199,8 @@ int libdw__addr2line(u64 addr, char **file, unsigned int *line_nr,
> * between the regular ELF addr2line addresses and those to use with
> * libdw.
> */
> - if (!dwfl_module_getdwarf(mod, &bias)) {
> + dw = dwfl_module_getdwarf(mod, &bias);
> + if (!dw) {
> /*
> * Free the Dwfl session so the mmap'd ELF binary is unmapped
> * immediately, and mark the DSO as lacking srcline/DWARF info
> @@ -211,7 +214,8 @@ int libdw__addr2line(u64 addr, char **file, unsigned int *line_nr,
> }
>
> /* Find source line information for the address. */
> - dwline = dwfl_module_getsrc(mod, addr + bias);
> + cudie = cu_find_by_addr(dw, addr, &cu_mem);
> + dwline = cudie ? dwarf_getsrc_die(cudie, addr) : NULL;
> if (!dwline) {
> /* conclusively missing information -> abort fallbacks */
> ret = 0;
> @@ -219,8 +223,8 @@ int libdw__addr2line(u64 addr, char **file, unsigned int *line_nr,
> }
>
> /* Get line information. */
> - src = dwfl_lineinfo(dwline, /*addr=*/NULL, &lineno, /*col=*/NULL, /*mtime=*/NULL,
> - /*length=*/NULL);
> + src = dwarf_linesrc(dwline, /*mtime=*/NULL, /*length=*/NULL);
> + dwarf_lineno(dwline, &lineno);
>
> if (file)
> *file = src ? strdup(src) : NULL;
> @@ -229,8 +233,6 @@ int libdw__addr2line(u64 addr, char **file, unsigned int *line_nr,
>
> /* Optionally unwind inline function call chain. */
> if (unwind_inlines && node) {
> - Dwarf_Addr unused_bias;
> - Dwarf_Die *cudie = dwfl_module_addrdie(mod, addr + bias, &unused_bias);
> struct libdw_a2l_cb_args args = {
> .dso = dso,
> .sym = sym,
> @@ -248,8 +250,7 @@ int libdw__addr2line(u64 addr, char **file, unsigned int *line_nr,
> }
>
> /* Walk from the parent down to the leaf. */
> - if (cudie)
> - cu_walk_functions_at(cudie, addr, libdw_a2l_cb, &args);
> + cu_walk_functions_at(cudie, addr, libdw_a2l_cb, &args);
>
> if (!args.leaf_srcline_used)
> free(args.leaf_srcline);
>
> --
> 2.43.0
>
next prev parent reply other threads:[~2026-11-09 4:51 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-06 10:48 [PATCH v2 0/4] perf tools: LLVM dwarf and flaky test fixes James Clark
2026-11-06 10:48 ` [PATCH v2 1/4] perf libdw: Find the CU by iterating all CUs when aranges are missing James Clark
2026-11-09 4:51 ` Namhyung Kim [this message]
2026-11-06 10:48 ` [PATCH v2 2/4] perf dwarf-aux: Support DW_OP_addrx locations for global variables James Clark
2026-11-06 10:48 ` [PATCH v2 3/4] perf test probe_vfs_getname: Fix missing debuginfo detection James Clark
2026-11-06 10:48 ` [PATCH v2 4/4] perf test: Don't starve per-process tests with system-wide events James Clark
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=avFRQh8EL_Ab9Qcs@z2 \
--to=namhyung@kernel.org \
--cc=acme@kernel.org \
--cc=acme@redhat.com \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=irogers@google.com \
--cc=james.clark@linaro.org \
--cc=jbrnak@redhat.com \
--cc=jolsa@kernel.org \
--cc=leo.yan@arm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®