Linux Perf Users
 help / color / mirror / Atom feed
From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	 Arnaldo Carvalho de Melo <acme@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
	 Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	 James Clark <james.clark@linaro.org>,
	Nick Terrell <terrelln@fb.com>,  David Sterba <dsterba@suse.com>,
	Nathan Chancellor <nathan@kernel.org>,
	Tomas Glozar <tglozar@redhat.com>,
	 Blake Jones <blakejones@google.com>,
	Dmitrii Dolgov <9erthalion6@gmail.com>,
	 Alexandre Chartre <alexandre.chartre@oracle.com>,
	Costa Shulyupin <costa.shul@redhat.com>,
	 Yuzhuo Jing <yuzhuo@google.com>,
	Michael Jeanson <mjeanson@efficios.com>,
	Leo Yan <leo.yan@arm.com>,  Tianyou Li <tianyou.li@intel.com>,
	Zecheng Li <zecheng@google.com>,
	 Rong Bao <rong.bao@csmantle.top>,
	linux-kernel@vger.kernel.org,  linux-perf-users@vger.kernel.org,
	bpf@vger.kernel.org
Subject: [PATCH v1 6/7] perf annotate: Support BPF JIT disassembly via genelf
Date: Mon,  8 Jun 2026 22:17:58 -0700	[thread overview]
Message-ID: <20260609051759.405027-7-irogers@google.com> (raw)
In-Reply-To: <20260609051759.405027-1-irogers@google.com>

For in-memory BPF DSOs (DSO_BINARY_TYPE__BPF_PROG_INFO), write the
JITted instruction buffer to a temporary ELF file on disk using the
existing genelf framework (jit_write_elf). Reroute disassembly to
this temporary ELF file, allowing objdump and libasm to disassemble it
natively. Clean up the temporary file afterward.

Assisted-by: Antigravity:Google Gemini 3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/disasm.c | 107 ++++++++++++++++++++++++++++++++++++---
 tools/perf/util/disasm.h |   1 +
 2 files changed, 101 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index 42af3603fdff..8c78ef765787 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -23,6 +23,9 @@
 #include "debug.h"
 #include "disasm.h"
 #include "libasm.h"
+#ifdef HAVE_LIBELF_SUPPORT
+#include "genelf.h"
+#endif
 #include "dso.h"
 #include "dwarf-regs.h"
 #include "env.h"
@@ -1420,7 +1423,7 @@ static int symbol__disassemble_objdump(const char *filename, struct symbol *sym,
 	struct child_process objdump_process;
 	int err;
 
-	if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO)
+	if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO && !args->is_temp_elf)
 		return symbol__disassemble_bpf_libbfd(sym, args);
 
 	if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE)
@@ -1540,6 +1543,41 @@ static int symbol__disassemble_objdump(const char *filename, struct symbol *sym,
 	return err;
 }
 
+#ifdef HAVE_LIBELF_SUPPORT
+static int symbol__create_bpf_temp_elf(const char *filename, struct symbol *sym,
+				       struct annotate_args *args,
+				       char *tmp_elf, size_t tmp_elf_sz)
+{
+	struct map *map = args->ms->map;
+	struct dso *dso = map__dso(map);
+	u8 *code_buf = NULL;
+	const u8 *buf;
+	u64 buf_len;
+	bool is_64bit;
+	int tmp_fd;
+	int err = -1;
+
+	buf = dso__read_symbol(dso, filename, map, sym, &code_buf, &buf_len, &is_64bit);
+	if (!buf)
+		return -1;
+
+	snprintf(tmp_elf, tmp_elf_sz, "/tmp/perf-bpf-XXXXXX");
+	tmp_fd = mkstemp(tmp_elf);
+	if (tmp_fd >= 0) {
+		if (jit_write_elf(tmp_fd, map__rip_2objdump(map, sym->start),
+				  sym->name, buf, buf_len,
+				  NULL, 0, NULL, 0, 0) == 0) {
+			err = 0;
+		}
+		close(tmp_fd);
+		if (err)
+			unlink(tmp_elf);
+	}
+	free(code_buf);
+	return err;
+}
+#endif
+
 int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
 {
 	struct annotation_options *options = args->options;
@@ -1549,8 +1587,11 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
 	bool delete_extract = false;
 	struct kcore_extract kce;
 	bool decomp = false;
-	int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
+	int err;
 
+	args->is_temp_elf = false;
+
+	err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
 	if (err)
 		return err;
 
@@ -1605,7 +1646,25 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
 
 	/* FIXME: LLVM and CAPSTONE should support source code */
 	if (options->annotate_src && !options->hide_src_code) {
-		err = symbol__disassemble_objdump(symfs_filename, sym, args);
+		const char *disasm_filename = symfs_filename;
+		bool is_temp = false;
+		char tmp_elf[PATH_MAX];
+
+#ifdef HAVE_LIBELF_SUPPORT
+		if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) {
+			if (symbol__create_bpf_temp_elf(symfs_filename, sym, args,
+							tmp_elf, sizeof(tmp_elf)) == 0) {
+				disasm_filename = tmp_elf;
+				is_temp = true;
+				args->is_temp_elf = true;
+			}
+		}
+#endif
+		err = symbol__disassemble_objdump(disasm_filename, sym, args);
+		if (is_temp) {
+			unlink(tmp_elf);
+			args->is_temp_elf = false;
+		}
 		if (err == 0)
 			goto out_remove_tmp;
 	}
