From nobody Fri Sep 25 04:07:25 2026 Received: from mail-pg1-f198.google.com (mail-pg1-f198.google.com [209.85.215.198]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 388984E2F35 for ; Wed, 16 Sep 2026 23:44:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.198 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789602259; cv=none; b=X2V429OPnJGc3Tqo02WPXg1fAht9//GsmtbMw+tpLjePz4nO4UYBmuzmoogGDm2UQNC7E8EiK2jJwggc4S39aIgK/HTBFmhNV20UmPChU7Cx7NC7nKac1JdTWxTHUA3LEJaChc/GRaoY6VVqeuGtXCzOvsZkyGUaoQOebzdI4zk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789602259; c=relaxed/simple; bh=qK2F0IQnQx9yHiNaJ5bSOqCmyHGiE7Ags8NWaLOS0q8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=tqrtZ2vIl1VVnxpHVWm5ZdnxyaHaHaOubQeV3WT/llRboh4g3/xN9FfZjGT3p6OVdZlkZss0Xp8HRwj63qtIRxkJ5Md6P09s6pSHs6FMBichfvBiHnKnlNHg7GIEq02PnOJYVs1WdAMsdLvOzZ4Tbch4OoeM87u3yxfcN2oOHDw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=jskvm062; arc=none smtp.client-ip=209.85.215.198 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="jskvm062" Received: by mail-pg1-f198.google.com with SMTP id 41be03b00d2f7-cc18ced1a5aso420899a12.1 for ; Wed, 16 Sep 2026 16:44:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1789602256; x=1790207056; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=HzyGf/qaGyRxZDcMV7tktQob1qNSWeRtQ/8IGLc4qXY=; b=jskvm0622rIm19/RXMX2yrs7+ApKT11ojKNhxV2OTvKSD9HVIZOs4HcqpMRBN+sxXB SaMTREiEAPk1Q9iQScWMi25K7ojniuDl188OK/OPVFV5gc6/WHN51adyJyr8tZsgS9wr pz4UReFehdI3zaj5TOpTV8MXerWWG0NtqR928LJTNBcvmV41y2m8y2uzUEWlXo6Qa0YF HyDqlaDfOZqppAUVeaIESrQvqa4z8EWoWbwMQSrMJyo31Lv5F/BqH+qp8+fBxaGX9ccq tbOE2FFCKkjJwH9w27aPRKxYzb1mPYZHXCKcM8mqkfkFaVe9DFtygOdaxnMWYb1XF9m5 ZCMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789602256; x=1790207056; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=HzyGf/qaGyRxZDcMV7tktQob1qNSWeRtQ/8IGLc4qXY=; b=WLETYH1jwh0StXJFy+aNLqCSRFZ+1m+pUg1SKm/8kMJg364PI5Bqf3w9i+fWXe9/ZH qhNi1eTV+HdCMlbwiZVovt5MIGKaWhFJ67Hp8uB1JKX7UxntBLNgDFyhVHkJiaeBR/V8 tJ2RA2VVZ2+Xz0aJPJ1g04o2ceDTiyy6u8svSEP91UJImqcURVtsFkHoTF/emRlNpqjM d+datgrttqeYJ/eg0qUeaKvYTiYi4ggLevOztYh8VWuyMZt3Au2+Eb9fzF09bx77KmuC 1czqPdsWAq0YHZRCvygzdcY+rmz0MECfyuoGCq4WQv3r4GtrI0VfGWQtD1wjromsc05b xL3w== X-Forwarded-Encrypted: i=1; AKwUvBy/5yPpcdeOGwKfaXRzqXWbGJVf18IFRdmwYI7m4u4XyHHa8rPn3YQF5CoBMfzfAs9sels8CXASX8EG+T0=@vger.kernel.org X-Gm-Message-State: AFuF++mvE43gYPkHdAsi+h3CMl5LTQUGs4wyiLmjf64FMa1yVBmB7iCp +/Qljcw1fleBm3Xw+7Pa+w4CE+B0nNIWxNPE0I/P/1d/0utfDnaESV/4xpm4ZXET0ATzoKc5oZq B9D/HRoTlOg== X-Received: from dled18-n2.prod.google.com ([2002:a05:701b:42d2:20b0:144:bef2:bc76]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:4a81:b0:3da:3492:83d0 with SMTP id adf61e73a8af0-3dd5f7ad04cmr10322072637.23.1789602256339; Wed, 16 Sep 2026 16:44:16 -0700 (PDT) Date: Wed, 16 Sep 2026 16:44:00 -0700 In-Reply-To: <20260916234402.437113-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260916063545.3103314-1-irogers@google.com> <20260916234402.437113-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.1082.g2b9226bbc0-goog Message-ID: <20260916234402.437113-2-irogers@google.com> Subject: [PATCH v3 1/3] perf libdw: Fix Dwfl discovery with split files From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org Cc: adrian.hunter@intel.com, james.clark@linaro.org, jolsa@kernel.org, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, mingo@redhat.com, peterz@infradead.org, tmricht@linux.ibm.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" dso__libdw_dwfl() opens the Dwfl with dso__long_name(), the file the samples came from. When the debug information lives in a separate file, symbol loading finds it and records it as the dso's symsrc filename, but the Dwfl still refers to the original file, so libdw has no DWARF to resolve addresses against. Open the Dwfl with the symsrc filename when one is known and fall back to the long name when it isn't. The symsrc file is found while symbols are loaded, which can happen after the Dwfl has been created and cached, so drop the cached Dwfl and the addr2line cache built from it when the symsrc filename is set. That teardown can run while another thread is using the cache, so take the dso lock across both the teardown and the Dwfl accessors, and re-read dso__symsrc_filename() under the dso lock in libbfd__addr2line() and cmd__addr2line() to prevent a TOCTOU race with cache invalidation. Fixes: b7a2b011e962 ("perf powerpc: Unify the skip-callchain-idx libdw with= that for addr2line") Signed-off-by: Ian Rogers Assisted-by: Antigravity:gemini-3.1-pro --- .../arch/powerpc/util/skip-callchain-idx.c | 4 +- tools/perf/util/addr2line.c | 41 +++++++++--- tools/perf/util/dso.c | 9 +++ tools/perf/util/dso.h | 5 +- tools/perf/util/libbfd.c | 29 ++++++--- tools/perf/util/libdw.c | 39 ++++++++---- tools/perf/util/srcline.c | 61 ++++++++++++------ tools/perf/util/unwind-libdw.c | 2 + tools/perf/util/unwind-libunwind.c | 62 ++++++++++++++----- 9 files changed, 183 insertions(+), 69 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..472714cfad38 100644 --- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c +++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c @@ -152,9 +152,10 @@ static int check_return_addr(struct dso *dso, Dwarf_Ad= dr mapped_pc) Dwarf_Addr end =3D mapped_pc; bool signalp; =20 + mutex_lock(dso__lock(dso)); dwfl =3D dso__libdw_dwfl(dso); if (!dwfl) - return -1; + goto out; =20 mod =3D dwfl_addrmodule(dwfl, mapped_pc); if (!mod) { @@ -183,6 +184,7 @@ static int check_return_addr(struct dso *dso, Dwarf_Add= r mapped_pc) rc =3D check_return_reg(ra_regno, frame); =20 out: + mutex_unlock(dso__lock(dso)); return rc; } =20 diff --git a/tools/perf/util/addr2line.c b/tools/perf/util/addr2line.c index 4b0d349ed334..0abe8dd07670 100644 --- a/tools/perf/util/addr2line.c +++ b/tools/perf/util/addr2line.c @@ -284,7 +284,7 @@ int cmd__addr2line(const char *dso_name, u64 addr, struct inline_node *node, struct symbol *sym __maybe_unused) { - struct child_process *a2l =3D dso__a2l(dso); + struct child_process *a2l; char *record_function =3D NULL; char *record_filename =3D NULL; unsigned int record_line_nr =3D 0; @@ -296,24 +296,38 @@ int cmd__addr2line(const char *dso_name, u64 addr, ssize_t written; struct io io =3D { .eof =3D false }; enum cmd_a2l_style cmd_a2l_style; + const char *current_dso_name; + + mutex_lock(dso__lock(dso)); + current_dso_name =3D dso__symsrc_filename(dso) ?: dso_name; + a2l =3D dso__a2l(dso); =20 if (!a2l) { - if (!filename__has_section(dso_name, ".debug_line")) - goto out; + if (!filename__has_section(current_dso_name, ".debug_line")) + goto out_unlock; =20 dso__set_a2l(dso, - addr2line_subprocess_init(symbol_conf.addr2line_path, dso_name)); + addr2line_subprocess_init(symbol_conf.addr2line_path, + current_dso_name)); a2l =3D dso__a2l(dso); } =20 if (a2l =3D=3D NULL) { if (!symbol_conf.addr2line_disable_warn) pr_warning("%s %s: addr2line_subprocess_init failed\n", __func__, dso_n= ame); - goto out; + goto out_unlock; } cmd_a2l_style =3D cmd_addr2line_configure(a2l, dso_name); if (cmd_a2l_style =3D=3D BROKEN) - goto out; + goto out_unlock; + + /* + * Take ownership of the a2l subprocess so we can safely perform + * blocking IPC without holding the dso lock. If another thread + * resolves a symbol concurrently, it will spawn a new a2l process. + */ + dso__set_a2l(dso, NULL); + mutex_unlock(dso__lock(dso)); =20 /* * Send our request and then *deliberately* send something that can't be @@ -414,12 +428,21 @@ int cmd__addr2line(const char *dso_name, u64 addr, } =20 out: + mutex_lock(dso__lock(dso)); free(record_function); free(record_filename); - if (io.eof) { - dso__set_a2l(dso, NULL); + + current_dso_name =3D dso__symsrc_filename(dso) ?: dso__long_name(dso); + if (!io.eof && dso__a2l(dso) =3D=3D NULL && current_dso_name && + !strcmp(current_dso_name, dso_name)) + dso__set_a2l(dso, a2l); + else addr2line_subprocess_cleanup(a2l); - } + mutex_unlock(dso__lock(dso)); + return ret; + +out_unlock: + mutex_unlock(dso__lock(dso)); return ret; } =20 diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 42bfe30a3b51..df39e6ca88e6 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -2075,3 +2075,12 @@ struct debuginfo *dso__debuginfo(struct dso *dso) free(name); return dinfo; } + +void dso__set_symsrc_filename(struct dso *dso, char *val) +{ + RC_CHK_ACCESS(dso)->symsrc_filename =3D val; + dso__free_libdw(dso); + dso__free_a2l(dso); + dso__set_has_srcline(dso, true); + dso__set_a2l_fails(dso, 0); +} diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 55c4aaa53c38..7966c7048c85 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -735,10 +735,7 @@ static inline const char *dso__symsrc_filename(const s= truct dso *dso) return RC_CHK_ACCESS(dso)->symsrc_filename; } =20 -static inline void dso__set_symsrc_filename(struct dso *dso, char *val) -{ - RC_CHK_ACCESS(dso)->symsrc_filename =3D val; -} +void dso__set_symsrc_filename(struct dso *dso, char *val); =20 static inline void dso__free_symsrc_filename(struct dso *dso) { diff --git a/tools/perf/util/libbfd.c b/tools/perf/util/libbfd.c index 1b23a261a9ce..807944cd978c 100644 --- a/tools/perf/util/libbfd.c +++ b/tools/perf/util/libbfd.c @@ -255,7 +255,11 @@ int libbfd__addr2line(const char *dso_name, u64 addr, struct symbol *sym) { int ret =3D 0; - struct a2l_data *a2l =3D dso__a2l(dso); + struct a2l_data *a2l; + + mutex_lock(dso__lock(dso)); + dso_name =3D dso__symsrc_filename(dso) ?: dso_name; + a2l =3D dso__a2l(dso); =20 if (!a2l) { a2l =3D addr2line_init(dso_name); @@ -265,7 +269,8 @@ int libbfd__addr2line(const char *dso_name, u64 addr, if (a2l =3D=3D NULL) { if (!symbol_conf.addr2line_disable_warn) pr_warning("addr2line_init failed for %s\n", dso_name); - return 0; + ret =3D -1; + goto out; } =20 a2l->addr =3D addr; @@ -273,14 +278,18 @@ int libbfd__addr2line(const char *dso_name, u64 addr, =20 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); =20 - if (!a2l->found) - return 0; + if (!a2l->found) { + ret =3D 0; + goto out; + } =20 if (unwind_inlines) { int cnt =3D 0; =20 - if (node && inline_list__append_dso_a2l(dso, node, sym)) - return 0; + if (node && inline_list__append_dso_a2l(dso, node, sym)) { + ret =3D 0; + goto out; + } =20 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, &a2l->funcname, &a2l->line) && @@ -290,8 +299,10 @@ int libbfd__addr2line(const char *dso_name, u64 addr, a2l->filename =3D NULL; =20 if (node !=3D NULL) { - if (inline_list__append_dso_a2l(dso, node, sym)) - return 0; + if (inline_list__append_dso_a2l(dso, node, sym)) { + ret =3D 0; + goto out; + } // found at least one inline frame ret =3D 1; } @@ -306,6 +317,8 @@ int libbfd__addr2line(const char *dso_name, u64 addr, if (line) *line =3D a2l->line; =20 +out: + mutex_unlock(dso__lock(dso)); return ret; } =20 diff --git a/tools/perf/util/libdw.c b/tools/perf/util/libdw.c index 4ca7e7e4fbe9..c4504cceb313 100644 --- a/tools/perf/util/libdw.c +++ b/tools/perf/util/libdw.c @@ -35,7 +35,7 @@ struct Dwfl *dso__libdw_dwfl(struct dso *dso) if (dwfl) return dwfl; =20 - dso_name =3D dso__long_name(dso); + dso_name =3D dso__symsrc_filename(dso) ?: dso__long_name(dso); /* * Initialize Dwfl session. * We need to open the DSO file to report it to libdw. @@ -167,32 +167,41 @@ int libdw__addr2line(u64 addr, char **file, unsigned = int *line_nr, struct dso *dso, bool unwind_inlines, struct inline_node *node, struct symbol *sym) { - Dwfl *dwfl =3D dso__libdw_dwfl(dso); + Dwfl *dwfl; Dwfl_Module *mod; Dwfl_Line *dwline; Dwarf_Addr bias; const char *src; int lineno =3D 0; + int ret =3D 0; =20 + mutex_lock(dso__lock(dso)); + dwfl =3D dso__libdw_dwfl(dso); if (!dwfl) - return 0; + goto out; =20 mod =3D dwfl_addrmodule(dwfl, addr); - if (!mod) - return 0; + if (!mod) { + ret =3D 0; + goto out; + } =20 /* * Get/ignore the dwarf information. Determine the bias, difference * between the regular ELF addr2line addresses and those to use with * libdw. */ - if (!dwfl_module_getdwarf(mod, &bias)) - return 0; + if (!dwfl_module_getdwarf(mod, &bias)) { + ret =3D -1; + goto out; + } =20 /* Find source line information for the address. */ dwline =3D dwfl_module_getsrc(mod, addr + bias); - if (!dwline) - return 0; + if (!dwline) { + ret =3D -1; + goto out; + } =20 /* Get line information. */ src =3D dwfl_lineinfo(dwline, /*addr=3D*/NULL, &lineno, /*col=3D*/NULL, /= *mtime=3D*/NULL, @@ -219,7 +228,8 @@ int libdw__addr2line(u64 addr, char **file, unsigned in= t *line_nr, free(*file); *file =3D NULL; } - return 0; + ret =3D 0; + goto out; } =20 /* Walk from the parent down to the leaf. */ @@ -235,8 +245,13 @@ int libdw__addr2line(u64 addr, char **file, unsigned i= nt *line_nr, *file =3D NULL; } inline_node__clear_frames(node); - return 0; + ret =3D 0; + goto out; } } - return 1; + ret =3D 1; + +out: + mutex_unlock(dso__lock(dso)); + return ret; } diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index b082178c279b..e60dea472507 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -1,40 +1,48 @@ // SPDX-License-Identifier: GPL-2.0 #include "srcline.h" + +#include +#include +#include + +#include +#include + #include "addr2line.h" -#include "dso.h" #include "callchain.h" +#include "debug.h" +#include "dso.h" #include "libbfd.h" +#include "libdw.h" #include "llvm.h" #include "symbol.h" -#include "libdw.h" -#include "debug.h" #include "util.h" =20 -#include -#include -#include -#include - bool srcline_full_filename; =20 char *srcline__unknown =3D (char *)"??:0"; =20 -static const char *srcline_dso_name(struct dso *dso) +static char *srcline_dso_name(struct dso *dso) { const char *dso_name; + char *ret =3D NULL; =20 + mutex_lock(dso__lock(dso)); if (dso__symsrc_filename(dso)) dso_name =3D dso__symsrc_filename(dso); else dso_name =3D dso__long_name(dso); =20 if (dso_name[0] =3D=3D '[') - return NULL; + goto out; =20 if (is_perf_pid_map_name(dso_name)) - return NULL; + goto out; =20 - return dso_name; + ret =3D strdup(dso_name); +out: + mutex_unlock(dso__lock(dso)); + return ret; } =20 int inline_list__append(struct symbol *symbol, char *srcline, struct inlin= e_node *node) @@ -258,7 +266,7 @@ char *__get_srcline(struct dso *dso, u64 addr, struct s= ymbol *sym, char *file =3D NULL; unsigned line =3D 0; char *srcline; - const char *dso_name; + char *dso_name; =20 if (!dso__has_srcline(dso)) goto out; @@ -268,8 +276,11 @@ char *__get_srcline(struct dso *dso, u64 addr, struct = symbol *sym, goto out_err; =20 if (!addr2line(dso_name, addr, &file, &line, dso, - unwind_inlines, /*node=3D*/NULL, sym)) + unwind_inlines, /*node=3D*/NULL, sym)) { + free(dso_name); goto out_err; + } + free(dso_name); =20 srcline =3D srcline_from_fileline(file, line); free(file); @@ -277,16 +288,20 @@ char *__get_srcline(struct dso *dso, u64 addr, struct= symbol *sym, if (!srcline) goto out_err; =20 + mutex_lock(dso__lock(dso)); dso__set_a2l_fails(dso, 0); + mutex_unlock(dso__lock(dso)); =20 return srcline; =20 out_err: + mutex_lock(dso__lock(dso)); dso__set_a2l_fails(dso, dso__a2l_fails(dso) + 1); if (dso__a2l_fails(dso) > A2L_FAIL_LIMIT) { dso__set_has_srcline(dso, false); dso__free_a2l(dso); } + mutex_unlock(dso__lock(dso)); out: if (!show_addr) return (show_sym && sym) ? @@ -305,7 +320,7 @@ char *__get_srcline(struct dso *dso, u64 addr, struct s= ymbol *sym, char *get_srcline_split(struct dso *dso, u64 addr, unsigned *line) { char *file =3D NULL; - const char *dso_name; + char *dso_name; =20 if (!dso__has_srcline(dso)) return NULL; @@ -315,18 +330,25 @@ char *get_srcline_split(struct dso *dso, u64 addr, un= signed *line) goto out_err; =20 if (!addr2line(dso_name, addr, &file, line, dso, /*unwind_inlines=3D*/tru= e, - /*node=3D*/NULL, /*sym=3D*/NULL)) + /*node=3D*/NULL, /*sym=3D*/NULL)) { + free(dso_name); goto out_err; + } + free(dso_name); =20 + mutex_lock(dso__lock(dso)); dso__set_a2l_fails(dso, 0); + mutex_unlock(dso__lock(dso)); return file; =20 out_err: + mutex_lock(dso__lock(dso)); dso__set_a2l_fails(dso, dso__a2l_fails(dso) + 1); if (dso__a2l_fails(dso) > A2L_FAIL_LIMIT) { dso__set_has_srcline(dso, false); dso__free_a2l(dso); } + mutex_unlock(dso__lock(dso)); =20 return NULL; } @@ -420,13 +442,16 @@ void srcline__tree_delete(struct rb_root_cached *tree) struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr, struct symbol *sym) { - const char *dso_name; + char *dso_name; + struct inline_node *node; =20 dso_name =3D srcline_dso_name(dso); if (dso_name =3D=3D NULL) return NULL; =20 - return addr2inlines(dso_name, addr, dso, sym); + node =3D addr2inlines(dso_name, addr, dso, sym); + free(dso_name); + return node; } =20 void inline_node__clear_frames(struct inline_node *node) diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c index ebea101e1001..4ccfcc7c2dfc 100644 --- a/tools/perf/util/unwind-libdw.c +++ b/tools/perf/util/unwind-libdw.c @@ -42,8 +42,10 @@ static int __find_debuginfo(Dwfl_Module *mod __maybe_unu= sed, void **userdata, const struct dso *dso =3D *userdata; =20 assert(dso); + mutex_lock(dso__lock((struct dso *)dso)); if (dso__symsrc_filename(dso) && strcmp(file_name, dso__symsrc_filename(d= so))) *debuginfo_file_name =3D strdup(dso__symsrc_filename(dso)); + mutex_unlock(dso__lock((struct dso *)dso)); return -1; } =20 diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-li= bunwind.c index 73d191ce51a5..3bccab303282 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c @@ -1,20 +1,26 @@ // SPDX-License-Identifier: GPL-2.0 +#include "unwind.h" + +#include +#include +#include + +#include +#include +#include + +#include + #include "callchain.h" #include "debug.h" #include "dso.h" #include "env.h" +#include "libunwind-arch/libunwind-arch.h" #include "map.h" #include "perf_regs.h" #include "session.h" #include "symbol.h" #include "thread.h" -#include "unwind.h" -#include "libunwind-arch/libunwind-arch.h" -#include -#include -#include -#include -#include =20 #define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ #define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ @@ -293,10 +299,19 @@ static int read_unwind_spec_debug_frame(struct dso *d= so, } =20 if (ofs <=3D 0) { - fd =3D open(dso__symsrc_filename(dso), O_RDONLY); - if (fd >=3D 0) { - ofs =3D elf_section_offset(fd, ".debug_frame"); - close(fd); + char *alloc_name; + + mutex_lock(dso__lock(dso)); + alloc_name =3D dso__symsrc_filename(dso) ? + strdup(dso__symsrc_filename(dso)) : NULL; + mutex_unlock(dso__lock(dso)); + if (alloc_name) { + fd =3D open(alloc_name, O_RDONLY); + if (fd >=3D 0) { + ofs =3D elf_section_offset(fd, ".debug_frame"); + close(fd); + } + free(alloc_name); } } =20 @@ -321,6 +336,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso, } } if (ofs > 0) { + mutex_lock(dso__lock(dso)); if (dso__symsrc_filename(dso) !=3D NULL) { pr_warning( "%s: overwrite symsrc(%s,%s)\n", @@ -330,6 +346,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso, dso__free_symsrc_filename(dso); } dso__set_symsrc_filename(dso, debuglink); + mutex_unlock(dso__lock(dso)); } else { free(debuglink); } @@ -429,12 +446,23 @@ int __libunwind__find_proc_info(void *as, uint64_t ip= , void *pi, int need_unwind dso__data_put_fd(dso); } =20 - symfile =3D dso__symsrc_filename(dso) ?: dso__name(dso); - - if (libunwind_arch__dwarf_find_debug_frame(ui->e_machine, /*found=3D*/0,= &di, ip, - base, symfile, start, map__end(map))) { - ret =3D libunwind_arch__dwarf_search_unwind_table(ui->e_machine, as, ip= , &di, pi, - need_unwind_info, arg); + mutex_lock(dso__lock(dso)); + symfile =3D dso__symsrc_filename(dso) ? + strdup(dso__symsrc_filename(dso)) : + strdup(dso__name(dso)); + mutex_unlock(dso__lock(dso)); + + if (symfile) { + if (libunwind_arch__dwarf_find_debug_frame(ui->e_machine, + /*found=3D*/0, &di, ip, + base, symfile, start, + map__end(map))) { + ret =3D libunwind_arch__dwarf_search_unwind_table(ui->e_machine, as, + ip, &di, pi, + need_unwind_info, + arg); + } + free((char *)symfile); } } map__put(map); --=20 2.55.0.1082.g2b9226bbc0-goog From nobody Fri Sep 25 04:07:25 2026 Received: from mail-pl1-f199.google.com (mail-pl1-f199.google.com [209.85.214.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 643024BFE70 for ; Wed, 16 Sep 2026 23:44:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.199 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789602261; cv=none; b=ft+8lclva+cERJhhrABaKP6U9fF3PevN2+YcYo/D6Kd3uBE3pfNRJjzqd6mS0ZO/9TtSKExXFqrOdi/5ARYjp5mSGaZ9bhVOdOnp+/P6mJ6WfOnHfaYb8yO5UaoiksnzndibzHdtLvp+K1Au/shXlzpffh+BcRIbQM0gHc96l4I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789602261; c=relaxed/simple; bh=xP10taDMLP0iuYlIVVM2a23fZRTDyL4vs128okCOz4A=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=GFGz9PR00mWQpN7oz9308+07ERr6SkAbOgMiwN006XoHid0LuF8uz8Awdtsj+p4r3IWBgJxorWvEz9wBFwCCnSxhJFDR0xkc1nqa86uvw1QoqM58o480SK9tCtt1YrAIfxSpSq76u2kpoR22eLqtsqLi+sSCW7ianYj1Mqye680= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=drfOY0Nj; arc=none smtp.client-ip=209.85.214.199 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="drfOY0Nj" Received: by mail-pl1-f199.google.com with SMTP id d9443c01a7336-2d9057fab9eso3966215ad.1 for ; Wed, 16 Sep 2026 16:44:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1789602259; x=1790207059; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=DrTRcdREb/1Pe51W7xJkyBsA0asz0RYuJXXZoVXSudE=; b=drfOY0NjbqfW8EmO2PPv1zf+jaUBwvFOAkc4M2NIShFm1wg55KWFKEfQqfJ+dUTRcN 43CFTdxTf73sO4U7mvirOsVEbX5nW0tgRmkbfFbz+2J/DIn9qGubRTBZsDGB1mDuxFuO d75ML1IGH2nlZqE2pplvW1Hot7tFt0A7e5IGqk+HOz0jyLzzY591jD/ESgabUqVCq3n+ HunFznRZb/mUbLOVEPQW+ko7+JEV+voGUEBEuJog/8ybbSi2DR9BID7xnK9Rsw981GW4 o7LPumeDXGefa/udqcNmcv6N+Nk6Gx4d1kdXkYJbjj1af4uSyKP4Ji+/UY6+4AAwdLe4 DzIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789602259; x=1790207059; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=DrTRcdREb/1Pe51W7xJkyBsA0asz0RYuJXXZoVXSudE=; b=aKPRH4IqkvX0K+9CE4MJvTpb8BWRqRIdaMJvIUYydG7VfeOvZA46Km4MQk4gsjPVxg l7rTwL3Dd+uIaQOR+ZRqYj4l9lRQl6jgVv4gGGYBt8+zHs9D7IKR7krSX5syoAvTtrgr Q0M/QVL26xcItzlfvSFq+ISNOFXl6gVtKycQ0GEXtb4SYCcHh7fQEapwf3+kAnWhQ1iQ 5h7iaiTjH+9o8NhQB2qb4+rkUMETtk2uRjzoVBTu5pxG2vZu/mCMhfjREzc7q9tR5gdl hbOS2Oe1jVAQTHk0tgOIFp5/sT2Ij8+1HLs3sW2aViefwRWFWoJZ7Vf7Jnj6QlcXjd8q OafQ== X-Forwarded-Encrypted: i=1; AKwUvBxZ1FtKjw7UeGLFrFIYu4IWsP/90+p7cCCLX9yczbJjVi3G/Y7OJ9QvtPDgSyfajHyxrhj0+WX3s9zjHAM=@vger.kernel.org X-Gm-Message-State: AFuF++n3R6fzs433ED2Ea8pqDe5jISpJzfZsNpXERBtQTe5b/KAExZpC wDsi7GPwDlZ3ZgkaMHpNr43isr8hLgf80wjlkN8+MMzQVTY6p7tSDmOPAU0pm5TGqno1CdsjAPl lByjR+JTmNw== X-Received: from dyuw12-n2.prod.google.com ([2002:a05:693c:880c:20b0:313:b34f:8861]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:2ac6:b0:2db:55d6:349d with SMTP id d9443c01a7336-2dd8e75600emr102850515ad.21.1789602258533; Wed, 16 Sep 2026 16:44:18 -0700 (PDT) Date: Wed, 16 Sep 2026 16:44:01 -0700 In-Reply-To: <20260916234402.437113-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260916063545.3103314-1-irogers@google.com> <20260916234402.437113-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.1082.g2b9226bbc0-goog Message-ID: <20260916234402.437113-3-irogers@google.com> Subject: [PATCH v3 2/3] perf dso: Separate libbfd and cmd addr2line caches to fix confusion From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org Cc: adrian.hunter@intel.com, james.clark@linaro.org, jolsa@kernel.org, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, mingo@redhat.com, peterz@infradead.org, tmricht@linux.ibm.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When a dso executes addr2line via libbfd it instantiates an a2l_data pointer. If the DSO later executes via the command-line fallback due to an inlined bug, the a2l pointer is unconditionally populated with a child_process process wrapper. If libbfd is queried again, the offline reader attempts to cast struct a2l_data into child_process, coercing random arbitrary instruction addresses and causing silent aborts. This cleanly splits the caches. Fixes: 257046a36750 ("perf srcline: Fallback between addr2line implementati= ons") Signed-off-by: Ian Rogers Assisted-by: Antigravity:gemini-3.1-pro --- tools/perf/util/dso.c | 49 +++++++++++++++++++++++---------------- tools/perf/util/dso.h | 21 +++++++++++++++-- tools/perf/util/libbfd.c | 10 ++++---- tools/perf/util/srcline.c | 2 ++ 4 files changed, 55 insertions(+), 27 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index df39e6ca88e6..6510767177be 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1,38 +1,45 @@ // SPDX-License-Identifier: GPL-2.0 +#include "dso.h" + +#include +#include + #include +#include #include #include #include -#include #include -#include #include +#include +#include #include -#include -#include -#include -#ifdef HAVE_LIBBPF_SUPPORT -#include -#include "bpf-event.h" -#include "bpf-utils.h" -#endif + +#include "annotate-data.h" +#include "auxtrace.h" #include "compress.h" +#include "debug.h" +#include "dso.h" +#include "dsos.h" #include "env.h" +#include "libbfd.h" +#include "libdw.h" +#include "machine.h" +#include "map.h" #include "namespaces.h" #include "path.h" -#include "map.h" -#include "symbol.h" #include "srcline.h" -#include "dso.h" -#include "dsos.h" -#include "machine.h" -#include "auxtrace.h" -#include "util.h" /* O_CLOEXEC for older systems */ -#include "debug.h" #include "string2.h" +#include "symbol.h" +#include "util.h" /* O_CLOEXEC for older systems */ #include "vdso.h" -#include "annotate-data.h" -#include "libdw.h" + +#ifdef HAVE_LIBBPF_SUPPORT +#include + +#include "bpf-event.h" +#include "bpf-utils.h" +#endif =20 static const char * const debuglink_paths[] =3D { "%.0s%s", @@ -1757,6 +1764,7 @@ void dso__delete(struct dso *dso) auxtrace_cache__free(RC_CHK_ACCESS(dso)->auxtrace_cache); dso_cache__free(dso); dso__free_a2l(dso); + dso__free_a2l_libbfd(dso); dso__free_libdw(dso); dso__free_symsrc_filename(dso); nsinfo__zput(RC_CHK_ACCESS(dso)->nsinfo); @@ -2081,6 +2089,7 @@ void dso__set_symsrc_filename(struct dso *dso, char *= val) RC_CHK_ACCESS(dso)->symsrc_filename =3D val; dso__free_libdw(dso); dso__free_a2l(dso); + dso__free_a2l_libbfd(dso); dso__set_has_srcline(dso, true); dso__set_a2l_fails(dso, 0); } diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 7966c7048c85..e7d5f4bbf894 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -304,7 +304,12 @@ DECLARE_RC_STRUCT(dso) { const char *short_name; const char *long_name; void *a2l; +#ifdef HAVE_LIBBFD_SUPPORT + void *a2l_libbfd; +#endif +#ifdef HAVE_LIBDW_SUPPORT void *libdw; +#endif char *symsrc_filename; struct nsinfo *nsinfo; struct auxtrace_cache *auxtrace_cache; @@ -368,6 +373,20 @@ static inline void dso__set_a2l(struct dso *dso, void = *val) RC_CHK_ACCESS(dso)->a2l =3D val; } =20 +#ifdef HAVE_LIBBFD_SUPPORT +static inline void *dso__a2l_libbfd(const struct dso *dso) +{ + return RC_CHK_ACCESS(dso)->a2l_libbfd; +} + +static inline void dso__set_a2l_libbfd(struct dso *dso, void *val) +{ + RC_CHK_ACCESS(dso)->a2l_libbfd =3D val; +} +#endif + +struct Dwfl; +#ifdef HAVE_LIBDW_SUPPORT static inline void *dso__libdw(const struct dso *dso) { return RC_CHK_ACCESS(dso)->libdw; @@ -378,8 +397,6 @@ static inline void dso__set_libdw(struct dso *dso, void= *val) RC_CHK_ACCESS(dso)->libdw =3D val; } =20 -struct Dwfl; -#ifdef HAVE_LIBDW_SUPPORT struct Dwfl *dso__libdw_dwfl(struct dso *dso); #else static inline struct Dwfl *dso__libdw_dwfl(struct dso *dso __maybe_unused) diff --git a/tools/perf/util/libbfd.c b/tools/perf/util/libbfd.c index 807944cd978c..d87242d88525 100644 --- a/tools/perf/util/libbfd.c +++ b/tools/perf/util/libbfd.c @@ -239,7 +239,7 @@ static int inline_list__append_dso_a2l(struct dso *dso, struct inline_node *node, struct symbol *sym) { - struct a2l_data *a2l =3D dso__a2l(dso); + struct a2l_data *a2l =3D dso__a2l_libbfd(dso); struct symbol *inline_sym =3D new_inline_sym(dso, sym, a2l->funcname); char *srcline =3D NULL; =20 @@ -259,11 +259,11 @@ int libbfd__addr2line(const char *dso_name, u64 addr, =20 mutex_lock(dso__lock(dso)); dso_name =3D dso__symsrc_filename(dso) ?: dso_name; - a2l =3D dso__a2l(dso); + a2l =3D dso__a2l_libbfd(dso); =20 if (!a2l) { a2l =3D addr2line_init(dso_name); - dso__set_a2l(dso, a2l); + dso__set_a2l_libbfd(dso, a2l); } =20 if (a2l =3D=3D NULL) { @@ -324,14 +324,14 @@ int libbfd__addr2line(const char *dso_name, u64 addr, =20 void dso__free_a2l_libbfd(struct dso *dso) { - struct a2l_data *a2l =3D dso__a2l(dso); + struct a2l_data *a2l =3D dso__a2l_libbfd(dso); =20 if (!a2l) return; =20 addr2line_cleanup(a2l); =20 - dso__set_a2l(dso, NULL); + dso__set_a2l_libbfd(dso, NULL); } =20 static int bfd_symbols__cmpvalue(const void *a, const void *b) diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index e60dea472507..68798a4de887 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -300,6 +300,7 @@ char *__get_srcline(struct dso *dso, u64 addr, struct s= ymbol *sym, if (dso__a2l_fails(dso) > A2L_FAIL_LIMIT) { dso__set_has_srcline(dso, false); dso__free_a2l(dso); + dso__free_a2l_libbfd(dso); } mutex_unlock(dso__lock(dso)); out: @@ -347,6 +348,7 @@ char *get_srcline_split(struct dso *dso, u64 addr, unsi= gned *line) if (dso__a2l_fails(dso) > A2L_FAIL_LIMIT) { dso__set_has_srcline(dso, false); dso__free_a2l(dso); + dso__free_a2l_libbfd(dso); } mutex_unlock(dso__lock(dso)); =20 --=20 2.55.0.1082.g2b9226bbc0-goog From nobody Fri Sep 25 04:07:25 2026 Received: from mail-pj1-f70.google.com (mail-pj1-f70.google.com [209.85.216.70]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B1314501F47 for ; Wed, 16 Sep 2026 23:44:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.70 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789602263; cv=none; b=FwFge/WrwztV7ZILILxUY0DRcHE8iF4zfZNpDghUH11Rx0K3RP2YoRFD//bN+brHpoOWZusRj1SZLAzElLxCfMNzdfHxJPuAvNlf8hz9q7z0MdZNdrMG6L45DyxFyqFzR0hpIQjS6fPGk1Gf9tB5UUj3L0Bc4timEmddpaE99ec= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789602263; c=relaxed/simple; bh=jeEJpcUOnMW1H6iQsMNBSRPc1DiwXIDweaguQDaQWkA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Hcua5Qxc3mHK+2Dco7GFKZwu5tiRtXfdB038NyC9vn7Ey+E4a6PA6KgT/Y8Wz2VKOgkRSDd5106vlQ24SjTJ4kWoURtgWcOwr4jjBXzgw04iCGvCNa/wto+b2vggMoCPK+CHP8XjyX2idxsr2Aq4XF3rdy3smLd1x1leDPHOt4E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=vWBKjFJu; arc=none smtp.client-ip=209.85.216.70 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="vWBKjFJu" Received: by mail-pj1-f70.google.com with SMTP id 98e67ed59e1d1-39b77130a7fso428816a91.2 for ; Wed, 16 Sep 2026 16:44:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1789602261; x=1790207061; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Juznuv85kRzuednz/BkmExb07fgMhpHO/r2YE0AU9aA=; b=vWBKjFJudfRw7A2p+0nHk/bCpqH4l4+T8oj/cp16S6aO7SqI/wcplnQbyTFJ4BvJp2 EYw08kK6NyCPOcfqog0kdzodi6nMw7IYUbzXPN5r5F0vw8/GsggsOzLZgo8GP2LIBReZ x+ZrEeuid8QTXfnIMHB+lkH9FVnacdR7rKPuLUZFG9BVc0aPDXcvQc6YXS+sN51Xxkza wfXTcUjkpTHqE5HqvqqRjKmvv7XSyKZhgtCfMT3G9yI39Wt8UnLU+2PsGTVo/O9J8UIf J0nBh7217gHHxC2BblXKI5yjantSJ3FEV5Zmr8R7wSSB6kycz8jI3kUbUDC+c2atGn06 Ahgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789602261; x=1790207061; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Juznuv85kRzuednz/BkmExb07fgMhpHO/r2YE0AU9aA=; b=knKhQYysuKbOnC1I1MpXmeQB1SO8e2MPOnAPFso1eVUHDlOi/Nms5EZuoYa3mD5gAd lJ5uo1m0lrzz9aWgSBXrLVi2Twz1AUV5k/d1wZfLOcbDotgnC1re2Q8Vt3eYwKQ8Lqbf NC/kyL10IRdeM6owlWOYWW1fysDVb3TvsU2IU8kiAkvz+tBPEniQ3suIrLXLOPjLG0Gb VB4LW1s+V8RR3q6j7hGq6mVRP5DW6Pn0Y2ufzvBYftHnffi83x/jldjD3KiZB/N9ZTul 9GI8wMmioAbROWpVShUJUQSAXZFq9su7EjaQNuVviJoGQ48QphNpNykt7TbJ2fiXMfIl oJbw== X-Forwarded-Encrypted: i=1; AKwUvBw217mwniyXFe6m6R+W5SgNYqFH+8T+cHuZtYQHObmNl3ZR70SilRpeG1Bg93EWGwZZtR4unSTgaOANqks=@vger.kernel.org X-Gm-Message-State: AFuF++nms61xXzqa51mH62SBo6KnozfyMdwFlQxcd+wUtB2gbFTNxDV5 q1oCBBmGnl099ptrzj3kFP1Ld1Aos8F6EJBsAwn+eqxYgTckala3c24P99zNiUqAykcIQOOhxzq JkPLCaH6U7Q== X-Received: from dlbvv15.prod.google.com ([2002:a05:7022:5f0f:b0:143:7a1a:167d]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:5108:b0:39d:b769:3067 with SMTP id 98e67ed59e1d1-39e1df6154emr9932917a91.0.1789602260835; Wed, 16 Sep 2026 16:44:20 -0700 (PDT) Date: Wed, 16 Sep 2026 16:44:02 -0700 In-Reply-To: <20260916234402.437113-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260916063545.3103314-1-irogers@google.com> <20260916234402.437113-1-irogers@google.com> X-Mailer: git-send-email 2.55.0.1082.g2b9226bbc0-goog Message-ID: <20260916234402.437113-4-irogers@google.com> Subject: [PATCH v3 3/3] perf libbfd: Report success when an address is found From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org Cc: adrian.hunter@intel.com, james.clark@linaro.org, jolsa@kernel.org, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, mingo@redhat.com, peterz@infradead.org, tmricht@linux.ibm.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 implementati= ons") Signed-off-by: Ian Rogers 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 =3D 0; =20 if (node && inline_list__append_dso_a2l(dso, node, sym)) { + inline_node__clear_frames(node); ret =3D 0; goto out; } @@ -300,23 +301,32 @@ int libbfd__addr2line(const char *dso_name, u64 addr, =20 if (node !=3D NULL) { if (inline_list__append_dso_a2l(dso, node, sym)) { + inline_node__clear_frames(node); ret =3D 0; goto out; } - // found at least one inline frame - ret =3D 1; } } } =20 if (file) { *file =3D a2l->filename ? strdup(a2l->filename) : NULL; - ret =3D *file ? 1 : 0; + if (!*file) { + /* Leave ret as 0 so that another addr2line is tried. */ + goto out; + } } =20 if (line) *line =3D a2l->line; =20 + /* + * 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 =3D 1; + out: mutex_unlock(dso__lock(dso)); return ret; --=20 2.55.0.1082.g2b9226bbc0-goog