mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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
> 

  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®