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>,
Mark Rutland <mark.rutland@arm.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
Kan Liang <kan.liang@linux.intel.com>,
Nathan Chancellor <nathan@kernel.org>,
Nick Desaulniers <ndesaulniers@google.com>,
Bill Wendling <morbo@google.com>,
Justin Stitt <justinstitt@google.com>,
Aditya Gupta <adityag@linux.ibm.com>,
"Steinar H. Gunderson" <sesse@google.com>,
Charlie Jenkins <charlie@rivosinc.com>,
Changbin Du <changbin.du@huawei.com>,
"Masami Hiramatsu (Google)" <mhiramat@kernel.org>,
James Clark <james.clark@linaro.org>,
Kajol Jain <kjain@linux.ibm.com>,
Athira Rajeev <atrajeev@linux.vnet.ibm.com>,
Li Huafei <lihuafei1@huawei.com>,
Dmitry Vyukov <dvyukov@google.com>,
Andi Kleen <ak@linux.intel.com>,
Chaitanya S Prakash <chaitanyas.prakash@arm.com>,
linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
llvm@lists.linux.dev, Song Liu <song@kernel.org>,
bpf@vger.kernel.org
Subject: [PATCH v2 09/17] perf dso: Move read_symbol from llvm/capstone to dso
Date: Tue, 21 Jan 2025 22:23:24 -0800 [thread overview]
Message-ID: <20250122062332.577009-10-irogers@google.com> (raw)
In-Reply-To: <20250122062332.577009-1-irogers@google.com>
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 <irogers@google.com>
---
tools/perf/util/capstone.c | 64 +++++-----------------------
tools/perf/util/dso.c | 67 +++++++++++++++++++++++++++++
tools/perf/util/dso.h | 4 ++
tools/perf/util/llvm.c | 87 +++++++-------------------------------
4 files changed, 97 insertions(+), 125 deletions(-)
diff --git a/tools/perf/util/capstone.c b/tools/perf/util/capstone.c
index 8d65c7a55a8b..f103988184c8 100644
--- a/tools/perf/util/capstone.c
+++ b/tools/perf/util/capstone.c
@@ -434,66 +434,23 @@ static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg)
return 0;
}
-static u8 *
-read_symbol(const char *filename, struct map *map, struct symbol *sym,
- u64 *len, bool *is_64bit)
-{
- struct dso *dso = map__dso(map);
- struct nscookie nsc;
- u64 start = map__rip_2objdump(map, sym->start);
- u64 end = map__rip_2objdump(map, sym->end);
- int fd, count;
- u8 *buf = NULL;
- struct find_file_offset_data data = {
- .ip = start,
- };
-
- *is_64bit = false;
-
- nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
- fd = open(filename, O_RDONLY);
- nsinfo__mountns_exit(&nsc);
- if (fd < 0)
- return NULL;
-
- if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data,
- is_64bit) == 0)
- goto err;
-
- *len = end - start;
- buf = malloc(*len);
- if (buf == NULL)
- goto err;
-
- count = pread(fd, buf, *len, data.offset);
- close(fd);
- fd = -1;
-
- if ((u64)count != *len)
- goto err;
-
- return buf;
-
-err:
- if (fd >= 0)
- close(fd);
- free(buf);
- return NULL;
-}
-
int symbol__disassemble_capstone(const char *filename __maybe_unused,
struct symbol *sym __maybe_unused,
struct annotate_args *args __maybe_unused)
{
struct annotation *notes = symbol__annotation(sym);
struct map *map = args->ms.map;
+ struct dso *dso = map__dso(map);
u64 start = map__rip_2objdump(map, sym->start);
- u64 len;
u64 offset;
int i, count, free_count;
bool is_64bit = false;
bool needs_cs_close = false;
- u8 *buf = NULL;
+ /* Malloc-ed buffer containing instructions read from disk. */
+ u8 *code_buf = NULL;
+ /* Pointer to code to be disassembled. */
+ const u8 *buf;
+ u64 buf_len;
csh handle;
struct cs_insn *insn = NULL;
char disasm_buf[512];
@@ -503,7 +460,8 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
if (args->options->objdump_path)
return -1;
- buf = read_symbol(filename, map, sym, &len, &is_64bit);
+ buf = dso__read_symbol(dso, filename, map, sym,
+ &code_buf, &buf_len, &is_64bit);
if (buf == NULL)
return -1;
@@ -532,7 +490,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
needs_cs_close = true;
- free_count = count = perf_cs_disasm(handle, buf, len, start, len, &insn);
+ free_count = count = perf_cs_disasm(handle, buf, buf_len, start, buf_len, &insn);
for (i = 0, offset = 0; i < count; i++) {
int printed;
@@ -556,7 +514,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
}
/* It failed in the middle: probably due to unknown instructions */
- if (offset != len) {
+ if (offset != buf_len) {
struct list_head *list = ¬es->src->source;
/* Discard all lines and fallback to objdump */
@@ -575,7 +533,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
if (free_count > 0)
perf_cs_free(insn, free_count);
}
- free(buf);
+ free(code_buf);
return count < 0 ? count : 0;
err:
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 5c6e85fdae0d..0285904ed26d 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1664,3 +1664,70 @@ bool is_perf_pid_map_name(const char *dso_name)
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 = arg;
+
+ if (start <= data->ip && data->ip < start + len) {
+ data->offset = 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 = map__rip_2objdump(map, sym->start);
+ u64 end = map__rip_2objdump(map, sym->end);
+ int fd, count;
+ u8 *buf = NULL;
+ size_t len;
+ struct find_file_offset_data data = {
+ .ip = start,
+ };
+
+ *out_buf = NULL;
+ *out_buf_len = 0;
+ *is_64bit = false;
+
+ nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
+ fd = open(symfs_filename, O_RDONLY);
+ nsinfo__mountns_exit(&nsc);
+ if (fd < 0)
+ return NULL;
+
+ if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data, is_64bit) == 0)
+ goto err;
+
+ len = end - start;
+ buf = malloc(len);
+ if (buf == NULL)
+ goto err;
+
+ count = pread(fd, buf, len, data.offset);
+ close(fd);
+ fd = -1;
+
+ if ((u64)count != len)
+ goto err;
+
+ *out_buf = buf;
+ *out_buf_len = len;
+ return buf;
+
+err:
+ if (fd >= 0)
+ close(fd);
+ free(buf);
+ return NULL;
+}
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index bb8e8f444054..734e3a3d95f0 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -828,4 +828,8 @@ u64 dso__findnew_global_type(struct dso *dso, u64 addr, u64 offset);
bool perf_pid_map_tid(const char *dso_name, int *tid);
bool is_perf_pid_map_name(const char *dso_name);
+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 f6a8943b7c9d..a0774373f0d6 100644
--- a/tools/perf/util/llvm.c
+++ b/tools/perf/util/llvm.c
@@ -296,71 +296,6 @@ void dso__free_a2l_llvm(struct dso *dso __maybe_unused)
/* Nothing to free. */
}
-
-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 = arg;
-
- if (start <= data->ip && data->ip < start + len) {
- data->offset = 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 = map__dso(map);
- struct nscookie nsc;
- u64 start = map__rip_2objdump(map, sym->start);
- u64 end = map__rip_2objdump(map, sym->end);
- int fd, count;
- u8 *buf = NULL;
- struct find_file_offset_data data = {
- .ip = start,
- };
-
- *is_64bit = false;
-
- nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
- fd = open(filename, O_RDONLY);
- nsinfo__mountns_exit(&nsc);
- if (fd < 0)
- return NULL;
-
- if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data,
- is_64bit) == 0)
- goto err;
-
- *len = end - start;
- buf = malloc(*len);
- if (buf == NULL)
- goto err;
-
- count = pread(fd, buf, *len, data.offset);
- close(fd);
- fd = -1;
-
- if ((u64)count != *len)
- goto err;
-
- return buf;
-
-err:
- if (fd >= 0)
- close(fd);
- free(buf);
- return NULL;
-}
-
/*
* Whenever LLVM wants to resolve an address into a symbol, it calls this
* callback. We don't ever actually _return_ anything (in particular, because
@@ -397,8 +332,11 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
struct map *map = args->ms.map;
struct dso *dso = map__dso(map);
u64 start = map__rip_2objdump(map, sym->start);
- u8 *buf;
- u64 len;
+ /* Malloc-ed buffer containing instructions read from disk. */
+ u8 *code_buf = NULL;
+ /* Pointer to code to be disassembled. */
+ const u8 *buf;
+ u64 buf_len;
u64 pc;
bool is_64bit;
char triplet[64];
@@ -418,7 +356,8 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
perf_LLVMInitializeAllTargetMCs();
perf_LLVMInitializeAllDisassemblers();
- buf = read_symbol(filename, map, sym, &len, &is_64bit);
+ buf = dso__read_symbol(dso, filename, map, sym,
+ &code_buf, &buf_len, &is_64bit);
if (buf == NULL)
return -1;
@@ -466,14 +405,18 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
annotation_line__add(&dl->al, ¬es->src->source);
pc = start;
- for (u64 offset = 0; offset < len; ) {
+ for (u64 offset = 0; offset < buf_len; ) {
unsigned int ins_len;
storage.branch_addr = 0;
storage.pcrel_load_addr = 0;
- ins_len = perf_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 = perf_LLVMDisasmInstruction(disasm, (u8 *)(buf + offset),
+ buf_len - offset, pc,
disasm_buf, sizeof(disasm_buf));
if (ins_len == 0)
goto err;
@@ -531,7 +474,7 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
err:
perf_LLVMDisasmDispose(disasm);
- free(buf);
+ free(code_buf);
free(line_storage);
return ret;
}
--
2.48.0.rc2.279.g1de40edade-goog
next prev parent reply other threads:[~2025-01-22 6:25 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-22 6:23 [PATCH v2 00/17] Support dynamic opening of capstone/llvm remove BUILD_NONDISTRO Ian Rogers
2025-01-22 6:23 ` [PATCH v2 01/17] perf build: Remove libtracefs configuration Ian Rogers
2025-01-22 6:23 ` [PATCH v2 02/17] perf map: Constify objdump offset/address conversion APIs Ian Rogers
2025-01-22 6:23 ` [PATCH v2 03/17] perf capstone: Move capstone functionality into its own file Ian Rogers
2025-01-22 6:23 ` [PATCH v2 04/17] perf llvm: Move llvm " Ian Rogers
2025-01-22 6:23 ` [PATCH v2 05/17] perf capstone: Remove open_capstone_handle Ian Rogers
2025-01-22 6:23 ` [PATCH v2 06/17] perf capstone: Support for dlopen-ing libcapstone.so Ian Rogers
2025-01-22 6:23 ` [PATCH v2 07/17] perf llvm: Support for dlopen-ing libLLVM.so Ian Rogers
2025-01-22 6:23 ` [PATCH v2 08/17] perf llvm: Mangle libperf-llvm.so function names Ian Rogers
2025-01-22 6:23 ` Ian Rogers [this message]
2025-01-22 6:23 ` [PATCH v2 10/17] perf dso: Support BPF programs in dso__read_symbol Ian Rogers
2025-01-22 6:23 ` [PATCH v2 11/17] perf llvm: Disassemble cleanup Ian Rogers
2025-01-22 6:23 ` [PATCH v2 12/17] perf dso: Clean up read_symbol error handling Ian Rogers
2025-01-22 6:23 ` [PATCH v2 13/17] perf build: Remove libbfd support Ian Rogers
2025-01-22 6:23 ` [PATCH v2 14/17] perf build: Remove libiberty support Ian Rogers
2025-01-22 6:23 ` [PATCH v2 15/17] perf build: Remove unused defines Ian Rogers
2025-01-22 6:23 ` [PATCH v2 16/17] perf disasm: Remove disasm_bpf Ian Rogers
2025-01-22 6:23 ` [PATCH v2 17/17] perf disasm: Make ins__scnprintf and ins__is_nop static Ian Rogers
2025-01-22 15:20 ` [PATCH v2 00/17] Support dynamic opening of capstone/llvm remove BUILD_NONDISTRO Andi Kleen
2025-01-22 16:11 ` Ian Rogers
2025-01-23 18:19 ` Andi Kleen
2025-01-23 21:24 ` Ian Rogers
2025-01-23 21:59 ` Namhyung Kim
2025-01-23 23:36 ` Ian Rogers
2025-02-10 18:06 ` Ian Rogers
2025-03-12 21:04 ` Ian Rogers
2025-03-13 22:24 ` Namhyung Kim
2025-03-14 5:54 ` Ian Rogers
2025-03-14 17:06 ` Arnaldo Carvalho de Melo
2025-03-14 20:34 ` Ian Rogers
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=20250122062332.577009-10-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adityag@linux.ibm.com \
--cc=adrian.hunter@intel.com \
--cc=ak@linux.intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=atrajeev@linux.vnet.ibm.com \
--cc=bpf@vger.kernel.org \
--cc=chaitanyas.prakash@arm.com \
--cc=changbin.du@huawei.com \
--cc=charlie@rivosinc.com \
--cc=dvyukov@google.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=justinstitt@google.com \
--cc=kan.liang@linux.intel.com \
--cc=kjain@linux.ibm.com \
--cc=lihuafei1@huawei.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=mark.rutland@arm.com \
--cc=mhiramat@kernel.org \
--cc=mingo@redhat.com \
--cc=morbo@google.com \
--cc=namhyung@kernel.org \
--cc=nathan@kernel.org \
--cc=ndesaulniers@google.com \
--cc=peterz@infradead.org \
--cc=sesse@google.com \
--cc=song@kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.