Received: by 2002:ab2:6816:0:b0:1f9:5764:f03e with SMTP id t22csp2063312lqo; Sun, 19 May 2024 11:24:13 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWEVwxMMcB2otRdksenorQ66f75oXhEcTxj0LKaNRcHGC7l3q4u84XcB7yOF26IPH1JaJtIOr4wokc06kCXCe4Sui4cSb2IUr66epwPzQ== X-Google-Smtp-Source: AGHT+IEWoooKQezO9pcL9TbI1iqwtdFs5kfawctjbjJgkqDgpviD1sP8Td4aXTSXHqijvXYn7G84 X-Received: by 2002:a17:902:f602:b0:1eb:7bc7:8855 with SMTP id d9443c01a7336-1ef43d17094mr362791055ad.2.1716143053742; Sun, 19 May 2024 11:24:13 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1716143053; cv=pass; d=google.com; s=arc-20160816; b=WFH3g0tacT4SSCWO/80ay+2pwuVWXV25kJYwY0OR0dknnl05rnJO1z9GPbDUrwQzbt 5eFu7GteS8aDQKf5n4kKZV5oojOKcrBKj4BGH+nxBNpA4rn0/f/Sba6jpGMAH7FJCntp VWe7vyZVLICB3ro3TxalWi5LsO+WzuCxQ8jvXXvgrxNruF6YnKfmlZ5NYk8pne/C+vkC VPxQERYcmdjhZRwEZjBgUBI0ZMJPOscx4ZgXCkvVmr+kHIvFTnZkpBVud9MjbY7ir4tI iwOzrrTGS8CQZSbh3JvDuoNE70Abn5Z9QqRsNu+ncO/MgUmx8IUhj0YjoJQ4Js9E9nvf 1UJA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:list-unsubscribe:list-subscribe :list-id:precedence:dkim-signature; bh=584NAcSuuyFaCL2QspW175GCA9CrQzEbq4x1MVwYU38=; fh=mC4n3Gr7kErnNwBT9t2nio6cSm24W2ZNjfzl+Yr5Xis=; b=Z0AyunfjPGEtvLqqQOIifY88JyHvX4LGywokSE0DWIRsTpuWlDs2BlyyiUOvO2vxvr Cu4hWfPPjkM9i1zXOdDuTGtz9hor5iD0KeX7vE5WpFgPU0IIM0yaZIiHZ26/4hxmyZWZ zU/j/RgiQUSdshXXCUKWFdHsofsP2Wypo5/VfsUSbdBgjxjbmk1Z32LNKZr4Kfz/lWet OzFRNBLbO0GVgo9ESkN1DLrUJ+59p0S2MKxpGHg86Wfhe6BXI//88NslKg7oYnv0JtOr wpokqCDKFNXvC0tLLc3faitaDrnOFpLjjfbS1Cr8FMYLicDcN9ZnWqGW1/z9SQo/v6wY g7uA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=0u6+hFNo; arc=pass (i=1 spf=pass spfdomain=google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-183196-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-183196-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id d9443c01a7336-1ef0bf31611si8998045ad.233.2024.05.19.11.24.13 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 May 2024 11:24:13 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-183196-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=0u6+hFNo; arc=pass (i=1 spf=pass spfdomain=google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-183196-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-183196-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 9839BB210CB for ; Sun, 19 May 2024 18:24:09 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B63526A8AD; Sun, 19 May 2024 18:24:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="0u6+hFNo" Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) (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 8DC424501B for ; Sun, 19 May 2024 18:23:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.180 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716143041; cv=none; b=aTi3O+8Z53KB5Q7TrVenmRvSYnVTC2fPVU6kJofCg+yQyrMwE6wKyQdLr9Nvn1Uf0sdl6siWXb0r09P8qVG33lMkHTEYSckItjtWs2o0d2M/sqNGCqE1krJmPIxgK6kMulJykF9M51/HT+t0Onf0HmDHzI4Vqg/Wo7ovnulYsDU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716143041; c=relaxed/simple; bh=mr+eZUx5FBxznYNvPO60v1qdYd5RLgJiv+DwL4EVqMg=; h=MIME-Version:References:In-Reply-To:From:Date:Message-ID:Subject: To:Cc:Content-Type; b=diDst/48obfQbeBusminzd2q30jsg+5A/sKodMPh06WDsv+uIeBEbccOMCeUBcjgMcTRjYOyl/4Sswt6KVfIb6eZwZGwHsn3bLOHHLyyXnFQmTBD1A2ygxMxweNIqhw4w+bC1XredLPAM3EokFwoCdnUV1n8rtwknG5I2TLjGXY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=0u6+hFNo; arc=none smtp.client-ip=209.85.214.180 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=google.com Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-1ee0ccf9c2fso105715ad.0 for ; Sun, 19 May 2024 11:23:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1716143039; x=1716747839; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=584NAcSuuyFaCL2QspW175GCA9CrQzEbq4x1MVwYU38=; b=0u6+hFNoueDEk9SlIVS2wgWg+V8jCyKe28Hs1/7ngaB3AJAOYAJ0mOYuGFVT4t/zRo oY+fNHO4lYZhlbcZncPwyb3Wjc2uenreiomQr08IHY4P32kOA5wxqPyb5i3/BOpQqwgI FwGwyGsP3Gqr1lVc1JBQRJ+OkAvfHqAXw0c1ijbzq3o4eqn5fxnRGulIUeuTwLoDQMH7 l+5fntUtTyfL7HMXv77ms2DLhEJhuUN15XvWJxJLz27oeaQ3F9G/6wQdRvUYflVdHhMH /XdGBG66CsxsoeUM1R9on3l0nGKzUyjIo/I/BA2D0z8DSsYULJmb5/MyUWzAWTYstU/Y gHYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1716143039; x=1716747839; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=584NAcSuuyFaCL2QspW175GCA9CrQzEbq4x1MVwYU38=; b=qYNgRaM3X7uscALPDc7IAv5xJjHjldX1Y08iVIQ+7OYdPWAfsUmhbDalzjanuRHTFr FKp33xCw/q54/HkhxzEqOvQO078XZl9v3cmjb33n5bJfemofFlV5AKTRMP6o06qOo7Bx Yw/n6gXMM/PlmGDqX3hb3oop+j0ejW2DlLg6TVSkMsHK91bqq93C4h4Zy6J1WHLiQZlD 2zUAGUkzjeh+8lnLstUBw0yyq9IRaSqQtdSchsSUEKq1IS9zBPByIlm6U9UINKVsC1K5 ZQKdFysLlvbFDuKfoeNVH+1wTBLxEISwHnTXkrfKIuiXdArtwhMgOBWZXLf5rSLpStD5 kEMQ== X-Forwarded-Encrypted: i=1; AJvYcCWmDt2kHMrlIyKHOpk9Cntj76nDm61R7+0rDmgIrfZBpB2+phjdoiRfw4Q9u06PUpydTJeIdlPBx7PiThzw66wqv8A2Y0c/jTMnWLl9 X-Gm-Message-State: AOJu0YzkUYYW5D4VMYCMMccJG6ZRbrZ0lH5sWxdwxGXsGrLEKMu9IN4X Gu+IGsUsGBJzI2zAWkgSLRkx80lY5jYN7kWkmiK5Lb9+RqzpVhQfftKjB26pIY5gblWky3k4FhD 9yj/zGpq/ok4XX+wUo8A2qMrvDGY6Wjc672ol X-Received: by 2002:a17:902:a381:b0:1e0:f525:a831 with SMTP id d9443c01a7336-1f2ecc4f308mr2330515ad.28.1716143038434; Sun, 19 May 2024 11:23:58 -0700 (PDT) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 References: <20240518165335.3963530-1-sesse@google.com> In-Reply-To: <20240518165335.3963530-1-sesse@google.com> From: Ian Rogers Date: Sun, 19 May 2024 11:23:26 -0700 Message-ID: Subject: Re: [PATCH v2 1/3] perf report: Support LLVM for addr2line() To: "Steinar H. Gunderson" Cc: acme@kernel.org, linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Sat, May 18, 2024 at 9:53=E2=80=AFAM Steinar H. Gunderson wrote: > > In addition to the existing support for libbfd and calling out to > an external addr2line command, add support for using libllvm directly. > This is both faster than libbfd, and can be enabled in distro builds > (the LLVM license has an explicit provision for GPLv2 compatibility). > Thus, it is set as the primary choice if available. > > As an example, running perf report on a medium-size profile with > DWARF-based backtraces took 58 seconds with LLVM, 78 seconds with > libbfd, 153 seconds with external llvm-addr2line, and I got tired > and aborted the test after waiting for 55 minutes with external > bfd addr2line (which is the default for perf as compiled by distributions > today). Evidently, for this case, the bfd addr2line process needs > 18 seconds (on a 5.2 GHz Zen 3) to load the .debug ELF in question, > hits the 1-second timeout and gets killed during initialization, > getting restarted anew every time. Having an in-process addr2line > makes this much more robust. > > As future extensions, libllvm can be used in many other places where > we currently use libbfd or other libraries: > > - Symbol enumeration (in particular, for PE binaries). > - Demangling (including non-Itanium demangling, e.g. Microsoft > or Rust). > - Disassembling (perf annotate). > > However, these are much less pressing; most people don't profile > PE binaries, and perf has non-bfd paths for ELF. The same with > demangling; the default _cxa_demangle path works fine for most > users. Disassembling is coming in a later patch in the series; > however do note that while bfd objdump can be slow on large binaries, > it is possible to use --objdump=3Dllvm-objdump to get the speed benefits. > (It appears LLVM-based demangling is very simple, should we want > that.) > > Tested with LLVM 14, 16, 18 and 19. For some reason, LLVM 12 was not > correctly detected using feature_check, and thus was not tested. > > Signed-off-by: Steinar H. Gunderson > --- > tools/perf/Makefile.config | 15 ++++ > tools/perf/builtin-version.c | 1 + > tools/perf/util/Build | 1 + > tools/perf/util/llvm-c-helpers.cpp | 129 +++++++++++++++++++++++++++++ > tools/perf/util/llvm-c-helpers.h | 47 +++++++++++ > tools/perf/util/srcline.c | 57 ++++++++++++- > 6 files changed, 249 insertions(+), 1 deletion(-) > create mode 100644 tools/perf/util/llvm-c-helpers.cpp > create mode 100644 tools/perf/util/llvm-c-helpers.h > > diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config > index 7f1e016a9253..414a37f712bd 100644 > --- a/tools/perf/Makefile.config > +++ b/tools/perf/Makefile.config > @@ -969,6 +969,21 @@ ifdef BUILD_NONDISTRO > endif > endif > > +ifndef NO_LLVM > + $(call feature_check,llvm) > + ifeq ($(feature-llvm), 1) > + CFLAGS +=3D -DHAVE_LLVM_SUPPORT > + CXXFLAGS +=3D -DHAVE_LLVM_SUPPORT > + CXXFLAGS +=3D $(shell $(LLVM_CONFIG) --cxxflags) > + LIBLLVM =3D $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG= ) --system-libs) > + EXTLIBS +=3D -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM) > + $(call detected,CONFIG_LLVM) I think we might want to display this in the feature list during the build: https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tr= ee/tools/build/Makefile.feature?h=3Dperf-tools-next#n123 > + else > + $(warning No libllvm found, slower source file resolution, please in= stall llvm-devel/llvm-dev) > + NO_LLVM :=3D 1 > + endif > +endif > + > ifndef NO_DEMANGLE > $(call feature_check,cxa-demangle) > ifeq ($(feature-cxa-demangle), 1) > diff --git a/tools/perf/builtin-version.c b/tools/perf/builtin-version.c > index 398aa53e9e2e..4b252196de12 100644 > --- a/tools/perf/builtin-version.c > +++ b/tools/perf/builtin-version.c > @@ -65,6 +65,7 @@ static void library_status(void) > STATUS(HAVE_LIBBFD_SUPPORT, libbfd); > STATUS(HAVE_DEBUGINFOD_SUPPORT, debuginfod); > STATUS(HAVE_LIBELF_SUPPORT, libelf); > + STATUS(HAVE_LIBLLVM_SUPPORT, libllvm); s/HAVE_LIBLLVM_SUPPORT/HAVE_LLVM_SUPPORT/ > STATUS(HAVE_LIBNUMA_SUPPORT, libnuma); > STATUS(HAVE_LIBNUMA_SUPPORT, numa_num_possible_cpus); > STATUS(HAVE_LIBPERL_SUPPORT, libperl); > diff --git a/tools/perf/util/Build b/tools/perf/util/Build > index da64efd8718f..32c4e5e634ed 100644 > --- a/tools/perf/util/Build > +++ b/tools/perf/util/Build > @@ -226,6 +226,7 @@ perf-$(CONFIG_CXX_DEMANGLE) +=3D demangle-cxx.o > perf-y +=3D demangle-ocaml.o > perf-y +=3D demangle-java.o > perf-y +=3D demangle-rust.o > +perf-$(CONFIG_LLVM) +=3D llvm-c-helpers.o > > ifdef CONFIG_JITDUMP > perf-$(CONFIG_LIBELF) +=3D jitdump.o > diff --git a/tools/perf/util/llvm-c-helpers.cpp b/tools/perf/util/llvm-c-= helpers.cpp > new file mode 100644 > index 000000000000..2dafaaa86234 > --- /dev/null > +++ b/tools/perf/util/llvm-c-helpers.cpp > @@ -0,0 +1,129 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +/* > + * Must come before the linux/compiler.h include, which defines several > + * macros (e.g. noinline) that conflict with compiler builtins used > + * by LLVM. */ > +#pragma GCC diagnostic push > +#pragma GCC diagnostic ignored "-Wunused-parameter" /* Needed for LLVM = 14. */ nit: pehaps disabling this should be conditional: #if LLVM_VERSION_MAJOR =3D=3D 14 > +#include > +#pragma GCC diagnostic pop > + > +#include > +#include > +#include > +#include "symbol_conf.h" > +#include "llvm-c-helpers.h" > + > +using namespace llvm; > +using llvm::symbolize::LLVMSymbolizer; > + > +/* > + * Allocate a static LLVMSymbolizer, which will live to the end of the p= rogram. > + * Unlike the bfd paths, LLVMSymbolizer has its own cache, so we do not = need > + * to store anything in the dso struct. > + */ > +static LLVMSymbolizer *get_symbolizer() > +{ > + static LLVMSymbolizer *instance =3D nullptr; > + if (instance =3D=3D nullptr) { > + LLVMSymbolizer::Options opts; > + /* > + * LLVM sometimes demangles slightly different from the r= est > + * of the code, and this mismatch can cause new_inline_sy= m() > + * to get confused and mark non-inline symbol as inlined > + * (since the name does not properly match up with base_s= ym). > + * Thus, disable the demangling and let the rest of the c= ode > + * handle it. > + */ > + opts.Demangle =3D false; > + instance =3D new LLVMSymbolizer(opts); > + } > + return instance; > +} > + > +/* Returns 0 on error, 1 on success. */ > +static int extract_file_and_line(const DILineInfo& line_info, char **fil= e, > + unsigned int *line) > +{ > + if (file) { > + if (line_info.FileName =3D=3D "") { > + /* Match the convention of libbfd. */ > + *file =3D nullptr; Should "*file" be cleared if "!file" so the caller can reliably free it? I did some testing and everything looks good. Thanks, Ian > + } else { > + /* The caller expects to get something it can fre= e(). */ > + *file =3D strdup(line_info.FileName.c_str()); > + if (*file =3D=3D nullptr) > + return 0; > + } > + } > + if (line) > + *line =3D line_info.Line; > + return 1; > +} > + > +extern "C" > +int llvm_addr2line(const char *dso_name, u64 addr, > + char **file, unsigned int *line, > + bool unwind_inlines, > + llvm_a2l_frame** inline_frames) > +{ > + LLVMSymbolizer *symbolizer =3D get_symbolizer(); > + object::SectionedAddress sectioned_addr =3D { > + addr, > + object::SectionedAddress::UndefSection > + }; > + > + if (unwind_inlines) { > + Expected res_or_err =3D > + symbolizer->symbolizeInlinedCode(dso_name, > + sectioned_addr); > + if (!res_or_err) > + return 0; > + unsigned num_frames =3D res_or_err->getNumberOfFrames(); > + if (num_frames =3D=3D 0) > + return 0; > + > + if (extract_file_and_line( > + res_or_err->getFrame(0), file, line) =3D=3D 0) > + return 0; > + > + *inline_frames =3D (llvm_a2l_frame*)malloc( > + sizeof(**inline_frames) * num_frames); > + if (*inline_frames =3D=3D nullptr) > + return 0; > + > + for (unsigned i =3D 0; i < num_frames; ++i) { > + const DILineInfo& src =3D res_or_err->getFrame(i)= ; > + llvm_a2l_frame& dst =3D (*inline_frames)[i]; > + if (src.FileName =3D=3D "") > + /* Match the convention of libbfd. */ > + dst.filename =3D nullptr; > + else > + dst.filename =3D strdup(src.FileName.c_st= r()); > + dst.funcname =3D strdup(src.FunctionName.c_str())= ; > + dst.line =3D src.Line; > + > + if (dst.filename =3D=3D nullptr || > + dst.funcname =3D=3D nullptr) { > + for (unsigned j =3D 0; j <=3D i; ++j) { > + free((*inline_frames)[j].filename= ); > + free((*inline_frames)[j].funcname= ); > + } > + free(*inline_frames); > + return 0; > + } > + } > + > + return num_frames; > + } else { > + if (inline_frames) > + *inline_frames =3D nullptr; > + > + Expected res_or_err =3D > + symbolizer->symbolizeCode(dso_name, sectioned_add= r); > + if (!res_or_err) > + return 0; > + return extract_file_and_line(*res_or_err, file, line); > + } > +} > diff --git a/tools/perf/util/llvm-c-helpers.h b/tools/perf/util/llvm-c-he= lpers.h > new file mode 100644 > index 000000000000..f295aa2bcf2d > --- /dev/null > +++ b/tools/perf/util/llvm-c-helpers.h > @@ -0,0 +1,47 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#ifndef __PERF_LLVM_ADDR2LINE > +#define __PERF_LLVM_ADDR2LINE 1 > + > +/* > + * Helpers to call into LLVM C++ code from C, for the parts that do not = have > + * C APIs. > + */ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +struct llvm_a2l_frame { > + char *filename; > + char *funcname; > + unsigned int line; > +}; > + > +/* > + * Implement addr2line() using libLLVM. LLVM is a C++ API, and > + * many of the linux/ headers cannot be included in a C++ compile unit, > + * so we need to make a little bridge code here. llvm_addr2line() will > + * convert the inline frame information from LLVM's internal structures > + * and put them into a flat array given in inline_frames. The caller > + * is then responsible for taking that array and convert it into perf's > + * regular inline frame structures (which depend on e.g. struct list_hea= d). > + * > + * If the address could not be resolved, or an error occurred (e.g. OOM)= , > + * returns 0. Otherwise, returns the number of inline frames (which mean= s 1 > + * if the address was not part of an inlined function). If unwind_inline= s > + * is set and the return code is nonzero, inline_frames will be set to > + * a newly allocated array with that length. The caller is then responsi= ble > + * for freeing both the strings and the array itself. > + */ > +int llvm_addr2line(const char *dso_name, > + u64 addr, > + char **file, > + unsigned int *line, > + bool unwind_inlines, > + struct llvm_a2l_frame **inline_frames); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif /* __PERF_LLVM_ADDR2LINE */ > diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c > index 9d670d8c1c08..0505b4c16608 100644 > --- a/tools/perf/util/srcline.c > +++ b/tools/perf/util/srcline.c > @@ -16,6 +16,9 @@ > #include "util/debug.h" > #include "util/callchain.h" > #include "util/symbol_conf.h" > +#ifdef HAVE_LLVM_SUPPORT > +#include "util/llvm-c-helpers.h" > +#endif > #include "srcline.h" > #include "string2.h" > #include "symbol.h" > @@ -130,7 +133,59 @@ static struct symbol *new_inline_sym(struct dso *dso= , > > #define MAX_INLINE_NEST 1024 > > -#ifdef HAVE_LIBBFD_SUPPORT > +#ifdef HAVE_LLVM_SUPPORT > + > +static void free_llvm_inline_frames(struct llvm_a2l_frame *inline_frames= , > + int num_frames) > +{ > + if (inline_frames !=3D NULL) { > + for (int i =3D 0; i < num_frames; ++i) { > + free(inline_frames[i].filename); > + free(inline_frames[i].funcname); > + } > + free(inline_frames); > + } > +} > + > +static int addr2line(const char *dso_name, u64 addr, > + char **file, unsigned int *line, struct dso *dso, > + bool unwind_inlines, struct inline_node *node, > + struct symbol *sym) > +{ > + struct llvm_a2l_frame *inline_frames =3D NULL; > + int num_frames =3D llvm_addr2line(dso_name, addr, file, line, > + node && unwind_inlines, &inline_f= rames); > + > + if (num_frames =3D=3D 0 || !inline_frames) { > + /* Error, or we didn't want inlines. */ > + return num_frames; > + } > + > + for (int i =3D 0; i < num_frames; ++i) { > + struct symbol *inline_sym =3D > + new_inline_sym(dso, sym, inline_frames[i].funcnam= e); > + char *srcline =3D NULL; > + > + if (inline_frames[i].filename) > + srcline =3D srcline_from_fileline( > + inline_frames[i].filename, > + inline_frames[i].line); > + if (inline_list__append(inline_sym, srcline, node) !=3D 0= ) { > + free_llvm_inline_frames(inline_frames, num_frames= ); > + return 0; > + } > + } > + free_llvm_inline_frames(inline_frames, num_frames); > + > + return num_frames; > +} > + > +void dso__free_a2l(struct dso *) > +{ > + /* Nothing to free. */ > +} > + > +#elif defined(HAVE_LIBBFD_SUPPORT) > > /* > * Implement addr2line using libbfd. > -- > 2.43.0 >