From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (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 BD1754749F5 for ; Tue, 28 Jul 2026 20:42:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785271348; cv=none; b=JmNtx/u4r9TIOMfNsru2FmGcv6aEtBP2xflSWXGl+4DGbci2A0mtz7VwZRmdHRe/Zh+PsAZzH5CjhfgTVI//GzFlfxS//OlLiDYlS+D8yE5xVY7Hi2Vx2tW+zuBBG3ML4uhvCpGMCm4oP22YPKIRUVv7ej0WiQQL+yibWLJ84uo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785271348; c=relaxed/simple; bh=vtwEJPeB3XSeziXiic+4w9Nt+pag5cz+X4V7fDhugMI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Jx+/m+/n/mCd2TdZUnD32CW19Im8zMPPtdGKN4Miu72Ka8p/RLMkN8/Q0/D6Rk0pj69eOJ7DWOYVEAc5r+uLwn1lHmBBdXVZxQUrgPv2VXsdtQREAes1jmsj6/Vi64HGWjdsHBet3Oj7NMW+cLea3GKbh5bdbmNro0UUJelQqQ0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=pass smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=bo7Gfgta; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="bo7Gfgta" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-4954d29264cso1081645e9.2 for ; Tue, 28 Jul 2026 13:42:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1785271345; x=1785876145; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=neJwsrreenqN9sr1ylLIXFSbq0W3o0rmjNfXzSlyrAA=; b=bo7Gfgta7jABHTUjkY7qGi9R6VGx2sYnWSNzJLI55vBKOB4pr/UCYeV3k0GmR3lO8a vvpLOz+OR+qoU/H1XskmI2R2CgKdDscUQXYMKn/XQSpnKH19cwqNgUkKgmaoq0A82kvS 9ckI17Ho6XW0gZe2ZT9cXtPb3jK7wNCigxnDklJcsEd6CrNioO/RTHtqhcZ46y/SinqR bzMQG7sHmLRisvjVXsgBo8ju9H+0wTga32PZRIdnN8yoOf5CMyCwBIHjyFLO0tr3NdVb atVHm84kIpzI2VyJu0W0IzM97PF9rLOY9gtMICnBYnMID0vx2y8jWV1AUFiK59T8otDW n8PA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785271345; x=1785876145; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=neJwsrreenqN9sr1ylLIXFSbq0W3o0rmjNfXzSlyrAA=; b=OOj6t95ooabN8POKtXLq0nBNq8Lt9IWsAeo7dt4D5M/Iv9Y5KYuSI4Xn16L22Ug9Kc d5isXHvnHV0yJaBTftd+d1zBoGvRR09RiXIm4jqLdQHA3ag9Pi3Ex89/jPq4AtLxp9Z2 TvCEiHz/6FwWiXF2QrFLh4vbY2oOqwA66OQWb8i5DVgAO+e96hxuQo00JgywcEhk+8Ez 54U2mEZmz4Gri0pv6ds/nZV4rRb4EoyHaHu/XgzBj2oUtoGvaYeC60DKg7zWR3T5F3Ih 0ijiSoASUAmP5vubq/hEPAXBGQ+WXO0wf0Eof3sGsFU/wrYXYPozxnqdlILEu6h25z4W EbWQ== X-Forwarded-Encrypted: i=1; AHgh+Rqdslk7xX2fMFABupPx5fjsEKhLs+aC6+Hz0lDcY8nwoxI6V400+FZzW13bHol8W6H0jmrXQzNUZMDy82A=@vger.kernel.org X-Gm-Message-State: AOJu0YzGOCcyAsF/N7NBi9iW6Eh5E5b9KQ3HamV+NaTl4x/42XwlnAYa EQhEy/xQigdGLr1uBsvDWr41XGvnRzqwc50rQWLWEtWZYRfVou8c+hISnQzeBUZdMfU= X-Gm-Gg: AR+sD12MmwGGfzmxrSvrrrDO8e/GFGHC0CjN+IQIzTxRRptPwRSHiTELGXpwOscJvvG t2tnIg6BfODXJmyUUpEgbP/+x02r0DJp0dJ0N9Ek2q9QGbFAqVW7YopCMcAOYq952e/zH0YXCFq MFt0TnOyvKymF7ac9zdIy4/SyTi2FxgUt/V5lTkyf0TSnahzjRvAMCN/hb51ZuFWTd8uJnvE3uR 2Kk9bCM9tLYxKiQHCD/SygW4U4PeZHZSyuUF2KJkpId6JuZW/oE/vZSRI9i1TuTAj5qufPTWmOL QaTR7Gp2aLdqY+rDIaXA8zHsFjXAhg/NT8d4NgAmp8rAOsuh80EngC7DHlEuH57f3/jvbgFIv3a 75R06ahclaHcU/WHAM2Kdicu/TPt+eVUDsAFNe3TuzdfeCUvQyPyUtTCv5WSStFOkRnakpf80lO nG8B6ZnyquD7//wT5Y9BrDEt/fPTikESq0cCfeoggLZ/sMUOj5tV4zC8alNuRBN+L4HXdaQXCmT cDFn2EcF1cFg1k= X-Received: by 2002:a05:600c:46d0:b0:495:4a34:16e1 with SMTP id 5b1f17b1804b1-496c656e064mr41905755e9.23.1785271344982; Tue, 28 Jul 2026 13:42:24 -0700 (PDT) Received: from dev-mliang.dev.purestorage.com ([208.88.159.129]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4957bfc2ff2sm293304475e9.4.2026.07.28.13.42.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Jul 2026 13:42:24 -0700 (PDT) From: Michael Liang To: Arnaldo Carvalho de Melo , Namhyung Kim , Peter Zijlstra , Ingo Molnar Cc: Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Michael Liang Subject: [PATCH 1/1] perf libdw: Fix outer-frame name resolution and spurious "(inlined)" tag Date: Tue, 28 Jul 2026 14:42:15 -0600 Message-Id: <20260728204215.327318-2-mliang@purestorage.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260728204215.327318-1-mliang@purestorage.com> References: <20260728204215.327318-1-mliang@purestorage.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit cu_walk_functions_at() calls libdw_a2l_cb() with the containing DW_TAG_subprogram DIE first, then each DW_TAG_inlined_subroutine nested inside. The callback treated both the same way, causing two bugs: 1) die_name() returns the unqualified DW_AT_name, so every C++ frame lost its namespace/class prefix (ns::Class::method collapsed to method). 2) new_inline_sym() re-uses base_sym only when funcname matches base_sym->name exactly; otherwise it fabricates a fake symbol tagged "(inlined)". Any mismatch between the DWARF name and the ELF symbol name mis-tags an outer, non-inline frame as inlined. This hits C++ (die_name()'s unqualified output never matches the demangled ELF symbol) and it also hits C functions that GCC IPA-cloned (foo vs foo.isra.0 / .constprop / .part / .cold), since DW_AT_linkage_name doesn't reflect those renames. Fix both: * Prefer die_get_linkage_name() (mangled, fully qualified), falling back to die_name() when absent (C, extern "C"). new_inline_sym() already demangles via dso__demangle_sym(). * For DW_TAG_subprogram DIEs, use base_sym directly -- the DIE tag already tells us it is the outer function, sidestepping the name comparison entirely for both C++ qualification and GCC IPA-clone renames. Fixes: 88c51002d06f9a68 ("perf addr2line: Add a libdw implementation") Signed-off-by: Michael Liang --- tools/perf/util/libdw.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/libdw.c b/tools/perf/util/libdw.c index d5d2958902c0..4ca7e7e4fbe9 100644 --- a/tools/perf/util/libdw.c +++ b/tools/perf/util/libdw.c @@ -82,13 +82,39 @@ struct libdw_a2l_cb_args { static int libdw_a2l_cb(Dwarf_Die *die, void *_args) { struct libdw_a2l_cb_args *args = _args; - struct symbol *inline_sym = new_inline_sym(args->dso, args->sym, die_name(die)); const char *call_fname = die_get_call_file(die); int call_lineno = die_get_call_lineno(die); char *call_srcline = srcline__unknown; - - if (!inline_sym) - goto abort_enomem; + struct symbol *inline_sym; + + if (dwarf_tag(die) == DW_TAG_subprogram && args->sym) { + /* + * cu_walk_functions_at() opens the walk with the + * containing DW_TAG_subprogram DIE (the non-inlined outer + * function). That's just the base symbol -- use it + * directly. Avoids a fragile name-vs-name compare in + * new_inline_sym() that misfires when GCC IPA passes + * (.isra/.constprop/.part/.cold) rename the ELF symbol + * while DWARF keeps the pre-clone linkage name, which + * left the outer frame spuriously tagged "(inlined)". + */ + inline_sym = args->sym; + } else { + /* + * Prefer DW_AT_linkage_name so C++ inline frames keep + * their namespace/class qualification. new_inline_sym() + * runs the name through dso__demangle_sym(), so the + * mangled linkage name is turned back into + * "Namespace::Class::method". Fall back to DW_AT_name + * (unqualified) when no linkage name is present, e.g. + * for C code or extern "C" functions. + */ + const char *funcname = die_get_linkage_name(die) ?: die_name(die); + + inline_sym = new_inline_sym(args->dso, args->sym, funcname); + if (!inline_sym) + goto abort_enomem; + } /* Assign caller information to the parent. */ if (call_fname) -- 2.34.1