@@ -1613,29 +1672,63 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
 	err = -1;
 	for (u8 i = 0; i < ARRAY_SIZE(options->disassemblers) && err != 0; i++) {
 		enum perf_disassembler dis = options->disassemblers[i];
+		const char *disasm_filename = symfs_filename;
+		bool is_temp = false;
+		char tmp_elf[PATH_MAX];
+
+		switch (dis) {
+		case PERF_DISASM_LIBASM:
+		case PERF_DISASM_OBJDUMP:
+#ifdef HAVE_LIBELF_SUPPORT
+			if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) {
+				if (symbol__create_bpf_temp_elf(symfs_filename, sym, args,
+								tmp_elf, sizeof(tmp_elf)) == 0) {
+					disasm_filename = tmp_elf;
+					is_temp = true;
+					args->is_temp_elf = true;
+				}
+			}
+#endif
+			break;
+		case PERF_DISASM_LLVM:
+		case PERF_DISASM_CAPSTONE:
+		case PERF_DISASM_UNKNOWN:
+		default:
+			break;
+		}
 
 		switch (dis) {
 		case PERF_DISASM_LLVM:
 			args->options->disassembler_used = PERF_DISASM_LLVM;
-			err = symbol__disassemble_llvm(symfs_filename, sym, args);
+			err = symbol__disassemble_llvm(disasm_filename, sym, args);
 			break;
 		case PERF_DISASM_CAPSTONE:
 			args->options->disassembler_used = PERF_DISASM_CAPSTONE;
-			err = symbol__disassemble_capstone(symfs_filename, sym, args);
+			err = symbol__disassemble_capstone(disasm_filename, sym, args);
 			break;
 		case PERF_DISASM_LIBASM:
 			args->options->disassembler_used = PERF_DISASM_LIBASM;
-			err = symbol__disassemble_libasm(symfs_filename, sym, args);
+			err = symbol__disassemble_libasm(disasm_filename, sym, args);
 			break;
 		case PERF_DISASM_OBJDUMP:
 			args->options->disassembler_used = PERF_DISASM_OBJDUMP;
-			err = symbol__disassemble_objdump(symfs_filename, sym, args);
+			err = symbol__disassemble_objdump(disasm_filename, sym, args);
 			break;
 		case PERF_DISASM_UNKNOWN: /* End of disassemblers. */
 		default:
 			args->options->disassembler_used = PERF_DISASM_UNKNOWN;
+			if (is_temp) {
+				unlink(tmp_elf);
+				args->is_temp_elf = false;
+			}
 			goto out_remove_tmp;
 		}
+
+		if (is_temp) {
+			unlink(tmp_elf);
+			args->is_temp_elf = false;
+		}
+
 		if (err == 0)
 			pr_debug("Disassembled with %s\n", perf_disassembler__strs[dis]);
 	}
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index 25756e3f47e4..32a5b3f5d1c6 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -106,6 +106,7 @@ struct annotate_args {
 	char			  *line;
 	int			  line_nr;
 	char			  *fileloc;
+	bool			  is_temp_elf;
 };
 
 const struct arch *arch__find(uint16_t e_machine, uint32_t e_flags, const char *cpuid);
-- 
2.54.0.1064.gd145956f57-goog


  parent reply	other threads:[~2026-06-09  5:18 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-09  5:17 [PATCH v1 0/7] perf annotate: Add elfutils libasm disassembler backend Ian Rogers
2026-06-09  5:17 ` [PATCH v1 1/7] tools build: Add feature check for elfutils libasm Ian Rogers
2026-06-09  5:28   ` sashiko-bot
2026-06-09  5:17 ` [PATCH v1 2/7] perf build: Add build support and capability " Ian Rogers
2026-06-09  5:28   ` sashiko-bot
2026-06-09  5:17 ` [PATCH v1 3/7] perf annotate: Implement elfutils libasm disassembler backend Ian Rogers
2026-06-09  5:30   ` sashiko-bot
2026-06-09  5:17 ` [PATCH v1 4/7] perf annotate: Add --disassembler command-line option Ian Rogers
2026-06-09  5:17 ` [PATCH v1 5/7] perf test: Enhance annotate test coverage and isolate config Ian Rogers
2026-06-09  5:28   ` sashiko-bot
2026-06-09  5:17 ` Ian Rogers [this message]
2026-06-09  5:33   ` [PATCH v1 6/7] perf annotate: Support BPF JIT disassembly via genelf sashiko-bot
2026-06-09  5:17 ` [PATCH v1 7/7] perf test: Add BPF JIT annotation test coverage for all disassemblers Ian Rogers
2026-06-09  5:36   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260609051759.405027-7-irogers@google.com \
    --to=irogers@google.com \
    --cc=9erthalion6@gmail.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexandre.chartre@oracle.com \
    --cc=blakejones@google.com \
    --cc=bpf@vger.kernel.org \
    --cc=costa.shul@redhat.com \
    --cc=dsterba@suse.com \
    --cc=james.clark@linaro.org \
    --cc=jolsa@kernel.org \
    --cc=leo.yan@arm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=mjeanson@efficios.com \
    --cc=namhyung@kernel.org \
    --cc=nathan@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rong.bao@csmantle.top \
    --cc=terrelln@fb.com \
    --cc=tglozar@redhat.com \
    --cc=tianyou.li@intel.com \
    --cc=yuzhuo@google.com \
    --cc=zecheng@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox