* [PATCH v1 00/11] perf annotate arch clean up
@ 2026-01-22 7:31 Ian Rogers
2026-01-22 7:31 ` [PATCH v1 01/11] perf maps: Fix reference count leak in maps__find_ams Ian Rogers
` (11 more replies)
0 siblings, 12 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
2 initial memory leak fix patches for perf annotate.
Move the disasm.c #included arch files into a new util/annotate-arch
directory. Make the code compile standalone. Try to better encapsulate
architecture specific code within the files and with a
arch__new_<arch> function that allows additional data to be associated
with the struct arch using the standard container_of trick.
Make the lookup of struct arch use the ELF machine gather from a
thread rather than an evsel. For example, the evsel can't determine
the difference between EM_386 and EM_X86_64 so generally the latter
has currently been used. This means the dwarf registers are off as
register 1 is CX with EM_386 and DX with EM_X86_64. To facilitate this
change map_symbol is refactored to use a struct thread rather than a
struct maps, the maps being obtainable from the thread.
To make in and out arguments clearer, for safety, etc. try to constify
struct arch and its related structs.
Ian Rogers (11):
perf maps: Fix reference count leak in maps__find_ams
perf annotate: Fix args leak of map_symbol
perf disasm: Constify use of struct arch
perf disasm: Constify use of struct ins_op
perf disasm: Constify use of struct ins
perf disasm: Rework the string arch__is to use the ELF machine
perf disasm: Don't include C files from the arch directory
perf disasm: Refactor ins__is_call/jump to avoid exposing arch ins_ops
perf map_symbol: Switch from holding maps to holding thread
perf disasm: Refactor arch__find and initialization of arch structs
perf disasm: Minor layout tweaks for struct arch
tools/perf/arch/arc/annotate/instructions.c | 11 -
.../perf/arch/riscv64/annotate/instructions.c | 36 --
tools/perf/ui/browsers/annotate.c | 6 +-
tools/perf/ui/browsers/hists.c | 3 +-
tools/perf/util/Build | 1 +
tools/perf/util/addr_location.c | 4 -
tools/perf/util/addr_location.h | 1 -
tools/perf/util/annotate-arch/Build | 11 +
tools/perf/util/annotate-arch/annotate-arc.c | 18 +
.../annotate-arch/annotate-arm.c} | 48 +-
.../annotate-arch/annotate-arm64.c} | 59 +--
.../annotate-arch/annotate-csky.c} | 29 +-
.../annotate-arch/annotate-loongarch.c} | 57 ++-
.../annotate-arch/annotate-mips.c} | 29 +-
.../annotate-arch/annotate-powerpc.c} | 125 +++++-
.../util/annotate-arch/annotate-riscv64.c | 41 ++
.../annotate-arch/annotate-s390.c} | 59 ++-
.../annotate-arch/annotate-sparc.c} | 26 +-
.../annotate-arch/annotate-x86.c} | 89 ++--
tools/perf/util/annotate-data.c | 12 +-
tools/perf/util/annotate-data.h | 2 +-
tools/perf/util/annotate.c | 88 ++--
tools/perf/util/annotate.h | 10 +-
tools/perf/util/callchain.c | 12 +-
tools/perf/util/capstone.c | 18 +-
tools/perf/util/db-export.c | 1 -
tools/perf/util/disasm.c | 424 +++++++-----------
tools/perf/util/disasm.h | 95 ++--
tools/perf/util/event.c | 2 -
tools/perf/util/hist.c | 18 +-
tools/perf/util/llvm.c | 8 +-
tools/perf/util/machine.c | 13 +-
tools/perf/util/map_symbol.c | 5 +-
tools/perf/util/map_symbol.h | 3 +-
tools/perf/util/maps.c | 1 +
tools/perf/util/sort.c | 2 +-
tools/perf/util/unwind-libdw.c | 2 +-
tools/perf/util/unwind-libunwind-local.c | 2 +-
38 files changed, 752 insertions(+), 619 deletions(-)
delete mode 100644 tools/perf/arch/arc/annotate/instructions.c
delete mode 100644 tools/perf/arch/riscv64/annotate/instructions.c
create mode 100644 tools/perf/util/annotate-arch/Build
create mode 100644 tools/perf/util/annotate-arch/annotate-arc.c
rename tools/perf/{arch/arm/annotate/instructions.c => util/annotate-arch/annotate-arm.c} (59%)
rename tools/perf/{arch/arm64/annotate/instructions.c => util/annotate-arch/annotate-arm64.c} (70%)
rename tools/perf/{arch/csky/annotate/instructions.c => util/annotate-arch/annotate-csky.c} (67%)
rename tools/perf/{arch/loongarch/annotate/instructions.c => util/annotate-arch/annotate-loongarch.c} (66%)
rename tools/perf/{arch/mips/annotate/instructions.c => util/annotate-arch/annotate-mips.c} (59%)
rename tools/perf/{arch/powerpc/annotate/instructions.c => util/annotate-arch/annotate-powerpc.c} (73%)
create mode 100644 tools/perf/util/annotate-arch/annotate-riscv64.c
rename tools/perf/{arch/s390/annotate/instructions.c => util/annotate-arch/annotate-s390.c} (70%)
rename tools/perf/{arch/sparc/annotate/instructions.c => util/annotate-arch/annotate-sparc.c} (85%)
rename tools/perf/{arch/x86/annotate/instructions.c => util/annotate-arch/annotate-x86.c} (93%)
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 01/11] perf maps: Fix reference count leak in maps__find_ams
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 7:31 ` [PATCH v1 02/11] perf annotate: Fix args leak of map_symbol Ian Rogers
` (10 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
ams and so ams->ms.map is an in argument, however, it is also
overwritten. As a map is reference counted, ensure a map__put is done
before overwriting it.
Signed-off-by: Ian Rogers <irogers@google.com>
Fixes: 42fd623b58db ("perf maps: Get map before returning in maps__find")
---
tools/perf/util/maps.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c
index 8ccc46d515b6..4092211cff62 100644
--- a/tools/perf/util/maps.c
+++ b/tools/perf/util/maps.c
@@ -708,6 +708,7 @@ int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams)
if (ams->addr < map__start(ams->ms.map) || ams->addr >= map__end(ams->ms.map)) {
if (maps == NULL)
return -1;
+ map__put(ams->ms.map);
ams->ms.map = maps__find(maps, ams->addr);
if (ams->ms.map == NULL)
return -1;
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 02/11] perf annotate: Fix args leak of map_symbol
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
2026-01-22 7:31 ` [PATCH v1 01/11] perf maps: Fix reference count leak in maps__find_ams Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 11:46 ` Suchit Karunakaran
2026-01-22 7:31 ` [PATCH v1 03/11] perf disasm: Constify use of struct arch Ian Rogers
` (9 subsequent siblings)
11 siblings, 1 reply; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
map_symbol__exit needs calling on an annotate_args.ms, however, rather
than introduce proper reference count handling to symbol__annotate
just switch to passing the map_symbol pointer parameter around, making
the puts the caller's responsibility.
Signed-off-by: Ian Rogers <irogers@google.com>
Fixes: 56e144fe9826 ("perf mem_info: Add and use map_symbol__exit and addr_map_symbol__exit")
---
tools/perf/util/annotate.c | 2 +-
tools/perf/util/capstone.c | 14 +++++++-------
tools/perf/util/disasm.c | 32 +++++++++++++++++---------------
tools/perf/util/disasm.h | 2 +-
tools/perf/util/llvm.c | 6 +++---
5 files changed, 29 insertions(+), 27 deletions(-)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index cc7764455faf..791d60f97c23 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1031,7 +1031,7 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
return 0;
args.arch = arch;
- args.ms = *ms;
+ args.ms = ms;
if (notes->src == NULL) {
notes->src = annotated_source__new();
diff --git a/tools/perf/util/capstone.c b/tools/perf/util/capstone.c
index be5fd44b1f9d..2c7feab61b7b 100644
--- a/tools/perf/util/capstone.c
+++ b/tools/perf/util/capstone.c
@@ -143,7 +143,7 @@ static void print_capstone_detail(cs_insn *insn, char *buf, size_t len,
struct annotate_args *args, u64 addr)
{
int i;
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct symbol *sym;
/* TODO: support more architectures */
@@ -222,7 +222,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
{
#ifdef HAVE_LIBCAPSTONE_SUPPORT
struct annotation *notes = symbol__annotation(sym);
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
u64 start = map__rip_2objdump(map, sym->start);
u64 offset;
@@ -256,7 +256,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
args->line = disasm_buf;
args->line_nr = 0;
args->fileloc = NULL;
- args->ms.sym = sym;
+ args->ms->sym = sym;
dl = disasm_line__new(args);
if (dl == NULL)
@@ -268,7 +268,7 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
!strcmp(args->options->disassembler_style, "att"))
disassembler_style = true;
- if (capstone_init(maps__machine(args->ms.maps), &handle, is_64bit, disassembler_style) < 0)
+ if (capstone_init(maps__machine(args->ms->maps), &handle, is_64bit, disassembler_style) < 0)
goto err;
needs_cs_close = true;
@@ -345,7 +345,7 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused,
{
#ifdef HAVE_LIBCAPSTONE_SUPPORT
struct annotation *notes = symbol__annotation(sym);
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
struct nscookie nsc;
u64 start = map__rip_2objdump(map, sym->start);
@@ -382,7 +382,7 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused,
!strcmp(args->options->disassembler_style, "att"))
disassembler_style = true;
- if (capstone_init(maps__machine(args->ms.maps), &handle, is_64bit, disassembler_style) < 0)
+ if (capstone_init(maps__machine(args->ms->maps), &handle, is_64bit, disassembler_style) < 0)
goto err;
needs_cs_close = true;
@@ -408,7 +408,7 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused,
args->line = disasm_buf;
args->line_nr = 0;
args->fileloc = NULL;
- args->ms.sym = sym;
+ args->ms->sym = sym;
dl = disasm_line__new(args);
if (dl == NULL)
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index 50b9433f3f8e..96c78b01e17a 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -269,9 +269,7 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_s
{
char *endptr, *tok, *name;
struct map *map = ms->map;
- struct addr_map_symbol target = {
- .ms = { .map = map, },
- };
+ struct addr_map_symbol target;
ops->target.addr = strtoull(ops->raw, &endptr, 16);
@@ -296,12 +294,16 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_s
if (ops->target.name == NULL)
return -1;
find_target:
- target.addr = map__objdump_2mem(map, ops->target.addr);
+ target = (struct addr_map_symbol) {
+ .ms = { .map = map__get(map), },
+ .addr = map__objdump_2mem(map, ops->target.addr),
+ };
if (maps__find_ams(ms->maps, &target) == 0 &&
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
ops->target.sym = target.ms.sym;
+ addr_map_symbol__exit(&target);
return 0;
indirect_call:
@@ -366,7 +368,7 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s
struct map *map = ms->map;
struct symbol *sym = ms->sym;
struct addr_map_symbol target = {
- .ms = { .map = map, },
+ .ms = { .map = map__get(map), },
};
const char *c = strchr(ops->raw, ',');
u64 start, end;
@@ -440,7 +442,7 @@ static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_s
} else {
ops->target.offset_avail = false;
}
-
+ addr_map_symbol__exit(&target);
return 0;
}
@@ -1046,7 +1048,7 @@ static size_t disasm_line_size(int nr)
struct disasm_line *disasm_line__new(struct annotate_args *args)
{
struct disasm_line *dl = NULL;
- struct annotation *notes = symbol__annotation(args->ms.sym);
+ struct annotation *notes = symbol__annotation(args->ms->sym);
int nr = notes->src->nr_events;
dl = zalloc(disasm_line_size(nr));
@@ -1064,7 +1066,7 @@ struct disasm_line *disasm_line__new(struct annotate_args *args)
} else if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
goto out_free_line;
- disasm_line__init_ins(dl, args->arch, &args->ms);
+ disasm_line__init_ins(dl, args->arch, args->ms);
}
return dl;
@@ -1119,7 +1121,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
struct annotate_args *args,
char *parsed_line, int *line_nr, char **fileloc)
{
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct annotation *notes = symbol__annotation(sym);
struct disasm_line *dl;
char *tmp;
@@ -1151,7 +1153,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
args->line = parsed_line;
args->line_nr = *line_nr;
args->fileloc = *fileloc;
- args->ms.sym = sym;
+ args->ms->sym = sym;
dl = disasm_line__new(args);
(*line_nr)++;
@@ -1172,7 +1174,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
.ms = { .map = map, },
};
- if (!maps__find_ams(args->ms.maps, &target) &&
+ if (!maps__find_ams(args->ms->maps, &target) &&
target.ms.sym->start == target.al_addr)
dl->ops.target.sym = target.ms.sym;
}
@@ -1338,7 +1340,7 @@ static int symbol__disassemble_raw(char *filename, struct symbol *sym,
struct annotate_args *args)
{
struct annotation *notes = symbol__annotation(sym);
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
u64 start = map__rip_2objdump(map, sym->start);
u64 end = map__rip_2objdump(map, sym->end);
@@ -1375,7 +1377,7 @@ static int symbol__disassemble_raw(char *filename, struct symbol *sym,
args->line = disasm_buf;
args->line_nr = 0;
args->fileloc = NULL;
- args->ms.sym = sym;
+ args->ms->sym = sym;
dl = disasm_line__new(args);
if (dl == NULL)
@@ -1501,7 +1503,7 @@ static int symbol__disassemble_objdump(const char *filename, struct symbol *sym,
struct annotate_args *args)
{
struct annotation_options *opts = &annotate_opts;
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
char *command;
FILE *file;
@@ -1644,7 +1646,7 @@ static int symbol__disassemble_objdump(const char *filename, struct symbol *sym,
int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
{
struct annotation_options *options = args->options;
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
char symfs_filename[PATH_MAX];
bool delete_extract = false;
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index d2cb555e4a3b..a3ea9d676281 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -97,7 +97,7 @@ struct ins_ops {
struct annotate_args {
struct arch *arch;
- struct map_symbol ms;
+ struct map_symbol *ms;
struct annotation_options *options;
s64 offset;
char *line;
diff --git a/tools/perf/util/llvm.c b/tools/perf/util/llvm.c
index 2ebf1f5f65bf..4ada9a10bd93 100644
--- a/tools/perf/util/llvm.c
+++ b/tools/perf/util/llvm.c
@@ -118,7 +118,7 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
{
#ifdef HAVE_LIBLLVM_SUPPORT
struct annotation *notes = symbol__annotation(sym);
- struct map *map = args->ms.map;
+ struct map *map = args->ms->map;
struct dso *dso = map__dso(map);
u64 start = map__rip_2objdump(map, sym->start);
/* Malloc-ed buffer containing instructions read from disk. */
@@ -184,7 +184,7 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
args->line = disasm_buf;
args->line_nr = 0;
args->fileloc = NULL;
- args->ms.sym = sym;
+ args->ms->sym = sym;
dl = disasm_line__new(args);
if (dl == NULL)
@@ -242,7 +242,7 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
&line_storage_len);
args->line_nr = 0;
args->fileloc = NULL;
- args->ms.sym = sym;
+ args->ms->sym = sym;
llvm_addr2line(filename, pc, &args->fileloc,
(unsigned int *)&args->line_nr, false, NULL);
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 03/11] perf disasm: Constify use of struct arch
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
2026-01-22 7:31 ` [PATCH v1 01/11] perf maps: Fix reference count leak in maps__find_ams Ian Rogers
2026-01-22 7:31 ` [PATCH v1 02/11] perf annotate: Fix args leak of map_symbol Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 7:31 ` [PATCH v1 04/11] perf disasm: Constify use of struct ins_op Ian Rogers
` (8 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
The struct arch holds variables that are read but not written, except
during some initialization. Change most uses to be for a "const struct
arch *" version to capture this immutability.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/arch/arm64/annotate/instructions.c | 2 +-
.../arch/loongarch/annotate/instructions.c | 12 ++++--
tools/perf/arch/s390/annotate/instructions.c | 7 ++--
tools/perf/arch/x86/annotate/instructions.c | 4 +-
tools/perf/ui/browsers/annotate.c | 2 +-
tools/perf/util/annotate-data.c | 2 +-
tools/perf/util/annotate-data.h | 2 +-
tools/perf/util/annotate.c | 28 ++++++-------
tools/perf/util/annotate.h | 10 ++---
tools/perf/util/disasm.c | 42 ++++++++++---------
tools/perf/util/disasm.h | 14 +++----
11 files changed, 67 insertions(+), 58 deletions(-)
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index 16cb62d40bd9..5099fa36180d 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -10,7 +10,7 @@ struct arm64_annotate {
jump_insn;
};
-static int arm64_mov__parse(struct arch *arch __maybe_unused,
+static int arm64_mov__parse(const struct arch *arch __maybe_unused,
struct ins_operands *ops,
struct map_symbol *ms __maybe_unused,
struct disasm_line *dl __maybe_unused)
diff --git a/tools/perf/arch/loongarch/annotate/instructions.c b/tools/perf/arch/loongarch/annotate/instructions.c
index 70262d5f1444..4ca4fb6bbcf9 100644
--- a/tools/perf/arch/loongarch/annotate/instructions.c
+++ b/tools/perf/arch/loongarch/annotate/instructions.c
@@ -5,8 +5,10 @@
* Copyright (C) 2020-2023 Loongson Technology Corporation Limited
*/
-static int loongarch_call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
- struct disasm_line *dl __maybe_unused)
+static int loongarch_call__parse(const struct arch *arch, struct ins_operands *ops,
+ struct map_symbol *ms,
+ struct disasm_line *dl __maybe_unused)
+
{
char *c, *endptr, *tok, *name;
struct map *map = ms->map;
@@ -52,8 +54,10 @@ static struct ins_ops loongarch_call_ops = {
.scnprintf = call__scnprintf,
};
-static int loongarch_jump__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
- struct disasm_line *dl __maybe_unused)
+static int loongarch_jump__parse(const struct arch *arch, struct ins_operands *ops,
+ struct map_symbol *ms,
+ struct disasm_line *dl __maybe_unused)
+
{
struct map *map = ms->map;
struct symbol *sym = ms->sym;
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index c61193f1e096..8d66c0ea3810 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
-static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
- struct map_symbol *ms, struct disasm_line *dl __maybe_unused)
+static int s390_call__parse(const struct arch *arch, struct ins_operands *ops,
+ struct map_symbol *ms,
+ struct disasm_line *dl __maybe_unused)
{
char *endptr, *tok, *name;
struct map *map = ms->map;
@@ -50,7 +51,7 @@ static struct ins_ops s390_call_ops = {
.scnprintf = call__scnprintf,
};
-static int s390_mov__parse(struct arch *arch __maybe_unused,
+static int s390_mov__parse(const struct arch *arch __maybe_unused,
struct ins_operands *ops,
struct map_symbol *ms __maybe_unused,
struct disasm_line *dl __maybe_unused)
diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c
index 803f9351a3fb..24b388bacdae 100644
--- a/tools/perf/arch/x86/annotate/instructions.c
+++ b/tools/perf/arch/x86/annotate/instructions.c
@@ -119,7 +119,7 @@ static struct ins x86__instructions[] = {
{ .name = "xorps", .ops = &mov_ops, },
};
-static bool amd__ins_is_fused(struct arch *arch, const char *ins1,
+static bool amd__ins_is_fused(const struct arch *arch, const char *ins1,
const char *ins2)
{
if (strstr(ins2, "jmp"))
@@ -142,7 +142,7 @@ static bool amd__ins_is_fused(struct arch *arch, const char *ins1,
return false;
}
-static bool intel__ins_is_fused(struct arch *arch, const char *ins1,
+static bool intel__ins_is_fused(const struct arch *arch, const char *ins1,
const char *ins2)
{
if (arch->family != 6 || arch->model < 0x1e || strstr(ins2, "jmp"))
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 36aca8d6d003..3df61cd46652 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -30,7 +30,7 @@ struct annotate_browser {
struct rb_root entries;
struct rb_node *curr_hot;
struct annotation_line *selection;
- struct arch *arch;
+ const struct arch *arch;
/*
* perf top can delete hist_entry anytime. Callers should make sure
* its lifetime.
diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index 07cf9c334be0..edfcd6e9df9c 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -160,7 +160,7 @@ bool has_reg_type(struct type_state *state, int reg)
return (unsigned)reg < ARRAY_SIZE(state->regs);
}
-static void init_type_state(struct type_state *state, struct arch *arch)
+static void init_type_state(struct type_state *state, const struct arch *arch)
{
memset(state, 0, sizeof(*state));
INIT_LIST_HEAD(&state->stack_vars);
diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h
index 869307c7f130..9b222869e42d 100644
--- a/tools/perf/util/annotate-data.h
+++ b/tools/perf/util/annotate-data.h
@@ -117,7 +117,7 @@ extern struct annotated_data_type canary_type;
*/
struct data_loc_info {
/* These are input field, should be filled by caller */
- struct arch *arch;
+ const struct arch *arch;
struct thread *thread;
struct map_symbol *ms;
u64 ip;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 791d60f97c23..132af2556aec 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -761,7 +761,7 @@ static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_wi
}
static struct annotated_data_type *
-__hist_entry__get_data_type(struct hist_entry *he, struct arch *arch,
+__hist_entry__get_data_type(struct hist_entry *he, const struct arch *arch,
struct debuginfo *dbg, struct disasm_line *dl,
int *type_offset);
@@ -980,11 +980,11 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)
annotation__calc_percent(notes, evsel, symbol__size(sym));
}
-int evsel__get_arch(struct evsel *evsel, struct arch **parch)
+int evsel__get_arch(struct evsel *evsel, const struct arch **parch)
{
struct perf_env *env = evsel__env(evsel);
const char *arch_name = perf_env__arch(env);
- struct arch *arch;
+ const struct arch *arch;
int err;
if (!arch_name) {
@@ -999,7 +999,7 @@ int evsel__get_arch(struct evsel *evsel, struct arch **parch)
}
if (arch->init) {
- err = arch->init(arch, env ? env->cpuid : NULL);
+ err = arch->init((struct arch *)arch, env ? env->cpuid : NULL);
if (err) {
pr_err("%s: failed to initialize %s arch priv area\n",
__func__, arch->name);
@@ -1010,14 +1010,14 @@ int evsel__get_arch(struct evsel *evsel, struct arch **parch)
}
int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
- struct arch **parch)
+ const struct arch **parch)
{
struct symbol *sym = ms->sym;
struct annotation *notes = symbol__annotation(sym);
struct annotate_args args = {
.options = &annotate_opts,
};
- struct arch *arch = NULL;
+ const struct arch *arch = NULL;
int err, nr;
err = evsel__get_arch(evsel, &arch);
@@ -2204,7 +2204,7 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes
}
int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
- struct arch **parch)
+ const struct arch **parch)
{
struct symbol *sym = ms->sym;
struct annotation *notes = symbol__annotation(sym);
@@ -2457,7 +2457,7 @@ int annotate_check_args(void)
* to revisit the format when it handles different architecture.
* Fills @reg and @offset when return 0.
*/
-static int extract_reg_offset(struct arch *arch, const char *str,
+static int extract_reg_offset(const struct arch *arch, const char *str,
struct annotated_op_loc *op_loc)
{
char *p;
@@ -2538,7 +2538,7 @@ static int extract_reg_offset(struct arch *arch, const char *str,
* # dst_reg1 = rbx, dst_reg2 = rcx, dst_mem = 1
* # dst_multi_regs = 1, dst_offset = 8
*/
-int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl,
+int annotate_get_insn_location(const struct arch *arch, struct disasm_line *dl,
struct annotated_insn_loc *loc)
{
struct ins_operands *ops;
@@ -2673,7 +2673,7 @@ static struct annotated_item_stat *annotate_data_stat(struct list_head *head,
return istat;
}
-static bool is_stack_operation(struct arch *arch, struct disasm_line *dl)
+static bool is_stack_operation(const struct arch *arch, struct disasm_line *dl)
{
if (arch__is(arch, "x86")) {
if (!strncmp(dl->ins.name, "push", 4) ||
@@ -2686,7 +2686,7 @@ static bool is_stack_operation(struct arch *arch, struct disasm_line *dl)
return false;
}
-static bool is_stack_canary(struct arch *arch, struct annotated_op_loc *loc)
+static bool is_stack_canary(const struct arch *arch, struct annotated_op_loc *loc)
{
/* On x86_64, %gs:40 is used for stack canary */
if (arch__is(arch, "x86")) {
@@ -2702,7 +2702,7 @@ static bool is_stack_canary(struct arch *arch, struct annotated_op_loc *loc)
* Returns true if the instruction has a memory operand without
* performing a load/store
*/
-static bool is_address_gen_insn(struct arch *arch, struct disasm_line *dl)
+static bool is_address_gen_insn(const struct arch *arch, struct disasm_line *dl)
{
if (arch__is(arch, "x86")) {
if (!strncmp(dl->ins.name, "lea", 3))
@@ -2791,7 +2791,7 @@ void debuginfo_cache__delete(void)
}
static struct annotated_data_type *
-__hist_entry__get_data_type(struct hist_entry *he, struct arch *arch,
+__hist_entry__get_data_type(struct hist_entry *he, const struct arch *arch,
struct debuginfo *dbg, struct disasm_line *dl,
int *type_offset)
{
@@ -2895,7 +2895,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
{
struct map_symbol *ms = &he->ms;
struct evsel *evsel = hists_to_evsel(he->hists);
- struct arch *arch;
+ const struct arch *arch;
struct disasm_line *dl;
struct annotated_data_type *mem_type;
struct annotated_item_stat *istat;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index d4990bff29a7..58eaf4b2fa65 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -202,7 +202,7 @@ struct annotation_write_ops {
struct annotation_print_data {
struct hist_entry *he;
struct evsel *evsel;
- struct arch *arch;
+ const struct arch *arch;
struct debuginfo *dbg;
/* save data type info keyed by al->offset */
struct hashmap *type_hash;
@@ -441,10 +441,10 @@ void symbol__annotate_zero_histograms(struct symbol *sym);
int symbol__annotate(struct map_symbol *ms,
struct evsel *evsel,
- struct arch **parch);
+ const struct arch **parch);
int symbol__annotate2(struct map_symbol *ms,
struct evsel *evsel,
- struct arch **parch);
+ const struct arch **parch);
enum symbol_disassemble_errno {
SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
@@ -546,7 +546,7 @@ struct annotated_insn_loc {
i++, op_loc++)
/* Get detailed location info in the instruction */
-int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl,
+int annotate_get_insn_location(const struct arch *arch, struct disasm_line *dl,
struct annotated_insn_loc *loc);
/* Returns a data type from the sample instruction (if any) */
@@ -586,5 +586,5 @@ int annotation_br_cntr_entry(char **str, int br_cntr_nr, u64 *br_cntr,
int num_aggr, struct evsel *evsel);
int annotation_br_cntr_abbr_list(char **str, struct evsel *evsel, bool header);
-int evsel__get_arch(struct evsel *evsel, struct arch **parch);
+int evsel__get_arch(struct evsel *evsel, const struct arch **parch);
#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index 96c78b01e17a..d41a0f96a6f6 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -213,7 +213,7 @@ static void arch__sort(void)
qsort(architectures, nmemb, sizeof(struct arch), arch__cmp);
}
-struct arch *arch__find(const char *name)
+const struct arch *arch__find(const char *name)
{
const int nmemb = ARRAY_SIZE(architectures);
static bool sorted;
@@ -226,7 +226,7 @@ struct arch *arch__find(const char *name)
return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp);
}
-bool arch__is(struct arch *arch, const char *name)
+bool arch__is(const struct arch *arch, const char *name)
{
return !strcmp(arch->name, name);
}
@@ -256,7 +256,7 @@ static int ins__scnprintf(struct ins *ins, char *bf, size_t size,
return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
}
-bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
+bool ins__is_fused(const struct arch *arch, const char *ins1, const char *ins2)
{
if (!arch || !arch->ins_is_fused)
return false;
@@ -264,7 +264,7 @@ bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
return arch->ins_is_fused(arch, ins1, ins2);
}
-static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
+static int call__parse(const struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
struct disasm_line *dl __maybe_unused)
{
char *endptr, *tok, *name;
@@ -362,7 +362,7 @@ static inline const char *validate_comma(const char *c, struct ins_operands *ops
return c;
}
-static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
+static int jump__parse(const struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
struct disasm_line *dl __maybe_unused)
{
struct map *map = ms->map;
@@ -525,7 +525,7 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
return 0;
}
-static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
+static int lock__parse(const struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
struct disasm_line *dl __maybe_unused)
{
ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
@@ -592,7 +592,7 @@ static struct ins_ops lock_ops = {
* But it doesn't care segment selectors like %gs:0x5678(%rcx), so just check
* the input string after 'memory_ref_char' if exists.
*/
-static bool check_multi_regs(struct arch *arch, const char *op)
+static bool check_multi_regs(const struct arch *arch, const char *op)
{
int count = 0;
@@ -613,8 +613,9 @@ static bool check_multi_regs(struct arch *arch, const char *op)
return count > 1;
}
-static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused,
- struct disasm_line *dl __maybe_unused)
+static int mov__parse(const struct arch *arch, struct ins_operands *ops,
+ struct map_symbol *ms __maybe_unused,
+ struct disasm_line *dl __maybe_unused)
{
char *s = strchr(ops->raw, ','), *target, *comment, prev;
@@ -719,7 +720,7 @@ static int arithmetic__scnprintf(struct ins *ins, char *bf, size_t size,
* - Add to Zero Extended XO-form ( Ex: addze, addzeo )
* - Subtract From Zero Extended XO-form ( Ex: subfze )
*/
-static int arithmetic__parse(struct arch *arch __maybe_unused, struct ins_operands *ops,
+static int arithmetic__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
struct map_symbol *ms __maybe_unused, struct disasm_line *dl)
{
int opcode = PPC_OP(dl->raw.raw_insn);
@@ -756,7 +757,7 @@ static int load_store__scnprintf(struct ins *ins, char *bf, size_t size,
* used by powerpc and since binary instruction code is used to
* extract opcode, regs and offset, no other parsing is needed here
*/
-static int load_store__parse(struct arch *arch __maybe_unused, struct ins_operands *ops,
+static int load_store__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
struct map_symbol *ms __maybe_unused, struct disasm_line *dl __maybe_unused)
{
ops->source.mem_ref = true;
@@ -776,8 +777,9 @@ static struct ins_ops load_store_ops = {
.scnprintf = load_store__scnprintf,
};
-static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms __maybe_unused,
- struct disasm_line *dl __maybe_unused)
+static int dec__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
+ struct map_symbol *ms __maybe_unused,
+ struct disasm_line *dl __maybe_unused)
{
char *target, *comment, *s, prev;
@@ -867,7 +869,8 @@ static void ins__sort(struct arch *arch)
qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
}
-static struct ins_ops *__ins__find(struct arch *arch, const char *name, struct disasm_line *dl)
+static struct ins_ops *__ins__find(const struct arch *arch, const char *name,
+ struct disasm_line *dl)
{
struct ins *ins;
const int nmemb = arch->nr_instructions;
@@ -885,8 +888,8 @@ static struct ins_ops *__ins__find(struct arch *arch, const char *name, struct d
}
if (!arch->sorted_instructions) {
- ins__sort(arch);
- arch->sorted_instructions = true;
+ ins__sort((struct arch *)arch);
+ ((struct arch *)arch)->sorted_instructions = true;
}
ins = bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
@@ -913,17 +916,18 @@ static struct ins_ops *__ins__find(struct arch *arch, const char *name, struct d
return ins ? ins->ops : NULL;
}
-struct ins_ops *ins__find(struct arch *arch, const char *name, struct disasm_line *dl)
+struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl)
{
struct ins_ops *ops = __ins__find(arch, name, dl);
if (!ops && arch->associate_instruction_ops)
- ops = arch->associate_instruction_ops(arch, name);
+ ops = arch->associate_instruction_ops((struct arch *)arch, name);
return ops;
}
-static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
+static void disasm_line__init_ins(struct disasm_line *dl, const struct arch *arch,
+ struct map_symbol *ms)
{
dl->ins.ops = ins__find(arch, dl->ins.name, dl);
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index a3ea9d676281..273a9c906514 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -30,7 +30,7 @@ struct arch {
unsigned int model;
unsigned int family;
int (*init)(struct arch *arch, char *cpuid);
- bool (*ins_is_fused)(struct arch *arch, const char *ins1,
+ bool (*ins_is_fused)(const struct arch *arch, const char *ins1,
const char *ins2);
struct {
char comment_char;
@@ -89,14 +89,14 @@ struct ins_operands {
struct ins_ops {
void (*free)(struct ins_operands *ops);
- int (*parse)(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
+ int (*parse)(const struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
struct disasm_line *dl);
int (*scnprintf)(struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name);
};
struct annotate_args {
- struct arch *arch;
+ const struct arch *arch;
struct map_symbol *ms;
struct annotation_options *options;
s64 offset;
@@ -105,14 +105,14 @@ struct annotate_args {
char *fileloc;
};
-struct arch *arch__find(const char *name);
-bool arch__is(struct arch *arch, const char *name);
+const struct arch *arch__find(const char *name);
+bool arch__is(const struct arch *arch, const char *name);
-struct ins_ops *ins__find(struct arch *arch, const char *name, struct disasm_line *dl);
+struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl);
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_fused(const struct arch *arch, const char *ins1, const char *ins2);
bool ins__is_ret(const struct ins *ins);
bool ins__is_lock(const struct ins *ins);
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 04/11] perf disasm: Constify use of struct ins_op
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
` (2 preceding siblings ...)
2026-01-22 7:31 ` [PATCH v1 03/11] perf disasm: Constify use of struct arch Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 7:31 ` [PATCH v1 05/11] perf disasm: Constify use of struct ins Ian Rogers
` (7 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
The struct ins_op holds variables to function pointers that are read
but not written. Change uses to be for a "const struct ins_op *"
version to capture this immutability.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/arch/arm/annotate/instructions.c | 4 +-
tools/perf/arch/arm64/annotate/instructions.c | 6 +--
tools/perf/arch/csky/annotate/instructions.c | 6 +--
.../arch/loongarch/annotate/instructions.c | 8 ++--
tools/perf/arch/mips/annotate/instructions.c | 4 +-
.../perf/arch/powerpc/annotate/instructions.c | 6 +--
.../perf/arch/riscv64/annotate/instructions.c | 4 +-
tools/perf/arch/s390/annotate/instructions.c | 8 ++--
tools/perf/arch/sparc/annotate/instructions.c | 4 +-
tools/perf/util/disasm.c | 46 +++++++++----------
tools/perf/util/disasm.h | 6 +--
11 files changed, 51 insertions(+), 51 deletions(-)
diff --git a/tools/perf/arch/arm/annotate/instructions.c b/tools/perf/arch/arm/annotate/instructions.c
index 5e667b0f5512..b997d127fedd 100644
--- a/tools/perf/arch/arm/annotate/instructions.c
+++ b/tools/perf/arch/arm/annotate/instructions.c
@@ -11,10 +11,10 @@ struct arm_annotate {
jump_insn;
};
-static struct ins_ops *arm__associate_instruction_ops(struct arch *arch, const char *name)
+static const struct ins_ops *arm__associate_instruction_ops(struct arch *arch, const char *name)
{
struct arm_annotate *arm = arch->priv;
- struct ins_ops *ops;
+ const struct ins_ops *ops;
regmatch_t match[2];
if (!regexec(&arm->call_insn, name, 2, match, 0))
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index 5099fa36180d..363af2f55122 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -63,15 +63,15 @@ static int arm64_mov__parse(const struct arch *arch __maybe_unused,
static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name);
-static struct ins_ops arm64_mov_ops = {
+static const struct ins_ops arm64_mov_ops = {
.parse = arm64_mov__parse,
.scnprintf = mov__scnprintf,
};
-static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
+static const struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
{
struct arm64_annotate *arm = arch->priv;
- struct ins_ops *ops;
+ const struct ins_ops *ops;
regmatch_t match[2];
if (!regexec(&arm->jump_insn, name, 2, match, 0))
diff --git a/tools/perf/arch/csky/annotate/instructions.c b/tools/perf/arch/csky/annotate/instructions.c
index 14270311d215..4a55c84a320a 100644
--- a/tools/perf/arch/csky/annotate/instructions.c
+++ b/tools/perf/arch/csky/annotate/instructions.c
@@ -3,10 +3,10 @@
#include <linux/compiler.h>
-static struct ins_ops *csky__associate_ins_ops(struct arch *arch,
- const char *name)
+static const struct ins_ops *csky__associate_ins_ops(struct arch *arch,
+ const char *name)
{
- struct ins_ops *ops = NULL;
+ const struct ins_ops *ops = NULL;
/* catch all kind of jumps */
if (!strcmp(name, "bt") ||
diff --git a/tools/perf/arch/loongarch/annotate/instructions.c b/tools/perf/arch/loongarch/annotate/instructions.c
index 4ca4fb6bbcf9..ee360faad420 100644
--- a/tools/perf/arch/loongarch/annotate/instructions.c
+++ b/tools/perf/arch/loongarch/annotate/instructions.c
@@ -49,7 +49,7 @@ static int loongarch_call__parse(const struct arch *arch, struct ins_operands *o
return 0;
}
-static struct ins_ops loongarch_call_ops = {
+static const struct ins_ops loongarch_call_ops = {
.parse = loongarch_call__parse,
.scnprintf = call__scnprintf,
};
@@ -98,15 +98,15 @@ static int loongarch_jump__parse(const struct arch *arch, struct ins_operands *o
return 0;
}
-static struct ins_ops loongarch_jump_ops = {
+static const struct ins_ops loongarch_jump_ops = {
.parse = loongarch_jump__parse,
.scnprintf = jump__scnprintf,
};
static
-struct ins_ops *loongarch__associate_ins_ops(struct arch *arch, const char *name)
+const struct ins_ops *loongarch__associate_ins_ops(struct arch *arch, const char *name)
{
- struct ins_ops *ops = NULL;
+ const struct ins_ops *ops = NULL;
if (!strcmp(name, "bl"))
ops = &loongarch_call_ops;
diff --git a/tools/perf/arch/mips/annotate/instructions.c b/tools/perf/arch/mips/annotate/instructions.c
index b50b46c613d6..0fbe0a7df95a 100644
--- a/tools/perf/arch/mips/annotate/instructions.c
+++ b/tools/perf/arch/mips/annotate/instructions.c
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
static
-struct ins_ops *mips__associate_ins_ops(struct arch *arch, const char *name)
+const struct ins_ops *mips__associate_ins_ops(struct arch *arch, const char *name)
{
- struct ins_ops *ops = NULL;
+ const struct ins_ops *ops = NULL;
if (!strncmp(name, "bal", 3) ||
!strncmp(name, "bgezal", 6) ||
diff --git a/tools/perf/arch/powerpc/annotate/instructions.c b/tools/perf/arch/powerpc/annotate/instructions.c
index ca567cfdcbdb..d1be55425e35 100644
--- a/tools/perf/arch/powerpc/annotate/instructions.c
+++ b/tools/perf/arch/powerpc/annotate/instructions.c
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
-static struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name)
+static const struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name)
{
int i;
- struct ins_ops *ops;
+ const struct ins_ops *ops;
/*
* - Interested only if instruction starts with 'b'.
@@ -189,7 +189,7 @@ static int cmp_offset(const void *a, const void *b)
return (val1->value - val2->value);
}
-static struct ins_ops *check_ppc_insn(struct disasm_line *dl)
+static const struct ins_ops *check_ppc_insn(struct disasm_line *dl)
{
int raw_insn = dl->raw.raw_insn;
int opcode = PPC_OP(raw_insn);
diff --git a/tools/perf/arch/riscv64/annotate/instructions.c b/tools/perf/arch/riscv64/annotate/instructions.c
index 55cf911633f8..a34798864fab 100644
--- a/tools/perf/arch/riscv64/annotate/instructions.c
+++ b/tools/perf/arch/riscv64/annotate/instructions.c
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
static
-struct ins_ops *riscv64__associate_ins_ops(struct arch *arch, const char *name)
+const struct ins_ops *riscv64__associate_ins_ops(struct arch *arch, const char *name)
{
- struct ins_ops *ops = NULL;
+ const struct ins_ops *ops = NULL;
if (!strncmp(name, "jal", 3) ||
!strncmp(name, "jr", 2) ||
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index 8d66c0ea3810..38f7e918ebf8 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -46,7 +46,7 @@ static int s390_call__parse(const struct arch *arch, struct ins_operands *ops,
return 0;
}
-static struct ins_ops s390_call_ops = {
+static const struct ins_ops s390_call_ops = {
.parse = s390_call__parse,
.scnprintf = call__scnprintf,
};
@@ -100,14 +100,14 @@ static int s390_mov__parse(const struct arch *arch __maybe_unused,
}
-static struct ins_ops s390_mov_ops = {
+static const struct ins_ops s390_mov_ops = {
.parse = s390_mov__parse,
.scnprintf = mov__scnprintf,
};
-static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
+static const struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
{
- struct ins_ops *ops = NULL;
+ const struct ins_ops *ops = NULL;
/* catch all kind of jumps */
if (strchr(name, 'j') ||
diff --git a/tools/perf/arch/sparc/annotate/instructions.c b/tools/perf/arch/sparc/annotate/instructions.c
index 68c31580ccfc..a08d8734c883 100644
--- a/tools/perf/arch/sparc/annotate/instructions.c
+++ b/tools/perf/arch/sparc/annotate/instructions.c
@@ -117,9 +117,9 @@ static int is_branch_float_cond(const char *cond)
return 0;
}
-static struct ins_ops *sparc__associate_instruction_ops(struct arch *arch, const char *name)
+static const struct ins_ops *sparc__associate_instruction_ops(struct arch *arch, const char *name)
{
- struct ins_ops *ops = NULL;
+ const struct ins_ops *ops = NULL;
if (!strcmp(name, "call") ||
!strcmp(name, "jmp") ||
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index d41a0f96a6f6..dbeb89047fd1 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -33,15 +33,15 @@
static regex_t file_lineno;
/* These can be referred from the arch-dependent code */
-static struct ins_ops call_ops;
-static struct ins_ops dec_ops;
-static struct ins_ops jump_ops;
-static struct ins_ops mov_ops;
-static struct ins_ops nop_ops;
-static struct ins_ops lock_ops;
-static struct ins_ops ret_ops;
-static struct ins_ops load_store_ops;
-static struct ins_ops arithmetic_ops;
+static const struct ins_ops call_ops;
+static const struct ins_ops dec_ops;
+static const struct ins_ops jump_ops;
+static const struct ins_ops mov_ops;
+static const struct ins_ops nop_ops;
+static const struct ins_ops lock_ops;
+static const struct ins_ops ret_ops;
+static const struct ins_ops load_store_ops;
+static const struct ins_ops arithmetic_ops;
static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name);
@@ -85,7 +85,7 @@ static int arch__grow_instructions(struct arch *arch)
goto out_update_instructions;
}
-static int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops)
+static int arch__associate_ins_ops(struct arch *arch, const char *name, const struct ins_ops *ops)
{
struct ins *ins;
@@ -334,7 +334,7 @@ static int call__scnprintf(struct ins *ins, char *bf, size_t size,
return scnprintf(bf, size, "%-*s *%" PRIx64, max_ins_name, ins->name, ops->target.addr);
}
-static struct ins_ops call_ops = {
+static const struct ins_ops call_ops = {
.parse = call__parse,
.scnprintf = call__scnprintf,
};
@@ -487,7 +487,7 @@ static void jump__delete(struct ins_operands *ops __maybe_unused)
*/
}
-static struct ins_ops jump_ops = {
+static const struct ins_ops jump_ops = {
.free = jump__delete,
.parse = jump__parse,
.scnprintf = jump__scnprintf,
@@ -579,7 +579,7 @@ static void lock__delete(struct ins_operands *ops)
zfree(&ops->target.name);
}
-static struct ins_ops lock_ops = {
+static const struct ins_ops lock_ops = {
.free = lock__delete,
.parse = lock__parse,
.scnprintf = lock__scnprintf,
@@ -688,7 +688,7 @@ static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
ops->target.name ?: ops->target.raw);
}
-static struct ins_ops mov_ops = {
+static const struct ins_ops mov_ops = {
.parse = mov__parse,
.scnprintf = mov__scnprintf,
};
@@ -738,7 +738,7 @@ static int arithmetic__parse(const struct arch *arch __maybe_unused, struct ins_
return 0;
}
-static struct ins_ops arithmetic_ops = {
+static const struct ins_ops arithmetic_ops = {
.parse = arithmetic__parse,
.scnprintf = arithmetic__scnprintf,
};
@@ -772,7 +772,7 @@ static int load_store__parse(const struct arch *arch __maybe_unused, struct ins_
return 0;
}
-static struct ins_ops load_store_ops = {
+static const struct ins_ops load_store_ops = {
.parse = load_store__parse,
.scnprintf = load_store__scnprintf,
};
@@ -813,7 +813,7 @@ static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
ops->target.name ?: ops->target.raw);
}
-static struct ins_ops dec_ops = {
+static const struct ins_ops dec_ops = {
.parse = dec__parse,
.scnprintf = dec__scnprintf,
};
@@ -824,11 +824,11 @@ static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
return scnprintf(bf, size, "%-*s", max_ins_name, "nop");
}
-static struct ins_ops nop_ops = {
+static const struct ins_ops nop_ops = {
.scnprintf = nop__scnprintf,
};
-static struct ins_ops ret_ops = {
+static const struct ins_ops ret_ops = {
.scnprintf = ins__raw_scnprintf,
};
@@ -869,7 +869,7 @@ static void ins__sort(struct arch *arch)
qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
}
-static struct ins_ops *__ins__find(const struct arch *arch, const char *name,
+static const struct ins_ops *__ins__find(const struct arch *arch, const char *name,
struct disasm_line *dl)
{
struct ins *ins;
@@ -880,7 +880,7 @@ static struct ins_ops *__ins__find(const struct arch *arch, const char *name,
* For powerpc, identify the instruction ops
* from the opcode using raw_insn.
*/
- struct ins_ops *ops;
+ const struct ins_ops *ops;
ops = check_ppc_insn(dl);
if (ops)
@@ -916,9 +916,9 @@ static struct ins_ops *__ins__find(const struct arch *arch, const char *name,
return ins ? ins->ops : NULL;
}
-struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl)
+const struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl)
{
- struct ins_ops *ops = __ins__find(arch, name, dl);
+ const struct ins_ops *ops = __ins__find(arch, name, dl);
if (!ops && arch->associate_instruction_ops)
ops = arch->associate_instruction_ops((struct arch *)arch, name);
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index 273a9c906514..dc5233f2a773 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -22,7 +22,7 @@ struct arch {
struct ins *instructions;
size_t nr_instructions;
size_t nr_instructions_allocated;
- struct ins_ops *(*associate_instruction_ops)(struct arch *arch, const char *name);
+ const struct ins_ops *(*associate_instruction_ops)(struct arch *arch, const char *name);
bool sorted_instructions;
bool initialized;
const char *insn_suffix;
@@ -52,7 +52,7 @@ struct arch {
struct ins {
const char *name;
- struct ins_ops *ops;
+ const struct ins_ops *ops;
};
struct ins_operands {
@@ -108,7 +108,7 @@ struct annotate_args {
const struct arch *arch__find(const char *name);
bool arch__is(const struct arch *arch, const char *name);
-struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl);
+const struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl);
bool ins__is_call(const struct ins *ins);
bool ins__is_jump(const struct ins *ins);
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 05/11] perf disasm: Constify use of struct ins
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
` (3 preceding siblings ...)
2026-01-22 7:31 ` [PATCH v1 04/11] perf disasm: Constify use of struct ins_op Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 7:31 ` [PATCH v1 06/11] perf disasm: Rework the string arch__is to use the ELF machine Ian Rogers
` (6 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
The struct ins holds variables that are read but not written, except
during some initialization. Change most uses to be for a "const struct
ins *" version to capture this immutability. So the x86__instructions
can be const pre-sort it and make the sorted variable true.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/arch/arm64/annotate/instructions.c | 2 +-
tools/perf/arch/x86/annotate/instructions.c | 26 +++++++++++----
tools/perf/util/disasm.c | 32 ++++++++++---------
tools/perf/util/disasm.h | 4 +--
4 files changed, 40 insertions(+), 24 deletions(-)
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index 363af2f55122..44db33854dba 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -60,7 +60,7 @@ static int arm64_mov__parse(const struct arch *arch __maybe_unused,
return -1;
}
-static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
+static int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name);
static const struct ins_ops arm64_mov_ops = {
diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c
index 24b388bacdae..ffca3029388b 100644
--- a/tools/perf/arch/x86/annotate/instructions.c
+++ b/tools/perf/arch/x86/annotate/instructions.c
@@ -7,7 +7,7 @@
* So this table should not have entries with the suffix unless it's
* a complete different instruction than ones without the suffix.
*/
-static struct ins x86__instructions[] = {
+static const struct ins x86__instructions[] = {
{ .name = "adc", .ops = &mov_ops, },
{ .name = "add", .ops = &mov_ops, },
{ .name = "addsd", .ops = &mov_ops, },
@@ -19,9 +19,9 @@ static struct ins x86__instructions[] = {
{ .name = "btr", .ops = &mov_ops, },
{ .name = "bts", .ops = &mov_ops, },
{ .name = "call", .ops = &call_ops, },
+ { .name = "cmovae", .ops = &mov_ops, },
{ .name = "cmovbe", .ops = &mov_ops, },
{ .name = "cmove", .ops = &mov_ops, },
- { .name = "cmovae", .ops = &mov_ops, },
{ .name = "cmp", .ops = &mov_ops, },
{ .name = "cmpxch", .ops = &mov_ops, },
{ .name = "cmpxchg", .ops = &mov_ops, },
@@ -73,23 +73,23 @@ static struct ins x86__instructions[] = {
{ .name = "movaps", .ops = &mov_ops, },
{ .name = "movdqa", .ops = &mov_ops, },
{ .name = "movdqu", .ops = &mov_ops, },
+ { .name = "movsb", .ops = &mov_ops, },
{ .name = "movsd", .ops = &mov_ops, },
+ { .name = "movsl", .ops = &mov_ops, },
{ .name = "movss", .ops = &mov_ops, },
- { .name = "movsb", .ops = &mov_ops, },
{ .name = "movsw", .ops = &mov_ops, },
- { .name = "movsl", .ops = &mov_ops, },
{ .name = "movupd", .ops = &mov_ops, },
{ .name = "movups", .ops = &mov_ops, },
{ .name = "movzb", .ops = &mov_ops, },
- { .name = "movzw", .ops = &mov_ops, },
{ .name = "movzl", .ops = &mov_ops, },
+ { .name = "movzw", .ops = &mov_ops, },
{ .name = "mulsd", .ops = &mov_ops, },
{ .name = "mulss", .ops = &mov_ops, },
{ .name = "nop", .ops = &nop_ops, },
{ .name = "or", .ops = &mov_ops, },
{ .name = "orps", .ops = &mov_ops, },
- { .name = "pand", .ops = &mov_ops, },
{ .name = "paddq", .ops = &mov_ops, },
+ { .name = "pand", .ops = &mov_ops, },
{ .name = "pcmpeqb", .ops = &mov_ops, },
{ .name = "por", .ops = &mov_ops, },
{ .name = "rcl", .ops = &mov_ops, },
@@ -202,6 +202,20 @@ static int x86__annotate_init(struct arch *arch, char *cpuid)
if (x86__cpuid_parse(arch, cpuid))
err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
}
+
+#ifndef NDEBUG
+ {
+ static bool sorted_check;
+
+ if (!sorted_check) {
+ for (size_t i = 0; i < arch->nr_instructions - 1; i++) {
+ assert(strcmp(arch->instructions[i].name,
+ arch->instructions[i + 1].name) <= 0);
+ }
+ sorted_check = true;
+ }
+ }
+#endif
arch->e_machine = EM_X86_64;
arch->e_flags = 0;
arch->initialized = true;
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index dbeb89047fd1..7cfea3419041 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -43,9 +43,9 @@ static const struct ins_ops ret_ops;
static const struct ins_ops load_store_ops;
static const struct ins_ops arithmetic_ops;
-static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
+static int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name);
-static int call__scnprintf(struct ins *ins, char *bf, size_t size,
+static int call__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name);
static void ins__sort(struct arch *arch);
@@ -66,7 +66,8 @@ static int arch__grow_instructions(struct arch *arch)
goto grow_from_non_allocated_table;
new_nr_allocated = arch->nr_instructions_allocated + 128;
- new_instructions = realloc(arch->instructions, new_nr_allocated * sizeof(struct ins));
+ new_instructions = realloc((void *)arch->instructions,
+ new_nr_allocated * sizeof(struct ins));
if (new_instructions == NULL)
return -1;
@@ -93,7 +94,7 @@ static int arch__associate_ins_ops(struct arch *arch, const char *name, const st
arch__grow_instructions(arch))
return -1;
- ins = &arch->instructions[arch->nr_instructions];
+ ins = (struct ins *)&arch->instructions[arch->nr_instructions];
ins->name = strdup(name);
if (!ins->name)
return -1;
@@ -146,6 +147,7 @@ static struct arch architectures[] = {
.init = x86__annotate_init,
.instructions = x86__instructions,
.nr_instructions = ARRAY_SIZE(x86__instructions),
+ .sorted_instructions = true,
.insn_suffix = "bwlq",
.objdump = {
.comment_char = '#',
@@ -241,13 +243,13 @@ static void ins_ops__delete(struct ins_operands *ops)
zfree(&ops->target.name);
}
-static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
+static int ins__raw_scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name)
{
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->raw);
}
-static int ins__scnprintf(struct ins *ins, char *bf, size_t size,
+static int ins__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name)
{
if (ins->ops->scnprintf)
@@ -319,7 +321,7 @@ static int call__parse(const struct arch *arch, struct ins_operands *ops, struct
goto find_target;
}
-static int call__scnprintf(struct ins *ins, char *bf, size_t size,
+static int call__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name)
{
if (ops->target.sym)
@@ -446,7 +448,7 @@ static int jump__parse(const struct arch *arch, struct ins_operands *ops, struct
return 0;
}
-static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
+static int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name)
{
const char *c;
@@ -551,7 +553,7 @@ static int lock__parse(const struct arch *arch, struct ins_operands *ops, struct
return 0;
}
-static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
+static int lock__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name)
{
int printed;
@@ -680,7 +682,7 @@ static int mov__parse(const struct arch *arch, struct ins_operands *ops,
return -1;
}
-static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
+static int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name)
{
return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,
@@ -699,7 +701,7 @@ static const struct ins_ops mov_ops = {
#define ADD_ZERO_EXT_XO_FORM 202
#define SUB_ZERO_EXT_XO_FORM 200
-static int arithmetic__scnprintf(struct ins *ins, char *bf, size_t size,
+static int arithmetic__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name)
{
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
@@ -743,7 +745,7 @@ static const struct ins_ops arithmetic_ops = {
.scnprintf = arithmetic__scnprintf,
};
-static int load_store__scnprintf(struct ins *ins, char *bf, size_t size,
+static int load_store__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name)
{
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
@@ -806,7 +808,7 @@ static int dec__parse(const struct arch *arch __maybe_unused, struct ins_operand
return 0;
}
-static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
+static int dec__scnprintf(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name)
{
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
@@ -818,7 +820,7 @@ static const struct ins_ops dec_ops = {
.scnprintf = dec__scnprintf,
};
-static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
+static int nop__scnprintf(const struct ins *ins __maybe_unused, char *bf, size_t size,
struct ins_operands *ops __maybe_unused, int max_ins_name)
{
return scnprintf(bf, size, "%-*s", max_ins_name, "nop");
@@ -866,7 +868,7 @@ static void ins__sort(struct arch *arch)
{
const int nmemb = arch->nr_instructions;
- qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
+ qsort((void *)arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
}
static const struct ins_ops *__ins__find(const struct arch *arch, const char *name,
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index dc5233f2a773..4f5c9a985786 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -19,7 +19,7 @@ struct disasm_line;
struct arch {
const char *name;
- struct ins *instructions;
+ const struct ins *instructions;
size_t nr_instructions;
size_t nr_instructions_allocated;
const struct ins_ops *(*associate_instruction_ops)(struct arch *arch, const char *name);
@@ -91,7 +91,7 @@ struct ins_ops {
void (*free)(struct ins_operands *ops);
int (*parse)(const struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
struct disasm_line *dl);
- int (*scnprintf)(struct ins *ins, char *bf, size_t size,
+ int (*scnprintf)(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name);
};
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 06/11] perf disasm: Rework the string arch__is to use the ELF machine
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
` (4 preceding siblings ...)
2026-01-22 7:31 ` [PATCH v1 05/11] perf disasm: Constify use of struct ins Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 7:31 ` [PATCH v1 07/11] perf disasm: Don't include C files from the arch directory Ian Rogers
` (5 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
Add new arch__is_x86 and arch__is_powerpc functions that avoid string
comparisons and use the ELF machine. Remove arch__is that is no longer
used.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/annotate-data.c | 10 +++++-----
tools/perf/util/annotate.c | 16 ++++++++--------
tools/perf/util/capstone.c | 2 +-
tools/perf/util/disasm.c | 15 ++++++++++-----
tools/perf/util/disasm.h | 3 ++-
tools/perf/util/llvm.c | 2 +-
6 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index edfcd6e9df9c..44fbd41e3845 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -165,7 +165,7 @@ static void init_type_state(struct type_state *state, const struct arch *arch)
memset(state, 0, sizeof(*state));
INIT_LIST_HEAD(&state->stack_vars);
- if (arch__is(arch, "x86")) {
+ if (arch__is_x86(arch)) {
state->regs[0].caller_saved = true;
state->regs[1].caller_saved = true;
state->regs[2].caller_saved = true;
@@ -526,7 +526,7 @@ static enum type_match_result check_variable(struct data_loc_info *dloc,
needs_pointer = false;
else if (reg == dloc->fbreg || is_fbreg)
needs_pointer = false;
- else if (arch__is(dloc->arch, "x86") && reg == X86_REG_SP)
+ else if (arch__is_x86(dloc->arch) && reg == X86_REG_SP)
needs_pointer = false;
/* Get the type of the variable */
@@ -1071,7 +1071,7 @@ static void delete_var_types(struct die_var_type *var_types)
/* should match to is_stack_canary() in util/annotate.c */
static void setup_stack_canary(struct data_loc_info *dloc)
{
- if (arch__is(dloc->arch, "x86")) {
+ if (arch__is_x86(dloc->arch)) {
dloc->op->segment = INSN_SEG_X86_GS;
dloc->op->imm = true;
dloc->op->offset = 40;
@@ -1311,7 +1311,7 @@ static enum type_match_result check_matching_type(struct type_state *state,
/* Direct this-cpu access like "%gs:0x34740" */
if (dloc->op->segment == INSN_SEG_X86_GS && dloc->op->imm &&
- arch__is(dloc->arch, "x86")) {
+ arch__is_x86(dloc->arch)) {
pr_debug_dtp("this-cpu var");
addr = dloc->op->offset;
@@ -1397,7 +1397,7 @@ static enum type_match_result find_data_type_insn(struct data_loc_info *dloc,
static int arch_supports_insn_tracking(struct data_loc_info *dloc)
{
- if ((arch__is(dloc->arch, "x86")) || (arch__is(dloc->arch, "powerpc")))
+ if ((arch__is_x86(dloc->arch)) || (arch__is_powerpc(dloc->arch)))
return 1;
return 0;
}
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 132af2556aec..79702072568b 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -2474,7 +2474,7 @@ static int extract_reg_offset(const struct arch *arch, const char *str,
* %gs:0x18(%rbx). In that case it should skip the part.
*/
if (*str == arch->objdump.register_char) {
- if (arch__is(arch, "x86")) {
+ if (arch__is_x86(arch)) {
/* FIXME: Handle other segment registers */
if (!strncmp(str, "%gs:", 4))
op_loc->segment = INSN_SEG_X86_GS;
@@ -2571,7 +2571,7 @@ int annotate_get_insn_location(const struct arch *arch, struct disasm_line *dl,
op_loc->reg2 = -1;
if (insn_str == NULL) {
- if (!arch__is(arch, "powerpc"))
+ if (!arch__is_powerpc(arch))
continue;
}
@@ -2580,7 +2580,7 @@ int annotate_get_insn_location(const struct arch *arch, struct disasm_line *dl,
* required fields for op_loc, ie reg1, reg2, offset from the
* raw instruction.
*/
- if (arch__is(arch, "powerpc")) {
+ if (arch__is_powerpc(arch)) {
op_loc->mem_ref = mem_ref;
op_loc->multi_regs = multi_regs;
get_powerpc_regs(dl->raw.raw_insn, !i, op_loc);
@@ -2591,7 +2591,7 @@ int annotate_get_insn_location(const struct arch *arch, struct disasm_line *dl,
} else {
char *s, *p = NULL;
- if (arch__is(arch, "x86")) {
+ if (arch__is_x86(arch)) {
/* FIXME: Handle other segment registers */
if (!strncmp(insn_str, "%gs:", 4)) {
op_loc->segment = INSN_SEG_X86_GS;
@@ -2675,7 +2675,7 @@ static struct annotated_item_stat *annotate_data_stat(struct list_head *head,
static bool is_stack_operation(const struct arch *arch, struct disasm_line *dl)
{
- if (arch__is(arch, "x86")) {
+ if (arch__is_x86(arch)) {
if (!strncmp(dl->ins.name, "push", 4) ||
!strncmp(dl->ins.name, "pop", 3) ||
!strncmp(dl->ins.name, "call", 4) ||
@@ -2689,7 +2689,7 @@ static bool is_stack_operation(const struct arch *arch, struct disasm_line *dl)
static bool is_stack_canary(const struct arch *arch, struct annotated_op_loc *loc)
{
/* On x86_64, %gs:40 is used for stack canary */
- if (arch__is(arch, "x86")) {
+ if (arch__is_x86(arch)) {
if (loc->segment == INSN_SEG_X86_GS && loc->imm &&
loc->offset == 40)
return true;
@@ -2704,7 +2704,7 @@ static bool is_stack_canary(const struct arch *arch, struct annotated_op_loc *lo
*/
static bool is_address_gen_insn(const struct arch *arch, struct disasm_line *dl)
{
- if (arch__is(arch, "x86")) {
+ if (arch__is_x86(arch)) {
if (!strncmp(dl->ins.name, "lea", 3))
return true;
}
@@ -2847,7 +2847,7 @@ __hist_entry__get_data_type(struct hist_entry *he, const struct arch *arch,
}
/* This CPU access in kernel - pretend PC-relative addressing */
- if (dso__kernel(map__dso(ms->map)) && arch__is(arch, "x86") &&
+ if (dso__kernel(map__dso(ms->map)) && arch__is_x86(arch) &&
op_loc->segment == INSN_SEG_X86_GS && op_loc->imm) {
dloc.var_addr = op_loc->offset;
op_loc->reg1 = DWARF_REG_PC;
diff --git a/tools/perf/util/capstone.c b/tools/perf/util/capstone.c
index 2c7feab61b7b..ce06cfd253ef 100644
--- a/tools/perf/util/capstone.c
+++ b/tools/perf/util/capstone.c
@@ -147,7 +147,7 @@ static void print_capstone_detail(cs_insn *insn, char *buf, size_t len,
struct symbol *sym;
/* TODO: support more architectures */
- if (!arch__is(args->arch, "x86"))
+ if (!arch__is_x86(args->arch))
return;
if (insn->detail == NULL)
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index 7cfea3419041..bc6cc7a60e3c 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -228,9 +228,14 @@ const struct arch *arch__find(const char *name)
return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp);
}
-bool arch__is(const struct arch *arch, const char *name)
+bool arch__is_x86(const struct arch *arch)
{
- return !strcmp(arch->name, name);
+ return arch->e_machine == EM_386 || arch->e_machine == EM_X86_64;
+}
+
+bool arch__is_powerpc(const struct arch *arch)
+{
+ return arch->e_machine == EM_PPC || arch->e_machine == EM_PPC64;
}
static void ins_ops__delete(struct ins_operands *ops)
@@ -877,7 +882,7 @@ static const struct ins_ops *__ins__find(const struct arch *arch, const char *na
struct ins *ins;
const int nmemb = arch->nr_instructions;
- if (arch__is(arch, "powerpc")) {
+ if (arch__is_powerpc(arch)) {
/*
* For powerpc, identify the instruction ops
* from the opcode using raw_insn.
@@ -1066,7 +1071,7 @@ struct disasm_line *disasm_line__new(struct annotate_args *args)
goto out_delete;
if (args->offset != -1) {
- if (arch__is(args->arch, "powerpc")) {
+ if (arch__is_powerpc(args->arch)) {
if (disasm_line__parse_powerpc(dl, args) < 0)
goto out_free_line;
} else if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
@@ -1698,7 +1703,7 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
* and typeoff, disassemble to mnemonic notation is not required in
* case of powerpc.
*/
- if (arch__is(args->arch, "powerpc")) {
+ if (arch__is_powerpc(args->arch)) {
extern const char *sort_order;
if (sort_order && !strstr(sort_order, "sym")) {
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index 4f5c9a985786..db7f1ee3d8e7 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -106,7 +106,8 @@ struct annotate_args {
};
const struct arch *arch__find(const char *name);
-bool arch__is(const struct arch *arch, const char *name);
+bool arch__is_x86(const struct arch *arch);
+bool arch__is_powerpc(const struct arch *arch);
const struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl);
diff --git a/tools/perf/util/llvm.c b/tools/perf/util/llvm.c
index 4ada9a10bd93..0d126d233c01 100644
--- a/tools/perf/util/llvm.c
+++ b/tools/perf/util/llvm.c
@@ -146,7 +146,7 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
return errno;
init_llvm();
- if (arch__is(args->arch, "x86")) {
+ if (arch__is_x86(args->arch)) {
const char *triplet = is_64bit ? "x86_64-pc-linux" : "i686-pc-linux";
disasm = LLVMCreateDisasm(triplet, &storage, /*tag_type=*/0,
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 07/11] perf disasm: Don't include C files from the arch directory
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
` (5 preceding siblings ...)
2026-01-22 7:31 ` [PATCH v1 06/11] perf disasm: Rework the string arch__is to use the ELF machine Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 7:31 ` [PATCH v1 08/11] perf disasm: Refactor ins__is_call/jump to avoid exposing arch ins_ops Ian Rogers
` (4 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
Move the arch instructions.c files into appropriately named files in
annotate-arch in the util directory. Don't #include to compile the
code, switch to building the files and fix up the #includes
accordingly. Move powerpc specific disasm code out of disasm.c and
into annotate-powerpc.c. Declarations and static removed as
appropriate for the code to compile as separate compilation units. The
e_machine and e_flags set up is moved to the disasm.c architectures
array so that later patches can sort by them.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/Build | 1 +
tools/perf/util/annotate-arch/Build | 11 +
.../annotate-arch/annotate-arc.c} | 5 +-
.../annotate-arch/annotate-arm.c} | 9 +-
.../annotate-arch/annotate-arm64.c} | 14 +-
.../annotate-arch/annotate-csky.c} | 11 +-
.../annotate-arch/annotate-loongarch.c} | 15 +-
.../annotate-arch/annotate-mips.c} | 6 +-
.../annotate-arch/annotate-powerpc.c} | 105 ++++++++-
.../annotate-arch/annotate-riscv64.c} | 6 +-
.../annotate-arch/annotate-s390.c} | 15 +-
.../annotate-arch/annotate-sparc.c} | 7 +-
.../annotate-arch/annotate-x86.c} | 85 +++++---
tools/perf/util/disasm.c | 199 ++++--------------
tools/perf/util/disasm.h | 38 ++++
15 files changed, 289 insertions(+), 238 deletions(-)
create mode 100644 tools/perf/util/annotate-arch/Build
rename tools/perf/{arch/arc/annotate/instructions.c => util/annotate-arch/annotate-arc.c} (53%)
rename tools/perf/{arch/arm/annotate/instructions.c => util/annotate-arch/annotate-arm.c} (90%)
rename tools/perf/{arch/arm64/annotate/instructions.c => util/annotate-arch/annotate-arm64.c} (90%)
rename tools/perf/{arch/csky/annotate/instructions.c => util/annotate-arch/annotate-csky.c} (83%)
rename tools/perf/{arch/loongarch/annotate/instructions.c => util/annotate-arch/annotate-loongarch.c} (93%)
rename tools/perf/{arch/mips/annotate/instructions.c => util/annotate-arch/annotate-mips.c} (94%)
rename tools/perf/{arch/powerpc/annotate/instructions.c => util/annotate-arch/annotate-powerpc.c} (76%)
rename tools/perf/{arch/riscv64/annotate/instructions.c => util/annotate-arch/annotate-riscv64.c} (91%)
rename tools/perf/{arch/s390/annotate/instructions.c => util/annotate-arch/annotate-s390.c} (91%)
rename tools/perf/{arch/sparc/annotate/instructions.c => util/annotate-arch/annotate-sparc.c} (96%)
rename tools/perf/{arch/x86/annotate/instructions.c => util/annotate-arch/annotate-x86.c} (97%)
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index c30ff257f8b4..b9925c6902ca 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -1,6 +1,7 @@
include $(srctree)/tools/scripts/Makefile.include
include $(srctree)/tools/scripts/utilities.mak
+perf-util-y += annotate-arch/
perf-util-y += arm64-frame-pointer-unwind-support.o
perf-util-y += addr2line.o
perf-util-y += addr_location.o
diff --git a/tools/perf/util/annotate-arch/Build b/tools/perf/util/annotate-arch/Build
new file mode 100644
index 000000000000..23316743fdc5
--- /dev/null
+++ b/tools/perf/util/annotate-arch/Build
@@ -0,0 +1,11 @@
+perf-util-y += annotate-arc.o
+perf-util-y += annotate-arm.o
+perf-util-y += annotate-arm64.o
+perf-util-y += annotate-csky.o
+perf-util-y += annotate-loongarch.o
+perf-util-y += annotate-mips.o
+perf-util-y += annotate-x86.o
+perf-util-y += annotate-powerpc.o
+perf-util-y += annotate-riscv64.o
+perf-util-y += annotate-s390.o
+perf-util-y += annotate-sparc.o
diff --git a/tools/perf/arch/arc/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-arc.c
similarity index 53%
rename from tools/perf/arch/arc/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-arc.c
index e5619770a1af..d7ca08ca5600 100644
--- a/tools/perf/arch/arc/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-arc.c
@@ -1,11 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
+#include "../disasm.h"
-static int arc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+int arc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
arch->initialized = true;
arch->objdump.comment_char = ';';
- arch->e_machine = EM_ARC;
- arch->e_flags = 0;
return 0;
}
diff --git a/tools/perf/arch/arm/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-arm.c
similarity index 90%
rename from tools/perf/arch/arm/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-arm.c
index b997d127fedd..08c49067c3c9 100644
--- a/tools/perf/arch/arm/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-arm.c
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
+#include <stdlib.h>
#include <linux/compiler.h>
#include <linux/zalloc.h>
#include <errno.h>
-#include <sys/types.h>
#include <regex.h>
-#include <stdlib.h>
+#include "../annotate.h"
+#include "../disasm.h"
struct arm_annotate {
regex_t call_insn,
@@ -28,7 +29,7 @@ static const struct ins_ops *arm__associate_instruction_ops(struct arch *arch, c
return ops;
}
-static int arm__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+int arm__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
struct arm_annotate *arm;
int err;
@@ -54,8 +55,6 @@ static int arm__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
arch->associate_instruction_ops = arm__associate_instruction_ops;
arch->objdump.comment_char = ';';
arch->objdump.skip_functions_char = '+';
- arch->e_machine = EM_ARM;
- arch->e_flags = 0;
return 0;
out_free_call:
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-arm64.c
similarity index 90%
rename from tools/perf/arch/arm64/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-arm64.c
index 44db33854dba..d2ea32984b0d 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-arm64.c
@@ -1,9 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
#include <errno.h>
-#include <sys/types.h>
-#include <regex.h>
#include <stdlib.h>
+#include <string.h>
+#include <linux/zalloc.h>
+#include <regex.h>
+#include "../annotate.h"
+#include "../disasm.h"
struct arm64_annotate {
regex_t call_insn,
@@ -60,9 +63,6 @@ static int arm64_mov__parse(const struct arch *arch __maybe_unused,
return -1;
}
-static int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name);
-
static const struct ins_ops arm64_mov_ops = {
.parse = arm64_mov__parse,
.scnprintf = mov__scnprintf,
@@ -87,7 +87,7 @@ static const struct ins_ops *arm64__associate_instruction_ops(struct arch *arch,
return ops;
}
-static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
struct arm64_annotate *arm;
int err;
@@ -114,8 +114,6 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
arch->associate_instruction_ops = arm64__associate_instruction_ops;
arch->objdump.comment_char = '/';
arch->objdump.skip_functions_char = '+';
- arch->e_machine = EM_AARCH64;
- arch->e_flags = 0;
return 0;
out_free_call:
diff --git a/tools/perf/arch/csky/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-csky.c
similarity index 83%
rename from tools/perf/arch/csky/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-csky.c
index 4a55c84a320a..0b0b09b068ec 100644
--- a/tools/perf/arch/csky/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-csky.c
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
-
+#include <string.h>
#include <linux/compiler.h>
+#include "../disasm.h"
static const struct ins_ops *csky__associate_ins_ops(struct arch *arch,
const char *name)
@@ -38,16 +39,10 @@ static const struct ins_ops *csky__associate_ins_ops(struct arch *arch,
return ops;
}
-static int csky__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+int csky__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
arch->initialized = true;
arch->objdump.comment_char = '/';
arch->associate_instruction_ops = csky__associate_ins_ops;
- arch->e_machine = EM_CSKY;
-#if defined(__CSKYABIV2__)
- arch->e_flags = EF_CSKY_ABIV2;
-#else
- arch->e_flags = EF_CSKY_ABIV1;
-#endif
return 0;
}
diff --git a/tools/perf/arch/loongarch/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-loongarch.c
similarity index 93%
rename from tools/perf/arch/loongarch/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-loongarch.c
index ee360faad420..4bd651b63652 100644
--- a/tools/perf/arch/loongarch/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-loongarch.c
@@ -4,11 +4,17 @@
*
* Copyright (C) 2020-2023 Loongson Technology Corporation Limited
*/
+#include <stdlib.h>
+#include <string.h>
+#include <linux/compiler.h>
+#include "../disasm.h"
+#include "../map.h"
+#include "../maps.h"
+#include "../symbol.h"
static int loongarch_call__parse(const struct arch *arch, struct ins_operands *ops,
struct map_symbol *ms,
struct disasm_line *dl __maybe_unused)
-
{
char *c, *endptr, *tok, *name;
struct map *map = ms->map;
@@ -49,7 +55,7 @@ static int loongarch_call__parse(const struct arch *arch, struct ins_operands *o
return 0;
}
-static const struct ins_ops loongarch_call_ops = {
+const struct ins_ops loongarch_call_ops = {
.parse = loongarch_call__parse,
.scnprintf = call__scnprintf,
};
@@ -98,7 +104,7 @@ static int loongarch_jump__parse(const struct arch *arch, struct ins_operands *o
return 0;
}
-static const struct ins_ops loongarch_jump_ops = {
+const struct ins_ops loongarch_jump_ops = {
.parse = loongarch_jump__parse,
.scnprintf = jump__scnprintf,
};
@@ -128,15 +134,12 @@ const struct ins_ops *loongarch__associate_ins_ops(struct arch *arch, const char
return ops;
}
-static
int loongarch__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
if (!arch->initialized) {
arch->associate_instruction_ops = loongarch__associate_ins_ops;
arch->initialized = true;
arch->objdump.comment_char = '#';
- arch->e_machine = EM_LOONGARCH;
- arch->e_flags = 0;
}
return 0;
diff --git a/tools/perf/arch/mips/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-mips.c
similarity index 94%
rename from tools/perf/arch/mips/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-mips.c
index 0fbe0a7df95a..f14b34ed77d3 100644
--- a/tools/perf/arch/mips/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-mips.c
@@ -1,4 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
+#include <string.h>
+#include <linux/compiler.h>
+#include "../disasm.h"
static
const struct ins_ops *mips__associate_ins_ops(struct arch *arch, const char *name)
@@ -33,15 +36,12 @@ const struct ins_ops *mips__associate_ins_ops(struct arch *arch, const char *nam
return ops;
}
-static
int mips__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
if (!arch->initialized) {
arch->associate_instruction_ops = mips__associate_ins_ops;
arch->initialized = true;
arch->objdump.comment_char = '#';
- arch->e_machine = EM_MIPS;
- arch->e_flags = 0;
}
return 0;
diff --git a/tools/perf/arch/powerpc/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-powerpc.c
similarity index 76%
rename from tools/perf/arch/powerpc/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-powerpc.c
index d1be55425e35..593c138c8104 100644
--- a/tools/perf/arch/powerpc/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-powerpc.c
@@ -1,5 +1,97 @@
// SPDX-License-Identifier: GPL-2.0
+#include <string.h>
#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include "../annotate-data.h"
+#include "../debug.h"
+#include "../disasm.h"
+
+#define PPC_OP(op) (((op) >> 26) & 0x3F)
+#define PPC_21_30(R) (((R) >> 1) & 0x3ff)
+#define PPC_22_30(R) (((R) >> 1) & 0x1ff)
+
+#define MINUS_EXT_XO_FORM 234
+#define SUB_EXT_XO_FORM 232
+#define ADD_ZERO_EXT_XO_FORM 202
+#define SUB_ZERO_EXT_XO_FORM 200
+
+static int arithmetic__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name)
+{
+ return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
+ ops->raw);
+}
+
+/*
+ * Sets the fields: multi_regs and "mem_ref".
+ * "mem_ref" is set for ops->source which is later used to
+ * fill the objdump->memory_ref-char field. This ops is currently
+ * used by powerpc and since binary instruction code is used to
+ * extract opcode, regs and offset, no other parsing is needed here.
+ *
+ * Dont set multi regs for 4 cases since it has only one operand
+ * for source:
+ * - Add to Minus One Extended XO-form ( Ex: addme, addmeo )
+ * - Subtract From Minus One Extended XO-form ( Ex: subfme )
+ * - Add to Zero Extended XO-form ( Ex: addze, addzeo )
+ * - Subtract From Zero Extended XO-form ( Ex: subfze )
+ */
+static int arithmetic__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
+ struct map_symbol *ms __maybe_unused, struct disasm_line *dl)
+{
+ int opcode = PPC_OP(dl->raw.raw_insn);
+
+ ops->source.mem_ref = false;
+ if (opcode == 31) {
+ if ((opcode != MINUS_EXT_XO_FORM) && (opcode != SUB_EXT_XO_FORM) &&
+ (opcode != ADD_ZERO_EXT_XO_FORM) && (opcode != SUB_ZERO_EXT_XO_FORM))
+ ops->source.multi_regs = true;
+ }
+
+ ops->target.mem_ref = false;
+ ops->target.multi_regs = false;
+
+ return 0;
+}
+
+static const struct ins_ops arithmetic_ops = {
+ .parse = arithmetic__parse,
+ .scnprintf = arithmetic__scnprintf,
+};
+
+static int load_store__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name)
+{
+ return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
+ ops->raw);
+}
+
+/*
+ * Sets the fields: multi_regs and "mem_ref".
+ * "mem_ref" is set for ops->source which is later used to
+ * fill the objdump->memory_ref-char field. This ops is currently
+ * used by powerpc and since binary instruction code is used to
+ * extract opcode, regs and offset, no other parsing is needed here
+ */
+static int load_store__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
+ struct map_symbol *ms __maybe_unused, struct disasm_line *dl __maybe_unused)
+{
+ ops->source.mem_ref = true;
+ ops->source.multi_regs = false;
+ /* opcode 31 is of X form */
+ if (PPC_OP(dl->raw.raw_insn) == 31)
+ ops->source.multi_regs = true;
+
+ ops->target.mem_ref = false;
+ ops->target.multi_regs = false;
+
+ return 0;
+}
+
+static const struct ins_ops load_store_ops = {
+ .parse = load_store__parse,
+ .scnprintf = load_store__scnprintf,
+};
static const struct ins_ops *powerpc__associate_instruction_ops(struct arch *arch, const char *name)
{
@@ -49,10 +141,6 @@ static const struct ins_ops *powerpc__associate_instruction_ops(struct arch *arc
return ops;
}
-#define PPC_OP(op) (((op) >> 26) & 0x3F)
-#define PPC_21_30(R) (((R) >> 1) & 0x3ff)
-#define PPC_22_30(R) (((R) >> 1) & 0x1ff)
-
struct insn_offset {
const char *name;
int value;
@@ -189,7 +277,7 @@ static int cmp_offset(const void *a, const void *b)
return (val1->value - val2->value);
}
-static const struct ins_ops *check_ppc_insn(struct disasm_line *dl)
+const struct ins_ops *check_ppc_insn(struct disasm_line *dl)
{
int raw_insn = dl->raw.raw_insn;
int opcode = PPC_OP(raw_insn);
@@ -302,15 +390,16 @@ static void update_insn_state_powerpc(struct type_state *state,
}
#endif /* HAVE_LIBDW_SUPPORT */
-static int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
if (!arch->initialized) {
arch->initialized = true;
arch->associate_instruction_ops = powerpc__associate_instruction_ops;
arch->objdump.comment_char = '#';
annotate_opts.show_asm_raw = true;
- arch->e_machine = EM_PPC;
- arch->e_flags = 0;
+#ifdef HAVE_LIBDW_SUPPORT
+ arch->update_insn_state = update_insn_state_powerpc;
+#endif
}
return 0;
diff --git a/tools/perf/arch/riscv64/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-riscv64.c
similarity index 91%
rename from tools/perf/arch/riscv64/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-riscv64.c
index a34798864fab..15526824037a 100644
--- a/tools/perf/arch/riscv64/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-riscv64.c
@@ -1,4 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
+#include <string.h>
+#include <linux/compiler.h>
+#include "../disasm.h"
static
const struct ins_ops *riscv64__associate_ins_ops(struct arch *arch, const char *name)
@@ -21,15 +24,12 @@ const struct ins_ops *riscv64__associate_ins_ops(struct arch *arch, const char *
return ops;
}
-static
int riscv64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
if (!arch->initialized) {
arch->associate_instruction_ops = riscv64__associate_ins_ops;
arch->initialized = true;
arch->objdump.comment_char = '#';
- arch->e_machine = EM_RISCV;
- arch->e_flags = 0;
}
return 0;
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-s390.c
similarity index 91%
rename from tools/perf/arch/s390/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-s390.c
index 38f7e918ebf8..c1d06caa5f77 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-s390.c
@@ -1,5 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
+#include <string.h>
#include <linux/compiler.h>
+#include "../debug.h"
+#include "../disasm.h"
+#include "../map.h"
+#include "../maps.h"
+#include "../symbol.h"
+#include "../annotate.h"
+#include "../annotate-data.h"
static int s390_call__parse(const struct arch *arch, struct ins_operands *ops,
struct map_symbol *ms,
@@ -46,7 +54,7 @@ static int s390_call__parse(const struct arch *arch, struct ins_operands *ops,
return 0;
}
-static const struct ins_ops s390_call_ops = {
+const struct ins_ops s390_call_ops = {
.parse = s390_call__parse,
.scnprintf = call__scnprintf,
};
@@ -156,7 +164,7 @@ static int s390__cpuid_parse(struct arch *arch, char *cpuid)
return -1;
}
-static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
int err = 0;
@@ -167,8 +175,7 @@ static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
if (s390__cpuid_parse(arch, cpuid))
err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
}
- arch->e_machine = EM_S390;
- arch->e_flags = 0;
+ arch->objdump.comment_char = '#';
}
return err;
diff --git a/tools/perf/arch/sparc/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-sparc.c
similarity index 96%
rename from tools/perf/arch/sparc/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-sparc.c
index a08d8734c883..66a0174376dd 100644
--- a/tools/perf/arch/sparc/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-sparc.c
@@ -1,4 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
+#include <string.h>
+#include <linux/compiler.h>
+#include "../../util/disasm.h"
static int is_branch_cond(const char *cond)
{
@@ -157,14 +160,12 @@ static const struct ins_ops *sparc__associate_instruction_ops(struct arch *arch,
return ops;
}
-static int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
if (!arch->initialized) {
arch->initialized = true;
arch->associate_instruction_ops = sparc__associate_instruction_ops;
arch->objdump.comment_char = '#';
- arch->e_machine = EM_SPARC;
- arch->e_flags = 0;
}
return 0;
diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/util/annotate-arch/annotate-x86.c
similarity index 97%
rename from tools/perf/arch/x86/annotate/instructions.c
rename to tools/perf/util/annotate-arch/annotate-x86.c
index ffca3029388b..0c7957fe60da 100644
--- a/tools/perf/arch/x86/annotate/instructions.c
+++ b/tools/perf/util/annotate-arch/annotate-x86.c
@@ -1,4 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
+#include <string.h>
+#include <linux/compiler.h>
+#include <assert.h>
+#include <inttypes.h>
+#include "../annotate-data.h"
+#include "../debug.h"
+#include "../disasm.h"
+#include "../dso.h"
+#include "../map.h"
+#include "../string2.h" // strstarts
+#include "../symbol.h"
+
/*
* x86 instruction nmemonic table to parse disasm lines for annotate.
* This table is searched twice - one for exact match and another for
@@ -191,37 +203,6 @@ static int x86__cpuid_parse(struct arch *arch, char *cpuid)
return -1;
}
-static int x86__annotate_init(struct arch *arch, char *cpuid)
-{
- int err = 0;
-
- if (arch->initialized)
- return 0;
-
- if (cpuid) {
- if (x86__cpuid_parse(arch, cpuid))
- err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
- }
-
-#ifndef NDEBUG
- {
- static bool sorted_check;
-
- if (!sorted_check) {
- for (size_t i = 0; i < arch->nr_instructions - 1; i++) {
- assert(strcmp(arch->instructions[i].name,
- arch->instructions[i + 1].name) <= 0);
- }
- sorted_check = true;
- }
- }
-#endif
- arch->e_machine = EM_X86_64;
- arch->e_flags = 0;
- arch->initialized = true;
- return err;
-}
-
#ifdef HAVE_LIBDW_SUPPORT
static void update_insn_state_x86(struct type_state *state,
struct data_loc_info *dloc, Dwarf_Die *cu_die,
@@ -795,3 +776,45 @@ static void update_insn_state_x86(struct type_state *state,
/* Case 4. memory to memory transfers (not handled for now) */
}
#endif
+
+int x86__annotate_init(struct arch *arch, char *cpuid)
+{
+ int err = 0;
+
+ if (arch->initialized)
+ return 0;
+
+ if (cpuid) {
+ if (x86__cpuid_parse(arch, cpuid))
+ err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
+ }
+
+ arch->instructions = x86__instructions;
+ arch->nr_instructions = ARRAY_SIZE(x86__instructions);
+#ifndef NDEBUG
+ {
+ static bool sorted_check;
+
+ if (!sorted_check) {
+ for (size_t i = 0; i < arch->nr_instructions - 1; i++) {
+ assert(strcmp(arch->instructions[i].name,
+ arch->instructions[i + 1].name) <= 0);
+ }
+ sorted_check = true;
+ }
+ }
+#endif
+ arch->sorted_instructions = true;
+ arch->objdump.comment_char = '#';
+ arch->objdump.register_char = '%';
+ arch->objdump.memory_ref_char = '(';
+ arch->objdump.imm_char = '$';
+ arch->insn_suffix = "bwlq";
+ arch->e_machine = EM_X86_64;
+ arch->e_flags = 0;
+ arch->initialized = true;
+#ifdef HAVE_LIBDW_SUPPORT
+ arch->update_insn_state = update_insn_state_x86;
+#endif
+ return err;
+}
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index bc6cc7a60e3c..c732b015f2e8 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -33,20 +33,15 @@
static regex_t file_lineno;
/* These can be referred from the arch-dependent code */
-static const struct ins_ops call_ops;
-static const struct ins_ops dec_ops;
-static const struct ins_ops jump_ops;
-static const struct ins_ops mov_ops;
-static const struct ins_ops nop_ops;
-static const struct ins_ops lock_ops;
-static const struct ins_ops ret_ops;
-static const struct ins_ops load_store_ops;
-static const struct ins_ops arithmetic_ops;
-
-static int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name);
-static int call__scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name);
+const struct ins_ops call_ops;
+const struct ins_ops dec_ops;
+const struct ins_ops jump_ops;
+const struct ins_ops mov_ops;
+const struct ins_ops nop_ops;
+const struct ins_ops lock_ops;
+const struct ins_ops ret_ops;
+const struct ins_ops load_store_ops;
+const struct ins_ops arithmetic_ops;
static void ins__sort(struct arch *arch);
static int disasm_line__parse(char *line, const char **namep, char **rawp);
@@ -86,7 +81,7 @@ static int arch__grow_instructions(struct arch *arch)
goto out_update_instructions;
}
-static int arch__associate_ins_ops(struct arch *arch, const char *name, const struct ins_ops *ops)
+int arch__associate_ins_ops(struct arch *arch, const char *name, const struct ins_ops *ops)
{
struct ins *ins;
@@ -106,90 +101,66 @@ static int arch__associate_ins_ops(struct arch *arch, const char *name, const st
return 0;
}
-#include "arch/arc/annotate/instructions.c"
-#include "arch/arm/annotate/instructions.c"
-#include "arch/arm64/annotate/instructions.c"
-#include "arch/csky/annotate/instructions.c"
-#include "arch/loongarch/annotate/instructions.c"
-#include "arch/mips/annotate/instructions.c"
-#include "arch/x86/annotate/instructions.c"
-#include "arch/powerpc/annotate/instructions.c"
-#include "arch/riscv64/annotate/instructions.c"
-#include "arch/s390/annotate/instructions.c"
-#include "arch/sparc/annotate/instructions.c"
-
static struct arch architectures[] = {
{
.name = "arc",
.init = arc__annotate_init,
+ .e_machine = EM_ARC,
},
{
.name = "arm",
.init = arm__annotate_init,
+ .e_machine = EM_ARM,
},
{
.name = "arm64",
.init = arm64__annotate_init,
+ .e_machine = EM_AARCH64,
},
{
.name = "csky",
.init = csky__annotate_init,
+ .e_machine = EM_CSKY,
+#if defined(__CSKYABIV2__)
+ .e_flags = EF_CSKY_ABIV2,
+#else
+ .e_flags = EF_CSKY_ABIV1,
+#endif
},
{
.name = "mips",
.init = mips__annotate_init,
- .objdump = {
- .comment_char = '#',
- },
+ .e_machine = EM_MIPS,
},
{
.name = "x86",
.init = x86__annotate_init,
- .instructions = x86__instructions,
- .nr_instructions = ARRAY_SIZE(x86__instructions),
- .sorted_instructions = true,
- .insn_suffix = "bwlq",
- .objdump = {
- .comment_char = '#',
- .register_char = '%',
- .memory_ref_char = '(',
- .imm_char = '$',
- },
-#ifdef HAVE_LIBDW_SUPPORT
- .update_insn_state = update_insn_state_x86,
-#endif
+ .e_machine = EM_X86_64, // TODO: EM_386 too.
},
{
.name = "powerpc",
.init = powerpc__annotate_init,
-#ifdef HAVE_LIBDW_SUPPORT
- .update_insn_state = update_insn_state_powerpc,
-#endif
+ .e_machine = EM_PPC, // TODO: EM_PPC64 too.
},
{
.name = "riscv64",
.init = riscv64__annotate_init,
+ .e_machine = EM_RISCV,
},
{
.name = "s390",
.init = s390__annotate_init,
- .objdump = {
- .comment_char = '#',
- },
+ .e_machine = EM_S390,
},
{
.name = "sparc",
.init = sparc__annotate_init,
- .objdump = {
- .comment_char = '#',
- },
+ .e_machine = EM_SPARC,
},
{
.name = "loongarch",
.init = loongarch__annotate_init,
- .objdump = {
- .comment_char = '#',
- },
+ .e_machine = EM_LOONGARCH,
},
};
@@ -248,14 +219,14 @@ static void ins_ops__delete(struct ins_operands *ops)
zfree(&ops->target.name);
}
-static int ins__raw_scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name)
+int ins__raw_scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name)
{
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->raw);
}
-static int ins__scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name)
+int ins__scnprintf(const 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);
@@ -326,8 +297,8 @@ static int call__parse(const struct arch *arch, struct ins_operands *ops, struct
goto find_target;
}
-static int call__scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name)
+int call__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name)
{
if (ops->target.sym)
return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);
@@ -341,7 +312,7 @@ static int call__scnprintf(const struct ins *ins, char *bf, size_t size,
return scnprintf(bf, size, "%-*s *%" PRIx64, max_ins_name, ins->name, ops->target.addr);
}
-static const struct ins_ops call_ops = {
+const struct ins_ops call_ops = {
.parse = call__parse,
.scnprintf = call__scnprintf,
};
@@ -453,8 +424,8 @@ static int jump__parse(const struct arch *arch, struct ins_operands *ops, struct
return 0;
}
-static int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name)
+int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name)
{
const char *c;
@@ -494,7 +465,7 @@ static void jump__delete(struct ins_operands *ops __maybe_unused)
*/
}
-static const struct ins_ops jump_ops = {
+const struct ins_ops jump_ops = {
.free = jump__delete,
.parse = jump__parse,
.scnprintf = jump__scnprintf,
@@ -586,7 +557,7 @@ static void lock__delete(struct ins_operands *ops)
zfree(&ops->target.name);
}
-static const struct ins_ops lock_ops = {
+const struct ins_ops lock_ops = {
.free = lock__delete,
.parse = lock__parse,
.scnprintf = lock__scnprintf,
@@ -687,103 +658,19 @@ static int mov__parse(const struct arch *arch, struct ins_operands *ops,
return -1;
}
-static int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name)
+int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name)
{
return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,
ops->source.name ?: ops->source.raw,
ops->target.name ?: ops->target.raw);
}
-static const struct ins_ops mov_ops = {
+const struct ins_ops mov_ops = {
.parse = mov__parse,
.scnprintf = mov__scnprintf,
};
-#define PPC_22_30(R) (((R) >> 1) & 0x1ff)
-#define MINUS_EXT_XO_FORM 234
-#define SUB_EXT_XO_FORM 232
-#define ADD_ZERO_EXT_XO_FORM 202
-#define SUB_ZERO_EXT_XO_FORM 200
-
-static int arithmetic__scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name)
-{
- return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
- ops->raw);
-}
-
-/*
- * Sets the fields: multi_regs and "mem_ref".
- * "mem_ref" is set for ops->source which is later used to
- * fill the objdump->memory_ref-char field. This ops is currently
- * used by powerpc and since binary instruction code is used to
- * extract opcode, regs and offset, no other parsing is needed here.
- *
- * Dont set multi regs for 4 cases since it has only one operand
- * for source:
- * - Add to Minus One Extended XO-form ( Ex: addme, addmeo )
- * - Subtract From Minus One Extended XO-form ( Ex: subfme )
- * - Add to Zero Extended XO-form ( Ex: addze, addzeo )
- * - Subtract From Zero Extended XO-form ( Ex: subfze )
- */
-static int arithmetic__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
- struct map_symbol *ms __maybe_unused, struct disasm_line *dl)
-{
- int opcode = PPC_OP(dl->raw.raw_insn);
-
- ops->source.mem_ref = false;
- if (opcode == 31) {
- if ((opcode != MINUS_EXT_XO_FORM) && (opcode != SUB_EXT_XO_FORM) \
- && (opcode != ADD_ZERO_EXT_XO_FORM) && (opcode != SUB_ZERO_EXT_XO_FORM))
- ops->source.multi_regs = true;
- }
-
- ops->target.mem_ref = false;
- ops->target.multi_regs = false;
-
- return 0;
-}
-
-static const struct ins_ops arithmetic_ops = {
- .parse = arithmetic__parse,
- .scnprintf = arithmetic__scnprintf,
-};
-
-static int load_store__scnprintf(const struct ins *ins, char *bf, size_t size,
- struct ins_operands *ops, int max_ins_name)
-{
- return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
- ops->raw);
-}
-
-/*
- * Sets the fields: multi_regs and "mem_ref".
- * "mem_ref" is set for ops->source which is later used to
- * fill the objdump->memory_ref-char field. This ops is currently
- * used by powerpc and since binary instruction code is used to
- * extract opcode, regs and offset, no other parsing is needed here
- */
-static int load_store__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
- struct map_symbol *ms __maybe_unused, struct disasm_line *dl __maybe_unused)
-{
- ops->source.mem_ref = true;
- ops->source.multi_regs = false;
- /* opcode 31 is of X form */
- if (PPC_OP(dl->raw.raw_insn) == 31)
- ops->source.multi_regs = true;
-
- ops->target.mem_ref = false;
- ops->target.multi_regs = false;
-
- return 0;
-}
-
-static const struct ins_ops load_store_ops = {
- .parse = load_store__parse,
- .scnprintf = load_store__scnprintf,
-};
-
static int dec__parse(const struct arch *arch __maybe_unused, struct ins_operands *ops,
struct map_symbol *ms __maybe_unused,
struct disasm_line *dl __maybe_unused)
@@ -820,7 +707,7 @@ static int dec__scnprintf(const struct ins *ins, char *bf, size_t size,
ops->target.name ?: ops->target.raw);
}
-static const struct ins_ops dec_ops = {
+const struct ins_ops dec_ops = {
.parse = dec__parse,
.scnprintf = dec__scnprintf,
};
@@ -831,11 +718,11 @@ static int nop__scnprintf(const struct ins *ins __maybe_unused, char *bf, size_t
return scnprintf(bf, size, "%-*s", max_ins_name, "nop");
}
-static const struct ins_ops nop_ops = {
+const struct ins_ops nop_ops = {
.scnprintf = nop__scnprintf,
};
-static const struct ins_ops ret_ops = {
+const struct ins_ops ret_ops = {
.scnprintf = ins__raw_scnprintf,
};
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index db7f1ee3d8e7..83503c5075f9 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -109,6 +109,28 @@ const struct arch *arch__find(const char *name);
bool arch__is_x86(const struct arch *arch);
bool arch__is_powerpc(const struct arch *arch);
+extern const struct ins_ops call_ops;
+extern const struct ins_ops dec_ops;
+extern const struct ins_ops jump_ops;
+extern const struct ins_ops mov_ops;
+extern const struct ins_ops nop_ops;
+extern const struct ins_ops lock_ops;
+extern const struct ins_ops ret_ops;
+
+int arch__associate_ins_ops(struct arch *arch, const char *name, const struct ins_ops *ops);
+
+int arc__annotate_init(struct arch *arch, char *cpuid);
+int arm__annotate_init(struct arch *arch, char *cpuid);
+int arm64__annotate_init(struct arch *arch, char *cpuid);
+int csky__annotate_init(struct arch *arch, char *cpuid);
+int loongarch__annotate_init(struct arch *arch, char *cpuid);
+int mips__annotate_init(struct arch *arch, char *cpuid);
+int powerpc__annotate_init(struct arch *arch, char *cpuid);
+int riscv64__annotate_init(struct arch *arch, char *cpuid);
+int s390__annotate_init(struct arch *arch, char *cpuid);
+int sparc__annotate_init(struct arch *arch, char *cpuid);
+int x86__annotate_init(struct arch *arch, char *cpuid);
+
const struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl);
bool ins__is_call(const struct ins *ins);
@@ -117,12 +139,28 @@ bool ins__is_fused(const struct arch *arch, const char *ins1, const char *ins2);
bool ins__is_ret(const struct ins *ins);
bool ins__is_lock(const struct ins *ins);
+extern const struct ins_ops s390_call_ops;
+extern const struct ins_ops loongarch_call_ops;
+extern const struct ins_ops loongarch_jump_ops;
+const struct ins_ops *check_ppc_insn(struct disasm_line *dl);
+
struct disasm_line *disasm_line__new(struct annotate_args *args);
void disasm_line__free(struct disasm_line *dl);
int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size,
bool raw, int max_ins_name);
+int ins__raw_scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+int ins__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+int call__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+int jump__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+int mov__scnprintf(const struct ins *ins, char *bf, size_t size,
+ struct ins_operands *ops, int max_ins_name);
+
int symbol__disassemble(struct symbol *sym, struct annotate_args *args);
char *expand_tabs(char *line, char **storage, size_t *storage_len);
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 08/11] perf disasm: Refactor ins__is_call/jump to avoid exposing arch ins_ops
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
` (6 preceding siblings ...)
2026-01-22 7:31 ` [PATCH v1 07/11] perf disasm: Don't include C files from the arch directory Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 7:31 ` [PATCH v1 09/11] perf map_symbol: Switch from holding maps to holding thread Ian Rogers
` (3 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
Add booleans indicating whether and ins_ops are call or jump and
return it. This avoids exposing loongarch and s390 ins_ops for the
sake of matching.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/annotate-arch/annotate-loongarch.c | 6 ++++--
tools/perf/util/annotate-arch/annotate-s390.c | 3 ++-
tools/perf/util/disasm.c | 6 ++++--
tools/perf/util/disasm.h | 5 ++---
4 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/tools/perf/util/annotate-arch/annotate-loongarch.c b/tools/perf/util/annotate-arch/annotate-loongarch.c
index 4bd651b63652..b95ae5d6657f 100644
--- a/tools/perf/util/annotate-arch/annotate-loongarch.c
+++ b/tools/perf/util/annotate-arch/annotate-loongarch.c
@@ -55,9 +55,10 @@ static int loongarch_call__parse(const struct arch *arch, struct ins_operands *o
return 0;
}
-const struct ins_ops loongarch_call_ops = {
+static const struct ins_ops loongarch_call_ops = {
.parse = loongarch_call__parse,
.scnprintf = call__scnprintf,
+ .is_call = true,
};
static int loongarch_jump__parse(const struct arch *arch, struct ins_operands *ops,
@@ -104,9 +105,10 @@ static int loongarch_jump__parse(const struct arch *arch, struct ins_operands *o
return 0;
}
-const struct ins_ops loongarch_jump_ops = {
+static const struct ins_ops loongarch_jump_ops = {
.parse = loongarch_jump__parse,
.scnprintf = jump__scnprintf,
+ .is_jump = true,
};
static
diff --git a/tools/perf/util/annotate-arch/annotate-s390.c b/tools/perf/util/annotate-arch/annotate-s390.c
index c1d06caa5f77..6d1a1da277e2 100644
--- a/tools/perf/util/annotate-arch/annotate-s390.c
+++ b/tools/perf/util/annotate-arch/annotate-s390.c
@@ -54,9 +54,10 @@ static int s390_call__parse(const struct arch *arch, struct ins_operands *ops,
return 0;
}
-const struct ins_ops s390_call_ops = {
+static const struct ins_ops s390_call_ops = {
.parse = s390_call__parse,
.scnprintf = call__scnprintf,
+ .is_call = true,
};
static int s390_mov__parse(const struct arch *arch __maybe_unused,
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index c732b015f2e8..bc5323ecb5da 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -315,11 +315,12 @@ int call__scnprintf(const struct ins *ins, char *bf, size_t size,
const struct ins_ops call_ops = {
.parse = call__parse,
.scnprintf = call__scnprintf,
+ .is_call = true,
};
bool ins__is_call(const struct ins *ins)
{
- return ins->ops == &call_ops || ins->ops == &s390_call_ops || ins->ops == &loongarch_call_ops;
+ return ins->ops && ins->ops->is_call;
}
/*
@@ -469,11 +470,12 @@ const struct ins_ops jump_ops = {
.free = jump__delete,
.parse = jump__parse,
.scnprintf = jump__scnprintf,
+ .is_jump = true,
};
bool ins__is_jump(const struct ins *ins)
{
- return ins->ops == &jump_ops || ins->ops == &loongarch_jump_ops;
+ return ins->ops && ins->ops->is_jump;
}
static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index 83503c5075f9..b6a2a30fdf27 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -93,6 +93,8 @@ struct ins_ops {
struct disasm_line *dl);
int (*scnprintf)(const struct ins *ins, char *bf, size_t size,
struct ins_operands *ops, int max_ins_name);
+ bool is_jump;
+ bool is_call;
};
struct annotate_args {
@@ -139,9 +141,6 @@ bool ins__is_fused(const struct arch *arch, const char *ins1, const char *ins2);
bool ins__is_ret(const struct ins *ins);
bool ins__is_lock(const struct ins *ins);
-extern const struct ins_ops s390_call_ops;
-extern const struct ins_ops loongarch_call_ops;
-extern const struct ins_ops loongarch_jump_ops;
const struct ins_ops *check_ppc_insn(struct disasm_line *dl);
struct disasm_line *disasm_line__new(struct annotate_args *args);
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 09/11] perf map_symbol: Switch from holding maps to holding thread
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
` (7 preceding siblings ...)
2026-01-22 7:31 ` [PATCH v1 08/11] perf disasm: Refactor ins__is_call/jump to avoid exposing arch ins_ops Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 7:31 ` [PATCH v1 10/11] perf disasm: Refactor arch__find and initialization of arch structs Ian Rogers
` (2 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
maps may belong to >1 thread. In contexts like symbolization
information from the thread may be useful, such as the ELF machine. As
the maps can be gained from the thread switch from holding maps in
struct map_symbol to holding the thread. Holding the maps in
addr_location is also redundant, switch this to using thread__maps.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/ui/browsers/annotate.c | 2 +-
tools/perf/ui/browsers/hists.c | 3 ++-
tools/perf/util/addr_location.c | 4 ----
tools/perf/util/addr_location.h | 1 -
.../util/annotate-arch/annotate-loongarch.c | 5 +++--
tools/perf/util/annotate-arch/annotate-s390.c | 3 ++-
tools/perf/util/callchain.c | 12 +++++++-----
tools/perf/util/capstone.c | 6 ++++--
tools/perf/util/db-export.c | 1 -
tools/perf/util/disasm.c | 7 ++++---
tools/perf/util/event.c | 2 --
tools/perf/util/hist.c | 18 +++++++++---------
tools/perf/util/machine.c | 13 +++++++------
tools/perf/util/map_symbol.c | 5 +++--
tools/perf/util/map_symbol.h | 3 ++-
tools/perf/util/sort.c | 2 +-
tools/perf/util/unwind-libdw.c | 2 +-
tools/perf/util/unwind-libunwind-local.c | 2 +-
18 files changed, 47 insertions(+), 44 deletions(-)
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 3df61cd46652..91ded9c271ee 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -601,7 +601,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
return true;
}
- target_ms.maps = ms->maps;
+ target_ms.thread = ms->thread;
target_ms.map = ms->map;
target_ms.sym = dl->ops.target.sym;
annotation__unlock(notes);
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 08fecbe28a52..cfa6386e6e1d 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -3189,7 +3189,8 @@ static int evsel__hists_browse(struct evsel *evsel, int nr_events, const char *h
case 'k':
if (browser->selection != NULL)
hists_browser__zoom_map(browser,
- maps__machine(browser->selection->maps)->vmlinux_map);
+ maps__machine(thread__maps(browser->selection->thread)
+ )->vmlinux_map);
continue;
case 'V':
verbose = (verbose + 1) % 4;
diff --git a/tools/perf/util/addr_location.c b/tools/perf/util/addr_location.c
index 81a0b79c5e10..57e8217a00f9 100644
--- a/tools/perf/util/addr_location.c
+++ b/tools/perf/util/addr_location.c
@@ -7,7 +7,6 @@
void addr_location__init(struct addr_location *al)
{
al->thread = NULL;
- al->maps = NULL;
al->map = NULL;
al->sym = NULL;
al->srcline = NULL;
@@ -30,16 +29,13 @@ void addr_location__exit(struct addr_location *al)
{
map__zput(al->map);
thread__zput(al->thread);
- maps__zput(al->maps);
}
void addr_location__copy(struct addr_location *dst, struct addr_location *src)
{
thread__put(dst->thread);
- maps__put(dst->maps);
map__put(dst->map);
*dst = *src;
dst->thread = thread__get(src->thread);
- dst->maps = maps__get(src->maps);
dst->map = map__get(src->map);
}
diff --git a/tools/perf/util/addr_location.h b/tools/perf/util/addr_location.h
index 64b551025216..fdc4d3f3a68b 100644
--- a/tools/perf/util/addr_location.h
+++ b/tools/perf/util/addr_location.h
@@ -11,7 +11,6 @@ struct symbol;
struct addr_location {
struct thread *thread;
- struct maps *maps;
struct map *map;
struct symbol *sym;
const char *srcline;
diff --git a/tools/perf/util/annotate-arch/annotate-loongarch.c b/tools/perf/util/annotate-arch/annotate-loongarch.c
index b95ae5d6657f..a23744eafd6a 100644
--- a/tools/perf/util/annotate-arch/annotate-loongarch.c
+++ b/tools/perf/util/annotate-arch/annotate-loongarch.c
@@ -11,6 +11,7 @@
#include "../map.h"
#include "../maps.h"
#include "../symbol.h"
+#include "../thread.h"
static int loongarch_call__parse(const struct arch *arch, struct ins_operands *ops,
struct map_symbol *ms,
@@ -48,7 +49,7 @@ static int loongarch_call__parse(const struct arch *arch, struct ins_operands *o
target.addr = map__objdump_2mem(map, ops->target.addr);
- if (maps__find_ams(ms->maps, &target) == 0 &&
+ if (maps__find_ams(thread__maps(ms->thread), &target) == 0 &&
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
ops->target.sym = target.ms.sym;
@@ -91,7 +92,7 @@ static int loongarch_jump__parse(const struct arch *arch, struct ins_operands *o
ops->target.outside = target.addr < start || target.addr > end;
- if (maps__find_ams(ms->maps, &target) == 0 &&
+ if (maps__find_ams(thread__maps(ms->thread), &target) == 0 &&
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
ops->target.sym = target.ms.sym;
diff --git a/tools/perf/util/annotate-arch/annotate-s390.c b/tools/perf/util/annotate-arch/annotate-s390.c
index 6d1a1da277e2..cb112c1ba090 100644
--- a/tools/perf/util/annotate-arch/annotate-s390.c
+++ b/tools/perf/util/annotate-arch/annotate-s390.c
@@ -6,6 +6,7 @@
#include "../map.h"
#include "../maps.h"
#include "../symbol.h"
+#include "../thread.h"
#include "../annotate.h"
#include "../annotate-data.h"
@@ -47,7 +48,7 @@ static int s390_call__parse(const struct arch *arch, struct ins_operands *ops,
return -1;
target.addr = map__objdump_2mem(map, ops->target.addr);
- if (maps__find_ams(ms->maps, &target) == 0 &&
+ if (maps__find_ams(thread__maps(ms->thread), &target) == 0 &&
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
ops->target.sym = target.ms.sym;
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 428e5350d7a2..515bb8b5da01 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -31,6 +31,7 @@
#include "callchain.h"
#include "branch.h"
#include "symbol.h"
+#include "thread.h"
#include "util.h"
#include "../perf.h"
@@ -1042,7 +1043,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
list_for_each_entry_safe(list, next_list, &src->val, list) {
struct map_symbol ms = {
- .maps = maps__get(list->ms.maps),
+ .thread = thread__get(list->ms.thread),
.map = map__get(list->ms.map),
};
callchain_cursor_append(cursor, list->ip, &ms, false, NULL, 0, 0, 0, list->srcline);
@@ -1147,10 +1148,11 @@ int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *samp
int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
bool hide_unresolved)
{
- struct machine *machine = node->ms.maps ? maps__machine(node->ms.maps) : NULL;
+ struct machine *machine = NULL;
+
+ if (node->ms.thread)
+ machine = maps__machine(thread__maps(node->ms.thread));
- maps__put(al->maps);
- al->maps = maps__get(node->ms.maps);
map__put(al->map);
al->map = map__get(node->ms.map);
al->sym = node->ms.sym;
@@ -1163,7 +1165,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
if (al->map == NULL)
goto out;
}
- if (maps__equal(al->maps, machine__kernel_maps(machine))) {
+ if (maps__equal(thread__maps(al->thread), machine__kernel_maps(machine))) {
if (machine__is_host(machine)) {
al->cpumode = PERF_RECORD_MISC_KERNEL;
al->level = 'k';
diff --git a/tools/perf/util/capstone.c b/tools/perf/util/capstone.c
index ce06cfd253ef..9216916f848f 100644
--- a/tools/perf/util/capstone.c
+++ b/tools/perf/util/capstone.c
@@ -268,7 +268,8 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
!strcmp(args->options->disassembler_style, "att"))
disassembler_style = true;
- if (capstone_init(maps__machine(args->ms->maps), &handle, is_64bit, disassembler_style) < 0)
+ if (capstone_init(maps__machine(thread__maps(args->ms->thread)), &handle, is_64bit,
+ disassembler_style) < 0)
goto err;
needs_cs_close = true;
@@ -382,7 +383,8 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused,
!strcmp(args->options->disassembler_style, "att"))
disassembler_style = true;
- if (capstone_init(maps__machine(args->ms->maps), &handle, is_64bit, disassembler_style) < 0)
+ if (capstone_init(maps__machine(thread__maps(args->ms->thread)), &handle, is_64bit,
+ disassembler_style) < 0)
goto err;
needs_cs_close = true;
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index 8f52e8cefcf3..ae9a9065aab7 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -254,7 +254,6 @@ static struct call_path *call_path_from_sample(struct db_export *dbe,
addr_location__init(&al);
al.sym = node->ms.sym;
al.map = map__get(node->ms.map);
- al.maps = maps__get(thread__maps(thread));
al.addr = node->ip;
al.thread = thread__get(thread);
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index bc5323ecb5da..c537c12ff7cd 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -28,6 +28,7 @@
#include "namespaces.h"
#include "srcline.h"
#include "symbol.h"
+#include "thread.h"
#include "util.h"
static regex_t file_lineno;
@@ -277,7 +278,7 @@ static int call__parse(const struct arch *arch, struct ins_operands *ops, struct
.addr = map__objdump_2mem(map, ops->target.addr),
};
- if (maps__find_ams(ms->maps, &target) == 0 &&
+ if (maps__find_ams(thread__maps(ms->thread), &target) == 0 &&
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
ops->target.sym = target.ms.sym;
@@ -411,7 +412,7 @@ static int jump__parse(const struct arch *arch, struct ins_operands *ops, struct
* Actual navigation will come next, with further understanding of how
* the symbol searching and disassembly should be done.
*/
- if (maps__find_ams(ms->maps, &target) == 0 &&
+ if (maps__find_ams(thread__maps(ms->thread), &target) == 0 &&
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
ops->target.sym = target.ms.sym;
@@ -1074,7 +1075,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
.ms = { .map = map, },
};
- if (!maps__find_ams(args->ms->maps, &target) &&
+ if (!maps__find_ams(thread__maps(args->ms->thread), &target) &&
target.ms.sym->start == target.al_addr)
dl->ops.target.sym = target.ms.sym;
}
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 4c92cc1a952c..aa3f8a3a4438 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -646,7 +646,6 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
struct machine *machine = maps__machine(maps);
bool load_map = false;
- maps__zput(al->maps);
map__zput(al->map);
thread__zput(al->thread);
al->thread = thread__get(thread);
@@ -684,7 +683,6 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
return NULL;
}
- al->maps = maps__get(maps);
al->map = maps__find(maps, al->addr);
if (al->map != NULL) {
/*
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index ef4b569f7df4..7ffaa3d9851b 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -251,7 +251,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
if (h->cgroup) {
const char *cgrp_name = "unknown";
- struct cgroup *cgrp = cgroup__find(maps__machine(h->ms.maps)->env,
+ struct cgroup *cgrp = cgroup__find(maps__machine(thread__maps(h->ms.thread))->env,
h->cgroup);
if (cgrp != NULL)
cgrp_name = cgrp->name;
@@ -536,7 +536,7 @@ static int hist_entry__init(struct hist_entry *he,
memset(&he->stat, 0, sizeof(he->stat));
}
- he->ms.maps = maps__get(he->ms.maps);
+ he->ms.thread = thread__get(he->ms.thread);
he->ms.map = map__get(he->ms.map);
if (he->branch_info) {
@@ -552,9 +552,9 @@ static int hist_entry__init(struct hist_entry *he,
memcpy(he->branch_info, template->branch_info,
sizeof(*he->branch_info));
- he->branch_info->from.ms.maps = maps__get(he->branch_info->from.ms.maps);
+ he->branch_info->from.ms.thread = thread__get(he->branch_info->from.ms.thread);
he->branch_info->from.ms.map = map__get(he->branch_info->from.ms.map);
- he->branch_info->to.ms.maps = maps__get(he->branch_info->to.ms.maps);
+ he->branch_info->to.ms.thread = thread__get(he->branch_info->to.ms.thread);
he->branch_info->to.ms.map = map__get(he->branch_info->to.ms.map);
}
@@ -810,7 +810,7 @@ __hists__add_entry(struct hists *hists,
},
.cgroup = sample->cgroup,
.ms = {
- .maps = al->maps,
+ .thread = al->thread,
.map = al->map,
.sym = al->sym,
},
@@ -890,7 +890,7 @@ struct hist_entry *hists__add_entry_block(struct hists *hists,
.block_info = block_info,
.hists = hists,
.ms = {
- .maps = al->maps,
+ .thread = al->thread,
.map = al->map,
.sym = al->sym,
},
@@ -1020,8 +1020,8 @@ iter_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al)
if (iter->curr >= iter->total)
return 0;
- maps__put(al->maps);
- al->maps = maps__get(bi[i].to.ms.maps);
+ thread__put(al->thread);
+ al->thread = thread__get(bi[i].to.ms.thread);
map__put(al->map);
al->map = map__get(bi[i].to.ms.map);
al->sym = bi[i].to.ms.sym;
@@ -1232,7 +1232,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
.comm = thread__comm(al->thread),
.ip = al->addr,
.ms = {
- .maps = al->maps,
+ .thread = al->thread,
.map = al->map,
.sym = al->sym,
},
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 30d606fbf040..5b0f5a48ffd4 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -2016,7 +2016,7 @@ static void ip__resolve_ams(struct thread *thread,
ams->addr = ip;
ams->al_addr = al.addr;
ams->al_level = al.level;
- ams->ms.maps = maps__get(al.maps);
+ ams->ms.thread = thread__get(al.thread);
ams->ms.sym = al.sym;
ams->ms.map = map__get(al.map);
ams->phys_addr = 0;
@@ -2037,7 +2037,7 @@ static void ip__resolve_data(struct thread *thread,
ams->addr = addr;
ams->al_addr = al.addr;
ams->al_level = al.level;
- ams->ms.maps = maps__get(al.maps);
+ ams->ms.thread = thread__get(al.thread);
ams->ms.sym = al.sym;
ams->ms.map = map__get(al.map);
ams->phys_addr = phys_addr;
@@ -2120,7 +2120,7 @@ static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms
}
ilist_ms = (struct map_symbol) {
- .maps = maps__get(ms->maps),
+ .thread = thread__get(ms->thread),
.map = map__get(map),
};
list_for_each_entry(ilist, &inline_node->val, list) {
@@ -2220,7 +2220,7 @@ static int add_callchain_ip(struct thread *thread,
iter_cycles = iter->cycles;
}
- ms.maps = maps__get(al.maps);
+ ms.thread = thread__get(al.thread);
ms.map = map__get(al.map);
ms.sym = al.sym;
@@ -2383,7 +2383,7 @@ static void save_lbr_cursor_node(struct thread *thread,
map_symbol__exit(&lbr_stitch->prev_lbr_cursor[idx].ms);
memcpy(&lbr_stitch->prev_lbr_cursor[idx], cursor->curr,
sizeof(struct callchain_cursor_node));
- lbr_stitch->prev_lbr_cursor[idx].ms.maps = maps__get(cursor->curr->ms.maps);
+ lbr_stitch->prev_lbr_cursor[idx].ms.thread = thread__get(cursor->curr->ms.thread);
lbr_stitch->prev_lbr_cursor[idx].ms.map = map__get(cursor->curr->ms.map);
lbr_stitch->prev_lbr_cursor[idx].valid = true;
@@ -2596,7 +2596,8 @@ static bool has_stitched_lbr(struct thread *thread,
memcpy(&stitch_node->cursor, &lbr_stitch->prev_lbr_cursor[i],
sizeof(struct callchain_cursor_node));
- stitch_node->cursor.ms.maps = maps__get(lbr_stitch->prev_lbr_cursor[i].ms.maps);
+ stitch_node->cursor.ms.thread =
+ thread__get(lbr_stitch->prev_lbr_cursor[i].ms.thread);
stitch_node->cursor.ms.map = map__get(lbr_stitch->prev_lbr_cursor[i].ms.map);
if (callee)
diff --git a/tools/perf/util/map_symbol.c b/tools/perf/util/map_symbol.c
index 6ad2960bc289..11bc0a7f704c 100644
--- a/tools/perf/util/map_symbol.c
+++ b/tools/perf/util/map_symbol.c
@@ -2,10 +2,11 @@
#include "map_symbol.h"
#include "maps.h"
#include "map.h"
+#include "thread.h"
void map_symbol__exit(struct map_symbol *ms)
{
- maps__zput(ms->maps);
+ thread__zput(ms->thread);
map__zput(ms->map);
}
@@ -16,7 +17,7 @@ void addr_map_symbol__exit(struct addr_map_symbol *ams)
void map_symbol__copy(struct map_symbol *dst, struct map_symbol *src)
{
- dst->maps = maps__get(src->maps);
+ dst->thread = thread__get(src->thread);
dst->map = map__get(src->map);
dst->sym = src->sym;
}
diff --git a/tools/perf/util/map_symbol.h b/tools/perf/util/map_symbol.h
index e370bb32ed47..7437e319f4a3 100644
--- a/tools/perf/util/map_symbol.h
+++ b/tools/perf/util/map_symbol.h
@@ -4,12 +4,13 @@
#include <linux/types.h>
+struct thread;
struct maps;
struct map;
struct symbol;
struct map_symbol {
- struct maps *maps;
+ struct thread *thread;
struct map *map;
struct symbol *sym;
};
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index f963d61ac166..01a9d73ae348 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1016,7 +1016,7 @@ static int hist_entry__cgroup_snprintf(struct hist_entry *he,
const char *cgrp_name = "N/A";
if (he->cgroup) {
- struct cgroup *cgrp = cgroup__find(maps__machine(he->ms.maps)->env,
+ struct cgroup *cgrp = cgroup__find(maps__machine(thread__maps(he->ms.thread))->env,
he->cgroup);
if (cgrp != NULL)
cgrp_name = cgrp->name;
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index c1646ef5f971..9cb0960ef905 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -161,7 +161,7 @@ static int entry(u64 ip, struct unwind_info *ui)
}
e->ip = ip;
- e->ms.maps = maps__get(al.maps);
+ e->ms.thread = thread__get(al.thread);
e->ms.map = map__get(al.map);
e->ms.sym = al.sym;
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index a24b45106acd..ecf0c01fe51f 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -666,7 +666,7 @@ static int entry(u64 ip, struct thread *thread,
e.ms.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);
e.ip = ip;
e.ms.map = al.map;
- e.ms.maps = al.maps;
+ e.ms.thread = thread__get(al.thread);
pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
al.sym ? al.sym->name : "''",
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 10/11] perf disasm: Refactor arch__find and initialization of arch structs
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
` (8 preceding siblings ...)
2026-01-22 7:31 ` [PATCH v1 09/11] perf map_symbol: Switch from holding maps to holding thread Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 7:31 ` [PATCH v1 11/11] perf disasm: Minor layout tweaks for struct arch Ian Rogers
2026-01-22 10:43 ` [PATCH v1 00/11] perf annotate arch clean up James Clark
11 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
Switch arch__find to using an ELF machine number rather than a
string. Rather than an array of fixed size arch structs turn the init
functions into new functions indexed by the ELF machine they
correspond to. This allows data to be stored with a struct arch with
the container_of trick, so the priv variable can be removed. Switch to
using the thread to find the arch rather than the evsel as the evsel
only has limited notions of the running thread upon which disassembly
is performed. Factor out the e_machine and e_flags into their own
struct to make them easier to pass around.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/ui/browsers/annotate.c | 2 +-
tools/perf/util/annotate-arch/annotate-arc.c | 14 +-
tools/perf/util/annotate-arch/annotate-arm.c | 37 +++--
.../perf/util/annotate-arch/annotate-arm64.c | 39 +++--
tools/perf/util/annotate-arch/annotate-csky.c | 14 +-
.../util/annotate-arch/annotate-loongarch.c | 19 ++-
tools/perf/util/annotate-arch/annotate-mips.c | 19 ++-
.../util/annotate-arch/annotate-powerpc.c | 22 +--
.../util/annotate-arch/annotate-riscv64.c | 19 ++-
tools/perf/util/annotate-arch/annotate-s390.c | 29 ++--
.../perf/util/annotate-arch/annotate-sparc.c | 17 +-
tools/perf/util/annotate-arch/annotate-x86.c | 24 +--
tools/perf/util/annotate.c | 46 +++---
tools/perf/util/annotate.h | 2 +-
tools/perf/util/disasm.c | 153 ++++++++----------
tools/perf/util/disasm.h | 59 +++----
16 files changed, 278 insertions(+), 237 deletions(-)
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 91ded9c271ee..ea17e6d29a7e 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -1198,7 +1198,7 @@ int __hist_entry__tui_annotate(struct hist_entry *he, struct map_symbol *ms,
ui__warning("Annotation has no source code.");
}
} else {
- err = evsel__get_arch(evsel, &browser.arch);
+ err = thread__get_arch(ms->thread, &browser.arch);
if (err) {
annotate_browser__symbol_annotate_error(&browser, err);
return -1;
diff --git a/tools/perf/util/annotate-arch/annotate-arc.c b/tools/perf/util/annotate-arch/annotate-arc.c
index d7ca08ca5600..170103e383a4 100644
--- a/tools/perf/util/annotate-arch/annotate-arc.c
+++ b/tools/perf/util/annotate-arch/annotate-arc.c
@@ -1,10 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h>
+#include <linux/zalloc.h>
#include "../disasm.h"
-int arc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+const struct arch *arch__new_arc(const struct e_machine_and_e_flags *id,
+ const char *cpuid __maybe_unused)
{
- arch->initialized = true;
+ struct arch *arch = zalloc(sizeof(*arch));
+
+ if (!arch)
+ return NULL;
+
+ arch->name = "arc";
+ arch->id = *id;
arch->objdump.comment_char = ';';
- return 0;
+ return arch;
}
diff --git a/tools/perf/util/annotate-arch/annotate-arm.c b/tools/perf/util/annotate-arch/annotate-arm.c
index 08c49067c3c9..25086f5fce23 100644
--- a/tools/perf/util/annotate-arch/annotate-arm.c
+++ b/tools/perf/util/annotate-arch/annotate-arm.c
@@ -7,14 +7,15 @@
#include "../annotate.h"
#include "../disasm.h"
-struct arm_annotate {
- regex_t call_insn,
- jump_insn;
+struct arch_arm {
+ struct arch arch;
+ regex_t call_insn;
+ regex_t jump_insn;
};
static const struct ins_ops *arm__associate_instruction_ops(struct arch *arch, const char *name)
{
- struct arm_annotate *arm = arch->priv;
+ struct arch_arm *arm = container_of(arch, struct arch_arm, arch);
const struct ins_ops *ops;
regmatch_t match[2];
@@ -29,37 +30,39 @@ static const struct ins_ops *arm__associate_instruction_ops(struct arch *arch, c
return ops;
}
-int arm__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+const struct arch *arch__new_arm(const struct e_machine_and_e_flags *id,
+ const char *cpuid __maybe_unused)
{
- struct arm_annotate *arm;
int err;
+ struct arch_arm *arm = zalloc(sizeof(*arm));
+ struct arch *arch;
- if (arch->initialized)
- return 0;
-
- arm = zalloc(sizeof(*arm));
if (!arm)
- return ENOMEM;
+ return NULL;
+
+ arch = &arm->arch;
+ arch->name = "arm";
+ arch->id = *id;
+ arch->objdump.comment_char = ';';
+ arch->objdump.skip_functions_char = '+';
+ arch->associate_instruction_ops = arm__associate_instruction_ops;
#define ARM_CONDS "(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl|vc|vs)"
err = regcomp(&arm->call_insn, "^blx?" ARM_CONDS "?$", REG_EXTENDED);
if (err)
goto out_free_arm;
+
err = regcomp(&arm->jump_insn, "^bx?" ARM_CONDS "?$", REG_EXTENDED);
if (err)
goto out_free_call;
#undef ARM_CONDS
- arch->initialized = true;
- arch->priv = arm;
- arch->associate_instruction_ops = arm__associate_instruction_ops;
- arch->objdump.comment_char = ';';
- arch->objdump.skip_functions_char = '+';
return 0;
out_free_call:
regfree(&arm->call_insn);
out_free_arm:
free(arm);
- return SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
+ errno = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
+ return NULL;
}
diff --git a/tools/perf/util/annotate-arch/annotate-arm64.c b/tools/perf/util/annotate-arch/annotate-arm64.c
index d2ea32984b0d..da45c7d05757 100644
--- a/tools/perf/util/annotate-arch/annotate-arm64.c
+++ b/tools/perf/util/annotate-arch/annotate-arm64.c
@@ -8,9 +8,10 @@
#include "../annotate.h"
#include "../disasm.h"
-struct arm64_annotate {
- regex_t call_insn,
- jump_insn;
+struct arch_arm64 {
+ struct arch arch;
+ regex_t call_insn;
+ regex_t jump_insn;
};
static int arm64_mov__parse(const struct arch *arch __maybe_unused,
@@ -70,7 +71,7 @@ static const struct ins_ops arm64_mov_ops = {
static const struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
{
- struct arm64_annotate *arm = arch->priv;
+ struct arch_arm64 *arm = container_of(arch, struct arch_arm64, arch);
const struct ins_ops *ops;
regmatch_t match[2];
@@ -87,38 +88,44 @@ static const struct ins_ops *arm64__associate_instruction_ops(struct arch *arch,
return ops;
}
-int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+const struct arch *arch__new_arm64(const struct e_machine_and_e_flags *id,
+ const char *cpuid __maybe_unused)
{
- struct arm64_annotate *arm;
int err;
+ struct arch_arm64 *arm = zalloc(sizeof(*arm));
+ struct arch *arch;
- if (arch->initialized)
- return 0;
+ if (!arm)
+ return NULL;
+
+ arch = &arm->arch;
+ arch->name = "arm64";
+ arch->id = *id;
+ arch->objdump.comment_char = '/';
+ arch->objdump.skip_functions_char = '+';
+ arch->associate_instruction_ops = arm64__associate_instruction_ops;
arm = zalloc(sizeof(*arm));
if (!arm)
- return ENOMEM;
+ return NULL;
/* bl, blr */
err = regcomp(&arm->call_insn, "^blr?$", REG_EXTENDED);
if (err)
goto out_free_arm;
+
/* b, b.cond, br, cbz/cbnz, tbz/tbnz */
err = regcomp(&arm->jump_insn, "^[ct]?br?\\.?(cc|cs|eq|ge|gt|hi|hs|le|lo|ls|lt|mi|ne|pl|vc|vs)?n?z?$",
REG_EXTENDED);
if (err)
goto out_free_call;
- arch->initialized = true;
- arch->priv = arm;
- arch->associate_instruction_ops = arm64__associate_instruction_ops;
- arch->objdump.comment_char = '/';
- arch->objdump.skip_functions_char = '+';
- return 0;
+ return arch;
out_free_call:
regfree(&arm->call_insn);
out_free_arm:
free(arm);
- return SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
+ errno = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
+ return NULL;
}
diff --git a/tools/perf/util/annotate-arch/annotate-csky.c b/tools/perf/util/annotate-arch/annotate-csky.c
index 0b0b09b068ec..d2b18e4ea2c9 100644
--- a/tools/perf/util/annotate-arch/annotate-csky.c
+++ b/tools/perf/util/annotate-arch/annotate-csky.c
@@ -2,6 +2,7 @@
// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
#include <string.h>
#include <linux/compiler.h>
+#include <linux/zalloc.h>
#include "../disasm.h"
static const struct ins_ops *csky__associate_ins_ops(struct arch *arch,
@@ -39,10 +40,17 @@ static const struct ins_ops *csky__associate_ins_ops(struct arch *arch,
return ops;
}
-int csky__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+const struct arch *arch__new_csky(const struct e_machine_and_e_flags *id,
+ const char *cpuid __maybe_unused)
{
- arch->initialized = true;
+ struct arch *arch = zalloc(sizeof(*arch));
+
+ if (!arch)
+ return NULL;
+
+ arch->name = "csky";
+ arch->id = *id;
arch->objdump.comment_char = '/';
arch->associate_instruction_ops = csky__associate_ins_ops;
- return 0;
+ return arch;
}
diff --git a/tools/perf/util/annotate-arch/annotate-loongarch.c b/tools/perf/util/annotate-arch/annotate-loongarch.c
index a23744eafd6a..2027e3b816f4 100644
--- a/tools/perf/util/annotate-arch/annotate-loongarch.c
+++ b/tools/perf/util/annotate-arch/annotate-loongarch.c
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <string.h>
#include <linux/compiler.h>
+#include <linux/zalloc.h>
#include "../disasm.h"
#include "../map.h"
#include "../maps.h"
@@ -137,13 +138,17 @@ const struct ins_ops *loongarch__associate_ins_ops(struct arch *arch, const char
return ops;
}
-int loongarch__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+const struct arch *arch__new_loongarch(const struct e_machine_and_e_flags *id,
+ const char *cpuid __maybe_unused)
{
- if (!arch->initialized) {
- arch->associate_instruction_ops = loongarch__associate_ins_ops;
- arch->initialized = true;
- arch->objdump.comment_char = '#';
- }
+ struct arch *arch = zalloc(sizeof(*arch));
- return 0;
+ if (!arch)
+ return NULL;
+
+ arch->name = "loongarch";
+ arch->id = *id;
+ arch->associate_instruction_ops = loongarch__associate_ins_ops;
+ arch->objdump.comment_char = '#';
+ return arch;
}
diff --git a/tools/perf/util/annotate-arch/annotate-mips.c b/tools/perf/util/annotate-arch/annotate-mips.c
index f14b34ed77d3..e8d1c6c7e9f3 100644
--- a/tools/perf/util/annotate-arch/annotate-mips.c
+++ b/tools/perf/util/annotate-arch/annotate-mips.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <string.h>
#include <linux/compiler.h>
+#include <linux/zalloc.h>
#include "../disasm.h"
static
@@ -36,13 +37,17 @@ const struct ins_ops *mips__associate_ins_ops(struct arch *arch, const char *nam
return ops;
}
-int mips__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+const struct arch *arch__new_mips(const struct e_machine_and_e_flags *id,
+ const char *cpuid __maybe_unused)
{
- if (!arch->initialized) {
- arch->associate_instruction_ops = mips__associate_ins_ops;
- arch->initialized = true;
- arch->objdump.comment_char = '#';
- }
+ struct arch *arch = zalloc(sizeof(*arch));
- return 0;
+ if (!arch)
+ return NULL;
+
+ arch->name = "mips";
+ arch->id = *id;
+ arch->objdump.comment_char = '#';
+ arch->associate_instruction_ops = mips__associate_ins_ops;
+ return arch;
}
diff --git a/tools/perf/util/annotate-arch/annotate-powerpc.c b/tools/perf/util/annotate-arch/annotate-powerpc.c
index 593c138c8104..004e6137aa03 100644
--- a/tools/perf/util/annotate-arch/annotate-powerpc.c
+++ b/tools/perf/util/annotate-arch/annotate-powerpc.c
@@ -390,17 +390,21 @@ static void update_insn_state_powerpc(struct type_state *state,
}
#endif /* HAVE_LIBDW_SUPPORT */
-int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+const struct arch *arch__new_powerpc(const struct e_machine_and_e_flags *id,
+ const char *cpuid __maybe_unused)
{
- if (!arch->initialized) {
- arch->initialized = true;
- arch->associate_instruction_ops = powerpc__associate_instruction_ops;
- arch->objdump.comment_char = '#';
- annotate_opts.show_asm_raw = true;
+ struct arch *arch = zalloc(sizeof(*arch));
+
+ if (!arch)
+ return NULL;
+
+ arch->name = "powerpc";
+ arch->id = *id;
+ arch->objdump.comment_char = '#';
+ annotate_opts.show_asm_raw = true;
+ arch->associate_instruction_ops = powerpc__associate_instruction_ops;
#ifdef HAVE_LIBDW_SUPPORT
- arch->update_insn_state = update_insn_state_powerpc;
+ arch->update_insn_state = update_insn_state_powerpc;
#endif
- }
-
return 0;
}
diff --git a/tools/perf/util/annotate-arch/annotate-riscv64.c b/tools/perf/util/annotate-arch/annotate-riscv64.c
index 15526824037a..29a988fca8c9 100644
--- a/tools/perf/util/annotate-arch/annotate-riscv64.c
+++ b/tools/perf/util/annotate-arch/annotate-riscv64.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <string.h>
#include <linux/compiler.h>
+#include <linux/zalloc.h>
#include "../disasm.h"
static
@@ -24,13 +25,17 @@ const struct ins_ops *riscv64__associate_ins_ops(struct arch *arch, const char *
return ops;
}
-int riscv64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+const struct arch *arch__new_riscv64(const struct e_machine_and_e_flags *id,
+ const char *cpuid __maybe_unused)
{
- if (!arch->initialized) {
- arch->associate_instruction_ops = riscv64__associate_ins_ops;
- arch->initialized = true;
- arch->objdump.comment_char = '#';
- }
+ struct arch *arch = zalloc(sizeof(*arch));
- return 0;
+ if (!arch)
+ return NULL;
+
+ arch->name = "riscv";
+ arch->id = *id;
+ arch->objdump.comment_char = '#';
+ arch->associate_instruction_ops = riscv64__associate_ins_ops;
+ return arch;
}
diff --git a/tools/perf/util/annotate-arch/annotate-s390.c b/tools/perf/util/annotate-arch/annotate-s390.c
index cb112c1ba090..094b2e125363 100644
--- a/tools/perf/util/annotate-arch/annotate-s390.c
+++ b/tools/perf/util/annotate-arch/annotate-s390.c
@@ -145,7 +145,7 @@ static const struct ins_ops *s390__associate_ins_ops(struct arch *arch, const ch
return ops;
}
-static int s390__cpuid_parse(struct arch *arch, char *cpuid)
+static int s390__cpuid_parse(struct arch *arch, const char *cpuid)
{
unsigned int family;
char model[16], model_c[16], cpumf_v[16], cpumf_a[16];
@@ -166,19 +166,22 @@ static int s390__cpuid_parse(struct arch *arch, char *cpuid)
return -1;
}
-int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+const struct arch *arch__new_s390(const struct e_machine_and_e_flags *id, const char *cpuid)
{
- int err = 0;
-
- if (!arch->initialized) {
- arch->initialized = true;
- arch->associate_instruction_ops = s390__associate_ins_ops;
- if (cpuid) {
- if (s390__cpuid_parse(arch, cpuid))
- err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
+ struct arch *arch = zalloc(sizeof(*arch));
+
+ if (!arch)
+ return NULL;
+
+ arch->name = "s390";
+ arch->id = *id;
+ arch->associate_instruction_ops = s390__associate_ins_ops;
+ if (cpuid) {
+ if (s390__cpuid_parse(arch, cpuid)) {
+ errno = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
+ return NULL;
}
- arch->objdump.comment_char = '#';
}
-
- return err;
+ arch->objdump.comment_char = '#';
+ return arch;
}
diff --git a/tools/perf/util/annotate-arch/annotate-sparc.c b/tools/perf/util/annotate-arch/annotate-sparc.c
index 66a0174376dd..fe7a37966261 100644
--- a/tools/perf/util/annotate-arch/annotate-sparc.c
+++ b/tools/perf/util/annotate-arch/annotate-sparc.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <string.h>
#include <linux/compiler.h>
+#include <linux/zalloc.h>
#include "../../util/disasm.h"
static int is_branch_cond(const char *cond)
@@ -160,13 +161,17 @@ static const struct ins_ops *sparc__associate_instruction_ops(struct arch *arch,
return ops;
}
-int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
+const struct arch *arch__new_sparc(const struct e_machine_and_e_flags *id,
+ const char *cpuid __maybe_unused)
{
- if (!arch->initialized) {
- arch->initialized = true;
- arch->associate_instruction_ops = sparc__associate_instruction_ops;
- arch->objdump.comment_char = '#';
- }
+ struct arch *arch = zalloc(sizeof(*arch));
+
+ if (!arch)
+ return NULL;
+ arch->name = "sparc";
+ arch->id = *id;
+ arch->associate_instruction_ops = sparc__associate_instruction_ops;
+ arch->objdump.comment_char = '#';
return 0;
}
diff --git a/tools/perf/util/annotate-arch/annotate-x86.c b/tools/perf/util/annotate-arch/annotate-x86.c
index 0c7957fe60da..eb9a649ca656 100644
--- a/tools/perf/util/annotate-arch/annotate-x86.c
+++ b/tools/perf/util/annotate-arch/annotate-x86.c
@@ -182,7 +182,7 @@ static bool intel__ins_is_fused(const struct arch *arch, const char *ins1,
return false;
}
-static int x86__cpuid_parse(struct arch *arch, char *cpuid)
+static int x86__cpuid_parse(struct arch *arch, const char *cpuid)
{
unsigned int family, model, stepping;
int ret;
@@ -777,18 +777,21 @@ static void update_insn_state_x86(struct type_state *state,
}
#endif
-int x86__annotate_init(struct arch *arch, char *cpuid)
+const struct arch *arch__new_x86(const struct e_machine_and_e_flags *id, const char *cpuid)
{
- int err = 0;
+ struct arch *arch = zalloc(sizeof(*arch));
- if (arch->initialized)
- return 0;
+ if (!arch)
+ return NULL;
+ arch->name = "x86";
+ arch->id = *id;
if (cpuid) {
- if (x86__cpuid_parse(arch, cpuid))
- err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
+ if (x86__cpuid_parse(arch, cpuid)) {
+ errno = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING;
+ return NULL;
+ }
}
-
arch->instructions = x86__instructions;
arch->nr_instructions = ARRAY_SIZE(x86__instructions);
#ifndef NDEBUG
@@ -810,11 +813,8 @@ int x86__annotate_init(struct arch *arch, char *cpuid)
arch->objdump.memory_ref_char = '(';
arch->objdump.imm_char = '$';
arch->insn_suffix = "bwlq";
- arch->e_machine = EM_X86_64;
- arch->e_flags = 0;
- arch->initialized = true;
#ifdef HAVE_LIBDW_SUPPORT
arch->update_insn_state = update_insn_state_x86;
#endif
- return err;
+ return arch;
}
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 79702072568b..c16c6dfaa959 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -980,32 +980,27 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)
annotation__calc_percent(notes, evsel, symbol__size(sym));
}
-int evsel__get_arch(struct evsel *evsel, const struct arch **parch)
+int thread__get_arch(struct thread *thread, const struct arch **parch)
{
- struct perf_env *env = evsel__env(evsel);
- const char *arch_name = perf_env__arch(env);
const struct arch *arch;
- int err;
+ struct machine *machine;
+ uint16_t e_machine;
- if (!arch_name) {
+ if (!thread) {
*parch = NULL;
- return errno;
+ return -1;
}
- *parch = arch = arch__find(arch_name);
+ machine = maps__machine(thread__maps(thread));
+ e_machine = thread__e_machine(thread, machine);
+ arch = arch__find(e_machine, machine->env ? machine->env->cpuid : NULL);
if (arch == NULL) {
- pr_err("%s: unsupported arch %s\n", __func__, arch_name);
- return ENOTSUP;
+ pr_err("%s: unsupported arch %d\n", __func__, e_machine);
+ return errno;
}
+ if (parch)
+ *parch = arch;
- if (arch->init) {
- err = arch->init((struct arch *)arch, env ? env->cpuid : NULL);
- if (err) {
- pr_err("%s: failed to initialize %s arch priv area\n",
- __func__, arch->name);
- return err;
- }
- }
return 0;
}
@@ -1020,7 +1015,7 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
const struct arch *arch = NULL;
int err, nr;
- err = evsel__get_arch(evsel, &arch);
+ err = thread__get_arch(ms->thread, &arch);
if (err)
return err;
@@ -1268,7 +1263,7 @@ int hist_entry__annotate_printf(struct hist_entry *he, struct evsel *evsel)
apd.addr_fmt_width = annotated_source__addr_fmt_width(¬es->src->source,
notes->src->start);
- evsel__get_arch(evsel, &apd.arch);
+ thread__get_arch(ms->thread, &apd.arch);
apd.dbg = dso__debuginfo(dso);
list_for_each_entry(pos, ¬es->src->source, node) {
@@ -1373,7 +1368,7 @@ static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
struct annotation_line *al;
if (annotate_opts.code_with_type) {
- evsel__get_arch(apd->evsel, &apd->arch);
+ thread__get_arch(apd->he->ms.thread, &apd->arch);
apd->dbg = dso__debuginfo(map__dso(apd->he->ms.map));
}
@@ -2495,7 +2490,7 @@ static int extract_reg_offset(const struct arch *arch, const char *str,
if (regname == NULL)
return -1;
- op_loc->reg1 = get_dwarf_regnum(regname, arch->e_machine, arch->e_flags);
+ op_loc->reg1 = get_dwarf_regnum(regname, arch->id.e_machine, arch->id.e_flags);
free(regname);
/* Get the second register */
@@ -2508,7 +2503,7 @@ static int extract_reg_offset(const struct arch *arch, const char *str,
if (regname == NULL)
return -1;
- op_loc->reg2 = get_dwarf_regnum(regname, arch->e_machine, arch->e_flags);
+ op_loc->reg2 = get_dwarf_regnum(regname, arch->id.e_machine, arch->id.e_flags);
free(regname);
}
return 0;
@@ -2607,8 +2602,11 @@ int annotate_get_insn_location(const struct arch *arch, struct disasm_line *dl,
if (s == NULL)
return -1;
- if (*s == arch->objdump.register_char)
- op_loc->reg1 = get_dwarf_regnum(s, arch->e_machine, arch->e_flags);
+ if (*s == arch->objdump.register_char) {
+ op_loc->reg1 = get_dwarf_regnum(s,
+ arch->id.e_machine,
+ arch->id.e_flags);
+ }
else if (*s == arch->objdump.imm_char) {
op_loc->offset = strtol(s + 1, &p, 0);
if (p && p != s + 1)
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 58eaf4b2fa65..696e36dbf013 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -586,5 +586,5 @@ int annotation_br_cntr_entry(char **str, int br_cntr_nr, u64 *br_cntr,
int num_aggr, struct evsel *evsel);
int annotation_br_cntr_abbr_list(char **str, struct evsel *evsel, bool header);
-int evsel__get_arch(struct evsel *evsel, const struct arch **parch);
+int thread__get_arch(struct thread *thread, const struct arch **parch);
#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index c537c12ff7cd..e9f3155f3173 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -102,112 +102,101 @@ int arch__associate_ins_ops(struct arch *arch, const char *name, const struct in
return 0;
}
-static struct arch architectures[] = {
- {
- .name = "arc",
- .init = arc__annotate_init,
- .e_machine = EM_ARC,
- },
- {
- .name = "arm",
- .init = arm__annotate_init,
- .e_machine = EM_ARM,
- },
- {
- .name = "arm64",
- .init = arm64__annotate_init,
- .e_machine = EM_AARCH64,
- },
- {
- .name = "csky",
- .init = csky__annotate_init,
- .e_machine = EM_CSKY,
-#if defined(__CSKYABIV2__)
- .e_flags = EF_CSKY_ABIV2,
-#else
- .e_flags = EF_CSKY_ABIV1,
-#endif
- },
- {
- .name = "mips",
- .init = mips__annotate_init,
- .e_machine = EM_MIPS,
- },
- {
- .name = "x86",
- .init = x86__annotate_init,
- .e_machine = EM_X86_64, // TODO: EM_386 too.
- },
- {
- .name = "powerpc",
- .init = powerpc__annotate_init,
- .e_machine = EM_PPC, // TODO: EM_PPC64 too.
- },
- {
- .name = "riscv64",
- .init = riscv64__annotate_init,
- .e_machine = EM_RISCV,
- },
- {
- .name = "s390",
- .init = s390__annotate_init,
- .e_machine = EM_S390,
- },
- {
- .name = "sparc",
- .init = sparc__annotate_init,
- .e_machine = EM_SPARC,
- },
- {
- .name = "loongarch",
- .init = loongarch__annotate_init,
- .e_machine = EM_LOONGARCH,
- },
-};
+static int e_machine_and_eflags__cmp(const struct e_machine_and_e_flags *val1,
+ const struct e_machine_and_e_flags *val2)
+{
+ if (val1->e_machine == val2->e_machine) {
+ if (val1->e_machine != EM_CSKY)
+ return 0;
+ if ((val1->e_flags & EF_CSKY_ABIMASK) < (val2->e_flags & EF_CSKY_ABIMASK))
+ return -1;
+ return (val1->e_flags & EF_CSKY_ABIMASK) > (val2->e_flags & EF_CSKY_ABIMASK);
+ }
+ return val1->e_machine < val2->e_machine ? -1 : 1;
+}
-static int arch__key_cmp(const void *name, const void *archp)
+static int arch__key_cmp(const void *key, const void *archp)
{
- const struct arch *arch = archp;
+ const struct arch *const *arch = archp;
- return strcmp(name, arch->name);
+ return e_machine_and_eflags__cmp(key, &(*arch)->id);
}
static int arch__cmp(const void *a, const void *b)
{
- const struct arch *aa = a;
- const struct arch *ab = b;
+ const struct arch *const *aa = a;
+ const struct arch *const *ab = b;
- return strcmp(aa->name, ab->name);
+ return e_machine_and_eflags__cmp(&(*aa)->id, &(*ab)->id);
}
-static void arch__sort(void)
+const struct arch *arch__find(uint16_t e_machine, const char *cpuid)
{
- const int nmemb = ARRAY_SIZE(architectures);
+ static const struct arch *(*const arch_new_fn[])(const struct e_machine_and_e_flags *id,
+ const char *cpuid) = {
+ [EM_386] = arch__new_x86,
+ [EM_ARC] = arch__new_arc,
+ [EM_ARM] = arch__new_arm,
+ [EM_AARCH64] = arch__new_arm64,
+ [EM_CSKY] = arch__new_csky,
+ [EM_LOONGARCH] = arch__new_loongarch,
+ [EM_MIPS] = arch__new_mips,
+ [EM_PPC64] = arch__new_powerpc,
+ [EM_PPC] = arch__new_powerpc,
+ [EM_RISCV] = arch__new_riscv64,
+ [EM_S390] = arch__new_s390,
+ [EM_SPARC] = arch__new_sparc,
+ [EM_SPARCV9] = arch__new_sparc,
+ [EM_X86_64] = arch__new_x86,
+ };
+ static const struct arch **archs;
+ static size_t num_archs;
+ struct e_machine_and_e_flags key = {
+ .e_machine = e_machine,
+ // TODO: e_flags should really come from the same source as e_machine.
+ .e_flags = EF_HOST,
+ };
+ const struct arch *result = NULL, **tmp;
- qsort(architectures, nmemb, sizeof(struct arch), arch__cmp);
-}
+ if (num_archs > 0) {
+ tmp = bsearch(&key, archs, num_archs, sizeof(*archs), arch__key_cmp);
+ if (tmp)
+ result = *tmp;
+ }
-const struct arch *arch__find(const char *name)
-{
- const int nmemb = ARRAY_SIZE(architectures);
- static bool sorted;
+ if (result)
+ return result;
- if (!sorted) {
- arch__sort();
- sorted = true;
+ if (e_machine >= ARRAY_SIZE(arch_new_fn) || arch_new_fn[e_machine] == NULL) {
+ errno = ENOTSUP;
+ return NULL;
}
- return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp);
+ tmp = reallocarray(archs, num_archs + 1, sizeof(*archs));
+ if (!tmp)
+ return NULL;
+
+ result = arch_new_fn[e_machine](&key, cpuid);
+ if (!result) {
+ pr_err("%s: failed to initialize %s (%u) arch priv area\n",
+ __func__, result->name, e_machine);
+ free(tmp);
+ return NULL;
+ }
+ archs = tmp;
+ archs[num_archs++] = result;
+ qsort(archs, num_archs, sizeof(*archs), arch__cmp);
+ return result;
}
bool arch__is_x86(const struct arch *arch)
{
- return arch->e_machine == EM_386 || arch->e_machine == EM_X86_64;
+ return arch->id.e_machine == EM_386 || arch->id.e_machine == EM_X86_64;
}
bool arch__is_powerpc(const struct arch *arch)
{
- return arch->e_machine == EM_PPC || arch->e_machine == EM_PPC64;
+ return arch->id.e_machine == EM_PPC || arch->id.e_machine == EM_PPC64;
}
static void ins_ops__delete(struct ins_operands *ops)
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index b6a2a30fdf27..2793d48aa04e 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -17,21 +17,23 @@ struct data_loc_info;
struct type_state;
struct disasm_line;
+struct e_machine_and_e_flags {
+ uint16_t e_machine;
+ uint32_t e_flags;
+};
+
struct arch {
- const char *name;
+ /** @id: ELF machine and flags associated with arch. */
+ struct e_machine_and_e_flags id;
+ /** @name: name such as "x86" or "powerpc". */
+ const char *name;
const struct ins *instructions;
- size_t nr_instructions;
- size_t nr_instructions_allocated;
- const struct ins_ops *(*associate_instruction_ops)(struct arch *arch, const char *name);
- bool sorted_instructions;
- bool initialized;
- const char *insn_suffix;
- void *priv;
- unsigned int model;
- unsigned int family;
- int (*init)(struct arch *arch, char *cpuid);
- bool (*ins_is_fused)(const struct arch *arch, const char *ins1,
- const char *ins2);
+ size_t nr_instructions;
+ size_t nr_instructions_allocated;
+ bool sorted_instructions;
+ const char *insn_suffix;
+ unsigned int model;
+ unsigned int family;
struct {
char comment_char;
char skip_functions_char;
@@ -39,15 +41,14 @@ struct arch {
char memory_ref_char;
char imm_char;
} objdump;
+ bool (*ins_is_fused)(const struct arch *arch, const char *ins1,
+ const char *ins2);
+ const struct ins_ops *(*associate_instruction_ops)(struct arch *arch, const char *name);
#ifdef HAVE_LIBDW_SUPPORT
void (*update_insn_state)(struct type_state *state,
struct data_loc_info *dloc, Dwarf_Die *cu_die,
struct disasm_line *dl);
#endif
- /** @e_machine: ELF machine associated with arch. */
- unsigned int e_machine;
- /** @e_flags: Optional ELF flags associated with arch. */
- unsigned int e_flags;
};
struct ins {
@@ -107,7 +108,7 @@ struct annotate_args {
char *fileloc;
};
-const struct arch *arch__find(const char *name);
+const struct arch *arch__find(uint16_t e_machine, const char *cpuid);
bool arch__is_x86(const struct arch *arch);
bool arch__is_powerpc(const struct arch *arch);
@@ -121,17 +122,17 @@ extern const struct ins_ops ret_ops;
int arch__associate_ins_ops(struct arch *arch, const char *name, const struct ins_ops *ops);
-int arc__annotate_init(struct arch *arch, char *cpuid);
-int arm__annotate_init(struct arch *arch, char *cpuid);
-int arm64__annotate_init(struct arch *arch, char *cpuid);
-int csky__annotate_init(struct arch *arch, char *cpuid);
-int loongarch__annotate_init(struct arch *arch, char *cpuid);
-int mips__annotate_init(struct arch *arch, char *cpuid);
-int powerpc__annotate_init(struct arch *arch, char *cpuid);
-int riscv64__annotate_init(struct arch *arch, char *cpuid);
-int s390__annotate_init(struct arch *arch, char *cpuid);
-int sparc__annotate_init(struct arch *arch, char *cpuid);
-int x86__annotate_init(struct arch *arch, char *cpuid);
+const struct arch *arch__new_arc(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_arm(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_arm64(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_csky(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_loongarch(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_mips(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_powerpc(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_riscv64(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_s390(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_sparc(const struct e_machine_and_e_flags *id, const char *cpuid);
+const struct arch *arch__new_x86(const struct e_machine_and_e_flags *id, const char *cpuid);
const struct ins_ops *ins__find(const struct arch *arch, const char *name, struct disasm_line *dl);
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 11/11] perf disasm: Minor layout tweaks for struct arch
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
` (9 preceding siblings ...)
2026-01-22 7:31 ` [PATCH v1 10/11] perf disasm: Refactor arch__find and initialization of arch structs Ian Rogers
@ 2026-01-22 7:31 ` Ian Rogers
2026-01-22 10:43 ` [PATCH v1 00/11] perf annotate arch clean up James Clark
11 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 7:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, John Garry, Will Deacon, Leo Yan,
Guo Ren, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Zecheng Li, Tianyou Li,
Thomas Falcon, Julia Lawall, Suchit Karunakaran, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
Pack some holes to bring down the overall struct size from 96 to 88
bytes.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/disasm.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/perf/util/disasm.h b/tools/perf/util/disasm.h
index 2793d48aa04e..6a1905f9d4fc 100644
--- a/tools/perf/util/disasm.h
+++ b/tools/perf/util/disasm.h
@@ -18,22 +18,22 @@ struct type_state;
struct disasm_line;
struct e_machine_and_e_flags {
- uint16_t e_machine;
uint32_t e_flags;
+ uint16_t e_machine;
};
struct arch {
- /** @id: ELF machine and flags associated with arch. */
- struct e_machine_and_e_flags id;
/** @name: name such as "x86" or "powerpc". */
const char *name;
const struct ins *instructions;
size_t nr_instructions;
size_t nr_instructions_allocated;
- bool sorted_instructions;
const char *insn_suffix;
unsigned int model;
unsigned int family;
+ /** @id: ELF machine and flags associated with arch. */
+ struct e_machine_and_e_flags id;
+ bool sorted_instructions;
struct {
char comment_char;
char skip_functions_char;
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v1 00/11] perf annotate arch clean up
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
` (10 preceding siblings ...)
2026-01-22 7:31 ` [PATCH v1 11/11] perf disasm: Minor layout tweaks for struct arch Ian Rogers
@ 2026-01-22 10:43 ` James Clark
2026-01-22 10:47 ` James Clark
11 siblings, 1 reply; 17+ messages in thread
From: James Clark @ 2026-01-22 10:43 UTC (permalink / raw)
To: Ian Rogers
Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
John Garry, Will Deacon, Leo Yan, Guo Ren, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Nathan Chancellor,
Nick Desaulniers, Bill Wendling, Justin Stitt, Zecheng Li,
Tianyou Li, Thomas Falcon, Julia Lawall, Suchit Karunakaran,
Athira Rajeev, Aditya Bodkhe, Howard Chu,
Krzysztof Łopatowski, Dr. David Alan Gilbert, Shimin Guo,
Sergei Trofimovich, linux-kernel, linux-perf-users,
linux-arm-kernel, linux-csky, linux-riscv
On 22/01/2026 7:31 am, Ian Rogers wrote:
> 2 initial memory leak fix patches for perf annotate.
>
> Move the disasm.c #included arch files into a new util/annotate-arch
> directory. Make the code compile standalone. Try to better encapsulate
> architecture specific code within the files and with a
> arch__new_<arch> function that allows additional data to be associated
> with the struct arch using the standard container_of trick.
>
> Make the lookup of struct arch use the ELF machine gather from a
> thread rather than an evsel. For example, the evsel can't determine
> the difference between EM_386 and EM_X86_64 so generally the latter
> has currently been used. This means the dwarf registers are off as
> register 1 is CX with EM_386 and DX with EM_X86_64. To facilitate this
> change map_symbol is refactored to use a struct thread rather than a
> struct maps, the maps being obtainable from the thread.
>
> To make in and out arguments clearer, for safety, etc. try to constify
> struct arch and its related structs.
>
Hi Ian,
I get this crash, not sure which commit causes it exactly but it
happened 2/2 times on both x86 and arm:
$ perf record -- true
$ perf report
< Select first sample >
< Select annotate >
perf: Segmentation fault
-------- backtrace --------
#0 0x5df8f58ba973 in ui__signal_backtrace setup.c:110
#1 0x74373a642520 in __restore_rt libc_sigaction.c:0
#2 0x5df8f5963f0d in dso__kernel dso.h:532
#3 0x5df8f5965d0a in __map__const_kmap map.c:627
#4 0x5df8f5965a36 in map__rip_2objdump map.c:531
#5 0x5df8f58e5bef in symbol__parse_objdump_line disasm.c:1032
#6 0x5df8f58e498b in symbol__disassemble_objdump disasm.c:1503
#7 0x5df8f58e3852 in symbol__disassemble disasm.c:1621
#8 0x5df8f58c638d in symbol__annotate annotate.c:1055
#9 0x5df8f58c8628 in symbol__annotate2 annotate.c:2209
#10 0x5df8f58a36b7 in __hist_entry__tui_annotate annotate.c:1189
#11 0x5df8f58adf86 in do_annotate hists.c:2488
#12 0x5df8f58ad762 in evsel__hists_browse hists.c:3441
#13 0x5df8f58b78f2 in perf_evsel_menu__run hists.c:3556
#14 0x5df8f58adabc in __evlist__tui_browse_hists hists.c:3643
#15 0x5df8f58abf3b in evlist__tui_browse_hists hists.c:3691
#16 0x5df8f571ac3a in report__browse_hists builtin-report.c:688
#17 0x5df8f5719943 in __cmd_report builtin-report.c:1177
#18 0x5df8f57181bc in cmd_report builtin-report.c:1890
#19 0x5df8f57b5c3a in run_builtin perf.c:348
#20 0x5df8f57b53b3 in handle_internal_command perf.c:398
#21 0x5df8f57b5b2f in run_argv perf.c:445
#22 0x5df8f57b5091 in main perf.c:551
#23 0x74373a629d90 in __libc_start_call_main libc_start_call_main.h:58
#24 0x74373a629e40 in __libc_start_main@@GLIBC_2.34 libc-start.c:128
#25 0x5df8f56ead35 in _start perf[55d35]
> Ian Rogers (11):
> perf maps: Fix reference count leak in maps__find_ams
> perf annotate: Fix args leak of map_symbol
> perf disasm: Constify use of struct arch
> perf disasm: Constify use of struct ins_op
> perf disasm: Constify use of struct ins
> perf disasm: Rework the string arch__is to use the ELF machine
> perf disasm: Don't include C files from the arch directory
> perf disasm: Refactor ins__is_call/jump to avoid exposing arch ins_ops
> perf map_symbol: Switch from holding maps to holding thread
> perf disasm: Refactor arch__find and initialization of arch structs
> perf disasm: Minor layout tweaks for struct arch
>
> tools/perf/arch/arc/annotate/instructions.c | 11 -
> .../perf/arch/riscv64/annotate/instructions.c | 36 --
> tools/perf/ui/browsers/annotate.c | 6 +-
> tools/perf/ui/browsers/hists.c | 3 +-
> tools/perf/util/Build | 1 +
> tools/perf/util/addr_location.c | 4 -
> tools/perf/util/addr_location.h | 1 -
> tools/perf/util/annotate-arch/Build | 11 +
> tools/perf/util/annotate-arch/annotate-arc.c | 18 +
> .../annotate-arch/annotate-arm.c} | 48 +-
> .../annotate-arch/annotate-arm64.c} | 59 +--
> .../annotate-arch/annotate-csky.c} | 29 +-
> .../annotate-arch/annotate-loongarch.c} | 57 ++-
> .../annotate-arch/annotate-mips.c} | 29 +-
> .../annotate-arch/annotate-powerpc.c} | 125 +++++-
> .../util/annotate-arch/annotate-riscv64.c | 41 ++
> .../annotate-arch/annotate-s390.c} | 59 ++-
> .../annotate-arch/annotate-sparc.c} | 26 +-
> .../annotate-arch/annotate-x86.c} | 89 ++--
> tools/perf/util/annotate-data.c | 12 +-
> tools/perf/util/annotate-data.h | 2 +-
> tools/perf/util/annotate.c | 88 ++--
> tools/perf/util/annotate.h | 10 +-
> tools/perf/util/callchain.c | 12 +-
> tools/perf/util/capstone.c | 18 +-
> tools/perf/util/db-export.c | 1 -
> tools/perf/util/disasm.c | 424 +++++++-----------
> tools/perf/util/disasm.h | 95 ++--
> tools/perf/util/event.c | 2 -
> tools/perf/util/hist.c | 18 +-
> tools/perf/util/llvm.c | 8 +-
> tools/perf/util/machine.c | 13 +-
> tools/perf/util/map_symbol.c | 5 +-
> tools/perf/util/map_symbol.h | 3 +-
> tools/perf/util/maps.c | 1 +
> tools/perf/util/sort.c | 2 +-
> tools/perf/util/unwind-libdw.c | 2 +-
> tools/perf/util/unwind-libunwind-local.c | 2 +-
> 38 files changed, 752 insertions(+), 619 deletions(-)
> delete mode 100644 tools/perf/arch/arc/annotate/instructions.c
> delete mode 100644 tools/perf/arch/riscv64/annotate/instructions.c
> create mode 100644 tools/perf/util/annotate-arch/Build
> create mode 100644 tools/perf/util/annotate-arch/annotate-arc.c
> rename tools/perf/{arch/arm/annotate/instructions.c => util/annotate-arch/annotate-arm.c} (59%)
> rename tools/perf/{arch/arm64/annotate/instructions.c => util/annotate-arch/annotate-arm64.c} (70%)
> rename tools/perf/{arch/csky/annotate/instructions.c => util/annotate-arch/annotate-csky.c} (67%)
> rename tools/perf/{arch/loongarch/annotate/instructions.c => util/annotate-arch/annotate-loongarch.c} (66%)
> rename tools/perf/{arch/mips/annotate/instructions.c => util/annotate-arch/annotate-mips.c} (59%)
> rename tools/perf/{arch/powerpc/annotate/instructions.c => util/annotate-arch/annotate-powerpc.c} (73%)
> create mode 100644 tools/perf/util/annotate-arch/annotate-riscv64.c
> rename tools/perf/{arch/s390/annotate/instructions.c => util/annotate-arch/annotate-s390.c} (70%)
> rename tools/perf/{arch/sparc/annotate/instructions.c => util/annotate-arch/annotate-sparc.c} (85%)
> rename tools/perf/{arch/x86/annotate/instructions.c => util/annotate-arch/annotate-x86.c} (93%)
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 00/11] perf annotate arch clean up
2026-01-22 10:43 ` [PATCH v1 00/11] perf annotate arch clean up James Clark
@ 2026-01-22 10:47 ` James Clark
2026-01-22 11:56 ` Suchit Karunakaran
0 siblings, 1 reply; 17+ messages in thread
From: James Clark @ 2026-01-22 10:47 UTC (permalink / raw)
To: Ian Rogers
Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
John Garry, Will Deacon, Leo Yan, Guo Ren, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Nathan Chancellor,
Nick Desaulniers, Bill Wendling, Justin Stitt, Zecheng Li,
Tianyou Li, Thomas Falcon, Julia Lawall, Suchit Karunakaran,
Athira Rajeev, Aditya Bodkhe, Howard Chu,
Krzysztof Łopatowski, Dr. David Alan Gilbert, Shimin Guo,
Sergei Trofimovich, linux-kernel, linux-perf-users,
linux-arm-kernel, linux-csky, linux-riscv
On 22/01/2026 10:43 am, James Clark wrote:
>
>
> On 22/01/2026 7:31 am, Ian Rogers wrote:
>> 2 initial memory leak fix patches for perf annotate.
>>
>> Move the disasm.c #included arch files into a new util/annotate-arch
>> directory. Make the code compile standalone. Try to better encapsulate
>> architecture specific code within the files and with a
>> arch__new_<arch> function that allows additional data to be associated
>> with the struct arch using the standard container_of trick.
>>
>> Make the lookup of struct arch use the ELF machine gather from a
>> thread rather than an evsel. For example, the evsel can't determine
>> the difference between EM_386 and EM_X86_64 so generally the latter
>> has currently been used. This means the dwarf registers are off as
>> register 1 is CX with EM_386 and DX with EM_X86_64. To facilitate this
>> change map_symbol is refactored to use a struct thread rather than a
>> struct maps, the maps being obtainable from the thread.
>>
>> To make in and out arguments clearer, for safety, etc. try to constify
>> struct arch and its related structs.
>>
>
> Hi Ian,
>
> I get this crash, not sure which commit causes it exactly but it
> happened 2/2 times on both x86 and arm:
>
> $ perf record -- true
> $ perf report
>
> < Select first sample >
> < Select annotate >
>
> perf: Segmentation fault
> -------- backtrace --------
> #0 0x5df8f58ba973 in ui__signal_backtrace setup.c:110
> #1 0x74373a642520 in __restore_rt libc_sigaction.c:0
> #2 0x5df8f5963f0d in dso__kernel dso.h:532
> #3 0x5df8f5965d0a in __map__const_kmap map.c:627
> #4 0x5df8f5965a36 in map__rip_2objdump map.c:531
> #5 0x5df8f58e5bef in symbol__parse_objdump_line disasm.c:1032
> #6 0x5df8f58e498b in symbol__disassemble_objdump disasm.c:1503
> #7 0x5df8f58e3852 in symbol__disassemble disasm.c:1621
> #8 0x5df8f58c638d in symbol__annotate annotate.c:1055
> #9 0x5df8f58c8628 in symbol__annotate2 annotate.c:2209
> #10 0x5df8f58a36b7 in __hist_entry__tui_annotate annotate.c:1189
> #11 0x5df8f58adf86 in do_annotate hists.c:2488
> #12 0x5df8f58ad762 in evsel__hists_browse hists.c:3441
> #13 0x5df8f58b78f2 in perf_evsel_menu__run hists.c:3556
> #14 0x5df8f58adabc in __evlist__tui_browse_hists hists.c:3643
> #15 0x5df8f58abf3b in evlist__tui_browse_hists hists.c:3691
> #16 0x5df8f571ac3a in report__browse_hists builtin-report.c:688
> #17 0x5df8f5719943 in __cmd_report builtin-report.c:1177
> #18 0x5df8f57181bc in cmd_report builtin-report.c:1890
> #19 0x5df8f57b5c3a in run_builtin perf.c:348
> #20 0x5df8f57b53b3 in handle_internal_command perf.c:398
> #21 0x5df8f57b5b2f in run_argv perf.c:445
> #22 0x5df8f57b5091 in main perf.c:551
> #23 0x74373a629d90 in __libc_start_call_main libc_start_call_main.h:58
> #24 0x74373a629e40 in __libc_start_main@@GLIBC_2.34 libc-start.c:128
> #25 0x5df8f56ead35 in _start perf[55d35]
>
>
Also the annotate test fails:
$ sudo perf test 74
74: perf annotate basic tests : FAILED!
>> Ian Rogers (11):
>> perf maps: Fix reference count leak in maps__find_ams
>> perf annotate: Fix args leak of map_symbol
>> perf disasm: Constify use of struct arch
>> perf disasm: Constify use of struct ins_op
>> perf disasm: Constify use of struct ins
>> perf disasm: Rework the string arch__is to use the ELF machine
>> perf disasm: Don't include C files from the arch directory
>> perf disasm: Refactor ins__is_call/jump to avoid exposing arch ins_ops
>> perf map_symbol: Switch from holding maps to holding thread
>> perf disasm: Refactor arch__find and initialization of arch structs
>> perf disasm: Minor layout tweaks for struct arch
>>
>> tools/perf/arch/arc/annotate/instructions.c | 11 -
>> .../perf/arch/riscv64/annotate/instructions.c | 36 --
>> tools/perf/ui/browsers/annotate.c | 6 +-
>> tools/perf/ui/browsers/hists.c | 3 +-
>> tools/perf/util/Build | 1 +
>> tools/perf/util/addr_location.c | 4 -
>> tools/perf/util/addr_location.h | 1 -
>> tools/perf/util/annotate-arch/Build | 11 +
>> tools/perf/util/annotate-arch/annotate-arc.c | 18 +
>> .../annotate-arch/annotate-arm.c} | 48 +-
>> .../annotate-arch/annotate-arm64.c} | 59 +--
>> .../annotate-arch/annotate-csky.c} | 29 +-
>> .../annotate-arch/annotate-loongarch.c} | 57 ++-
>> .../annotate-arch/annotate-mips.c} | 29 +-
>> .../annotate-arch/annotate-powerpc.c} | 125 +++++-
>> .../util/annotate-arch/annotate-riscv64.c | 41 ++
>> .../annotate-arch/annotate-s390.c} | 59 ++-
>> .../annotate-arch/annotate-sparc.c} | 26 +-
>> .../annotate-arch/annotate-x86.c} | 89 ++--
>> tools/perf/util/annotate-data.c | 12 +-
>> tools/perf/util/annotate-data.h | 2 +-
>> tools/perf/util/annotate.c | 88 ++--
>> tools/perf/util/annotate.h | 10 +-
>> tools/perf/util/callchain.c | 12 +-
>> tools/perf/util/capstone.c | 18 +-
>> tools/perf/util/db-export.c | 1 -
>> tools/perf/util/disasm.c | 424 +++++++-----------
>> tools/perf/util/disasm.h | 95 ++--
>> tools/perf/util/event.c | 2 -
>> tools/perf/util/hist.c | 18 +-
>> tools/perf/util/llvm.c | 8 +-
>> tools/perf/util/machine.c | 13 +-
>> tools/perf/util/map_symbol.c | 5 +-
>> tools/perf/util/map_symbol.h | 3 +-
>> tools/perf/util/maps.c | 1 +
>> tools/perf/util/sort.c | 2 +-
>> tools/perf/util/unwind-libdw.c | 2 +-
>> tools/perf/util/unwind-libunwind-local.c | 2 +-
>> 38 files changed, 752 insertions(+), 619 deletions(-)
>> delete mode 100644 tools/perf/arch/arc/annotate/instructions.c
>> delete mode 100644 tools/perf/arch/riscv64/annotate/instructions.c
>> create mode 100644 tools/perf/util/annotate-arch/Build
>> create mode 100644 tools/perf/util/annotate-arch/annotate-arc.c
>> rename tools/perf/{arch/arm/annotate/instructions.c => util/
>> annotate-arch/annotate-arm.c} (59%)
>> rename tools/perf/{arch/arm64/annotate/instructions.c => util/
>> annotate-arch/annotate-arm64.c} (70%)
>> rename tools/perf/{arch/csky/annotate/instructions.c => util/
>> annotate-arch/annotate-csky.c} (67%)
>> rename tools/perf/{arch/loongarch/annotate/instructions.c => util/
>> annotate-arch/annotate-loongarch.c} (66%)
>> rename tools/perf/{arch/mips/annotate/instructions.c => util/
>> annotate-arch/annotate-mips.c} (59%)
>> rename tools/perf/{arch/powerpc/annotate/instructions.c => util/
>> annotate-arch/annotate-powerpc.c} (73%)
>> create mode 100644 tools/perf/util/annotate-arch/annotate-riscv64.c
>> rename tools/perf/{arch/s390/annotate/instructions.c => util/
>> annotate-arch/annotate-s390.c} (70%)
>> rename tools/perf/{arch/sparc/annotate/instructions.c => util/
>> annotate-arch/annotate-sparc.c} (85%)
>> rename tools/perf/{arch/x86/annotate/instructions.c => util/
>> annotate-arch/annotate-x86.c} (93%)
>>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 02/11] perf annotate: Fix args leak of map_symbol
2026-01-22 7:31 ` [PATCH v1 02/11] perf annotate: Fix args leak of map_symbol Ian Rogers
@ 2026-01-22 11:46 ` Suchit Karunakaran
2026-01-22 16:05 ` Ian Rogers
0 siblings, 1 reply; 17+ messages in thread
From: Suchit Karunakaran @ 2026-01-22 11:46 UTC (permalink / raw)
To: Ian Rogers
Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
James Clark, John Garry, Will Deacon, Leo Yan, Guo Ren,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
Zecheng Li, Tianyou Li, Thomas Falcon, Julia Lawall,
Athira Rajeev, Aditya Bodkhe, Howard Chu,
Krzysztof Łopatowski, Dr. David Alan Gilbert, Shimin Guo,
Sergei Trofimovich, linux-kernel, linux-perf-users,
linux-arm-kernel, linux-csky, linux-riscv
> @@ -1119,7 +1121,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
> struct annotate_args *args,
> char *parsed_line, int *line_nr, char **fileloc)
> {
> - struct map *map = args->ms.map;
> + struct map *map = args->ms->map;
> struct annotation *notes = symbol__annotation(sym);
> struct disasm_line *dl;
> char *tmp;
> @@ -1151,7 +1153,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
> args->line = parsed_line;
> args->line_nr = *line_nr;
> args->fileloc = *fileloc;
> - args->ms.sym = sym;
> + args->ms->sym = sym;
>
> dl = disasm_line__new(args);
> (*line_nr)++;
> @@ -1172,7 +1174,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
> .ms = { .map = map, },
> };
>
> - if (!maps__find_ams(args->ms.maps, &target) &&
> + if (!maps__find_ams(args->ms->maps, &target) &&
> target.ms.sym->start == target.al_addr)
> dl->ops.target.sym = target.ms.sym;
> }
Hi, a noob here so please correct me if I'm wrong.
Looking at symbol__parse_objdump_line(), shouldn't we be calling
map__get() when initializing the target struct? Since maps__find_ams()
now calls map__put() (after patch 1).
struct addr_map_symbol target = {
.addr = dl->ops.target.addr,
.ms = { .map = map__get(map), },
};
This would match the pattern used in call__parse() and jump__parse()
that were fixed in patch 2.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 00/11] perf annotate arch clean up
2026-01-22 10:47 ` James Clark
@ 2026-01-22 11:56 ` Suchit Karunakaran
0 siblings, 0 replies; 17+ messages in thread
From: Suchit Karunakaran @ 2026-01-22 11:56 UTC (permalink / raw)
To: James Clark
Cc: Ian Rogers, Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
John Garry, Will Deacon, Leo Yan, Guo Ren, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Nathan Chancellor,
Nick Desaulniers, Bill Wendling, Justin Stitt, Zecheng Li,
Tianyou Li, Thomas Falcon, Julia Lawall, Athira Rajeev,
Aditya Bodkhe, Howard Chu, Krzysztof Łopatowski,
Dr. David Alan Gilbert, Shimin Guo, Sergei Trofimovich,
linux-kernel, linux-perf-users, linux-arm-kernel, linux-csky,
linux-riscv
On Thu, 22 Jan 2026 at 16:17, James Clark <james.clark@linaro.org> wrote:
>
>
>
> On 22/01/2026 10:43 am, James Clark wrote:
> >
> >
> > On 22/01/2026 7:31 am, Ian Rogers wrote:
> >> 2 initial memory leak fix patches for perf annotate.
> >>
> >> Move the disasm.c #included arch files into a new util/annotate-arch
> >> directory. Make the code compile standalone. Try to better encapsulate
> >> architecture specific code within the files and with a
> >> arch__new_<arch> function that allows additional data to be associated
> >> with the struct arch using the standard container_of trick.
> >>
> >> Make the lookup of struct arch use the ELF machine gather from a
> >> thread rather than an evsel. For example, the evsel can't determine
> >> the difference between EM_386 and EM_X86_64 so generally the latter
> >> has currently been used. This means the dwarf registers are off as
> >> register 1 is CX with EM_386 and DX with EM_X86_64. To facilitate this
> >> change map_symbol is refactored to use a struct thread rather than a
> >> struct maps, the maps being obtainable from the thread.
> >>
> >> To make in and out arguments clearer, for safety, etc. try to constify
> >> struct arch and its related structs.
> >>
> >
> > Hi Ian,
> >
> > I get this crash, not sure which commit causes it exactly but it
> > happened 2/2 times on both x86 and arm:
> >
> > $ perf record -- true
> > $ perf report
> >
> > < Select first sample >
> > < Select annotate >
> >
> > perf: Segmentation fault
> > -------- backtrace --------
> > #0 0x5df8f58ba973 in ui__signal_backtrace setup.c:110
> > #1 0x74373a642520 in __restore_rt libc_sigaction.c:0
> > #2 0x5df8f5963f0d in dso__kernel dso.h:532
> > #3 0x5df8f5965d0a in __map__const_kmap map.c:627
> > #4 0x5df8f5965a36 in map__rip_2objdump map.c:531
> > #5 0x5df8f58e5bef in symbol__parse_objdump_line disasm.c:1032
> > #6 0x5df8f58e498b in symbol__disassemble_objdump disasm.c:1503
> > #7 0x5df8f58e3852 in symbol__disassemble disasm.c:1621
> > #8 0x5df8f58c638d in symbol__annotate annotate.c:1055
> > #9 0x5df8f58c8628 in symbol__annotate2 annotate.c:2209
> > #10 0x5df8f58a36b7 in __hist_entry__tui_annotate annotate.c:1189
> > #11 0x5df8f58adf86 in do_annotate hists.c:2488
> > #12 0x5df8f58ad762 in evsel__hists_browse hists.c:3441
> > #13 0x5df8f58b78f2 in perf_evsel_menu__run hists.c:3556
> > #14 0x5df8f58adabc in __evlist__tui_browse_hists hists.c:3643
> > #15 0x5df8f58abf3b in evlist__tui_browse_hists hists.c:3691
> > #16 0x5df8f571ac3a in report__browse_hists builtin-report.c:688
> > #17 0x5df8f5719943 in __cmd_report builtin-report.c:1177
> > #18 0x5df8f57181bc in cmd_report builtin-report.c:1890
> > #19 0x5df8f57b5c3a in run_builtin perf.c:348
> > #20 0x5df8f57b53b3 in handle_internal_command perf.c:398
> > #21 0x5df8f57b5b2f in run_argv perf.c:445
> > #22 0x5df8f57b5091 in main perf.c:551
> > #23 0x74373a629d90 in __libc_start_call_main libc_start_call_main.h:58
> > #24 0x74373a629e40 in __libc_start_main@@GLIBC_2.34 libc-start.c:128
> > #25 0x5df8f56ead35 in _start perf[55d35]
> >
> >
>
> Also the annotate test fails:
>
> $ sudo perf test 74
> 74: perf annotate basic tests : FAILED!
>
>
> >> Ian Rogers (11):
> >> perf maps: Fix reference count leak in maps__find_ams
> >> perf annotate: Fix args leak of map_symbol
> >> perf disasm: Constify use of struct arch
> >> perf disasm: Constify use of struct ins_op
> >> perf disasm: Constify use of struct ins
> >> perf disasm: Rework the string arch__is to use the ELF machine
> >> perf disasm: Don't include C files from the arch directory
> >> perf disasm: Refactor ins__is_call/jump to avoid exposing arch ins_ops
> >> perf map_symbol: Switch from holding maps to holding thread
> >> perf disasm: Refactor arch__find and initialization of arch structs
> >> perf disasm: Minor layout tweaks for struct arch
> >>
> >> tools/perf/arch/arc/annotate/instructions.c | 11 -
> >> .../perf/arch/riscv64/annotate/instructions.c | 36 --
> >> tools/perf/ui/browsers/annotate.c | 6 +-
> >> tools/perf/ui/browsers/hists.c | 3 +-
> >> tools/perf/util/Build | 1 +
> >> tools/perf/util/addr_location.c | 4 -
> >> tools/perf/util/addr_location.h | 1 -
> >> tools/perf/util/annotate-arch/Build | 11 +
> >> tools/perf/util/annotate-arch/annotate-arc.c | 18 +
> >> .../annotate-arch/annotate-arm.c} | 48 +-
> >> .../annotate-arch/annotate-arm64.c} | 59 +--
> >> .../annotate-arch/annotate-csky.c} | 29 +-
> >> .../annotate-arch/annotate-loongarch.c} | 57 ++-
> >> .../annotate-arch/annotate-mips.c} | 29 +-
> >> .../annotate-arch/annotate-powerpc.c} | 125 +++++-
> >> .../util/annotate-arch/annotate-riscv64.c | 41 ++
> >> .../annotate-arch/annotate-s390.c} | 59 ++-
> >> .../annotate-arch/annotate-sparc.c} | 26 +-
> >> .../annotate-arch/annotate-x86.c} | 89 ++--
> >> tools/perf/util/annotate-data.c | 12 +-
> >> tools/perf/util/annotate-data.h | 2 +-
> >> tools/perf/util/annotate.c | 88 ++--
> >> tools/perf/util/annotate.h | 10 +-
> >> tools/perf/util/callchain.c | 12 +-
> >> tools/perf/util/capstone.c | 18 +-
> >> tools/perf/util/db-export.c | 1 -
> >> tools/perf/util/disasm.c | 424 +++++++-----------
> >> tools/perf/util/disasm.h | 95 ++--
> >> tools/perf/util/event.c | 2 -
> >> tools/perf/util/hist.c | 18 +-
> >> tools/perf/util/llvm.c | 8 +-
> >> tools/perf/util/machine.c | 13 +-
> >> tools/perf/util/map_symbol.c | 5 +-
> >> tools/perf/util/map_symbol.h | 3 +-
> >> tools/perf/util/maps.c | 1 +
> >> tools/perf/util/sort.c | 2 +-
> >> tools/perf/util/unwind-libdw.c | 2 +-
> >> tools/perf/util/unwind-libunwind-local.c | 2 +-
> >> 38 files changed, 752 insertions(+), 619 deletions(-)
> >> delete mode 100644 tools/perf/arch/arc/annotate/instructions.c
> >> delete mode 100644 tools/perf/arch/riscv64/annotate/instructions.c
> >> create mode 100644 tools/perf/util/annotate-arch/Build
> >> create mode 100644 tools/perf/util/annotate-arch/annotate-arc.c
> >> rename tools/perf/{arch/arm/annotate/instructions.c => util/
> >> annotate-arch/annotate-arm.c} (59%)
> >> rename tools/perf/{arch/arm64/annotate/instructions.c => util/
> >> annotate-arch/annotate-arm64.c} (70%)
> >> rename tools/perf/{arch/csky/annotate/instructions.c => util/
> >> annotate-arch/annotate-csky.c} (67%)
> >> rename tools/perf/{arch/loongarch/annotate/instructions.c => util/
> >> annotate-arch/annotate-loongarch.c} (66%)
> >> rename tools/perf/{arch/mips/annotate/instructions.c => util/
> >> annotate-arch/annotate-mips.c} (59%)
> >> rename tools/perf/{arch/powerpc/annotate/instructions.c => util/
> >> annotate-arch/annotate-powerpc.c} (73%)
> >> create mode 100644 tools/perf/util/annotate-arch/annotate-riscv64.c
> >> rename tools/perf/{arch/s390/annotate/instructions.c => util/
> >> annotate-arch/annotate-s390.c} (70%)
> >> rename tools/perf/{arch/sparc/annotate/instructions.c => util/
> >> annotate-arch/annotate-sparc.c} (85%)
> >> rename tools/perf/{arch/x86/annotate/instructions.c => util/
> >> annotate-arch/annotate-x86.c} (93%)
> >>
> >
>
The annotate test fails after applying the 4th patch.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 02/11] perf annotate: Fix args leak of map_symbol
2026-01-22 11:46 ` Suchit Karunakaran
@ 2026-01-22 16:05 ` Ian Rogers
0 siblings, 0 replies; 17+ messages in thread
From: Ian Rogers @ 2026-01-22 16:05 UTC (permalink / raw)
To: Suchit Karunakaran
Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
James Clark, John Garry, Will Deacon, Leo Yan, Guo Ren,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
Zecheng Li, Tianyou Li, Thomas Falcon, Julia Lawall,
Athira Rajeev, Aditya Bodkhe, Howard Chu,
Krzysztof Łopatowski, Dr. David Alan Gilbert, Shimin Guo,
Sergei Trofimovich, linux-kernel, linux-perf-users,
linux-arm-kernel, linux-csky, linux-riscv
On Thu, Jan 22, 2026 at 3:47 AM Suchit Karunakaran
<suchitkarunakaran@gmail.com> wrote:
>
> > @@ -1119,7 +1121,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
> > struct annotate_args *args,
> > char *parsed_line, int *line_nr, char **fileloc)
> > {
> > - struct map *map = args->ms.map;
> > + struct map *map = args->ms->map;
> > struct annotation *notes = symbol__annotation(sym);
> > struct disasm_line *dl;
> > char *tmp;
> > @@ -1151,7 +1153,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
> > args->line = parsed_line;
> > args->line_nr = *line_nr;
> > args->fileloc = *fileloc;
> > - args->ms.sym = sym;
> > + args->ms->sym = sym;
> >
> > dl = disasm_line__new(args);
> > (*line_nr)++;
> > @@ -1172,7 +1174,7 @@ static int symbol__parse_objdump_line(struct symbol *sym,
> > .ms = { .map = map, },
> > };
> >
> > - if (!maps__find_ams(args->ms.maps, &target) &&
> > + if (!maps__find_ams(args->ms->maps, &target) &&
> > target.ms.sym->start == target.al_addr)
> > dl->ops.target.sym = target.ms.sym;
> > }
>
> Hi, a noob here so please correct me if I'm wrong.
> Looking at symbol__parse_objdump_line(), shouldn't we be calling
> map__get() when initializing the target struct? Since maps__find_ams()
> now calls map__put() (after patch 1).
> struct addr_map_symbol target = {
> .addr = dl->ops.target.addr,
> .ms = { .map = map__get(map), },
> };
> This would match the pattern used in call__parse() and jump__parse()
> that were fixed in patch 2.
Agreed this is another problem. I'll add the missing put and
addr_map_symbol__exit missing here.
Thanks,
Ian
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-01-22 16:06 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-22 7:31 [PATCH v1 00/11] perf annotate arch clean up Ian Rogers
2026-01-22 7:31 ` [PATCH v1 01/11] perf maps: Fix reference count leak in maps__find_ams Ian Rogers
2026-01-22 7:31 ` [PATCH v1 02/11] perf annotate: Fix args leak of map_symbol Ian Rogers
2026-01-22 11:46 ` Suchit Karunakaran
2026-01-22 16:05 ` Ian Rogers
2026-01-22 7:31 ` [PATCH v1 03/11] perf disasm: Constify use of struct arch Ian Rogers
2026-01-22 7:31 ` [PATCH v1 04/11] perf disasm: Constify use of struct ins_op Ian Rogers
2026-01-22 7:31 ` [PATCH v1 05/11] perf disasm: Constify use of struct ins Ian Rogers
2026-01-22 7:31 ` [PATCH v1 06/11] perf disasm: Rework the string arch__is to use the ELF machine Ian Rogers
2026-01-22 7:31 ` [PATCH v1 07/11] perf disasm: Don't include C files from the arch directory Ian Rogers
2026-01-22 7:31 ` [PATCH v1 08/11] perf disasm: Refactor ins__is_call/jump to avoid exposing arch ins_ops Ian Rogers
2026-01-22 7:31 ` [PATCH v1 09/11] perf map_symbol: Switch from holding maps to holding thread Ian Rogers
2026-01-22 7:31 ` [PATCH v1 10/11] perf disasm: Refactor arch__find and initialization of arch structs Ian Rogers
2026-01-22 7:31 ` [PATCH v1 11/11] perf disasm: Minor layout tweaks for struct arch Ian Rogers
2026-01-22 10:43 ` [PATCH v1 00/11] perf annotate arch clean up James Clark
2026-01-22 10:47 ` James Clark
2026-01-22 11:56 ` Suchit Karunakaran
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox