Re: [PATCH v2 11/12] perf disasm: Refactor arch__find and initialization of arch structs

Suchit Karunakaran
2026-01-22T18:45:25Z

On Thu, 22 Jan 2026 at 22:24, Ian Rogers <irogers@google.com> wrote:
>
> 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;

Please correct me if I'm wrong, but I think there's double allocation
here for the variable arm since we've already allocated memory for at
the start of the function.

>
> /* 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 6c94cb98a104..3aeab453a059 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"
> @@ -139,13 +140,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;

Shouldn't we return arch here?

> }
> 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 47573f0310c1..af9cabd0a586 100644
> --- a/tools/perf/util/annotate-arch/annotate-s390.c
> +++ b/tools/perf/util/annotate-arch/annotate-s390.c
> @@ -148,7 +148,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];
> @@ -169,19 +169,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;

Same here as well, 0 is returned instead of the arch pointer.

> }
> 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(&notes->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, &notes->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 d81469db0aac..46740d1e5858 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
>