From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pg1-f201.google.com (mail-pg1-f201.google.com [209.85.215.201]) (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 73E6D2BD5AF for ; Sun, 5 Oct 2025 21:22:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699344; cv=none; b=Oj6WEeCOfGzjMRE+I5Jkkp7rNM0JFWcg1HKzdrnvMkq+57dPlebGA+gdlXECIaNazASrJO3E+fpQbSEYCQVN5R/++wSS7TcT4dGNZ3rk31bID08+utycyXdhUI4VpSvchlmE/ZmcjuNzHUMgaKtzbat2bRG9n1qxcX8jLB5vi4s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699344; c=relaxed/simple; bh=/luZGaDcmbSsI2ELFDFE/EBkhdco1hXagnVGpUVsYwI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=AbgTi1eWY00dodRMtw7kNE9ot0/8m6cJGwYYf5U++5s6X5sz717+IvA30tSeKrNek7sXFzk8WpAXLHQPPDeUZXNinuPQ3GEoy8zDMmZC7czswyRtF2fdD6/02U9/nfUXyb+f5wnOyXGKNAP21jddmFN6+8zljqo4xg/lpCg+sN8= 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=S8HAgs+t; arc=none smtp.client-ip=209.85.215.201 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="S8HAgs+t" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-b5529da7771so2625799a12.0 for ; Sun, 05 Oct 2025 14:22:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699343; x=1760304143; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=hHVoU7VdAErJHQsuyUDkFaSuPa656SpDfPesPL1Iw7A=; b=S8HAgs+tuIFcFHWZluFX1V2ArU5mhlRIUv7OnmeUWYsOvITyfFwugvZpXHWvf4qAVY i/GsatlzOcMDl+pWFfQUzAVbRXzGTBwfkyoYSedRp13mMyaa+rKDuYNKYuY+XVyXudC7 33tk1S/Ald9PhmhKyv3aKvtJ0he0kxgFmrjfZYgdhL8nv9vSKnK4q4EP7Ye3yLZ6Dg09 aMz8KDB0nneJ0EfmYx/FXLeJ8k+aMGtVyH0NkSAnFNJ+tsnNw7jg9rL3eI7LELfQc4nm Qvqsb/VuJGQ/mXKCkwIFRLYOumNzpwYCkrGmk6fRXx6WaERvkmL302pR4f/PoyBKIACt 0oxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699343; x=1760304143; h=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; bh=hHVoU7VdAErJHQsuyUDkFaSuPa656SpDfPesPL1Iw7A=; b=hQA2xXADwgPtiIVbGzCum9SRbSFiNerNGoLAyQ1tPw4ybw4tf8fDe8jLC1nP28cKqC ZM/GJ8+DzYcAn72p0HQl4CSuakp8cp/bp2Lv9Orl8L4MWHeWCogxzzSjHKqzKcVYby+8 oq6jqQSXbXPIG/m3hSUWHR1rxpLDsi89FhboF+vsQpP3t1ovyqOuZARB9rCv6KG2wjY5 OT4UQc2a6ma5yI09jIsdO+XJT9NjJxyKjQAPHQdSmcwVFjTC7gVkOkHtBNyXyfpCAR9Z P5S6cUMqNlRf93IYvJUNhmjLUVii0r5vVWCIeT4/dOaNO1PmxL+OTcQMbDRGUugkWZNd 8Syg== X-Forwarded-Encrypted: i=1; AJvYcCU+xyMX6MAF08kRLjvU1/EmcHxBUF9v7Lh7Q/+IZRRxrHC/WgZ1ii0uhkxyGUVclGU5tnAG7N2Ng4paXzM=@vger.kernel.org X-Gm-Message-State: AOJu0YwDup3CYpkdK7teaFaCBU3G6KLiuFT2YbPA40NRe1xBHidKlN63 zaBmh+5SlimigjsfptePKZjs2lKP1ds6B6zKs5pbqcH3lwuRk1Az8odGAo3QKvkyO+7Ci+CNUBA A09XItzKT2A== X-Google-Smtp-Source: AGHT+IF9xACFD4NCBC8YA4+1DxHgAs4tVBez0mS1xBu199M+awLsaSCkEQ1/ioP2OUdMojXU72RjQE/JWxIn X-Received: from pjbpf16.prod.google.com ([2002:a17:90b:1d90:b0:330:6c04:207]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:e211:b0:240:1a3a:d7bc with SMTP id adf61e73a8af0-32b61dff87emr14700817637.3.1759699342575; Sun, 05 Oct 2025 14:22:22 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:02 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-2-irogers@google.com> Subject: [PATCH v7 01/11] perf check: Add libLLVM feature From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Advertise when perf is built with the HAVE_LIBLLVM_SUPPORT option. Signed-off-by: Ian Rogers --- tools/perf/Documentation/perf-check.txt | 1 + tools/perf/builtin-check.c | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/perf/Documentation/perf-check.txt b/tools/perf/Documenta= tion/perf-check.txt index ee92042082f7..4c9ccda6ce91 100644 --- a/tools/perf/Documentation/perf-check.txt +++ b/tools/perf/Documentation/perf-check.txt @@ -56,6 +56,7 @@ feature:: libcapstone / HAVE_LIBCAPSTONE_SUPPORT libdw-dwarf-unwind / HAVE_LIBDW_SUPPORT libelf / HAVE_LIBELF_SUPPORT + libLLVM / HAVE_LIBLLVM_SUPPORT libnuma / HAVE_LIBNUMA_SUPPORT libopencsd / HAVE_CSTRACE_SUPPORT libperl / HAVE_LIBPERL_SUPPORT diff --git a/tools/perf/builtin-check.c b/tools/perf/builtin-check.c index 8c0668911fb1..9ce2e71999df 100644 --- a/tools/perf/builtin-check.c +++ b/tools/perf/builtin-check.c @@ -48,6 +48,7 @@ struct feature_status supported_features[] =3D { FEATURE_STATUS("libcapstone", HAVE_LIBCAPSTONE_SUPPORT), FEATURE_STATUS("libdw-dwarf-unwind", HAVE_LIBDW_SUPPORT), FEATURE_STATUS("libelf", HAVE_LIBELF_SUPPORT), + FEATURE_STATUS("libLLVM", HAVE_LIBLLVM_SUPPORT), FEATURE_STATUS("libnuma", HAVE_LIBNUMA_SUPPORT), FEATURE_STATUS("libopencsd", HAVE_CSTRACE_SUPPORT), FEATURE_STATUS_TIP("libperl", HAVE_LIBPERL_SUPPORT, "Deprecated, use LIBP= ERL=3D1 and install perl-ExtUtils-Embed/libperl-dev to build with it"), --=20 2.51.0.618.g983fd99d29-goog From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (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 711012BE05F for ; Sun, 5 Oct 2025 21:22:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699348; cv=none; b=ta6y1kz3hF4//QNYDV8Q9aSXSKibIQl3Ngc//FDaPISANZ/w3Q0bTNF77o7H6iuIb2RZGQfFq2DaTSeZx6p5mNiyF2N9meT0hH5R0TC9RaNIGZGuJEeuSXx0zYY1UGoJ6obS+QjLQcekQsiX860EeG4deipgTcfrR+nm+So410k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699348; c=relaxed/simple; bh=jjogxjWTo8LEEeITCvVJ5lej7lh2270zJAspkUYjJfk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=QiN4kaGSTmYXlkrBT8sz8Y3us5/6xGxYxlUQKMhfprRKIJrcP6RypkuaT1e/r6dcSEZUepYiCOkKXe5Dd86TmeTEKZvH+5EvkOHu98n8xEuNbP62bSgzuwTy60XelxEWcP/9XtAnK6D4f5cc+yxFWf6JXHN9oXH4NtewgMrE7cE= 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=SepvnjU1; arc=none smtp.client-ip=209.85.214.202 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="SepvnjU1" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-2697c4e7354so50684095ad.0 for ; Sun, 05 Oct 2025 14:22:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699345; x=1760304145; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=zr9vg9+dbl377j7bj7cPlJqbhOg0YG22m54UFPy9WZs=; b=SepvnjU1Ud8J2ZZQxQGdPV2bc4S1FGHbD6D17/aWCpSPJ9ihEVF2KZDI5M05Zpb0zs t49rH4bREqOGMzHo4aB3BHweQtb/jDcphq+wnJN9S2+WUuVxw8xLPRKN5jnpg6fI36sX 6+TvrrIxTtUKHwoRT+sXESumjFMhp2rSfI72r+tHEYG0BHlgf/KulgizVf14sUlPCUQR Z8Ll5MHe7bU2QWRCq+1DIxieFto/DMiQYoZaVix7u1optdGKfzHfuv546+dE5Uqi8GPs iiTKywyRcQEqqZxBI7lvEtCx1Z3lO9TwU1H7X98/PWUdO1dj0thQoNc7h22w5FuKoLsy xMsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699345; x=1760304145; h=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; bh=zr9vg9+dbl377j7bj7cPlJqbhOg0YG22m54UFPy9WZs=; b=FiHB3Qto+wlkuWQNwf8+WcwKwylaHf8qZTgi9BYbapBJq0b3ukeqOuODMnfYVuHpA0 GTFSjruhUgCBilo3ODHu2IDxzH2bBuRCHSfkjmSpfvGXLJLGKyNp0kSuACDibHHGtFhG BSAJDMfMYKq98JA0IwkBKZhlD0FQ5ruHtuTt6Y8+t3aUBQRumts0fhwnO26aviAOVrWm OVe+sLmP7j5xghREeguUwxv1YeRAjDHQ/S6JvA29Zyw7mjx3QoeoMbdJEGtIu2AVymle 6KPcI7TjehqzEVhpLuub2modLhrXm/4q199iwRWEdfq3XU00YdUcCS/uqRfiiWLhjx8z EBWw== X-Forwarded-Encrypted: i=1; AJvYcCWb1/5OMhzL3iSzYm0OhPOQc+430EC12HbZdhRREJPr0vPlpRDBm5DVM9tRJLw1Q484CT8jHEeiW7ddh5A=@vger.kernel.org X-Gm-Message-State: AOJu0YzBhJQ7Qdxb1zGZ7HQYBCEmHwUM8WR4hYYrBuxpVF0Sft3Ot3rQ 3p7h79XliFcnrDliWkDjEwUu55kWvczTJ65MdO4giwnsYU7+1kBZh3rc/wzP/PlFqExt95dHtVu tT9tuRFDPuQ== X-Google-Smtp-Source: AGHT+IFEaM+mFQzGCobgqNknXJ7y1TlfovFXjd/cXa5mwCMiuAzlKf2cDvpg0Dz2Z/gtCSnKr3ofcMi/Sj1q X-Received: from pjbqo8.prod.google.com ([2002:a17:90b:3dc8:b0:32e:e06a:4668]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:2c0e:b0:27e:f03e:c6b7 with SMTP id d9443c01a7336-28e8d038b9cmr181830185ad.10.1759699344812; Sun, 05 Oct 2025 14:22:24 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:03 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-3-irogers@google.com> Subject: [PATCH v7 02/11] perf llvm: Reduce LLVM initialization From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the 3 LLVM initialization routines to be called in a single init_llvm function that has its own bool to avoid repeated initialization. Reduce the scope of triplet and avoid copying strings for x86. Signed-off-by: Ian Rogers --- tools/perf/util/llvm.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/llvm.c b/tools/perf/util/llvm.c index ddc737194692..2356778955fe 100644 --- a/tools/perf/util/llvm.c +++ b/tools/perf/util/llvm.c @@ -74,6 +74,17 @@ void dso__free_a2l_llvm(struct dso *dso __maybe_unused) /* Nothing to free. */ } =20 +static void init_llvm(void) +{ + static bool init; + + if (!init) { + LLVMInitializeAllTargetInfos(); + LLVMInitializeAllTargetMCs(); + LLVMInitializeAllDisassemblers(); + init =3D true; + } +} =20 #if defined(HAVE_LIBLLVM_SUPPORT) struct find_file_offset_data { @@ -184,7 +195,6 @@ int symbol__disassemble_llvm(const char *filename, stru= ct symbol *sym, u64 len; u64 pc; bool is_64bit; - char triplet[64]; char disasm_buf[2048]; size_t disasm_len; struct disasm_line *dl; @@ -197,26 +207,25 @@ int symbol__disassemble_llvm(const char *filename, st= ruct symbol *sym, if (args->options->objdump_path) return -1; =20 - LLVMInitializeAllTargetInfos(); - LLVMInitializeAllTargetMCs(); - LLVMInitializeAllDisassemblers(); - buf =3D read_symbol(filename, map, sym, &len, &is_64bit); if (buf =3D=3D NULL) return -1; =20 + init_llvm(); if (arch__is(args->arch, "x86")) { - if (is_64bit) - scnprintf(triplet, sizeof(triplet), "x86_64-pc-linux"); - else - scnprintf(triplet, sizeof(triplet), "i686-pc-linux"); + const char *triplet =3D is_64bit ? "x86_64-pc-linux" : "i686-pc-linux"; + + disasm =3D LLVMCreateDisasm(triplet, &storage, /*tag_type=3D*/0, + /*get_op_info=3D*/NULL, symbol_lookup_callback); } else { + char triplet[64]; + scnprintf(triplet, sizeof(triplet), "%s-linux-gnu", args->arch->name); + disasm =3D LLVMCreateDisasm(triplet, &storage, /*tag_type=3D*/0, + /*get_op_info=3D*/NULL, symbol_lookup_callback); } =20 - disasm =3D LLVMCreateDisasm(triplet, &storage, 0, NULL, - symbol_lookup_callback); if (disasm =3D=3D NULL) goto err; =20 --=20 2.51.0.618.g983fd99d29-goog From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (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 BFA472BF005 for ; Sun, 5 Oct 2025 21:22:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699349; cv=none; b=cl14KtESyUvA5t3hCX6egvKfihG9W5IzvnGut2yzg716yVVGZFG7+iPR25jEnhUUndJ+UxRjQkoN/vfW9SRe9n5cGEbmNk9jwE0UHUKyNOR1XY11gqW64yRMnwWxQ956Z5LpgzsUKWCD8lQZgj6sqQP1wcIf3CsQahgLcjGLlCo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699349; c=relaxed/simple; bh=1AcAVTJaNRek7hoOhiMLQ+rsKXs+qNDcn0xrSWd0d40=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=TNAz/sTstjBeGBQ8PNj97ek4E9PVoTYwmWXImpYmfY74M0TV6EdsABhoHhFmRoY6UyHuVJ+8LSmDKhJ+wOzdDq0XQkLSjbxR+gRUam3TLyAU6/xIKzuf917e491yj3+/TC8pW9i2Vt8ZnG743ewaAFiZR/Qf5Glkl9bbodUI7Pg= 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=qUQ4nYFO; arc=none smtp.client-ip=209.85.214.202 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="qUQ4nYFO" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-27ee41e062cso47670865ad.1 for ; Sun, 05 Oct 2025 14:22:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699347; x=1760304147; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=O+l/WGm8eAK1INkc4qzoRNUwkFMn5H1vWu1UxQ6sXUY=; b=qUQ4nYFOHzyK1yvED+gc3RiW+rftl9MjMRFHs3zNlizjPkxIT+f517HR1dQGpSfYr+ jVAVMRp3Z+9GLS8AwZCCLYCvDRw3uxhDW8dSzzsu2EPefby7Mj/qBrGjlDYQA1Fbfrt8 +H3GlpE/DAM4/j7W0w/P6+GnBGgNw2AB0GO1EdtgmxU/4j+25VahQvNaCuhnZbD/2AYl 319ysLY2eeMXsJaB/ZFGKsKOuKT5fEAwoGTNTHCwEuk6EvRDgMr7o8OUxSJ2L80trHzI hiDyfLQ+cWz0TphYN7Ym47/Pbb6lJMdKnaR/CVQQik49okWgXrrp6EQJTrZivAodGgOn Nr2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699347; x=1760304147; h=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; bh=O+l/WGm8eAK1INkc4qzoRNUwkFMn5H1vWu1UxQ6sXUY=; b=CfDjThpJjJ5FTH317ce1BQwXLO0w2d4J84BDylR7BS8q1w4NHQK5RglCe4sGFcWr1h +BjXsMY8HVAICNTZc5a3XkjBUH+xHvZ/Yk2DqyJa3ohszvqzxXyG6RaAt+OpHdS19zT/ SExhwm1rrBz6sWiIOFdGqZo3rhZuPCAaMaLMxYDQ7iCuHBN/7vs/N407ONORJwBQofrr ThnTQDTHUucsXnvzVLgp5fhWW8ggnxLpuExbV/w8sf+N3emqOjRyus6EHF5wxn6N2ow7 sajf7UMNXsfb2lGok2cb2V+NUtWZmY1RbllVYMAvIEe7F8uIb6mVaPyRHM0alPDxN9iE 7E/A== X-Forwarded-Encrypted: i=1; AJvYcCUl6FTtQRYyqXrhVRq/ngGDeXjRsQV/MdURbY//ACqlkJLIBx0GwqsYRqWr8whPjUHsrJ4F3Uj/g1StsVw=@vger.kernel.org X-Gm-Message-State: AOJu0YwRDFED7C0U0TNjzMYouNFeBTShKFitbuvni8KQaIIQaYg5Tj8J UNELbTNOKC7DBa3WFdbiieENeByS6Kcg9hjmUcKQTfmfM2JyHk2vNs83ESX7UW0tBGpu1ivFqvL /eAwnm/ihFQ== X-Google-Smtp-Source: AGHT+IFu3ifLGHl9t/SXSR8xeghMcMlScLbRJvVQc0sMzH1px7fbKrot0jtLZYXkZgynu4Xl7VItdjoJR39p X-Received: from pldb2.prod.google.com ([2002:a17:902:ed02:b0:269:6a61:3d1a]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:2c7:b0:269:96ee:17d3 with SMTP id d9443c01a7336-28e9a6fd7c4mr106405305ad.51.1759699347119; Sun, 05 Oct 2025 14:22:27 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:04 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-4-irogers@google.com> Subject: [PATCH v7 03/11] perf dso: Move read_symbol from llvm/capstone to dso From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the read_symbol function to dso.h, make the return type const and add a mutable out_buf out parameter. In future changes this will allow a code pointer to be returned without necessary allocating memory. Signed-off-by: Ian Rogers --- tools/perf/util/capstone.c | 66 +++++----------------------- tools/perf/util/dso.c | 67 +++++++++++++++++++++++++++++ tools/perf/util/dso.h | 4 ++ tools/perf/util/llvm.c | 88 +++++++------------------------------- 4 files changed, 97 insertions(+), 128 deletions(-) diff --git a/tools/perf/util/capstone.c b/tools/perf/util/capstone.c index 01e47d5c8e3e..c23df911e91c 100644 --- a/tools/perf/util/capstone.c +++ b/tools/perf/util/capstone.c @@ -215,55 +215,6 @@ static int find_file_offset(u64 start, u64 len, u64 pg= off, void *arg) } #endif =20 -#ifdef HAVE_LIBCAPSTONE_SUPPORT -static u8 * -read_symbol(const char *filename, struct map *map, struct symbol *sym, - u64 *len, bool *is_64bit) -{ - struct dso *dso =3D map__dso(map); - struct nscookie nsc; - u64 start =3D map__rip_2objdump(map, sym->start); - u64 end =3D map__rip_2objdump(map, sym->end); - int fd, count; - u8 *buf =3D NULL; - struct find_file_offset_data data =3D { - .ip =3D start, - }; - - *is_64bit =3D false; - - nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); - fd =3D open(filename, O_RDONLY); - nsinfo__mountns_exit(&nsc); - if (fd < 0) - return NULL; - - if (file__read_maps(fd, /*exe=3D*/true, find_file_offset, &data, - is_64bit) =3D=3D 0) - goto err; - - *len =3D end - start; - buf =3D malloc(*len); - if (buf =3D=3D NULL) - goto err; - - count =3D pread(fd, buf, *len, data.offset); - close(fd); - fd =3D -1; - - if ((u64)count !=3D *len) - goto err; - - return buf; - -err: - if (fd >=3D 0) - close(fd); - free(buf); - return NULL; -} -#endif - int symbol__disassemble_capstone(const char *filename __maybe_unused, struct symbol *sym __maybe_unused, struct annotate_args *args __maybe_unused) @@ -271,13 +222,17 @@ int symbol__disassemble_capstone(const char *filename= __maybe_unused, #ifdef HAVE_LIBCAPSTONE_SUPPORT struct annotation *notes =3D symbol__annotation(sym); struct map *map =3D args->ms.map; + struct dso *dso =3D map__dso(map); u64 start =3D map__rip_2objdump(map, sym->start); - u64 len; u64 offset; int i, count, free_count; bool is_64bit =3D false; bool needs_cs_close =3D false; - u8 *buf =3D NULL; + /* Malloc-ed buffer containing instructions read from disk. */ + u8 *code_buf =3D NULL; + /* Pointer to code to be disassembled. */ + const u8 *buf; + u64 buf_len; csh handle; cs_insn *insn =3D NULL; char disasm_buf[512]; @@ -287,7 +242,8 @@ int symbol__disassemble_capstone(const char *filename _= _maybe_unused, if (args->options->objdump_path) return -1; =20 - buf =3D read_symbol(filename, map, sym, &len, &is_64bit); + buf =3D dso__read_symbol(dso, filename, map, sym, + &code_buf, &buf_len, &is_64bit); if (buf =3D=3D NULL) return -1; =20 @@ -316,7 +272,7 @@ int symbol__disassemble_capstone(const char *filename _= _maybe_unused, =20 needs_cs_close =3D true; =20 - free_count =3D count =3D cs_disasm(handle, buf, len, start, len, &insn); + free_count =3D count =3D cs_disasm(handle, buf, buf_len, start, buf_len, = &insn); for (i =3D 0, offset =3D 0; i < count; i++) { int printed; =20 @@ -340,7 +296,7 @@ int symbol__disassemble_capstone(const char *filename _= _maybe_unused, } =20 /* It failed in the middle: probably due to unknown instructions */ - if (offset !=3D len) { + if (offset !=3D buf_len) { struct list_head *list =3D ¬es->src->source; =20 /* Discard all lines and fallback to objdump */ @@ -359,7 +315,7 @@ int symbol__disassemble_capstone(const char *filename _= _maybe_unused, if (free_count > 0) cs_free(insn, free_count); } - free(buf); + free(code_buf); return count < 0 ? count : 0; =20 err: diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 282e3af85d5a..87d075942de6 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1798,3 +1798,70 @@ bool is_perf_pid_map_name(const char *dso_name) =20 return perf_pid_map_tid(dso_name, &tid); } + +struct find_file_offset_data { + u64 ip; + u64 offset; +}; + +/* This will be called for each PHDR in an ELF binary */ +static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg) +{ + struct find_file_offset_data *data =3D arg; + + if (start <=3D data->ip && data->ip < start + len) { + data->offset =3D pgoff + data->ip - start; + return 1; + } + return 0; +} + +const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename, + const struct map *map, const struct symbol *sym, + u8 **out_buf, u64 *out_buf_len, bool *is_64bit) +{ + struct nscookie nsc; + u64 start =3D map__rip_2objdump(map, sym->start); + u64 end =3D map__rip_2objdump(map, sym->end); + int fd, count; + u8 *buf =3D NULL; + size_t len; + struct find_file_offset_data data =3D { + .ip =3D start, + }; + + *out_buf =3D NULL; + *out_buf_len =3D 0; + *is_64bit =3D false; + + nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); + fd =3D open(symfs_filename, O_RDONLY); + nsinfo__mountns_exit(&nsc); + if (fd < 0) + return NULL; + + if (file__read_maps(fd, /*exe=3D*/true, find_file_offset, &data, is_64bit= ) =3D=3D 0) + goto err; + + len =3D end - start; + buf =3D malloc(len); + if (buf =3D=3D NULL) + goto err; + + count =3D pread(fd, buf, len, data.offset); + close(fd); + fd =3D -1; + + if ((u64)count !=3D len) + goto err; + + *out_buf =3D buf; + *out_buf_len =3D len; + return buf; + +err: + if (fd >=3D 0) + close(fd); + free(buf); + return NULL; +} diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index fd8e95de77f7..f8ccb9816b89 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -924,4 +924,8 @@ static inline struct debuginfo *dso__debuginfo(struct d= so *dso) return debuginfo__new(dso__long_name(dso)); } =20 +const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename, + const struct map *map, const struct symbol *sym, + u8 **out_buf, u64 *out_buf_len, bool *is_64bit); + #endif /* __PERF_DSO */ diff --git a/tools/perf/util/llvm.c b/tools/perf/util/llvm.c index 2356778955fe..0369f3adcdb6 100644 --- a/tools/perf/util/llvm.c +++ b/tools/perf/util/llvm.c @@ -86,72 +86,6 @@ static void init_llvm(void) } } =20 -#if defined(HAVE_LIBLLVM_SUPPORT) -struct find_file_offset_data { - u64 ip; - u64 offset; -}; - -/* This will be called for each PHDR in an ELF binary */ -static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg) -{ - struct find_file_offset_data *data =3D arg; - - if (start <=3D data->ip && data->ip < start + len) { - data->offset =3D pgoff + data->ip - start; - return 1; - } - return 0; -} - -static u8 * -read_symbol(const char *filename, struct map *map, struct symbol *sym, - u64 *len, bool *is_64bit) -{ - struct dso *dso =3D map__dso(map); - struct nscookie nsc; - u64 start =3D map__rip_2objdump(map, sym->start); - u64 end =3D map__rip_2objdump(map, sym->end); - int fd, count; - u8 *buf =3D NULL; - struct find_file_offset_data data =3D { - .ip =3D start, - }; - - *is_64bit =3D false; - - nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); - fd =3D open(filename, O_RDONLY); - nsinfo__mountns_exit(&nsc); - if (fd < 0) - return NULL; - - if (file__read_maps(fd, /*exe=3D*/true, find_file_offset, &data, - is_64bit) =3D=3D 0) - goto err; - - *len =3D end - start; - buf =3D malloc(*len); - if (buf =3D=3D NULL) - goto err; - - count =3D pread(fd, buf, *len, data.offset); - close(fd); - fd =3D -1; - - if ((u64)count !=3D *len) - goto err; - - return buf; - -err: - if (fd >=3D 0) - close(fd); - free(buf); - return NULL; -} -#endif - /* * Whenever LLVM wants to resolve an address into a symbol, it calls this * callback. We don't ever actually _return_ anything (in particular, beca= use @@ -191,8 +125,11 @@ int symbol__disassemble_llvm(const char *filename, str= uct symbol *sym, struct map *map =3D args->ms.map; struct dso *dso =3D map__dso(map); u64 start =3D map__rip_2objdump(map, sym->start); - u8 *buf; - u64 len; + /* Malloc-ed buffer containing instructions read from disk. */ + u8 *code_buf =3D NULL; + /* Pointer to code to be disassembled. */ + const u8 *buf; + u64 buf_len; u64 pc; bool is_64bit; char disasm_buf[2048]; @@ -207,7 +144,8 @@ int symbol__disassemble_llvm(const char *filename, stru= ct symbol *sym, if (args->options->objdump_path) return -1; =20 - buf =3D read_symbol(filename, map, sym, &len, &is_64bit); + buf =3D dso__read_symbol(dso, filename, map, sym, + &code_buf, &buf_len, &is_64bit); if (buf =3D=3D NULL) return -1; =20 @@ -259,14 +197,18 @@ int symbol__disassemble_llvm(const char *filename, st= ruct symbol *sym, annotation_line__add(&dl->al, ¬es->src->source); =20 pc =3D start; - for (u64 offset =3D 0; offset < len; ) { + for (u64 offset =3D 0; offset < buf_len; ) { unsigned int ins_len; =20 storage.branch_addr =3D 0; storage.pcrel_load_addr =3D 0; =20 - ins_len =3D LLVMDisasmInstruction(disasm, buf + offset, - len - offset, pc, + /* + * LLVM's API has the code be disassembled as non-const, cast + * here as we may be disassembling from mapped read-only memory. + */ + ins_len =3D LLVMDisasmInstruction(disasm, (u8 *)(buf + offset), + buf_len - offset, pc, disasm_buf, sizeof(disasm_buf)); if (ins_len =3D=3D 0) goto err; @@ -324,7 +266,7 @@ int symbol__disassemble_llvm(const char *filename, stru= ct symbol *sym, =20 err: LLVMDisasmDispose(disasm); - free(buf); + free(code_buf); free(line_storage); return ret; #else // HAVE_LIBLLVM_SUPPORT --=20 2.51.0.618.g983fd99d29-goog From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (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 B238D2BFC60 for ; Sun, 5 Oct 2025 21:22:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699351; cv=none; b=l9zQ1KhG1/Qt3EdRFfJmITiP8TzuUe1u6SiXJaAC4LH5xOt1mYteB+s3ZBjhStPjcupKm7BT5OhyqdL6XHJY0Sa6wxWBT1YrvU263ozuk3csO1RcwvnQbqqlooq/CQSV8gDjehMQPFyYHEAk1G3UWnMO/LbNCoclNM1UblbNF30= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699351; c=relaxed/simple; bh=CCQPc58TSvr0cy3nKc2lprmjbQNbCaQTJI1JHBO4fZk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=UYocnPRfrr0SBI4jycFGNAR+2wAFOzwg/Jfxbu+5X537u6ltlJHrUCR0HQOpAjDnKVdfxFZFqkaty7tiEHN2BMBZGgKhii8rueINW6ABRAo5augz8q3OSodEHAiAONrFwX0AT8v2Yxg+18+CTySFzEO89+I4lrXA0+O8jzJXx/A= 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=FcMFlUpn; arc=none smtp.client-ip=209.85.214.201 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="FcMFlUpn" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-269af520712so44405865ad.2 for ; Sun, 05 Oct 2025 14:22:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699349; x=1760304149; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=fDQxJshrzMcNiF4ov5sFxJSEj5wisWjGXrUgTQiuK7I=; b=FcMFlUpndp5sInmz+zA9xLYJFRMm/CTgTtgtTNcOhjRvz4J0mgodt3RxPwrb0W38Pi gxg383Tcx+22FaNNcs86Quchuz4JH10ckxtRAKVKKwCH/r1HtydSBQi2aGujlrhRacxb D39JIG2QNgqU//gjQUah5e/UdOLOQSFYNrfPR2LV0U2EF5VQDnNIS9ChyM8fM7IvYyIa zKi3M7kMBfvuvDo613WLjYEaWghu4aotaByfaRc8iVueRqK1WLfofzH8Mcl6nm2JaoRk a5B3bNLQFow7k2C8J7qtVDcvEiYdH3HzO5X6kKRkj91ogrnOmT/m4x86SiO7ddy2ZZ0i EFNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699349; x=1760304149; h=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; bh=fDQxJshrzMcNiF4ov5sFxJSEj5wisWjGXrUgTQiuK7I=; b=s070wKoy5v6+Ao99vcGUDXQg3CiNnnoG/2RriXf6gmQitd58j7nhYM8hH4ajN54/Ej OBy8l7raCjIOEXfdfWkWebVfRUrTrp4tYAhf2hSS5poDyaDtp3xlTkitw14FWShTUEgp 4+Uph43J5vXhdSLCWzkD4ApUZOm+tC+lmThPvC/LQ92izbvnq44A1Me8iuwKo9vTyzcO /42jSRLtkF0Zv8zWDHB7kalaCWMDv80W5GnYqh5l10uPA8PqdT+2HfL/y67xsbzGaGsr ITXP5Rttk1vpylMx0QbiRlWzArRcTyW2aNzdkXRUmCGktt3kHoEBuj93zjioQMtimhl/ TRow== X-Forwarded-Encrypted: i=1; AJvYcCX3/x6NmaXikja/0KGdoOC7vUYDsOVJSA8jxK8hO4sBE5ci3K0FmBx1vDszJz0PHlP+uQ4Z0B0TXk+JWCc=@vger.kernel.org X-Gm-Message-State: AOJu0YxcG6//zlua049YmymZe1q5Cs9mxbjbn9XE1WrB5MNR+UwPDwUn C4sie0zJawjfyLm86XAvP4g6/rqRSVcS6StdcsJUglM4GGDX23dLHeaf4/Ckp62MzpOrEy7V18k m3eznpFCubw== X-Google-Smtp-Source: AGHT+IHNmdwNHNGJJio68vZQzxJW4gUw2wiEz4abGSKgXJDJaQ0VM0ja+fEKLhEkaSVx43BLmivRKC1zYmpG X-Received: from plps1.prod.google.com ([2002:a17:902:9881:b0:24c:966a:4a6b]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:2c0c:b0:24b:25f:5f81 with SMTP id d9443c01a7336-28e9a574b99mr129613255ad.17.1759699349121; Sun, 05 Oct 2025 14:22:29 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:05 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-5-irogers@google.com> Subject: [PATCH v7 04/11] perf dso: Support BPF programs in dso__read_symbol From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Set the buffer to the code in the BPF linear info. This enables BPF JIT code disassembly by LLVM and capstone. Move the common but minimal disassmble_bpf_image call to disassemble_objdump so that it is only called after falling back to the objdump option. Similarly move the disassmble_bpf function to disassemble_objdump and rename to disassmble_bpf_libbfd to make it clearer that this support relies on libbfd. Signed-off-by: Ian Rogers --- tools/perf/util/disasm.c | 12 +++-- tools/perf/util/dso.c | 100 ++++++++++++++++++++++++++------------- tools/perf/util/libbfd.c | 4 +- tools/perf/util/libbfd.h | 6 +-- 4 files changed, 80 insertions(+), 42 deletions(-) diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c index a1240543c89c..e64902e520ab 100644 --- a/tools/perf/util/disasm.c +++ b/tools/perf/util/disasm.c @@ -1521,6 +1521,12 @@ static int symbol__disassemble_objdump(const char *f= ilename, struct symbol *sym, struct child_process objdump_process; int err; =20 + if (dso__binary_type(dso) =3D=3D DSO_BINARY_TYPE__BPF_PROG_INFO) + return symbol__disassemble_bpf_libbfd(sym, args); + + if (dso__binary_type(dso) =3D=3D DSO_BINARY_TYPE__BPF_IMAGE) + return symbol__disassemble_bpf_image(sym, args); + err =3D asprintf(&command, "%s %s%s --start-address=3D0x%016" PRIx64 " --stop-address=3D0x%016" PRIx64 @@ -1655,11 +1661,7 @@ int symbol__disassemble(struct symbol *sym, struct a= nnotate_args *args) =20 pr_debug("annotating [%p] %30s : [%p] %30s\n", dso, dso__long_name(dso), = sym, sym->name); =20 - if (dso__binary_type(dso) =3D=3D DSO_BINARY_TYPE__BPF_PROG_INFO) { - return symbol__disassemble_bpf(sym, args); - } else if (dso__binary_type(dso) =3D=3D DSO_BINARY_TYPE__BPF_IMAGE) { - return symbol__disassemble_bpf_image(sym, args); - } else if (dso__binary_type(dso) =3D=3D DSO_BINARY_TYPE__NOT_FOUND) { + if (dso__binary_type(dso) =3D=3D DSO_BINARY_TYPE__NOT_FOUND) { return SYMBOL_ANNOTATE_ERRNO__COULDNT_DETERMINE_FILE_TYPE; } else if (dso__is_kcore(dso)) { kce.addr =3D map__rip_2objdump(map, sym->start); diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 87d075942de6..0aed5c8691bd 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1816,23 +1816,17 @@ static int find_file_offset(u64 start, u64 len, u64= pgoff, void *arg) return 0; } =20 -const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename, - const struct map *map, const struct symbol *sym, - u8 **out_buf, u64 *out_buf_len, bool *is_64bit) +static const u8 *__dso__read_symbol(struct dso *dso, const char *symfs_fil= ename, + u64 start, size_t len, + u8 **out_buf, u64 *out_buf_len, bool *is_64bit) { struct nscookie nsc; - u64 start =3D map__rip_2objdump(map, sym->start); - u64 end =3D map__rip_2objdump(map, sym->end); - int fd, count; - u8 *buf =3D NULL; - size_t len; + int fd; + ssize_t count; struct find_file_offset_data data =3D { .ip =3D start, }; - - *out_buf =3D NULL; - *out_buf_len =3D 0; - *is_64bit =3D false; + u8 *code_buf =3D NULL; =20 nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); fd =3D open(symfs_filename, O_RDONLY); @@ -1840,28 +1834,70 @@ const u8 *dso__read_symbol(struct dso *dso, const c= har *symfs_filename, if (fd < 0) return NULL; =20 - if (file__read_maps(fd, /*exe=3D*/true, find_file_offset, &data, is_64bit= ) =3D=3D 0) - goto err; - - len =3D end - start; - buf =3D malloc(len); - if (buf =3D=3D NULL) - goto err; - - count =3D pread(fd, buf, len, data.offset); + if (file__read_maps(fd, /*exe=3D*/true, find_file_offset, &data, is_64bit= ) =3D=3D 0) { + close(fd); + return NULL; + } + code_buf =3D malloc(len); + if (code_buf =3D=3D NULL) { + close(fd); + return NULL; + } + count =3D pread(fd, code_buf, len, data.offset); close(fd); - fd =3D -1; + if ((u64)count !=3D len) { + free(code_buf); + return NULL; + } + *out_buf =3D code_buf; + *out_buf_len =3D len; + return code_buf; +} =20 - if ((u64)count !=3D len) - goto err; +/* + * Read a symbol into memory for disassembly by a library like capstone of + * libLLVM. If memory is allocated out_buf holds it. + */ +const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename, + const struct map *map, const struct symbol *sym, + u8 **out_buf, u64 *out_buf_len, bool *is_64bit) +{ + u64 start =3D map__rip_2objdump(map, sym->start); + u64 end =3D map__rip_2objdump(map, sym->end); + size_t len =3D end - start; =20 - *out_buf =3D buf; - *out_buf_len =3D len; - return buf; + *out_buf =3D NULL; + *out_buf_len =3D 0; + *is_64bit =3D false; =20 -err: - if (fd >=3D 0) - close(fd); - free(buf); - return NULL; + if (dso__binary_type(dso) =3D=3D DSO_BINARY_TYPE__BPF_IMAGE) { + /* + * Note, there is fallback BPF image disassembly in the objdump + * version but it currently does nothing. + */ + return NULL; + } + if (dso__binary_type(dso) =3D=3D DSO_BINARY_TYPE__BPF_PROG_INFO) { +#ifdef HAVE_LIBBPF_SUPPORT + struct bpf_prog_info_node *info_node; + struct perf_bpil *info_linear; + + *is_64bit =3D sizeof(void *) =3D=3D sizeof(u64); + info_node =3D perf_env__find_bpf_prog_info(dso__bpf_prog(dso)->env, + dso__bpf_prog(dso)->id); + if (!info_node) { + errno =3D SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF; + return NULL; + } + info_linear =3D info_node->info_linear; + assert(len <=3D info_linear->info.jited_prog_len); + *out_buf_len =3D len; + return (const u8 *)(uintptr_t)(info_linear->info.jited_prog_insns); +#else + pr_debug("No BPF program disassembly support\n"); + return NULL; +#endif + } + return __dso__read_symbol(dso, symfs_filename, start, len, + out_buf, out_buf_len, is_64bit); } diff --git a/tools/perf/util/libbfd.c b/tools/perf/util/libbfd.c index 09a0eeb78a1a..01147fbf73b3 100644 --- a/tools/perf/util/libbfd.c +++ b/tools/perf/util/libbfd.c @@ -448,8 +448,8 @@ int libbfd_filename__read_debuglink(const char *filenam= e, char *debuglink, return err; } =20 -int symbol__disassemble_bpf(struct symbol *sym __maybe_unused, - struct annotate_args *args __maybe_unused) +int symbol__disassemble_bpf_libbfd(struct symbol *sym __maybe_unused, + struct annotate_args *args __maybe_unused) { #ifdef HAVE_LIBBPF_SUPPORT struct annotation *notes =3D symbol__annotation(sym); diff --git a/tools/perf/util/libbfd.h b/tools/perf/util/libbfd.h index 7441e95f8ec0..e300f171d1bd 100644 --- a/tools/perf/util/libbfd.h +++ b/tools/perf/util/libbfd.h @@ -29,7 +29,7 @@ int libbfd__read_build_id(const char *filename, struct bu= ild_id *bid, bool block =20 int libbfd_filename__read_debuglink(const char *filename, char *debuglink,= size_t size); =20 -int symbol__disassemble_bpf(struct symbol *sym, struct annotate_args *args= ); +int symbol__disassemble_bpf_libbfd(struct symbol *sym, struct annotate_arg= s *args); =20 #else // !defined(HAVE_LIBBFD_SUPPORT) #include "annotate.h" @@ -72,8 +72,8 @@ static inline int libbfd_filename__read_debuglink(const c= har *filename __always_ return -1; } =20 -static inline int symbol__disassemble_bpf(struct symbol *sym __always_unus= ed, - struct annotate_args *args __always_unused) +static inline int symbol__disassemble_bpf_libbfd(struct symbol *sym __alwa= ys_unused, + struct annotate_args *args __always_unused) { return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF; } --=20 2.51.0.618.g983fd99d29-goog From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (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 C69B82C08B1 for ; Sun, 5 Oct 2025 21:22:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699353; cv=none; b=Xu5DgVlQ6KzUoxXNYMRJsQ84SzNkVp4KwAEt1dRmZZNZuTOzqWAYM3PCMhRgm0HgJatHFGfCDKD5RMTLMfIiwaemIAUS9LAb74P4snjXxeaVxz5hH2TLVFNhJJC9qLjJvjxBX9G+xrPextE4dWl9bEHoxvwbWWyibNG+VKrKGmc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699353; c=relaxed/simple; bh=Apk/dx4vry6NQH8mEaGDTQ4foAvl3cC+7BrNRcZnR4k=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=rbLVBrGnXX9I6etXoY5QoNTZYBzHZurzCC3Ew7HQrx/BYSvOcJQqIwfI1qdf7iCs2kGHmM+Tq2Hl6hWQKeFTfl9dwwMu0cJvU50j/pzZJseNL8cPRw33UaMx1i9LVGAb3wiqdlkFMjQzNfupRUDlIC236VAlaF5K+B4cVrIfqPA= 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=Qojujbkf; arc=none smtp.client-ip=209.85.214.202 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="Qojujbkf" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-286a252bfbfso83842355ad.3 for ; Sun, 05 Oct 2025 14:22:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699351; x=1760304151; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=DCU0ELaC9EV+pXq9bhGKOQtESKkLJzIPHgh+H1HErVM=; b=QojujbkfO5KiFAtldBpCsGcEmNRwxdIk1ERELte4Y78gihIoIZsWvq3zjLPWPIO6X8 4otoWE+vzvRAnp+8Sn9v9DtNO/VsHqRMg2kSpmWLSOJSsOyTbt+bP82ELLcdLeA17kly 5aPIa4j8KsdsXiL1yo67669f5H5GLMk1rTACliY47QtjYAo18DbyLwVeiwTrhFsnlutO HeyG/jvvY6UI6mHzN0afI2CIGDdSLdkOdpam7C4YB7zxOAZkx4wkB/j7Hs7qBbjJZMdI hhNb4ucf1GFO3ksVowYg0iDJwlGMtRb1TsMgsDACje2N239YlZFQ3d3Fage0IqFGtoU/ bo+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699351; x=1760304151; h=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; bh=DCU0ELaC9EV+pXq9bhGKOQtESKkLJzIPHgh+H1HErVM=; b=AhXwsjM/b/MPPAp8IkKLXlX0LF/u4wdIC3L5P2R4oD2O9pu8qKF2K5UJfv5RaT7MqZ HYn87z+v1oUP05icfrL9b+8yVWTt3cUmxPe1DXnhcpCJWlIG+5iRwsyDrIC3BiC+gkQi 4VUWXw6FWSySzBF5p5HQPTGLLsAJbpBlUvV2qRjY8wuwmqMpN/WNwzK48fVDqjf6WBTD Fg49AeoItxdXb5nHea0CkRWd0+YcCUTlvTYtA00e+A8ZyZnW8UOUxgFGbHbY4atw109q e15xx6htyWqXakeY0lc7BY5K/AWCP/7fAoJg0H+0QV2hUExwfLx2dC9Lr+9C1Y4r2dVS AJvQ== X-Forwarded-Encrypted: i=1; AJvYcCXH9t59N5tVnWatSM6qokOLJEBhUAkJHBX2ZspWhm6MyuQmyl7F0orLZ/lVUQXjRLO0Ab2PTHpda4X3c54=@vger.kernel.org X-Gm-Message-State: AOJu0YxnPc2pajtXI8l0mpgopRWjKfzea1vIx+WKYi5GYiqOdGMt39xx 2lTEd6gq3PMXFYQc6K94xJ/UBQ35TSimPJ0b+sdISctWFKpzugd9mVXfr/KC2YuO8R8e96iBtMb 0EZ/TN1/4eQ== X-Google-Smtp-Source: AGHT+IEObakE2dl7ZB3J7e6NcFFPXma/CZs3oBgvcFiNAqIU+hl2VJBrud9gEmmuxGfQ8861tRaCUUzuXCrN X-Received: from plpa4.prod.google.com ([2002:a17:902:9004:b0:28e:804c:cc96]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:2b04:b0:27e:ed58:25e5 with SMTP id d9443c01a7336-28e9a5b037fmr121304265ad.24.1759699351184; Sun, 05 Oct 2025 14:22:31 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:06 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-6-irogers@google.com> Subject: [PATCH v7 05/11] perf dso: Clean up read_symbol error handling From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Ensure errno is set and return to caller for error handling. Unusually for perf the value isn't negated as expected by symbol__strerror_disassemble. Signed-off-by: Ian Rogers --- tools/perf/util/capstone.c | 3 ++- tools/perf/util/dso.c | 15 ++++++++++++--- tools/perf/util/llvm.c | 3 ++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/capstone.c b/tools/perf/util/capstone.c index c23df911e91c..be5fd44b1f9d 100644 --- a/tools/perf/util/capstone.c +++ b/tools/perf/util/capstone.c @@ -11,6 +11,7 @@ #include "print_insn.h" #include "symbol.h" #include "thread.h" +#include #include #include =20 @@ -245,7 +246,7 @@ int symbol__disassemble_capstone(const char *filename _= _maybe_unused, buf =3D dso__read_symbol(dso, filename, map, sym, &code_buf, &buf_len, &is_64bit); if (buf =3D=3D NULL) - return -1; + return errno; =20 /* add the function address and name */ scnprintf(disasm_buf, sizeof(disasm_buf), "%#"PRIx64" <%s>:", diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 0aed5c8691bd..344e689567ee 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1827,26 +1827,33 @@ static const u8 *__dso__read_symbol(struct dso *dso= , const char *symfs_filename, .ip =3D start, }; u8 *code_buf =3D NULL; + int saved_errno; =20 nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); fd =3D open(symfs_filename, O_RDONLY); + saved_errno =3D errno; nsinfo__mountns_exit(&nsc); - if (fd < 0) + if (fd < 0) { + errno =3D saved_errno; return NULL; - - if (file__read_maps(fd, /*exe=3D*/true, find_file_offset, &data, is_64bit= ) =3D=3D 0) { + } + if (file__read_maps(fd, /*exe=3D*/true, find_file_offset, &data, is_64bit= ) <=3D 0) { close(fd); + errno =3D ENOENT; return NULL; } code_buf =3D malloc(len); if (code_buf =3D=3D NULL) { close(fd); + errno =3D ENOMEM; return NULL; } count =3D pread(fd, code_buf, len, data.offset); + saved_errno =3D errno; close(fd); if ((u64)count !=3D len) { free(code_buf); + errno =3D saved_errno; return NULL; } *out_buf =3D code_buf; @@ -1875,6 +1882,7 @@ const u8 *dso__read_symbol(struct dso *dso, const cha= r *symfs_filename, * Note, there is fallback BPF image disassembly in the objdump * version but it currently does nothing. */ + errno =3D EOPNOTSUPP; return NULL; } if (dso__binary_type(dso) =3D=3D DSO_BINARY_TYPE__BPF_PROG_INFO) { @@ -1895,6 +1903,7 @@ const u8 *dso__read_symbol(struct dso *dso, const cha= r *symfs_filename, return (const u8 *)(uintptr_t)(info_linear->info.jited_prog_insns); #else pr_debug("No BPF program disassembly support\n"); + errno =3D EOPNOTSUPP; return NULL; #endif } diff --git a/tools/perf/util/llvm.c b/tools/perf/util/llvm.c index 0369f3adcdb6..2351393e33c5 100644 --- a/tools/perf/util/llvm.c +++ b/tools/perf/util/llvm.c @@ -7,6 +7,7 @@ #include "namespaces.h" #include "srcline.h" #include "symbol.h" +#include #include #include #include @@ -147,7 +148,7 @@ int symbol__disassemble_llvm(const char *filename, stru= ct symbol *sym, buf =3D dso__read_symbol(dso, filename, map, sym, &code_buf, &buf_len, &is_64bit); if (buf =3D=3D NULL) - return -1; + return errno; =20 init_llvm(); if (arch__is(args->arch, "x86")) { --=20 2.51.0.618.g983fd99d29-goog From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.202]) (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 0CC522C0F7C for ; Sun, 5 Oct 2025 21:22:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699355; cv=none; b=H5MY9H+YKw9oY5C9bRTglHWUUga9+dEnTrEgzjRU6XtHGt9QSKa/1nv/Ref7AUuKIEgTV0LI9R2E0+0uj6UN0etf0j5jRjOA5ws97uhBksUB/gRQmAGEGOwmQTb3yRk5YDEQsV3y9cAq7/l3ZswAOAJmA/hPMcig/0dD96qKKpc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699355; c=relaxed/simple; bh=WlZay7JBScKarmUmUW5W4rt0ZQNci9N/og2V+ODkwEE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=pEWwu1zWSbPHX+wEXkM1ZspYdKyUeMFfGtMGTvvKNEyoYZbXTU6H0NZG5cgQ1vuvYYtbupqcbi4uC7J5wfIx3voT4BrRxQWy25GbxzkZDCwXfDF6xNEHJM5CBz3X5aeNsVMaGcN4jS001lc841MasLRVQJIxef2XZ5J2vf0l5xY= 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=0rfF4aoE; arc=none smtp.client-ip=209.85.210.202 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="0rfF4aoE" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-77f5e6a324fso6416929b3a.0 for ; Sun, 05 Oct 2025 14:22:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699353; x=1760304153; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=wulS2NGvKURng0Egd2IGwMyFIkt/Pg3ipSmNBN6RrB4=; b=0rfF4aoEG5vsKg6z2lCfbHy9iPfb3X2nhejGwhUaXIG+h+SpERjF6P3elhAr+nDhsJ EI+/RtNRXreFDg1y7vX6uhLARYWQ8i73rqKfCIdzaEGERKx4bzk9jM+PCiR8xyQcNLAj 7OgXIMiGWKGxbBOcj1ojnO9rngadVW5aToVN0KJZCmMDqLNccZc669fZW1qrcJ5fNwQh YUaeI/XpU/eBqi+wJdyv+74rhGSWTduWYAXfpJ6NscnPSa2w28lLEk6RFiOY/37pRwBo lKHJaTxfFP5DrjF6+bpC+yk2eutH5/jeBPPsCoWzT+ASCGba4BQ8ghdT3zkzJn/xGZKu Ed4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699353; x=1760304153; h=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; bh=wulS2NGvKURng0Egd2IGwMyFIkt/Pg3ipSmNBN6RrB4=; b=gYtIqtejMaCIJDlY2WsHe0a2dmc1fRhUPQRlYEBrXHSg+EIbzU3b6mjXkPmQsMSWb5 tn9ecuMvcRejK9HuK50K1lv8yK9wVlGFbPAfu/OyMza+xy3xcQxsjfUKtFGrBxLC1h3m 0kcAJR2uxjWDi74US9+qlOD9Lx4q7tQCxf8uo29phmqKIO2CqapcakSVm0qVuurztpRJ SLWy4cUGW41wY+SA5b42SLwjCF4+CHnI3YvZHc/7t0C4rM2j2gFBcmLCgcm+srJmgtRb JOF7H5qiGMVtEXxw0+GG0TDUdU4Y6PltmR0bPOPRSAJBF/Y6YzOgfhnIS8htdv3U6uO+ aoXA== X-Forwarded-Encrypted: i=1; AJvYcCWfZhKwjOpzSLGYyZ4Mw6xF5qEQ8rU7ZQ0p6raKMkUMpnhOWBpZkDDw/UZNkyR4L7t9sPap6UHg0VEz+ug=@vger.kernel.org X-Gm-Message-State: AOJu0YwKFy193AT+QFAbOV4qbkiz7Eq/lCjCB1B/Vgi4W3if4IrQtb8m E8/AV/RgqTSPk4g8XRJ0pMokreVKIlbpd8UGftpQdbmG+r6b+KHO3AYMJ/NB27E8XGjvWliaMCy uLEuXG8kKkw== X-Google-Smtp-Source: AGHT+IGisVDrX4jLxBH+/IAg/iMlAvXEniLcqb7zAD7YH4cEtUgSeVtwpZqI4UICoBZYGGFSpiSyYOt983pn X-Received: from pgnr5.prod.google.com ([2002:a63:8f45:0:b0:b62:8092:7d58]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:7f90:b0:2c0:227b:13ea with SMTP id adf61e73a8af0-32b61e5c57emr14386613637.22.1759699353384; Sun, 05 Oct 2025 14:22:33 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:07 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-7-irogers@google.com> Subject: [PATCH v7 06/11] perf disasm: Make ins__scnprintf and ins__is_nop static From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Reduce the scope of ins__scnprintf and ins__is_nop that aren't used outside of disasm.c. Signed-off-by: Ian Rogers --- tools/perf/util/disasm.c | 6 +++--- tools/perf/util/disasm.h | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c index e64902e520ab..50b9433f3f8e 100644 --- a/tools/perf/util/disasm.c +++ b/tools/perf/util/disasm.c @@ -247,8 +247,8 @@ static int ins__raw_scnprintf(struct ins *ins, char *bf= , size_t size, return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->raw); } =20 -int ins__scnprintf(struct ins *ins, char *bf, size_t size, - struct ins_operands *ops, int max_ins_name) +static int ins__scnprintf(struct ins *ins, char *bf, size_t size, + struct ins_operands *ops, int max_ins_name) { if (ins->ops->scnprintf) return ins->ops->scnprintf(ins, bf, size, ops, max_ins_name); @@ -828,7 +828,7 @@ static struct ins_ops ret_ops =3D { .scnprintf =3D ins__raw_scnprintf, }; =20 -bool ins__is_nop(const struct ins *ins) +static bool ins__is_nop(const struct ins *ins) { return ins->ops =3D=3D &nop_ops; } diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h index 2cb4e1a6bd30..09c86f540f7f 100644 --- a/tools/perf/util/disasm.h +++ b/tools/perf/util/disasm.h @@ -110,13 +110,10 @@ struct arch *arch__find(const char *name); bool arch__is(struct arch *arch, const char *name); =20 struct ins_ops *ins__find(struct arch *arch, const char *name, struct disa= sm_line *dl); -int ins__scnprintf(struct ins *ins, char *bf, size_t size, - struct ins_operands *ops, int max_ins_name); =20 bool ins__is_call(const struct ins *ins); bool ins__is_jump(const struct ins *ins); bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2); -bool ins__is_nop(const struct ins *ins); bool ins__is_ret(const struct ins *ins); bool ins__is_lock(const struct ins *ins); =20 --=20 2.51.0.618.g983fd99d29-goog From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (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 374C32C11FB for ; Sun, 5 Oct 2025 21:22:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699359; cv=none; b=EWSq3gErek8P5wo3uJe8tgdebZ5X/kbWAKRpdLTqxJemEoNnmdWT95oGG/YkZQiiisR7RwmJEYwGXR9hvgGH/fqSStx2j9JpT2HXT4KPfk+sD61ds9Myv3IT4tRTyWS4IOPmu0k8RN6TNkY8M4LJvDGjzPKOp9OZN9dvLFXJCGs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699359; c=relaxed/simple; bh=BiTq4fssAm6mOmNgnub5TZ1Ugc7+SEH09i/QbCY9KbA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=TuTLJpdKaETqxgX0h3wjVPKnLMhVdqNaevJOPF4mjxkcHBTHtCbRVR5YeUabLCVMyS9idSU3gi763eXc9whL9r7mMrrykSXV9CqT52GszHSTKu4OB0MXRuKipf/Cyy/lLajIYe7rjYHTajGmcX8dnaFCRCy6GWc7bUe9QcBiX40= 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=MjBB6XQm; arc=none smtp.client-ip=209.85.214.202 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="MjBB6XQm" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-27356178876so26300485ad.1 for ; Sun, 05 Oct 2025 14:22:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699356; x=1760304156; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=2cA3lKnCtBfH4M0wODrAsUo3j0OeWCdqHdGSVaUVEmE=; b=MjBB6XQmjziqd+LZUT6QLt4AA8F1hhat556N0T+QBmhwlbryajUl5z4PTlU2Xr5VcP D++zEzaF2tWqa5Hqsm7aeQzT83p2QXgSkFFsRG8WxW8RFZNhJPA7epjq8ooEjL+z//VF JcoAoWMY/M7dWh3EI5VwOC9ft0tUNQNU6l2WQp6LOLaJ7b7nTl9AI07eYi61lYoww0C4 o6eRI5/jQpBymKM7CBh+tUdeX80mMBRydYbBevzr2+No9EBadPhzMbtPpfqlJ0SGb6jp +Jn4rH0O7Sk/Ei+URojnBU+AQH591juAlEsyXohol/9BIjWtdEGLjrD7MXPYvw2u4HQJ r5fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699356; x=1760304156; h=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; bh=2cA3lKnCtBfH4M0wODrAsUo3j0OeWCdqHdGSVaUVEmE=; b=cWGAZgCU0tt3sbNUOGncyeAAS5JVZ5CjRHNgIQ3IkAS61xiPE8Jz7oN7sZTziNbTwy arnsw7e0JS3MCFLMus+eFXi7COYrXikxBt9LG7IVDU6vClOJwzRXmJvkhtFPGoHjJDjQ 1huZzMHgsWksteiMQkued9/oPnHeFhWrTTsLSor1YFI5bkSsSPsW/e50g9DPN4EpgG7f mQKeZQk7EMk3ascwlNqB6oDW896kMX4HtW+46EAxa4wmJqUs/olZt5hBbm8jeSMqhram yOeOkQD/PqFx+HayCgqhdjYzfvY3JnVpybegEB8gLrbuXk3fprC3bfBG+j6R+tVVEHkW tBvQ== X-Forwarded-Encrypted: i=1; AJvYcCWpFkcnzwptPQy4su+AcRVSNXuyiZzhR6rHznS47oMp67nVBCOlt0sKIdqwF7bddC2+k/0oNmBl6IJQ2xQ=@vger.kernel.org X-Gm-Message-State: AOJu0YyzuSui2pthjZNWdj//c6U05ipg9cx3EutmGA3+sWNq3CglF1dK dJgubpS/n/ScatCcC2yOdwkBBAJ4xK/s/hQ7l9UBE2gT24gWyqC9SAg/kx4tVjSSh+80HHAZg4M YfCwS7xMB5w== X-Google-Smtp-Source: AGHT+IFvXBMVV5w/AF3VWxrW+XaOVbikBXiXWPFa7SjtjiGiK3DgGiu8R0bOo2AB4r2nTW1zud3tsLDsT+GV X-Received: from plsp10.prod.google.com ([2002:a17:902:bd0a:b0:267:a5c9:8a4c]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:f693:b0:269:96db:94f with SMTP id d9443c01a7336-28e9a635959mr133768165ad.49.1759699355633; Sun, 05 Oct 2025 14:22:35 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:08 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-8-irogers@google.com> Subject: [PATCH v7 07/11] perf srcline: Fallback between addr2line implementations From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Factor the addr2line function implementation into separate source files (addr2line.[ch]) and rename the addr2line function cmd__addr2line. In srcline replace the ifdef-ed addr2line implementations with one that first tries the llvm__addr2line implementation, then the deprecated libbfd__addr2line function and on failure uses cmd__addr2line. If HAVE_LIBLLVM_SUPPORT is enabled the llvm__addr2line will execute against the libLLVM.so it is linked against. If HAVE_LIBLLVM_DYNAMIC is enabled then libperf-llvm.so (that links against libLLVM.so) will be dlopened. If the dlopen succeeds then the behavior should match HAVE_LIBLLVM_SUPPORT. On failure cmd__addr2line is used. The dlopen is only tried once. If HAVE_LIBLLVM_DYNAMIC isn't enabled then llvm__addr2line immediately fails and cmd__addr2line is used. Clean up the dso__free_a2l logic, which is only needed in the non-LLVM version and moved to addr2line.c. Signed-off-by: Ian Rogers --- tools/perf/util/Build | 1 + tools/perf/util/addr2line.c | 439 ++++++++++++++++++++++++++++++++ tools/perf/util/addr2line.h | 20 ++ tools/perf/util/config.c | 2 +- tools/perf/util/llvm.c | 5 - tools/perf/util/llvm.h | 3 - tools/perf/util/srcline.c | 495 ++---------------------------------- tools/perf/util/srcline.h | 1 - 8 files changed, 485 insertions(+), 481 deletions(-) create mode 100644 tools/perf/util/addr2line.c create mode 100644 tools/perf/util/addr2line.h diff --git a/tools/perf/util/Build b/tools/perf/util/Build index e6b396d919bb..4be313cd115a 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -2,6 +2,7 @@ include $(srctree)/tools/scripts/Makefile.include include $(srctree)/tools/scripts/utilities.mak =20 perf-util-y +=3D arm64-frame-pointer-unwind-support.o +perf-util-y +=3D addr2line.o perf-util-y +=3D addr_location.o perf-util-y +=3D annotate.o perf-util-y +=3D block-info.o diff --git a/tools/perf/util/addr2line.c b/tools/perf/util/addr2line.c new file mode 100644 index 000000000000..f2d94a3272d7 --- /dev/null +++ b/tools/perf/util/addr2line.c @@ -0,0 +1,439 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "addr2line.h" +#include "debug.h" +#include "dso.h" +#include "string2.h" +#include "srcline.h" +#include "symbol.h" +#include "symbol_conf.h" + +#include +#include +#include + +#include +#include +#include +#include + +#define MAX_INLINE_NEST 1024 + +/* If addr2line doesn't return data for 1 second then timeout. */ +int addr2line_timeout_ms =3D 1 * 1000; + +static int filename_split(char *filename, unsigned int *line_nr) +{ + char *sep; + + sep =3D strchr(filename, '\n'); + if (sep) + *sep =3D '\0'; + + if (!strcmp(filename, "??:0")) + return 0; + + sep =3D strchr(filename, ':'); + if (sep) { + *sep++ =3D '\0'; + *line_nr =3D strtoul(sep, NULL, 0); + return 1; + } + pr_debug("addr2line missing ':' in filename split\n"); + return 0; +} + +static void addr2line_subprocess_cleanup(struct child_process *a2l) +{ + if (a2l->pid !=3D -1) { + kill(a2l->pid, SIGKILL); + finish_command(a2l); /* ignore result, we don't care */ + a2l->pid =3D -1; + close(a2l->in); + close(a2l->out); + } + + free(a2l); +} + +static struct child_process *addr2line_subprocess_init(const char *addr2li= ne_path, + const char *binary_path) +{ + const char *argv[] =3D { + addr2line_path ?: "addr2line", + "-e", binary_path, + "-a", "-i", "-f", NULL + }; + struct child_process *a2l =3D zalloc(sizeof(*a2l)); + int start_command_status =3D 0; + + if (a2l =3D=3D NULL) { + pr_err("Failed to allocate memory for addr2line"); + return NULL; + } + + a2l->pid =3D -1; + a2l->in =3D -1; + a2l->out =3D -1; + a2l->no_stderr =3D 1; + + a2l->argv =3D argv; + start_command_status =3D start_command(a2l); + a2l->argv =3D NULL; /* it's not used after start_command; avoid dangling = pointers */ + + if (start_command_status !=3D 0) { + pr_warning("could not start addr2line (%s) for %s: start_command return = code %d\n", + addr2line_path, binary_path, start_command_status); + addr2line_subprocess_cleanup(a2l); + return NULL; + } + + return a2l; +} + +enum a2l_style { + BROKEN, + GNU_BINUTILS, + LLVM, +}; + +static enum a2l_style addr2line_configure(struct child_process *a2l, const= char *dso_name) +{ + static bool cached; + static enum a2l_style style; + + if (!cached) { + char buf[128]; + struct io io; + int ch; + int lines; + + if (write(a2l->in, ",\n", 2) !=3D 2) + return BROKEN; + + io__init(&io, a2l->out, buf, sizeof(buf)); + ch =3D io__get_char(&io); + if (ch =3D=3D ',') { + style =3D LLVM; + cached =3D true; + lines =3D 1; + pr_debug3("Detected LLVM addr2line style\n"); + } else if (ch =3D=3D '0') { + style =3D GNU_BINUTILS; + cached =3D true; + lines =3D 3; + pr_debug3("Detected binutils addr2line style\n"); + } else { + if (!symbol_conf.disable_add2line_warn) { + char *output =3D NULL; + size_t output_len; + + io__getline(&io, &output, &output_len); + pr_warning("%s %s: addr2line configuration failed\n", + __func__, dso_name); + pr_warning("\t%c%s", ch, output); + } + pr_debug("Unknown/broken addr2line style\n"); + return BROKEN; + } + while (lines) { + ch =3D io__get_char(&io); + if (ch <=3D 0) + break; + if (ch =3D=3D '\n') + lines--; + } + /* Ignore SIGPIPE in the event addr2line exits. */ + signal(SIGPIPE, SIG_IGN); + } + return style; +} + +static int read_addr2line_record(struct io *io, + enum a2l_style style, + const char *dso_name, + u64 addr, + bool first, + char **function, + char **filename, + unsigned int *line_nr) +{ + /* + * Returns: + * -1 =3D=3D> error + * 0 =3D=3D> sentinel (or other ill-formed) record read + * 1 =3D=3D> a genuine record read + */ + char *line =3D NULL; + size_t line_len =3D 0; + unsigned int dummy_line_nr =3D 0; + int ret =3D -1; + + if (function !=3D NULL) + zfree(function); + + if (filename !=3D NULL) + zfree(filename); + + if (line_nr !=3D NULL) + *line_nr =3D 0; + + /* + * Read the first line. Without an error this will be: + * - for the first line an address like 0x1234, + * - the binutils sentinel 0x0000000000000000, + * - the llvm-addr2line the sentinel ',' character, + * - the function name line for an inlined function. + */ + if (io__getline(io, &line, &line_len) < 0 || !line_len) + goto error; + + pr_debug3("%s %s: addr2line read address for sentinel: %s", __func__, dso= _name, line); + if (style =3D=3D LLVM && line_len =3D=3D 2 && line[0] =3D=3D ',') { + /* Found the llvm-addr2line sentinel character. */ + zfree(&line); + return 0; + } else if (style =3D=3D GNU_BINUTILS && (!first || addr !=3D 0)) { + int zero_count =3D 0, non_zero_count =3D 0; + /* + * Check for binutils sentinel ignoring it for the case the + * requested address is 0. + */ + + /* A given address should always start 0x. */ + if (line_len >=3D 2 || line[0] !=3D '0' || line[1] !=3D 'x') { + for (size_t i =3D 2; i < line_len; i++) { + if (line[i] =3D=3D '0') + zero_count++; + else if (line[i] !=3D '\n') + non_zero_count++; + } + if (!non_zero_count) { + int ch; + + if (first && !zero_count) { + /* Line was erroneous just '0x'. */ + goto error; + } + /* + * Line was 0x0..0, the sentinel for binutils. Remove + * the function and filename lines. + */ + zfree(&line); + do { + ch =3D io__get_char(io); + } while (ch > 0 && ch !=3D '\n'); + do { + ch =3D io__get_char(io); + } while (ch > 0 && ch !=3D '\n'); + return 0; + } + } + } + /* Read the second function name line (if inline data then this is the fi= rst line). */ + if (first && (io__getline(io, &line, &line_len) < 0 || !line_len)) + goto error; + + pr_debug3("%s %s: addr2line read line: %s", __func__, dso_name, line); + if (function !=3D NULL) + *function =3D strdup(strim(line)); + + zfree(&line); + line_len =3D 0; + + /* Read the third filename and line number line. */ + if (io__getline(io, &line, &line_len) < 0 || !line_len) + goto error; + + pr_debug3("%s %s: addr2line filename:number : %s", __func__, dso_name, li= ne); + if (filename_split(line, line_nr =3D=3D NULL ? &dummy_line_nr : line_nr) = =3D=3D 0 && + style =3D=3D GNU_BINUTILS) { + ret =3D 0; + goto error; + } + + if (filename !=3D NULL) + *filename =3D strdup(line); + + zfree(&line); + line_len =3D 0; + + return 1; + +error: + free(line); + if (function !=3D NULL) + zfree(function); + if (filename !=3D NULL) + zfree(filename); + return ret; +} + +static int inline_list__append_record(struct dso *dso, + struct inline_node *node, + struct symbol *sym, + const char *function, + const char *filename, + unsigned int line_nr) +{ + struct symbol *inline_sym =3D new_inline_sym(dso, sym, function); + + return inline_list__append(inline_sym, srcline_from_fileline(filename, li= ne_nr), node); +} + +int cmd__addr2line(const char *dso_name, u64 addr, + char **file, unsigned int *line_nr, + struct dso *dso, + bool unwind_inlines, + struct inline_node *node, + struct symbol *sym __maybe_unused) +{ + struct child_process *a2l =3D dso__a2l(dso); + char *record_function =3D NULL; + char *record_filename =3D NULL; + unsigned int record_line_nr =3D 0; + int record_status =3D -1; + int ret =3D 0; + size_t inline_count =3D 0; + int len; + char buf[128]; + ssize_t written; + struct io io =3D { .eof =3D false }; + enum a2l_style a2l_style; + + if (!a2l) { + if (!filename__has_section(dso_name, ".debug_line")) + goto out; + + dso__set_a2l(dso, + addr2line_subprocess_init(symbol_conf.addr2line_path, dso_name)); + a2l =3D dso__a2l(dso); + } + + if (a2l =3D=3D NULL) { + if (!symbol_conf.disable_add2line_warn) + pr_warning("%s %s: addr2line_subprocess_init failed\n", __func__, dso_n= ame); + goto out; + } + a2l_style =3D addr2line_configure(a2l, dso_name); + if (a2l_style =3D=3D BROKEN) + goto out; + + /* + * Send our request and then *deliberately* send something that can't be + * interpreted as a valid address to ask addr2line about (namely, + * ","). This causes addr2line to first write out the answer to our + * request, in an unbounded/unknown number of records, and then to write + * out the lines "0x0...0", "??" and "??:0", for GNU binutils, or "," + * for llvm-addr2line, so that we can detect when it has finished giving + * us anything useful. + */ + len =3D snprintf(buf, sizeof(buf), "%016"PRIx64"\n,\n", addr); + written =3D len > 0 ? write(a2l->in, buf, len) : -1; + if (written !=3D len) { + if (!symbol_conf.disable_add2line_warn) + pr_warning("%s %s: could not send request\n", __func__, dso_name); + goto out; + } + io__init(&io, a2l->out, buf, sizeof(buf)); + io.timeout_ms =3D addr2line_timeout_ms; + switch (read_addr2line_record(&io, a2l_style, dso_name, addr, /*first=3D*= /true, + &record_function, &record_filename, &record_line_nr)) { + case -1: + if (!symbol_conf.disable_add2line_warn) + pr_warning("%s %s: could not read first record\n", __func__, dso_name); + goto out; + case 0: + /* + * The first record was invalid, so return failure, but first + * read another record, since we sent a sentinel ',' for the + * sake of detected the last inlined function. Treat this as the + * first of a record as the ',' generates a new start with GNU + * binutils, also force a non-zero address as we're no longer + * reading that record. + */ + switch (read_addr2line_record(&io, a2l_style, dso_name, + /*addr=3D*/1, /*first=3D*/true, + NULL, NULL, NULL)) { + case -1: + if (!symbol_conf.disable_add2line_warn) + pr_warning("%s %s: could not read sentinel record\n", + __func__, dso_name); + break; + case 0: + /* The sentinel as expected. */ + break; + default: + if (!symbol_conf.disable_add2line_warn) + pr_warning("%s %s: unexpected record instead of sentinel", + __func__, dso_name); + break; + } + goto out; + default: + /* First record as expected. */ + break; + } + + if (file) { + *file =3D strdup(record_filename); + ret =3D 1; + } + if (line_nr) + *line_nr =3D record_line_nr; + + if (unwind_inlines) { + if (node && inline_list__append_record(dso, node, sym, + record_function, + record_filename, + record_line_nr)) { + ret =3D 0; + goto out; + } + } + + /* + * We have to read the records even if we don't care about the inline + * info. This isn't the first record and force the address to non-zero + * as we're reading records beyond the first. + */ + while ((record_status =3D read_addr2line_record(&io, + a2l_style, + dso_name, + /*addr=3D*/1, + /*first=3D*/false, + &record_function, + &record_filename, + &record_line_nr)) =3D=3D 1) { + if (unwind_inlines && node && inline_count++ < MAX_INLINE_NEST) { + if (inline_list__append_record(dso, node, sym, + record_function, + record_filename, + record_line_nr)) { + ret =3D 0; + goto out; + } + ret =3D 1; /* found at least one inline frame */ + } + } + +out: + free(record_function); + free(record_filename); + if (io.eof) { + dso__set_a2l(dso, NULL); + addr2line_subprocess_cleanup(a2l); + } + return ret; +} + +void dso__free_a2l(struct dso *dso) +{ + struct child_process *a2l =3D dso__a2l(dso); + + if (!a2l) + return; + + addr2line_subprocess_cleanup(a2l); + + dso__set_a2l(dso, NULL); +} diff --git a/tools/perf/util/addr2line.h b/tools/perf/util/addr2line.h new file mode 100644 index 000000000000..d35a47ba8dab --- /dev/null +++ b/tools/perf/util/addr2line.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PERF_ADDR2LINE_H +#define __PERF_ADDR2LINE_H + +#include + +struct dso; +struct inline_node; +struct symbol; + +extern int addr2line_timeout_ms; + +int cmd__addr2line(const char *dso_name, u64 addr, + char **file, unsigned int *line_nr, + struct dso *dso, + bool unwind_inlines, + struct inline_node *node, + struct symbol *sym); + +#endif /* __PERF_ADDR2LINE_H */ diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index ae72b66b6ded..6f914620c6ff 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -19,7 +19,7 @@ #include "util/hist.h" /* perf_hist_config */ #include "util/stat.h" /* perf_stat__set_big_num */ #include "util/evsel.h" /* evsel__hw_names, evsel__use_bpf_counters */ -#include "util/srcline.h" /* addr2line_timeout_ms */ +#include "util/addr2line.h" /* addr2line_timeout_ms */ #include "build-id.h" #include "debug.h" #include "config.h" diff --git a/tools/perf/util/llvm.c b/tools/perf/util/llvm.c index 2351393e33c5..565cad1969e5 100644 --- a/tools/perf/util/llvm.c +++ b/tools/perf/util/llvm.c @@ -70,11 +70,6 @@ int llvm__addr2line(const char *dso_name __maybe_unused,= u64 addr __maybe_unused #endif } =20 -void dso__free_a2l_llvm(struct dso *dso __maybe_unused) -{ - /* Nothing to free. */ -} - static void init_llvm(void) { static bool init; diff --git a/tools/perf/util/llvm.h b/tools/perf/util/llvm.h index 8aa19bb6b068..57f6bafb24bb 100644 --- a/tools/perf/util/llvm.h +++ b/tools/perf/util/llvm.h @@ -15,9 +15,6 @@ int llvm__addr2line(const char *dso_name, u64 addr, bool unwind_inlines, struct inline_node *node, struct symbol *sym); =20 - -void dso__free_a2l_llvm(struct dso *dso); - int symbol__disassemble_llvm(const char *filename, struct symbol *sym, struct annotate_args *args); =20 diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index 23b942d4729e..27c0966611ab 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -1,30 +1,15 @@ // SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "util/dso.h" -#include "util/debug.h" -#include "util/callchain.h" -#include "util/symbol_conf.h" -#include "llvm.h" #include "srcline.h" -#include "string2.h" +#include "addr2line.h" +#include "dso.h" +#include "callchain.h" +#include "libbfd.h" +#include "llvm.h" #include "symbol.h" -#include "subcmd/run-command.h" =20 -/* If addr2line doesn't return data for 1 second then timeout. */ -int addr2line_timeout_ms =3D 1 * 1000; +#include +#include + bool srcline_full_filename; =20 char *srcline__unknown =3D (char *)"??:0"; @@ -129,458 +114,23 @@ struct symbol *new_inline_sym(struct dso *dso, return inline_sym; } =20 -#ifdef HAVE_LIBLLVM_SUPPORT -#include "llvm.h" - -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) -{ - return llvm__addr2line(dso_name, addr, file, line, dso, unwind_inlines, n= ode, sym); -} - -void dso__free_a2l(struct dso *dso) -{ - dso__free_a2l_llvm(dso); -} -#elif defined(HAVE_LIBBFD_SUPPORT) -#include "libbfd.h" - -static int addr2line(const char *dso_name, u64 addr, - char **file, unsigned int *line, struct dso *dso, - bool unwind_inlines, struct inline_node *node, +static int addr2line(const char *dso_name, u64 addr, char **file, unsigned= int *line_nr, + struct dso *dso, bool unwind_inlines, struct inline_node *node, struct symbol *sym) { - return libbfd__addr2line(dso_name, addr, file, line, dso, unwind_inlines,= node, sym); -} - -void dso__free_a2l(struct dso *dso) -{ - dso__free_a2l_libbfd(dso); -} - -#else /* HAVE_LIBBFD_SUPPORT */ - -static int filename_split(char *filename, unsigned int *line_nr) -{ - char *sep; - - sep =3D strchr(filename, '\n'); - if (sep) - *sep =3D '\0'; - - if (!strcmp(filename, "??:0")) - return 0; - - sep =3D strchr(filename, ':'); - if (sep) { - *sep++ =3D '\0'; - *line_nr =3D strtoul(sep, NULL, 0); - return 1; - } - pr_debug("addr2line missing ':' in filename split\n"); - return 0; -} - -static void addr2line_subprocess_cleanup(struct child_process *a2l) -{ - if (a2l->pid !=3D -1) { - kill(a2l->pid, SIGKILL); - finish_command(a2l); /* ignore result, we don't care */ - a2l->pid =3D -1; - close(a2l->in); - close(a2l->out); - } - - free(a2l); -} - -static struct child_process *addr2line_subprocess_init(const char *addr2li= ne_path, - const char *binary_path) -{ - const char *argv[] =3D { - addr2line_path ?: "addr2line", - "-e", binary_path, - "-a", "-i", "-f", NULL - }; - struct child_process *a2l =3D zalloc(sizeof(*a2l)); - int start_command_status =3D 0; - - if (a2l =3D=3D NULL) { - pr_err("Failed to allocate memory for addr2line"); - return NULL; - } - - a2l->pid =3D -1; - a2l->in =3D -1; - a2l->out =3D -1; - a2l->no_stderr =3D 1; - - a2l->argv =3D argv; - start_command_status =3D start_command(a2l); - a2l->argv =3D NULL; /* it's not used after start_command; avoid dangling = pointers */ - - if (start_command_status !=3D 0) { - pr_warning("could not start addr2line (%s) for %s: start_command return = code %d\n", - addr2line_path, binary_path, start_command_status); - addr2line_subprocess_cleanup(a2l); - return NULL; - } - - return a2l; -} - -enum a2l_style { - BROKEN, - GNU_BINUTILS, - LLVM, -}; - -static enum a2l_style addr2line_configure(struct child_process *a2l, const= char *dso_name) -{ - static bool cached; - static enum a2l_style style; - - if (!cached) { - char buf[128]; - struct io io; - int ch; - int lines; - - if (write(a2l->in, ",\n", 2) !=3D 2) - return BROKEN; - - io__init(&io, a2l->out, buf, sizeof(buf)); - ch =3D io__get_char(&io); - if (ch =3D=3D ',') { - style =3D LLVM; - cached =3D true; - lines =3D 1; - pr_debug3("Detected LLVM addr2line style\n"); - } else if (ch =3D=3D '0') { - style =3D GNU_BINUTILS; - cached =3D true; - lines =3D 3; - pr_debug3("Detected binutils addr2line style\n"); - } else { - if (!symbol_conf.disable_add2line_warn) { - char *output =3D NULL; - size_t output_len; - - io__getline(&io, &output, &output_len); - pr_warning("%s %s: addr2line configuration failed\n", - __func__, dso_name); - pr_warning("\t%c%s", ch, output); - } - pr_debug("Unknown/broken addr2line style\n"); - return BROKEN; - } - while (lines) { - ch =3D io__get_char(&io); - if (ch <=3D 0) - break; - if (ch =3D=3D '\n') - lines--; - } - /* Ignore SIGPIPE in the event addr2line exits. */ - signal(SIGPIPE, SIG_IGN); - } - return style; -} - -static int read_addr2line_record(struct io *io, - enum a2l_style style, - const char *dso_name, - u64 addr, - bool first, - char **function, - char **filename, - unsigned int *line_nr) -{ - /* - * Returns: - * -1 =3D=3D> error - * 0 =3D=3D> sentinel (or other ill-formed) record read - * 1 =3D=3D> a genuine record read - */ - char *line =3D NULL; - size_t line_len =3D 0; - unsigned int dummy_line_nr =3D 0; - int ret =3D -1; - - if (function !=3D NULL) - zfree(function); - - if (filename !=3D NULL) - zfree(filename); - - if (line_nr !=3D NULL) - *line_nr =3D 0; - - /* - * Read the first line. Without an error this will be: - * - for the first line an address like 0x1234, - * - the binutils sentinel 0x0000000000000000, - * - the llvm-addr2line the sentinel ',' character, - * - the function name line for an inlined function. - */ - if (io__getline(io, &line, &line_len) < 0 || !line_len) - goto error; - - pr_debug3("%s %s: addr2line read address for sentinel: %s", __func__, dso= _name, line); - if (style =3D=3D LLVM && line_len =3D=3D 2 && line[0] =3D=3D ',') { - /* Found the llvm-addr2line sentinel character. */ - zfree(&line); - return 0; - } else if (style =3D=3D GNU_BINUTILS && (!first || addr !=3D 0)) { - int zero_count =3D 0, non_zero_count =3D 0; - /* - * Check for binutils sentinel ignoring it for the case the - * requested address is 0. - */ - - /* A given address should always start 0x. */ - if (line_len >=3D 2 || line[0] !=3D '0' || line[1] !=3D 'x') { - for (size_t i =3D 2; i < line_len; i++) { - if (line[i] =3D=3D '0') - zero_count++; - else if (line[i] !=3D '\n') - non_zero_count++; - } - if (!non_zero_count) { - int ch; - - if (first && !zero_count) { - /* Line was erroneous just '0x'. */ - goto error; - } - /* - * Line was 0x0..0, the sentinel for binutils. Remove - * the function and filename lines. - */ - zfree(&line); - do { - ch =3D io__get_char(io); - } while (ch > 0 && ch !=3D '\n'); - do { - ch =3D io__get_char(io); - } while (ch > 0 && ch !=3D '\n'); - return 0; - } - } - } - /* Read the second function name line (if inline data then this is the fi= rst line). */ - if (first && (io__getline(io, &line, &line_len) < 0 || !line_len)) - goto error; - - pr_debug3("%s %s: addr2line read line: %s", __func__, dso_name, line); - if (function !=3D NULL) - *function =3D strdup(strim(line)); - - zfree(&line); - line_len =3D 0; - - /* Read the third filename and line number line. */ - if (io__getline(io, &line, &line_len) < 0 || !line_len) - goto error; - - pr_debug3("%s %s: addr2line filename:number : %s", __func__, dso_name, li= ne); - if (filename_split(line, line_nr =3D=3D NULL ? &dummy_line_nr : line_nr) = =3D=3D 0 && - style =3D=3D GNU_BINUTILS) { - ret =3D 0; - goto error; - } - - if (filename !=3D NULL) - *filename =3D strdup(line); - - zfree(&line); - line_len =3D 0; - - return 1; - -error: - free(line); - if (function !=3D NULL) - zfree(function); - if (filename !=3D NULL) - zfree(filename); - return ret; -} - -static int inline_list__append_record(struct dso *dso, - struct inline_node *node, - struct symbol *sym, - const char *function, - const char *filename, - unsigned int line_nr) -{ - struct symbol *inline_sym =3D new_inline_sym(dso, sym, function); - - return inline_list__append(inline_sym, srcline_from_fileline(filename, li= ne_nr), node); -} - -static int addr2line(const char *dso_name, u64 addr, - char **file, unsigned int *line_nr, - struct dso *dso, - bool unwind_inlines, - struct inline_node *node, - struct symbol *sym __maybe_unused) -{ - struct child_process *a2l =3D dso__a2l(dso); - char *record_function =3D NULL; - char *record_filename =3D NULL; - unsigned int record_line_nr =3D 0; - int record_status =3D -1; - int ret =3D 0; - size_t inline_count =3D 0; - int len; - char buf[128]; - ssize_t written; - struct io io =3D { .eof =3D false }; - enum a2l_style a2l_style; - - if (!a2l) { - if (!filename__has_section(dso_name, ".debug_line")) - goto out; - - dso__set_a2l(dso, - addr2line_subprocess_init(symbol_conf.addr2line_path, dso_name)); - a2l =3D dso__a2l(dso); - } - - if (a2l =3D=3D NULL) { - if (!symbol_conf.disable_add2line_warn) - pr_warning("%s %s: addr2line_subprocess_init failed\n", __func__, dso_n= ame); - goto out; - } - a2l_style =3D addr2line_configure(a2l, dso_name); - if (a2l_style =3D=3D BROKEN) - goto out; - - /* - * Send our request and then *deliberately* send something that can't be - * interpreted as a valid address to ask addr2line about (namely, - * ","). This causes addr2line to first write out the answer to our - * request, in an unbounded/unknown number of records, and then to write - * out the lines "0x0...0", "??" and "??:0", for GNU binutils, or "," - * for llvm-addr2line, so that we can detect when it has finished giving - * us anything useful. - */ - len =3D snprintf(buf, sizeof(buf), "%016"PRIx64"\n,\n", addr); - written =3D len > 0 ? write(a2l->in, buf, len) : -1; - if (written !=3D len) { - if (!symbol_conf.disable_add2line_warn) - pr_warning("%s %s: could not send request\n", __func__, dso_name); - goto out; - } - io__init(&io, a2l->out, buf, sizeof(buf)); - io.timeout_ms =3D addr2line_timeout_ms; - switch (read_addr2line_record(&io, a2l_style, dso_name, addr, /*first=3D*= /true, - &record_function, &record_filename, &record_line_nr)) { - case -1: - if (!symbol_conf.disable_add2line_warn) - pr_warning("%s %s: could not read first record\n", __func__, dso_name); - goto out; - case 0: - /* - * The first record was invalid, so return failure, but first - * read another record, since we sent a sentinel ',' for the - * sake of detected the last inlined function. Treat this as the - * first of a record as the ',' generates a new start with GNU - * binutils, also force a non-zero address as we're no longer - * reading that record. - */ - switch (read_addr2line_record(&io, a2l_style, dso_name, - /*addr=3D*/1, /*first=3D*/true, - NULL, NULL, NULL)) { - case -1: - if (!symbol_conf.disable_add2line_warn) - pr_warning("%s %s: could not read sentinel record\n", - __func__, dso_name); - break; - case 0: - /* The sentinel as expected. */ - break; - default: - if (!symbol_conf.disable_add2line_warn) - pr_warning("%s %s: unexpected record instead of sentinel", - __func__, dso_name); - break; - } - goto out; - default: - /* First record as expected. */ - break; - } - - if (file) { - *file =3D strdup(record_filename); - ret =3D 1; - } - if (line_nr) - *line_nr =3D record_line_nr; - - if (unwind_inlines) { - if (node && inline_list__append_record(dso, node, sym, - record_function, - record_filename, - record_line_nr)) { - ret =3D 0; - goto out; - } - } - - /* - * We have to read the records even if we don't care about the inline - * info. This isn't the first record and force the address to non-zero - * as we're reading records beyond the first. - */ - while ((record_status =3D read_addr2line_record(&io, - a2l_style, - dso_name, - /*addr=3D*/1, - /*first=3D*/false, - &record_function, - &record_filename, - &record_line_nr)) =3D=3D 1) { - if (unwind_inlines && node && inline_count++ < MAX_INLINE_NEST) { - if (inline_list__append_record(dso, node, sym, - record_function, - record_filename, - record_line_nr)) { - ret =3D 0; - goto out; - } - ret =3D 1; /* found at least one inline frame */ - } - } - -out: - free(record_function); - free(record_filename); - if (io.eof) { - dso__set_a2l(dso, NULL); - addr2line_subprocess_cleanup(a2l); - } - return ret; -} - -void dso__free_a2l(struct dso *dso) -{ - struct child_process *a2l =3D dso__a2l(dso); + int ret; =20 - if (!a2l) - return; + ret =3D llvm__addr2line(dso_name, addr, file, line_nr, dso, unwind_inline= s, node, sym); + if (ret > 0) + return ret; =20 - addr2line_subprocess_cleanup(a2l); + ret =3D libbfd__addr2line(dso_name, addr, file, line_nr, dso, unwind_inli= nes, node, sym); + if (ret > 0) + return ret; =20 - dso__set_a2l(dso, NULL); + return cmd__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines,= node, sym); } =20 -#endif /* HAVE_LIBBFD_SUPPORT */ - static struct inline_node *addr2inlines(const char *dso_name, u64 addr, struct dso *dso, struct symbol *sym) { @@ -595,7 +145,9 @@ static struct inline_node *addr2inlines(const char *dso= _name, u64 addr, INIT_LIST_HEAD(&node->val); node->addr =3D addr; =20 - addr2line(dso_name, addr, NULL, NULL, dso, true, node, sym); + addr2line(dso_name, addr, /*file=3D*/NULL, /*line_nr=3D*/NULL, dso, + /*unwind_inlines=3D*/true, node, sym); + return node; } =20 @@ -622,7 +174,7 @@ char *__get_srcline(struct dso *dso, u64 addr, struct s= ymbol *sym, goto out_err; =20 if (!addr2line(dso_name, addr, &file, &line, dso, - unwind_inlines, NULL, sym)) + unwind_inlines, /*node=3D*/NULL, sym)) goto out_err; =20 srcline =3D srcline_from_fileline(file, line); @@ -668,7 +220,8 @@ char *get_srcline_split(struct dso *dso, u64 addr, unsi= gned *line) if (dso_name =3D=3D NULL) goto out_err; =20 - if (!addr2line(dso_name, addr, &file, line, dso, true, NULL, NULL)) + if (!addr2line(dso_name, addr, &file, line, dso, /*unwind_inlines=3D*/tru= e, + /*node=3D*/NULL, /*sym=3D*/NULL)) goto out_err; =20 dso__set_a2l_fails(dso, 0); diff --git a/tools/perf/util/srcline.h b/tools/perf/util/srcline.h index 6e66ddbcc879..c36f573cd339 100644 --- a/tools/perf/util/srcline.h +++ b/tools/perf/util/srcline.h @@ -9,7 +9,6 @@ struct dso; struct symbol; =20 -extern int addr2line_timeout_ms; extern bool srcline_full_filename; char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, bool show_sym, bool show_addr, u64 ip); --=20 2.51.0.618.g983fd99d29-goog From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (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 436F32C21C2 for ; Sun, 5 Oct 2025 21:22:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699360; cv=none; b=Zcp6wlcN+kRbX8hvFnPJAmDgyOCIm2TgVUIkBos4Ax+E3hz+vz4ZoTGm7JAbm5SyD966Yb5L09EkQ/dCeiwdHsZ690NNORXnbnpxcOt5QKQpLfz5kOsXFvI2qUiXV1QDIjvJ991Z3Asp3BUdkS5vL3luPEScAA23IiGljn+91Vo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699360; c=relaxed/simple; bh=d45wEUY1c4jrn84/iwX20DQE8nKTJ3WT+ZgvlVq/fR8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=i94OOCFkOfAcSS4VBl4vQ3YrT6IxY+Z4b2hgvl4Yn5QpUPx/+q5D6Vcp53sXuUUeW4clZSLTn4YD9MZJnkVuQ4hiVhK5GIT01xE7YDwsZz8db8B1zgbIz8hw2deHbCihML57E1LdVK6cKe9MxudLFtkStVYRuC9S83TcUtmS8dE= 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=iNUpK6jh; arc=none smtp.client-ip=209.85.210.201 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="iNUpK6jh" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-7900f597d08so335920b3a.1 for ; Sun, 05 Oct 2025 14:22:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699358; x=1760304158; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=5UwuX+qcsVkIci0z0OtUlxAA0Fd588bD/7/Leb924no=; b=iNUpK6jhPiS5f/hKDyyWnevN+OHiX3QhhcYyX+IlJdkzeQ66LZzEt6M9X0NYe0WshC 1gS6cd6/5KuHzgs0hW3p7qCSZvV8krOdyGJ0QVlYzJaaNMkEepNQOdw2AdCpALrGc//I RYKINoeHj7LsI4WF8RPr8WcpSG5q/nUC3zzFGUGQp/FCM6T4z0ob9ZjrkX1p6yPKzceh 4Y3/NBeioidySuI6sX5jNXJwgCg/XYfmWm9IU8twlYnyHwSIYSJ3QDahNyOnoBfZy4u6 f+GR8GTQvvd0ptxbF6t8nxFI7lxwXne2dloWt28sXkwOK4vyHZu7SgHpDKNFl8RPKu7M N1zg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699358; x=1760304158; h=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; bh=5UwuX+qcsVkIci0z0OtUlxAA0Fd588bD/7/Leb924no=; b=aB+h/q/UJftHs59Fx9urAlJRm2xllUiT5oqWHZgvjN1Gg8GhNUeQ1ECe5MxMwQBZTT qcULKYhmpufpopxG1lOekJ0dzkSzui5LuA2NYoPmYzHxeCsFQMcpsfa9mP4xiX8Rq0la BiqSYPiRvAPPpXcjq+kZF0rHrw3shWASDETDq2S70Wh1nkmkjdQIBcpDkdoB5RULA6t1 x3IUbvvOqZaCD6KxWS5CKhEs/cTmnPp4WT5o4Ar15DTIObwNykf8jpNrdZfnhg6XDqPG sC62dSVNPDNjTM//C8pdHU6GHAF8U9FufDuxcyFOTK1tf0paHAFvtDhZuszQD9x+DV6a NLKw== X-Forwarded-Encrypted: i=1; AJvYcCVPSoG6Dc+V1f+OsOhvlcjVw2cqOdoOquEhUmqCG3hVmpXNuKs2m72O+SHm9arKAiywpgGko6nzTJfzUtI=@vger.kernel.org X-Gm-Message-State: AOJu0Yy1MUubeWC/Kvwqi/ruZpNAKZrz8x7goDTG+vJ0esi2z+Kq8iyp Ej0yc7i/QMlZCSb3X6r3kVAAUTq/SKKN58tYKqRGZ3PgtrultSPbEiws/2Yp6WlrxXQI1n8mGdr ZDC276UIEiA== X-Google-Smtp-Source: AGHT+IGvT5pslbMCXLmkI8dz33jGeGYCBPk++vUXwX3QDvVBJVh6+9SImEKQrDsiOMs+ve1hP/rqlLC1JAam X-Received: from pgac17.prod.google.com ([2002:a05:6a02:2951:b0:b58:7d6e:e9c3]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:d527:b0:32b:70a1:7c84 with SMTP id adf61e73a8af0-32b70a17d56mr10844469637.28.1759699357519; Sun, 05 Oct 2025 14:22:37 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:09 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-9-irogers@google.com> Subject: [PATCH v7 08/11] perf disasm: Remove unused evsel from annotate_args From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Set in symbol__annotate but never used. Signed-off-by: Ian Rogers --- tools/perf/util/annotate.c | 1 - tools/perf/util/disasm.h | 1 - 2 files changed, 2 deletions(-) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index c9b220d9f924..a2e34f149a07 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1015,7 +1015,6 @@ int symbol__annotate(struct map_symbol *ms, struct ev= sel *evsel, struct symbol *sym =3D ms->sym; struct annotation *notes =3D symbol__annotation(sym); struct annotate_args args =3D { - .evsel =3D evsel, .options =3D &annotate_opts, }; struct arch *arch =3D NULL; diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h index 09c86f540f7f..d2cb555e4a3b 100644 --- a/tools/perf/util/disasm.h +++ b/tools/perf/util/disasm.h @@ -98,7 +98,6 @@ struct ins_ops { struct annotate_args { struct arch *arch; struct map_symbol ms; - struct evsel *evsel; struct annotation_options *options; s64 offset; char *line; --=20 2.51.0.618.g983fd99d29-goog From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (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 75AB62BE053 for ; Sun, 5 Oct 2025 21:22:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699362; cv=none; b=HiEehII9DB/AudTQvRH9ndIaclyd8T3j2V2JEOz58Ae/xBjCaoHnDqm+ZG+MIrgbP60LTojW60UfUlf/20/aq4+wHnrB2sk6wr3NZvfv9NiQ+EUkt/4CVgDDuY2owM3v+HDRicShtYb+q521VEtYgMHMbZNqjxCiogkCZXH/7cA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699362; c=relaxed/simple; bh=aEAtMjVjgulTf0TDqlU6QiBFacJWqCSnPGZkk3a6iVs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=Kwwyt1tFXgw29eXvby9ORqgCtOhph9fYec5YRyz9/L5hOES6BXPWOKIQGkq3iQtkoxv1dZbeXfrOrLEzrd57zcvdFmMOEb2z3fRBTnfYuitA+7fmQM8ERFsvwW0m/PNH1q8IUJn2j6agePGmqO8bL66DIV2BduKj6vaSCYuLK5w= 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=g1BEeBLF; arc=none smtp.client-ip=209.85.214.201 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="g1BEeBLF" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-28bd8b3fa67so34376775ad.2 for ; Sun, 05 Oct 2025 14:22:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699360; x=1760304160; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=+k0ZT6dX6FpTW7iWOOUOC483WZu4iMuIQMOn3S3WjJM=; b=g1BEeBLFFwWVpuqwa+JCkgKBQASduUMGGVMyOVFJlfe8B9g/d7YhRYbY3FgAWW17Pa aMTJZt6TvshUeJdXCv5Qixdb9/7NUoy4z+pkS3MSF4LNlO+viJBRqxBTU/BZKdUDX2px JBiy8bThOzQkXntT6VA9xnzDx79tn6e4e/eS6CKClq4rGJnuhv5iTA6JqUJ7c2Cn/S2x BIdzWBUmjE421219xVHZHLfrq7+ziMNWJZDSTX3qZ4KtWmSt3z96+0EDvnb9a01F1p7H lJBb/Iw5yWGxe6EZBJHFsBQnXDgk2C8jeyH8CYLxK2l5mgdINuck48kmHQgRR5NL5zL/ AukA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699360; x=1760304160; h=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; bh=+k0ZT6dX6FpTW7iWOOUOC483WZu4iMuIQMOn3S3WjJM=; b=NGiidm56JFV3DCnhvw8edKZTVDYnirAVkHl9uHZBxnkxADGl4fWG8mSxj88lcb9J3Z UULVa8G5B/H1Ef1GnG8c/gdCqSOa2qaqpdQFvxQo6Axnp8JRq/6rZbIZB3aoDF5S6R7N 7bI72Oe6fYR+lXogrhnUotKnrwSiT8JINXnXc5DdltpiIAlrv1MwmRh509RtdWiByAKR zuvYKvZ/g9AocOxDiMJdehZr1NcBMWXpyOM5jqNNLUD+Y+MPxfdV0SPAg652JBGRhRH8 q8t4k1zS+wOqZZ4sCQB3sx+g5elLkVAJrxNJ0ysoYFG9M5+QJwzSmi3QzTjQy1+HVTXH LI+w== X-Forwarded-Encrypted: i=1; AJvYcCVQLA495dPzivQ1r+Xuzh+zQVmqTv7Cg8AUGKk7jKOoNs4GIWVMnuX9lL+mcPW+6W4ps0slhhMrcF/DGiQ=@vger.kernel.org X-Gm-Message-State: AOJu0YyCIxaMSfhfwPx3thBuqurakXmiOOjiHkGuHHzLhz681ed9t0wo FHaYfzxWUjZamqwUkLquVzdbTrweYvcKTeQ4ccwNP43dyxBIkiEw+HeBOuZGGcCkMKp39Xs78v/ ZBmjIRmHKkw== X-Google-Smtp-Source: AGHT+IE7TzRaz3P02u5ZiI8lFQ+hJj2uct7i7p47hLFvgQQWhDJOz8AiZOgEexNWWsBsjd/RVFefG8yDhlc4 X-Received: from pjbjx18.prod.google.com ([2002:a17:90b:46d2:b0:32e:b87b:6c84]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:dacd:b0:267:9aa5:f6a6 with SMTP id d9443c01a7336-28e9a566722mr140467185ad.19.1759699359809; Sun, 05 Oct 2025 14:22:39 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:10 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-10-irogers@google.com> Subject: [PATCH v7 09/11] perf capstone: Support for dlopen-ing libcapstone.so From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" If perf wasn't built against libcapstone, no HAVE_LIBCAPSTONE_SUPPORT, support dlopen-ing libcapstone.so and then calling the necessary functions by looking them up using dlsym. Reverse engineer the types in the API using pahole, adding only what's used in the perf code or necessary for the sake of struct size and alignment. Signed-off-by: Ian Rogers --- tools/perf/util/capstone.c | 285 ++++++++++++++++++++++++++++++++----- 1 file changed, 248 insertions(+), 37 deletions(-) diff --git a/tools/perf/util/capstone.c b/tools/perf/util/capstone.c index be5fd44b1f9d..88e270237443 100644 --- a/tools/perf/util/capstone.c +++ b/tools/perf/util/capstone.c @@ -11,20 +11,250 @@ #include "print_insn.h" #include "symbol.h" #include "thread.h" +#include #include #include +#include #include =20 #ifdef HAVE_LIBCAPSTONE_SUPPORT #include +#else +typedef size_t csh; +enum cs_arch { + CS_ARCH_ARM =3D 0, + CS_ARCH_ARM64 =3D 1, + CS_ARCH_X86 =3D 3, + CS_ARCH_SYSZ =3D 6, +}; +enum cs_mode { + CS_MODE_ARM =3D 0, + CS_MODE_32 =3D 1 << 2, + CS_MODE_64 =3D 1 << 3, + CS_MODE_V8 =3D 1 << 6, + CS_MODE_BIG_ENDIAN =3D 1 << 31, +}; +enum cs_opt_type { + CS_OPT_SYNTAX =3D 1, + CS_OPT_DETAIL =3D 2, +}; +enum cs_opt_value { + CS_OPT_SYNTAX_ATT =3D 2, + CS_OPT_ON =3D 3, +}; +enum cs_err { + CS_ERR_OK =3D 0, + CS_ERR_HANDLE =3D 3, +}; +enum x86_op_type { + X86_OP_IMM =3D 2, + X86_OP_MEM =3D 3, +}; +enum x86_reg { + X86_REG_RIP =3D 41, +}; +typedef int32_t x86_avx_bcast; +struct x86_op_mem { + enum x86_reg segment; + enum x86_reg base; + enum x86_reg index; + int scale; + int64_t disp; +}; + +struct cs_x86_op { + enum x86_op_type type; + union { + enum x86_reg reg; + int64_t imm; + struct x86_op_mem mem; + }; + uint8_t size; + uint8_t access; + x86_avx_bcast avx_bcast; + bool avx_zero_opmask; +}; +struct cs_x86_encoding { + uint8_t modrm_offset; + uint8_t disp_offset; + uint8_t disp_size; + uint8_t imm_offset; + uint8_t imm_size; +}; +typedef int32_t x86_xop_cc; +typedef int32_t x86_sse_cc; +typedef int32_t x86_avx_cc; +typedef int32_t x86_avx_rm; +struct cs_x86 { + uint8_t prefix[4]; + uint8_t opcode[4]; + uint8_t rex; + uint8_t addr_size; + uint8_t modrm; + uint8_t sib; + int64_t disp; + enum x86_reg sib_index; + int8_t sib_scale; + enum x86_reg sib_base; + x86_xop_cc xop_cc; + x86_sse_cc sse_cc; + x86_avx_cc avx_cc; + bool avx_sae; + x86_avx_rm avx_rm; + union { + uint64_t eflags; + uint64_t fpu_flags; + }; + uint8_t op_count; + struct cs_x86_op operands[8]; + struct cs_x86_encoding encoding; +}; +struct cs_detail { + uint16_t regs_read[12]; + uint8_t regs_read_count; + uint16_t regs_write[20]; + uint8_t regs_write_count; + uint8_t groups[8]; + uint8_t groups_count; + + union { + struct cs_x86 x86; + }; +}; +struct cs_insn { + unsigned int id; + uint64_t address; + uint16_t size; + uint8_t bytes[16]; + char mnemonic[32]; + char op_str[160]; + struct cs_detail *detail; +}; +#endif + +#ifndef HAVE_LIBCAPSTONE_SUPPORT +static void *perf_cs_dll_handle(void) +{ + static bool dll_handle_init; + static void *dll_handle; + + if (!dll_handle_init) { + dll_handle_init =3D true; + dll_handle =3D dlopen("libcapstone.so", RTLD_LAZY); + if (!dll_handle) + pr_debug("dlopen failed for libcapstone.so\n"); + } + return dll_handle; +} +#endif + +static enum cs_err perf_cs_open(enum cs_arch arch, enum cs_mode mode, csh = *handle) +{ +#ifdef HAVE_LIBCAPSTONE_SUPPORT + return cs_open(arch, mode, handle); +#else + static bool fn_init; + static enum cs_err (*fn)(enum cs_arch arch, enum cs_mode mode, csh *handl= e); + + if (!fn_init) { + fn =3D dlsym(perf_cs_dll_handle(), "cs_open"); + if (!fn) + pr_debug("dlsym failed for cs_open\n"); + fn_init =3D true; + } + if (!fn) + return CS_ERR_HANDLE; + return fn(arch, mode, handle); +#endif +} + +static enum cs_err perf_cs_option(csh handle, enum cs_opt_type type, size_= t value) +{ +#ifdef HAVE_LIBCAPSTONE_SUPPORT + return cs_option(handle, type, value); +#else + static bool fn_init; + static enum cs_err (*fn)(csh handle, enum cs_opt_type type, size_t value); + + if (!fn_init) { + fn =3D dlsym(perf_cs_dll_handle(), "cs_option"); + if (!fn) + pr_debug("dlsym failed for cs_option\n"); + fn_init =3D true; + } + if (!fn) + return CS_ERR_HANDLE; + return fn(handle, type, value); +#endif +} + +static size_t perf_cs_disasm(csh handle, const uint8_t *code, size_t code_= size, + uint64_t address, size_t count, struct cs_insn **insn) +{ +#ifdef HAVE_LIBCAPSTONE_SUPPORT + return cs_disasm(handle, code, code_size, address, count, insn); +#else + static bool fn_init; + static enum cs_err (*fn)(csh handle, const uint8_t *code, size_t code_siz= e, + uint64_t address, size_t count, struct cs_insn **insn); + + if (!fn_init) { + fn =3D dlsym(perf_cs_dll_handle(), "cs_disasm"); + if (!fn) + pr_debug("dlsym failed for cs_disasm\n"); + fn_init =3D true; + } + if (!fn) + return CS_ERR_HANDLE; + return fn(handle, code, code_size, address, count, insn); #endif +} =20 +static void perf_cs_free(struct cs_insn *insn, size_t count) +{ #ifdef HAVE_LIBCAPSTONE_SUPPORT + cs_free(insn, count); +#else + static bool fn_init; + static void (*fn)(struct cs_insn *insn, size_t count); + + if (!fn_init) { + fn =3D dlsym(perf_cs_dll_handle(), "cs_free"); + if (!fn) + pr_debug("dlsym failed for cs_free\n"); + fn_init =3D true; + } + if (!fn) + return; + fn(insn, count); +#endif +} + +static enum cs_err perf_cs_close(csh *handle) +{ +#ifdef HAVE_LIBCAPSTONE_SUPPORT + return cs_close(handle); +#else + static bool fn_init; + static enum cs_err (*fn)(csh *handle); + + if (!fn_init) { + fn =3D dlsym(perf_cs_dll_handle(), "cs_close"); + if (!fn) + pr_debug("dlsym failed for cs_close\n"); + fn_init =3D true; + } + if (!fn) + return CS_ERR_HANDLE; + return fn(handle); +#endif +} + static int capstone_init(struct machine *machine, csh *cs_handle, bool is6= 4, bool disassembler_style) { - cs_arch arch; - cs_mode mode; + enum cs_arch arch; + enum cs_mode mode; =20 if (machine__is(machine, "x86_64") && is64) { arch =3D CS_ARCH_X86; @@ -45,7 +275,7 @@ static int capstone_init(struct machine *machine, csh *c= s_handle, bool is64, return -1; } =20 - if (cs_open(arch, mode, cs_handle) !=3D CS_ERR_OK) { + if (perf_cs_open(arch, mode, cs_handle) !=3D CS_ERR_OK) { pr_warning_once("cs_open failed\n"); return -1; } @@ -57,27 +287,25 @@ static int capstone_init(struct machine *machine, csh = *cs_handle, bool is64, * is set via annotation args */ if (disassembler_style) - cs_option(*cs_handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); + perf_cs_option(*cs_handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); /* * Resolving address operands to symbols is implemented * on x86 by investigating instruction details. */ - cs_option(*cs_handle, CS_OPT_DETAIL, CS_OPT_ON); + perf_cs_option(*cs_handle, CS_OPT_DETAIL, CS_OPT_ON); } =20 return 0; } -#endif =20 -#ifdef HAVE_LIBCAPSTONE_SUPPORT -static size_t print_insn_x86(struct thread *thread, u8 cpumode, cs_insn *i= nsn, +static size_t print_insn_x86(struct thread *thread, u8 cpumode, struct cs_= insn *insn, int print_opts, FILE *fp) { struct addr_location al; size_t printed =3D 0; =20 if (insn->detail && insn->detail->x86.op_count =3D=3D 1) { - cs_x86_op *op =3D &insn->detail->x86.operands[0]; + struct cs_x86_op *op =3D &insn->detail->x86.operands[0]; =20 addr_location__init(&al); if (op->type =3D=3D X86_OP_IMM && @@ -95,7 +323,6 @@ static size_t print_insn_x86(struct thread *thread, u8 c= pumode, cs_insn *insn, printed +=3D fprintf(fp, "%s %s", insn[0].mnemonic, insn[0].op_str); return printed; } -#endif =20 =20 ssize_t capstone__fprintf_insn_asm(struct machine *machine __maybe_unused, @@ -106,9 +333,8 @@ ssize_t capstone__fprintf_insn_asm(struct machine *mach= ine __maybe_unused, uint64_t ip __maybe_unused, int *lenp __maybe_unused, int print_opts __maybe_unused, FILE *fp __maybe_unused) { -#ifdef HAVE_LIBCAPSTONE_SUPPORT size_t printed; - cs_insn *insn; + struct cs_insn *insn; csh cs_handle; size_t count; int ret; @@ -118,7 +344,7 @@ ssize_t capstone__fprintf_insn_asm(struct machine *mach= ine __maybe_unused, if (ret < 0) return ret; =20 - count =3D cs_disasm(cs_handle, code, code_size, ip, 1, &insn); + count =3D perf_cs_disasm(cs_handle, code, code_size, ip, 1, &insn); if (count > 0) { if (machine__normalized_is(machine, "x86")) printed =3D print_insn_x86(thread, cpumode, &insn[0], print_opts, fp); @@ -126,20 +352,16 @@ ssize_t capstone__fprintf_insn_asm(struct machine *ma= chine __maybe_unused, printed =3D fprintf(fp, "%s %s", insn[0].mnemonic, insn[0].op_str); if (lenp) *lenp =3D insn->size; - cs_free(insn, count); + perf_cs_free(insn, count); } else { printed =3D -1; } =20 - cs_close(&cs_handle); + perf_cs_close(&cs_handle); return printed; -#else - return -1; -#endif } =20 -#ifdef HAVE_LIBCAPSTONE_SUPPORT -static void print_capstone_detail(cs_insn *insn, char *buf, size_t len, +static void print_capstone_detail(struct cs_insn *insn, char *buf, size_t = len, struct annotate_args *args, u64 addr) { int i; @@ -154,7 +376,7 @@ static void print_capstone_detail(cs_insn *insn, char *= buf, size_t len, return; =20 for (i =3D 0; i < insn->detail->x86.op_count; i++) { - cs_x86_op *op =3D &insn->detail->x86.operands[i]; + struct cs_x86_op *op =3D &insn->detail->x86.operands[i]; u64 orig_addr; =20 if (op->type !=3D X86_OP_MEM) @@ -195,9 +417,7 @@ static void print_capstone_detail(cs_insn *insn, char *= buf, size_t len, break; } } -#endif =20 -#ifdef HAVE_LIBCAPSTONE_SUPPORT struct find_file_offset_data { u64 ip; u64 offset; @@ -214,13 +434,11 @@ static int find_file_offset(u64 start, u64 len, u64 p= goff, void *arg) } return 0; } -#endif =20 int symbol__disassemble_capstone(const char *filename __maybe_unused, struct symbol *sym __maybe_unused, struct annotate_args *args __maybe_unused) { -#ifdef HAVE_LIBCAPSTONE_SUPPORT struct annotation *notes =3D symbol__annotation(sym); struct map *map =3D args->ms.map; struct dso *dso =3D map__dso(map); @@ -235,7 +453,7 @@ int symbol__disassemble_capstone(const char *filename _= _maybe_unused, const u8 *buf; u64 buf_len; csh handle; - cs_insn *insn =3D NULL; + struct cs_insn *insn =3D NULL; char disasm_buf[512]; struct disasm_line *dl; bool disassembler_style =3D false; @@ -273,7 +491,7 @@ int symbol__disassemble_capstone(const char *filename _= _maybe_unused, =20 needs_cs_close =3D true; =20 - free_count =3D count =3D cs_disasm(handle, buf, buf_len, start, buf_len, = &insn); + free_count =3D count =3D perf_cs_disasm(handle, buf, buf_len, start, buf_= len, &insn); for (i =3D 0, offset =3D 0; i < count; i++) { int printed; =20 @@ -312,9 +530,9 @@ int symbol__disassemble_capstone(const char *filename _= _maybe_unused, =20 out: if (needs_cs_close) { - cs_close(&handle); + perf_cs_close(&handle); if (free_count > 0) - cs_free(insn, free_count); + perf_cs_free(insn, free_count); } free(code_buf); return count < 0 ? count : 0; @@ -334,16 +552,12 @@ int symbol__disassemble_capstone(const char *filename= __maybe_unused, } count =3D -1; goto out; -#else - return -1; -#endif } =20 int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unus= ed, struct symbol *sym __maybe_unused, struct annotate_args *args __maybe_unused) { -#ifdef HAVE_LIBCAPSTONE_SUPPORT struct annotation *notes =3D symbol__annotation(sym); struct map *map =3D args->ms.map; struct dso *dso =3D map__dso(map); @@ -456,7 +670,7 @@ int symbol__disassemble_capstone_powerpc(const char *fi= lename __maybe_unused, =20 out: if (needs_cs_close) - cs_close(&handle); + perf_cs_close(&handle); free(buf); return count < 0 ? count : 0; =20 @@ -465,7 +679,4 @@ int symbol__disassemble_capstone_powerpc(const char *fi= lename __maybe_unused, close(fd); count =3D -1; goto out; -#else - return -1; -#endif } --=20 2.51.0.618.g983fd99d29-goog From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (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 65CBE2C21F3 for ; Sun, 5 Oct 2025 21:22:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699366; cv=none; b=kpKQU1J4TKl/mDoaDhLnqQrrp++Lx3Af2Bm2WAnzfu5Gayqq0qod/o0XMtFKBHTStS5HBmT1E+z0XbdBwbi9W4f4x6e9Bt+MEUr0T1aT5xoFBFS/AL/vLryqQcwKWnqfqXkAb81HWrZIs4voiRbMYUNMdYzwhB9loIUsiv00f+k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699366; c=relaxed/simple; bh=YSFH4ikBMm/RbgwhioWjN0FnJQqv1IRaQQNFmgOwzRM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=oJ+cKHr2TigeabnEYwdOi31hD4CBdujBKhf+WEBQN3sJbDCEUaAToB/hlCiKu6cJtBQlvCVeiQ+c6+EKlwsT+vgbKxSmYzJk22iPC2xrry7qSjtWsOYu60HTkogULLPW0qE29/kBfJjPb3519N/qHEosYbGoZ5CN0llcT9NJoiI= 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=VdzLAlf+; arc=none smtp.client-ip=209.85.214.202 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="VdzLAlf+" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-27c62320f16so39935265ad.1 for ; Sun, 05 Oct 2025 14:22:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699362; x=1760304162; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=tV9ZwnPdF3/ywhrKnvvCbDJLcgE3u1kLaVjLMJAG3D8=; b=VdzLAlf+DLAeeFZDifOoHnuRUNAV/lXjJ/t4L4NUX4kVky9cZpezsw9iI+hSs/rSdc HSiigO93+DQCbWnzSiZDtS6RBCnC87ZQyMoFJtDDg2KJWXfBlioQrGiZNuYBb5Ve6M+J PNk9yHoAvazIdX7gqe7wUBk0fKuLCcomlCfTu6ttwXc9PhfW+OsFqzO+VwF2Zf9cYoVU 9wP0186DR4q+AVjKYlNZMcrNua5VELFgcUSCILAeyRHj9ZqcTQK4BBm012F+WrnGUG5/ W5Uo4oZLwtI0zkVf4vMvV5GCABBQolnzC70gGsNfATTXMGwtQmJWiY0g6hUvbLjE5TaW w8lQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699362; x=1760304162; h=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; bh=tV9ZwnPdF3/ywhrKnvvCbDJLcgE3u1kLaVjLMJAG3D8=; b=Q9XFcifyCNjCuIiKetaRXU8fuqIEofO63xpVsFdeiZm6VHHt4+yXwokILIOhpwC4m2 IF3KrCavfW0oEErpNAeDR2mSR8vPUCJcn2U7pm1FfjltZNdYGAyzaVzim3fZRDvB2Y75 GftPNBtA5PL9y+NzdEDm+l3Ijv1BEq5dnzpeS/XgLKxV1V/1G99MJjCVfnJPzz6BwX1C k7a3fOUKKh+MNPB0dQWZd8zKuCQhKCngb164rqLKC8U3q4QHzzV0Xm6ERw3VlgwOMjbT Gx+tM42Rpxh2Vq+8YTac3iGr3FBfYzVy1f30/D1HchYSrV499g/NIVq+jHBGDFwsIjtG C8IA== X-Forwarded-Encrypted: i=1; AJvYcCXafbMewLK7JyfedpeAFLz4HkT8bQOrCWz5GsQiMP4X9t0m6eZF10I2fzZ8iYzpEqbiabLtjR0+UwN48T8=@vger.kernel.org X-Gm-Message-State: AOJu0Yz0z8LBUnBsT/vfUSDHpJgoUcxODkvP974aaeu5QfanWYjXpUhA SodZrtefrpB+M2HYBaFpOUM3Y1FZzh49J5Pv959jxyouT939BfuxYelE/Bq/RGs+WUkCgg2KHkU PMRFiXfnPeA== X-Google-Smtp-Source: AGHT+IEHc/ThohTYvbF7TEqCW7IzZRTkGSOIuazrexKP8sPIf4mC3K6+ABo9usdQsENVbc7hS9kipPbb+JIT X-Received: from pjbbx13.prod.google.com ([2002:a17:90a:f48d:b0:330:72b8:fcc0]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:124c:b0:288:5d07:8a8f with SMTP id d9443c01a7336-28e9a58a334mr128814745ad.24.1759699361821; Sun, 05 Oct 2025 14:22:41 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:11 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-11-irogers@google.com> Subject: [PATCH v7 10/11] perf llvm: Support for dlopen-ing libLLVM.so From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" If perf wasn't built against libLLVM, no HAVE_LIBLLVM_SUPPORT, support dlopen-ing libLLVM.so and then calling the necessary functions by looking them up using dlsym. As the C++ code in llvm-c-helpers used for addr2line is problematic to call using dlsym, build that C++ code against libLLVM.so as a separate shared object, and support dynamic loading of it. This build option is enabled with LIBLLVM_DYNAMIC=3D1 Signed-off-by: Ian Rogers --- tools/perf/Makefile.config | 13 ++ tools/perf/Makefile.perf | 23 ++- tools/perf/tests/make | 2 + tools/perf/util/Build | 2 +- tools/perf/util/llvm-c-helpers.cpp | 113 +++++++++++- tools/perf/util/llvm.c | 273 +++++++++++++++++++++++++---- 6 files changed, 388 insertions(+), 38 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 0f09f30f1906..03bd11b6e248 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -960,6 +960,19 @@ ifndef NO_LIBLLVM NO_LIBLLVM :=3D 1 endif endif +ifdef LIBLLVM_DYNAMIC + ifndef NO_LIBLLVM + $(error LIBLLVM_DYNAMIC should be used with NO_LIBLLVM) + endif + $(call feature_check,llvm-perf) + ifneq ($(feature-llvm-perf), 1) + $(warning LIBLLVM_DYNAMIC requires libLLVM.so which wasn't feature det= ected) + endif + CFLAGS +=3D -DHAVE_LIBLLVM_DYNAMIC + CFLAGS +=3D $(shell $(LLVM_CONFIG) --cflags) + CXXFLAGS +=3D -DHAVE_LIBLLVM_DYNAMIC + CXXFLAGS +=3D $(shell $(LLVM_CONFIG) --cxxflags) +endif =20 ifndef NO_DEMANGLE $(call feature_check,cxa-demangle) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 7d6ac03a7109..fb888702bace 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -423,6 +423,12 @@ ifndef NO_JVMTI PROGRAMS +=3D $(OUTPUT)$(LIBJVMTI) endif =20 +LIBPERF_LLVM =3D libperf-llvm.so + +ifdef LIBLLVM_DYNAMIC +PROGRAMS +=3D $(OUTPUT)$(LIBPERF_LLVM) +endif + DLFILTERS :=3D dlfilter-test-api-v0.so dlfilter-test-api-v2.so dlfilter-sh= ow-cycles.so DLFILTERS :=3D $(patsubst %,$(OUTPUT)dlfilters/%,$(DLFILTERS)) =20 @@ -995,6 +1001,16 @@ $(LIBSYMBOL)-clean: $(call QUIET_CLEAN, libsymbol) $(Q)$(RM) -r -- $(LIBSYMBOL_OUTPUT) =20 +ifdef LIBLLVM_DYNAMIC +LIBPERF_LLVM_CXXFLAGS :=3D $(call filter-out,-DHAVE_LIBLLVM_DYNAMIC,$(CXXF= LAGS)) -DHAVE_LIBLLVM_SUPPORT +LIBPERF_LLVM_LIBS =3D -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM) -lstdc= ++ + +$(OUTPUT)$(LIBPERF_LLVM): util/llvm-c-helpers.cpp + $(QUIET_LINK)$(CXX) $(LIBPERF_LLVM_CXXFLAGS) $(LIBPERF_LLVM_LIBS) -shared= -o $@ $< + +$(OUTPUT)perf: $(OUTPUT)$(LIBPERF_LLVM) +endif + help: @echo 'Perf make targets:' @echo ' doc - make *all* documentation (see below)' @@ -1096,6 +1112,11 @@ ifndef NO_JVMTI $(call QUIET_INSTALL, $(LIBJVMTI)) \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \ $(INSTALL) $(OUTPUT)$(LIBJVMTI) '$(DESTDIR_SQ)$(libdir_SQ)'; +endif +ifdef LIBLLVM_DYNAMIC + $(call QUIET_INSTALL, $(LIBPERF_LLVM)) \ + $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \ + $(INSTALL) $(OUTPUT)$(LIBPERF_LLVM) '$(DESTDIR_SQ)$(libdir_SQ)'; endif $(call QUIET_INSTALL, libexec) \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' @@ -1281,7 +1302,7 @@ clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-= clean $(LIBSYMBOL)-clean $( -name '\.*.cmd' -delete -o -name '\.*.d' -delete -o -name '*.shellcheck_= log' -delete $(Q)$(RM) $(OUTPUT).config-detected $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso= 32 \ - perf-read-vdsox32 $(OUTPUT)$(LIBJVMTI).so + perf-read-vdsox32 $(OUTPUT)$(LIBJVMTI) $(OUTPUT)$(LIBPERF_LLVM) $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo= \ $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE \ $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \ diff --git a/tools/perf/tests/make b/tools/perf/tests/make index b650ce8864ed..691c7a7fc463 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -93,6 +93,7 @@ make_no_libbpf :=3D NO_LIBBPF=3D1 make_libbpf_dynamic :=3D LIBBPF_DYNAMIC=3D1 make_no_libbpf_DEBUG :=3D NO_LIBBPF=3D1 DEBUG=3D1 make_no_libllvm :=3D NO_LIBLLVM=3D1 +make_libllvm_dynamic :=3D NO_LIBLLVM=3D1 LIBLLVM_DYNAMIC=3D1 make_with_babeltrace:=3D LIBBABELTRACE=3D1 make_with_coresight :=3D CORESIGHT=3D1 make_no_sdt :=3D NO_SDT=3D1 @@ -162,6 +163,7 @@ run +=3D make_no_auxtrace run +=3D make_no_libbpf run +=3D make_no_libbpf_DEBUG run +=3D make_no_libllvm +run +=3D make_libllvm_dynamic run +=3D make_no_sdt run +=3D make_no_syscall_tbl run +=3D make_with_babeltrace diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 4be313cd115a..8cc9b08790a3 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -27,6 +27,7 @@ perf-util-y +=3D find_bit.o perf-util-y +=3D levenshtein.o perf-util-$(CONFIG_LIBBFD) +=3D libbfd.o perf-util-y +=3D llvm.o +perf-util-y +=3D llvm-c-helpers.o perf-util-y +=3D mmap.o perf-util-y +=3D memswap.o perf-util-y +=3D parse-events.o @@ -249,7 +250,6 @@ perf-util-$(CONFIG_CXX_DEMANGLE) +=3D demangle-cxx.o perf-util-y +=3D demangle-ocaml.o perf-util-y +=3D demangle-java.o perf-util-y +=3D demangle-rust-v0.o -perf-util-$(CONFIG_LIBLLVM) +=3D llvm-c-helpers.o =20 CFLAGS_demangle-rust-v0.o +=3D -Wno-shadow -Wno-declaration-after-statemen= t \ -Wno-switch-default -Wno-switch-enum -Wno-missing-field-initializers diff --git a/tools/perf/util/llvm-c-helpers.cpp b/tools/perf/util/llvm-c-he= lpers.cpp index 004081bd12c9..5a6f76e6b705 100644 --- a/tools/perf/util/llvm-c-helpers.cpp +++ b/tools/perf/util/llvm-c-helpers.cpp @@ -5,17 +5,23 @@ * macros (e.g. noinline) that conflict with compiler builtins used * by LLVM. */ +#ifdef HAVE_LIBLLVM_SUPPORT #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" /* Needed for LLVM <= =3D 15 */ #include #include #pragma GCC diagnostic pop +#endif =20 +#if !defined(HAVE_LIBLLVM_SUPPORT) || defined(HAVE_LIBLLVM_DYNAMIC) +#include +#endif #include #include #include #include extern "C" { +#include "debug.h" #include } #include "llvm-c-helpers.h" @@ -23,14 +29,33 @@ extern "C" { extern "C" char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name= ); =20 +#ifdef HAVE_LIBLLVM_SUPPORT using namespace llvm; using llvm::symbolize::LLVMSymbolizer; +#endif + +#if !defined(HAVE_LIBLLVM_SUPPORT) && defined(HAVE_LIBLLVM_DYNAMIC) +static void *perf_llvm_c_helpers_dll_handle(void) +{ + static bool dll_handle_init; + static void *dll_handle; + + if (!dll_handle_init) { + dll_handle_init =3D true; + dll_handle =3D dlopen("libperf-llvm.so", RTLD_LAZY); + if (!dll_handle) + pr_debug("dlopen failed for libperf-llvm.so\n"); + } + return dll_handle; +} +#endif =20 /* * Allocate a static LLVMSymbolizer, which will live to the end of the pro= gram. * Unlike the bfd paths, LLVMSymbolizer has its own cache, so we do not ne= ed * to store anything in the dso struct. */ +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) static LLVMSymbolizer *get_symbolizer() { static LLVMSymbolizer *instance =3D nullptr; @@ -49,8 +74,10 @@ static LLVMSymbolizer *get_symbolizer() } return instance; } +#endif =20 /* Returns 0 on error, 1 on success. */ +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) static int extract_file_and_line(const DILineInfo &line_info, char **file, unsigned int *line) { @@ -69,13 +96,15 @@ static int extract_file_and_line(const DILineInfo &line= _info, char **file, *line =3D line_info.Line; return 1; } +#endif =20 extern "C" -int llvm_addr2line(const char *dso_name, u64 addr, - char **file, unsigned int *line, - bool unwind_inlines, - llvm_a2l_frame **inline_frames) +int llvm_addr2line(const char *dso_name __maybe_unused, u64 addr __maybe_u= nused, + char **file __maybe_unused, unsigned int *line __maybe_unused, + bool unwind_inlines __maybe_unused, + llvm_a2l_frame **inline_frames __maybe_unused) { +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) LLVMSymbolizer *symbolizer =3D get_symbolizer(); object::SectionedAddress sectioned_addr =3D { addr, @@ -135,8 +164,33 @@ int llvm_addr2line(const char *dso_name, u64 addr, return 0; return extract_file_and_line(*res_or_err, file, line); } +#elif defined(HAVE_LIBLLVM_DYNAMIC) + static bool fn_init; + static int (*fn)(const char *dso_name, u64 addr, + char **file, unsigned int *line, + bool unwind_inlines, + llvm_a2l_frame **inline_frames); + + if (!fn_init) { + void * handle =3D perf_llvm_c_helpers_dll_handle(); + + if (!handle) + return 0; + + fn =3D reinterpret_cast(dlsym(handle, "llvm_addr2line")); + if (!fn) + pr_debug("dlsym failed for llvm_addr2line\n"); + fn_init =3D true; + } + if (!fn) + return 0; + return fn(dso_name, addr, file, line, unwind_inlines, inline_frames); +#else + return 0; +#endif } =20 +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) static char * make_symbol_relative_string(struct dso *dso, const char *sym_name, u64 addr, u64 base_addr) @@ -158,10 +212,13 @@ make_symbol_relative_string(struct dso *dso, const ch= ar *sym_name, return strdup(sym_name); } } +#endif =20 extern "C" -char *llvm_name_for_code(struct dso *dso, const char *dso_name, u64 addr) +char *llvm_name_for_code(struct dso *dso __maybe_unused, const char *dso_n= ame __maybe_unused, + u64 addr __maybe_unused) { +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) LLVMSymbolizer *symbolizer =3D get_symbolizer(); object::SectionedAddress sectioned_addr =3D { addr, @@ -175,11 +232,34 @@ char *llvm_name_for_code(struct dso *dso, const char = *dso_name, u64 addr) return make_symbol_relative_string( dso, res_or_err->FunctionName.c_str(), addr, res_or_err->StartAddress ? *res_or_err->StartAddress : 0); +#elif defined(HAVE_LIBLLVM_DYNAMIC) + static bool fn_init; + static char *(*fn)(struct dso *dso, const char *dso_name, u64 addr); + + if (!fn_init) { + void * handle =3D perf_llvm_c_helpers_dll_handle(); + + if (!handle) + return NULL; + + fn =3D reinterpret_cast(dlsym(handle, "llvm_name_for_code"= )); + if (!fn) + pr_debug("dlsym failed for llvm_name_for_code\n"); + fn_init =3D true; + } + if (!fn) + return NULL; + return fn(dso, dso_name, addr); +#else + return 0; +#endif } =20 extern "C" -char *llvm_name_for_data(struct dso *dso, const char *dso_name, u64 addr) +char *llvm_name_for_data(struct dso *dso __maybe_unused, const char *dso_n= ame __maybe_unused, + u64 addr __maybe_unused) { +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) LLVMSymbolizer *symbolizer =3D get_symbolizer(); object::SectionedAddress sectioned_addr =3D { addr, @@ -193,4 +273,25 @@ char *llvm_name_for_data(struct dso *dso, const char *= dso_name, u64 addr) return make_symbol_relative_string( dso, res_or_err->Name.c_str(), addr, res_or_err->Start); +#elif defined(HAVE_LIBLLVM_DYNAMIC) + static bool fn_init; + static char *(*fn)(struct dso *dso, const char *dso_name, u64 addr); + + if (!fn_init) { + void * handle =3D perf_llvm_c_helpers_dll_handle(); + + if (!handle) + return NULL; + + fn =3D reinterpret_cast(dlsym(handle, "llvm_name_for_data"= )); + if (!fn) + pr_debug("dlsym failed for llvm_name_for_data\n"); + fn_init =3D true; + } + if (!fn) + return NULL; + return fn(dso, dso_name, addr); +#else + return 0; +#endif } diff --git a/tools/perf/util/llvm.c b/tools/perf/util/llvm.c index 565cad1969e5..10def66ce8b2 100644 --- a/tools/perf/util/llvm.c +++ b/tools/perf/util/llvm.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include "llvm.h" +#include "llvm-c-helpers.h" #include "annotate.h" #include "debug.h" #include "dso.h" @@ -7,18 +8,244 @@ #include "namespaces.h" #include "srcline.h" #include "symbol.h" +#include #include #include +#include #include #include =20 -#ifdef HAVE_LIBLLVM_SUPPORT -#include "llvm-c-helpers.h" +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) #include #include +#else +typedef void *LLVMDisasmContextRef; +typedef int (*LLVMOpInfoCallback)(void *dis_info, uint64_t pc, uint64_t of= fset, + uint64_t op_size, uint64_t inst_size, + int tag_type, void *tag_buf); +typedef const char *(*LLVMSymbolLookupCallback)(void *dis_info, + uint64_t reference_value, + uint64_t *reference_type, + uint64_t reference_pc, + const char **reference_name); +#define LLVMDisassembler_ReferenceType_InOut_None 0 +#define LLVMDisassembler_ReferenceType_In_Branch 1 +#define LLVMDisassembler_ReferenceType_In_PCrel_Load 2 +#define LLVMDisassembler_Option_PrintImmHex 2 +#define LLVMDisassembler_Option_AsmPrinterVariant 4 +const char *llvm_targets[] =3D { + "AMDGPU", + "ARM", + "AVR", + "BPF", + "Hexagon", + "Lanai", + "LoongArch", + "Mips", + "MSP430", + "NVPTX", + "PowerPC", + "RISCV", + "Sparc", + "SystemZ", + "VE", + "WebAssembly", + "X86", + "XCore", + "M68k", + "Xtensa", +}; +#endif + +#if !defined(HAVE_LIBLLVM_SUPPORT) || defined(HAVE_LIBLLVM_DYNAMIC) +static void *perf_llvm_dll_handle(void) +{ + static bool dll_handle_init; + static void *dll_handle; + + if (!dll_handle_init) { + dll_handle_init =3D true; + dll_handle =3D dlopen("libLLVM.so", RTLD_LAZY); + if (!dll_handle) + pr_debug("dlopen failed for libLLVM.so\n"); + } + return dll_handle; +} +#endif + +#if !defined(HAVE_LIBLLVM_SUPPORT) || defined(HAVE_LIBLLVM_DYNAMIC) +static void *perf_llvm_dll_fun(const char *fmt, const char *target) +{ + char buf[128]; + void *fn; + + snprintf(buf, sizeof(buf), fmt, target); + fn =3D dlsym(perf_llvm_dll_handle(), buf); + if (!fn) + pr_debug("dlsym failed for %s\n", buf); + + return fn; +} +#endif + +static void perf_LLVMInitializeAllTargetInfos(void) +{ +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) + LLVMInitializeAllTargetInfos(); +#else + /* LLVMInitializeAllTargetInfos is a header file function not available a= s a symbol. */ + static bool done_init; + + if (done_init) + return; + + for (size_t i =3D 0; i < ARRAY_SIZE(llvm_targets); i++) { + void (*fn)(void) =3D perf_llvm_dll_fun("LLVMInitialize%sTargetInfo", + llvm_targets[i]); + + if (!fn) + continue; + fn(); + } + done_init =3D true; +#endif +} + +static void perf_LLVMInitializeAllTargetMCs(void) +{ +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) + LLVMInitializeAllTargetMCs(); +#else + /* LLVMInitializeAllTargetMCs is a header file function not available as = a symbol. */ + static bool done_init; + + if (done_init) + return; + + for (size_t i =3D 0; i < ARRAY_SIZE(llvm_targets); i++) { + void (*fn)(void) =3D perf_llvm_dll_fun("LLVMInitialize%sTargetMC", + llvm_targets[i]); + + if (!fn) + continue; + fn(); + } + done_init =3D true; +#endif +} + +static void perf_LLVMInitializeAllDisassemblers(void) +{ +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) + LLVMInitializeAllDisassemblers(); +#else + /* LLVMInitializeAllDisassemblers is a header file function not available= as a symbol. */ + static bool done_init; + + if (done_init) + return; + + for (size_t i =3D 0; i < ARRAY_SIZE(llvm_targets); i++) { + void (*fn)(void) =3D perf_llvm_dll_fun("LLVMInitialize%sDisassembler", + llvm_targets[i]); + + if (!fn) + continue; + fn(); + } + done_init =3D true; +#endif +} + +static LLVMDisasmContextRef perf_LLVMCreateDisasm(const char *triple_name,= void *dis_info, + int tag_type, LLVMOpInfoCallback get_op_info, + LLVMSymbolLookupCallback symbol_lookup) +{ +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) + return LLVMCreateDisasm(triple_name, dis_info, tag_type, get_op_info, sym= bol_lookup); +#else + static bool fn_init; + static LLVMDisasmContextRef (*fn)(const char *triple_name, void *dis_info, + int tag_type, LLVMOpInfoCallback get_op_info, + LLVMSymbolLookupCallback symbol_lookup); + + if (!fn_init) { + fn =3D dlsym(perf_llvm_dll_handle(), "LLVMCreateDisasm"); + if (!fn) + pr_debug("dlsym failed for LLVMCreateDisasm\n"); + fn_init =3D true; + } + if (!fn) + return NULL; + return fn(triple_name, dis_info, tag_type, get_op_info, symbol_lookup); +#endif +} + +static int perf_LLVMSetDisasmOptions(LLVMDisasmContextRef context, uint64_= t options) +{ +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) + return LLVMSetDisasmOptions(context, options); +#else + static bool fn_init; + static int (*fn)(LLVMDisasmContextRef context, uint64_t options); + + if (!fn_init) { + fn =3D dlsym(perf_llvm_dll_handle(), "LLVMSetDisasmOptions"); + if (!fn) + pr_debug("dlsym failed for LLVMSetDisasmOptions\n"); + fn_init =3D true; + } + if (!fn) + return 0; + return fn(context, options); +#endif +} + +static size_t perf_LLVMDisasmInstruction(LLVMDisasmContextRef context, uin= t8_t *bytes, + uint64_t bytes_size, uint64_t pc, + char *out_string, size_t out_string_size) +{ +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) + return LLVMDisasmInstruction(context, bytes, bytes_size, pc, out_string, = out_string_size); +#else + static bool fn_init; + static int (*fn)(LLVMDisasmContextRef context, uint8_t *bytes, + uint64_t bytes_size, uint64_t pc, + char *out_string, size_t out_string_size); + + if (!fn_init) { + fn =3D dlsym(perf_llvm_dll_handle(), "LLVMDisasmInstruction"); + if (!fn) + pr_debug("dlsym failed for LLVMDisasmInstruction\n"); + fn_init =3D true; + } + if (!fn) + return 0; + return fn(context, bytes, bytes_size, pc, out_string, out_string_size); +#endif +} + +static void perf_LLVMDisasmDispose(LLVMDisasmContextRef context) +{ +#if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) + LLVMDisasmDispose(context); +#else + static bool fn_init; + static int (*fn)(LLVMDisasmContextRef context); + + if (!fn_init) { + fn =3D dlsym(perf_llvm_dll_handle(), "LLVMDisasmDispose"); + if (!fn) + pr_debug("dlsym failed for LLVMDisasmDispose\n"); + fn_init =3D true; + } + if (!fn) + return; + fn(context); #endif +} + =20 -#ifdef HAVE_LIBLLVM_SUPPORT static void free_llvm_inline_frames(struct llvm_a2l_frame *inline_frames, int num_frames) { @@ -30,14 +257,12 @@ static void free_llvm_inline_frames(struct llvm_a2l_fr= ame *inline_frames, zfree(&inline_frames); } } -#endif =20 int llvm__addr2line(const char *dso_name __maybe_unused, u64 addr __maybe_= unused, char **file __maybe_unused, unsigned int *line __maybe_unused, struct dso *dso __maybe_unused, bool unwind_inlines __maybe_unused, struct inline_node *node __maybe_unused, struct symbol *sym __maybe= _unused) { -#ifdef HAVE_LIBLLVM_SUPPORT struct llvm_a2l_frame *inline_frames =3D NULL; int num_frames =3D llvm_addr2line(dso_name, addr, file, line, node && unwind_inlines, &inline_frames); @@ -65,9 +290,6 @@ int llvm__addr2line(const char *dso_name __maybe_unused,= u64 addr __maybe_unused free_llvm_inline_frames(inline_frames, num_frames); =20 return num_frames; -#else - return -1; -#endif } =20 static void init_llvm(void) @@ -75,9 +297,9 @@ static void init_llvm(void) static bool init; =20 if (!init) { - LLVMInitializeAllTargetInfos(); - LLVMInitializeAllTargetMCs(); - LLVMInitializeAllDisassemblers(); + perf_LLVMInitializeAllTargetInfos(); + perf_LLVMInitializeAllTargetMCs(); + perf_LLVMInitializeAllDisassemblers(); init =3D true; } } @@ -90,7 +312,6 @@ static void init_llvm(void) * should add some textual annotation for after the instruction. The caller * will use this information to add the actual annotation. */ -#ifdef HAVE_LIBLLVM_SUPPORT struct symbol_lookup_storage { u64 branch_addr; u64 pcrel_load_addr; @@ -111,12 +332,10 @@ symbol_lookup_callback(void *disinfo, uint64_t value, *ref_type =3D LLVMDisassembler_ReferenceType_InOut_None; return NULL; } -#endif =20 int symbol__disassemble_llvm(const char *filename, struct symbol *sym, struct annotate_args *args __maybe_unused) { -#ifdef HAVE_LIBLLVM_SUPPORT struct annotation *notes =3D symbol__annotation(sym); struct map *map =3D args->ms.map; struct dso *dso =3D map__dso(map); @@ -149,15 +368,15 @@ int symbol__disassemble_llvm(const char *filename, st= ruct symbol *sym, if (arch__is(args->arch, "x86")) { const char *triplet =3D is_64bit ? "x86_64-pc-linux" : "i686-pc-linux"; =20 - disasm =3D LLVMCreateDisasm(triplet, &storage, /*tag_type=3D*/0, - /*get_op_info=3D*/NULL, symbol_lookup_callback); + disasm =3D perf_LLVMCreateDisasm(triplet, &storage, /*tag_type=3D*/0, + /*get_op_info=3D*/NULL, symbol_lookup_callback); } else { char triplet[64]; =20 scnprintf(triplet, sizeof(triplet), "%s-linux-gnu", args->arch->name); - disasm =3D LLVMCreateDisasm(triplet, &storage, /*tag_type=3D*/0, - /*get_op_info=3D*/NULL, symbol_lookup_callback); + disasm =3D perf_LLVMCreateDisasm(triplet, &storage, /*tag_type=3D*/0, + /*get_op_info=3D*/NULL, symbol_lookup_callback); } =20 if (disasm =3D=3D NULL) @@ -165,8 +384,7 @@ int symbol__disassemble_llvm(const char *filename, stru= ct symbol *sym, =20 if (args->options->disassembler_style && !strcmp(args->options->disassembler_style, "intel")) - LLVMSetDisasmOptions(disasm, - LLVMDisassembler_Option_AsmPrinterVariant); + perf_LLVMSetDisasmOptions(disasm, LLVMDisassembler_Option_AsmPrinterVari= ant); =20 /* * This needs to be set after AsmPrinterVariant, due to a bug in LLVM; @@ -174,7 +392,7 @@ int symbol__disassemble_llvm(const char *filename, stru= ct symbol *sym, * forget about the PrintImmHex flag (which is applied before if both * are given to the same call). */ - LLVMSetDisasmOptions(disasm, LLVMDisassembler_Option_PrintImmHex); + perf_LLVMSetDisasmOptions(disasm, LLVMDisassembler_Option_PrintImmHex); =20 /* add the function address and name */ scnprintf(disasm_buf, sizeof(disasm_buf), "%#"PRIx64" <%s>:", @@ -203,9 +421,9 @@ int symbol__disassemble_llvm(const char *filename, stru= ct symbol *sym, * LLVM's API has the code be disassembled as non-const, cast * here as we may be disassembling from mapped read-only memory. */ - ins_len =3D LLVMDisasmInstruction(disasm, (u8 *)(buf + offset), - buf_len - offset, pc, - disasm_buf, sizeof(disasm_buf)); + ins_len =3D perf_LLVMDisasmInstruction(disasm, (u8 *)(buf + offset), + buf_len - offset, pc, + disasm_buf, sizeof(disasm_buf)); if (ins_len =3D=3D 0) goto err; disasm_len =3D strlen(disasm_buf); @@ -261,13 +479,8 @@ int symbol__disassemble_llvm(const char *filename, str= uct symbol *sym, ret =3D 0; =20 err: - LLVMDisasmDispose(disasm); + perf_LLVMDisasmDispose(disasm); free(code_buf); free(line_storage); return ret; -#else // HAVE_LIBLLVM_SUPPORT - pr_debug("The LLVM disassembler isn't linked in for %s in %s\n", - sym->name, filename); - return -1; -#endif } --=20 2.51.0.618.g983fd99d29-goog From nobody Wed Dec 17 19:20:45 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (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 98B0F2C2AA2 for ; Sun, 5 Oct 2025 21:22:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699366; cv=none; b=fvt5LJwYURvgbpnkWRXWU5q+B5JFI6ZJf+f1WeaTeqQWSwRLhTcVRnjxEHA9I9ZWKVldA5vJ8d6Rm6SqDxO7C9U1QzVCAEEAufGq7VGLdwjK1ObZx64VHF3ORB1Ncc8KRhv+9PR5K0s/jNsKKHG9QFCoeNjZFs7DPk97oZ/rDbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759699366; c=relaxed/simple; bh=JtyVHmPL3jUJI/IzEWGwXRcaHoNXfDEMzuW51+hNtlE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=P79DoaD4blZvRhlpARUHWpNKz49YJPSdUQ6f6o8yM4c9N6IDEWHJVfEeYrMrw8Hb1DNU9dkRcIGKm4Mxz+a5/33orRg9cQ+vY0AZoXiVKau6e9MgX+IL0MzZM1sQjIA68FQ+d3C+3YuyCzlWES3kq0fg+WxWMgG58Ac+OarDbW0= 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=PM7Ujz7E; arc=none smtp.client-ip=209.85.214.201 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="PM7Ujz7E" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-272b7bdf41fso50257595ad.0 for ; Sun, 05 Oct 2025 14:22:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759699364; x=1760304164; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=FmItgy1P9WGpafk8XeDqIHVArviA1RcMS4iYivsr3B4=; b=PM7Ujz7EIDYMTlFzBx2tpa2xGeyAOpd/vZrdL0acEg4DLRTTYDcl7U/5HRnio2iZJ9 6nztgmBX52JrJfGi/L//uxobmXpVIxSsOBEdFrpwhUrOBuIPcadzHX5REG+mtqx3SW+Y ynEeIBpSsSKh41a8DhNiKrtSuw9eqZBanzDXi3vew11D9240NNb78jLwXp3HIbP3SrnN Fk5rviKXbJpdq2UOyys9dZn901JP1Hnpqp3+9Grv6PDL7qaORX3AyR5y2M6TfSNbwMCM O8AAvqYfK6dUBX5JLQTL1LFRoYiSNVym1ApTj8Yk3QPXQ4ntYLW1jkvA2kOs7PHCfCg0 /ILA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759699364; x=1760304164; h=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; bh=FmItgy1P9WGpafk8XeDqIHVArviA1RcMS4iYivsr3B4=; b=QzOpw2QEC8hhxOHquCvsEjXawwOO/pnDenpv/q1pW/8taYK9y3w4jk/+n27jpAnT5q iCodson/8G66ly9S5AVKM+DWNf6i1pWD3uzprKEoIhfIkBnUI2V55hnPsiAalvMDso2S ffX/rJsLR5OXiHbCwJMymge5+F0d0RNvdB5Ob9yK/BkXvdUz//x5wFVYoWT3yajHtHz1 dq27YA2boCnMUwwhj8cP5xG/1diAzvmZ3jWuHwnlmTvMwxNwM8W8q+iw1k4wawVpyLKI vl6Ktn8U222kfrNcDFZQSjc6OOhKyaerxll3cLR9ETG6EPued3Wg+ofQ7jVC5fI8aZrF qBLA== X-Forwarded-Encrypted: i=1; AJvYcCXWXDh5kqzvzTeySZuxolJwz8LhloFn2xb9LOEDfLIJeWomVluXfoJnSSddAckBIPj8EIiPT6hChPvomU4=@vger.kernel.org X-Gm-Message-State: AOJu0YxYGfUbIl/hKPF8oIA/qjd50C5dfhjb77hgbLUciKfstVbpqL3R 7DLAZisf4QTtAXEt/eegra9mOfcwDBT/15BEG0IIO9nT4GcN8giBBtcTu4Ord7CQ1XiUkVhd67F TpgdeHgy/fw== X-Google-Smtp-Source: AGHT+IGsMqltbHKfLWsnUZm01yGw+1d1vWu8rl8Y/QDO7Xhs/2xgL98a4kKts2uqZh0Bfj3O8zJRQnJnRXI3 X-Received: from plwg11.prod.google.com ([2002:a17:902:f74b:b0:25c:22e5:1a27]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:2b0f:b0:258:c13d:9b1a with SMTP id d9443c01a7336-28e9a61ab55mr111861225ad.41.1759699363859; Sun, 05 Oct 2025 14:22:43 -0700 (PDT) Date: Sun, 5 Oct 2025 14:22:12 -0700 In-Reply-To: <20251005212212.2892175-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: <20251005212212.2892175-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.618.g983fd99d29-goog Message-ID: <20251005212212.2892175-12-irogers@google.com> Subject: [PATCH v7 11/11] perf llvm: Mangle libperf-llvm.so function names From: Ian Rogers To: Arnaldo Carvalho de Melo , Peter Zijlstra , Ingo Molnar , Namhyung Kim , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For a function like llvm_addr2line having the libperf-llvm.so exported symbol named llvm_addr2line meant that the perf llvm_addr2line could sometimes erroneously be returned. This led to infinite recursion and eventual stack overflow. To avoid this conflict add a new BUILDING_PERF_LLVMSO when libperf-llvm.so is being built and use it to alter the behavior of MANGLE_PERF_LLVM_API, a macro that prefixes the name when libperf-llvm.so is being built. The prefixed named avoids the name collision. Signed-off-by: Ian Rogers --- tools/perf/Makefile.perf | 3 ++- tools/perf/util/llvm-c-helpers.cpp | 29 ++++++++++++++++++----------- tools/perf/util/llvm-c-helpers.h | 24 ++++++++++++++++-------- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index fb888702bace..7e6054072cf1 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -1002,7 +1002,8 @@ $(LIBSYMBOL)-clean: $(Q)$(RM) -r -- $(LIBSYMBOL_OUTPUT) =20 ifdef LIBLLVM_DYNAMIC -LIBPERF_LLVM_CXXFLAGS :=3D $(call filter-out,-DHAVE_LIBLLVM_DYNAMIC,$(CXXF= LAGS)) -DHAVE_LIBLLVM_SUPPORT +LIBPERF_LLVM_CXXFLAGS :=3D $(call filter-out,-DHAVE_LIBLLVM_DYNAMIC,$(CXXF= LAGS)) +LIBPERF_LLVM_CXXFLAGS +=3D -DHAVE_LIBLLVM_SUPPORT -DBUILDING_PERF_LLVMSO LIBPERF_LLVM_LIBS =3D -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM) -lstdc= ++ =20 $(OUTPUT)$(LIBPERF_LLVM): util/llvm-c-helpers.cpp diff --git a/tools/perf/util/llvm-c-helpers.cpp b/tools/perf/util/llvm-c-he= lpers.cpp index 5a6f76e6b705..8cea380be5c2 100644 --- a/tools/perf/util/llvm-c-helpers.cpp +++ b/tools/perf/util/llvm-c-helpers.cpp @@ -99,10 +99,12 @@ static int extract_file_and_line(const DILineInfo &line= _info, char **file, #endif =20 extern "C" -int llvm_addr2line(const char *dso_name __maybe_unused, u64 addr __maybe_u= nused, - char **file __maybe_unused, unsigned int *line __maybe_unused, - bool unwind_inlines __maybe_unused, - llvm_a2l_frame **inline_frames __maybe_unused) +int MANGLE_PERF_LLVM_API(llvm_addr2line)(const char *dso_name __maybe_unus= ed, + u64 addr __maybe_unused, + char **file __maybe_unused, + unsigned int *line __maybe_unused, + bool unwind_inlines __maybe_unuse= d, + llvm_a2l_frame **inline_frames __= maybe_unused) { #if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) LLVMSymbolizer *symbolizer =3D get_symbolizer(); @@ -177,7 +179,8 @@ int llvm_addr2line(const char *dso_name __maybe_unused,= u64 addr __maybe_unused, if (!handle) return 0; =20 - fn =3D reinterpret_cast(dlsym(handle, "llvm_addr2line")); + fn =3D reinterpret_cast( + dlsym(handle, MANGLE_PERF_LLVM_API_STR(llvm_addr2line))); if (!fn) pr_debug("dlsym failed for llvm_addr2line\n"); fn_init =3D true; @@ -215,8 +218,9 @@ make_symbol_relative_string(struct dso *dso, const char= *sym_name, #endif =20 extern "C" -char *llvm_name_for_code(struct dso *dso __maybe_unused, const char *dso_n= ame __maybe_unused, - u64 addr __maybe_unused) +char *MANGLE_PERF_LLVM_API(llvm_name_for_code)(struct dso *dso __maybe_unu= sed, + const char *dso_name __maybe_unused, + u64 addr __maybe_unused) { #if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) LLVMSymbolizer *symbolizer =3D get_symbolizer(); @@ -242,7 +246,8 @@ char *llvm_name_for_code(struct dso *dso __maybe_unused= , const char *dso_name __ if (!handle) return NULL; =20 - fn =3D reinterpret_cast(dlsym(handle, "llvm_name_for_code"= )); + fn =3D reinterpret_cast( + dlsym(handle, MANGLE_PERF_LLVM_API_STR(llvm_name_for_code))); if (!fn) pr_debug("dlsym failed for llvm_name_for_code\n"); fn_init =3D true; @@ -256,8 +261,9 @@ char *llvm_name_for_code(struct dso *dso __maybe_unused= , const char *dso_name __ } =20 extern "C" -char *llvm_name_for_data(struct dso *dso __maybe_unused, const char *dso_n= ame __maybe_unused, - u64 addr __maybe_unused) +char *MANGLE_PERF_LLVM_API(llvm_name_for_data)(struct dso *dso __maybe_unu= sed, + const char *dso_name __maybe_unused, + u64 addr __maybe_unused) { #if defined(HAVE_LIBLLVM_SUPPORT) && !defined(HAVE_LIBLLVM_DYNAMIC) LLVMSymbolizer *symbolizer =3D get_symbolizer(); @@ -283,7 +289,8 @@ char *llvm_name_for_data(struct dso *dso __maybe_unused= , const char *dso_name __ if (!handle) return NULL; =20 - fn =3D reinterpret_cast(dlsym(handle, "llvm_name_for_data"= )); + fn =3D reinterpret_cast( + dlsym(handle, MANGLE_PERF_LLVM_API_STR(llvm_name_for_data))); if (!fn) pr_debug("dlsym failed for llvm_name_for_data\n"); fn_init =3D true; diff --git a/tools/perf/util/llvm-c-helpers.h b/tools/perf/util/llvm-c-help= ers.h index d2b99637a28a..cfcfd540cdae 100644 --- a/tools/perf/util/llvm-c-helpers.h +++ b/tools/perf/util/llvm-c-helpers.h @@ -13,6 +13,14 @@ extern "C" { #endif =20 +/* Support name mangling so that libperf_llvm.so's names don't match those= in perf. */ +#ifdef BUILDING_PERF_LLVMSO +#define MANGLE_PERF_LLVM_API(x) PERF_LLVM_SO_ ## x +#else +#define MANGLE_PERF_LLVM_API(x) x +#endif +#define MANGLE_PERF_LLVM_API_STR(x) "PERF_LLVM_SO_" #x + struct dso; =20 struct llvm_a2l_frame { @@ -37,12 +45,12 @@ struct llvm_a2l_frame { * a newly allocated array with that length. The caller is then responsible * 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); +int MANGLE_PERF_LLVM_API(llvm_addr2line)(const char *dso_name, + u64 addr, + char **file, + unsigned int *line, + bool unwind_inlines, + struct llvm_a2l_frame **inline_frames); =20 /* * Simple symbolizers for addresses; will convert something like @@ -50,8 +58,8 @@ int llvm_addr2line(const char* dso_name, * * The returned value must be freed by the caller, with free(). */ -char *llvm_name_for_code(struct dso *dso, const char *dso_name, u64 addr); -char *llvm_name_for_data(struct dso *dso, const char *dso_name, u64 addr); +char *MANGLE_PERF_LLVM_API(llvm_name_for_code)(struct dso *dso, const char= *dso_name, u64 addr); +char *MANGLE_PERF_LLVM_API(llvm_name_for_data)(struct dso *dso, const char= *dso_name, u64 addr); =20 #ifdef __cplusplus } --=20 2.51.0.618.g983fd99d29-goog