summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/perf/ui/browsers/annotate.c2
-rw-r--r--tools/perf/util/annotate-arch/annotate-arc.c14
-rw-r--r--tools/perf/util/annotate-arch/annotate-arm.c39
-rw-r--r--tools/perf/util/annotate-arch/annotate-arm64.c39
-rw-r--r--tools/perf/util/annotate-arch/annotate-csky.c14
-rw-r--r--tools/perf/util/annotate-arch/annotate-loongarch.c19
-rw-r--r--tools/perf/util/annotate-arch/annotate-mips.c19
-rw-r--r--tools/perf/util/annotate-arch/annotate-powerpc.c24
-rw-r--r--tools/perf/util/annotate-arch/annotate-riscv64.c19
-rw-r--r--tools/perf/util/annotate-arch/annotate-s390.c29
-rw-r--r--tools/perf/util/annotate-arch/annotate-sparc.c19
-rw-r--r--tools/perf/util/annotate-arch/annotate-x86.c24
-rw-r--r--tools/perf/util/annotate.c46
-rw-r--r--tools/perf/util/annotate.h2
-rw-r--r--tools/perf/util/disasm.c157
-rw-r--r--tools/perf/util/disasm.h59
16 files changed, 283 insertions, 242 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..afb413c80156 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;
+ 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-arm64.c b/tools/perf/util/annotate-arch/annotate-arm64.c
index d2ea32984b0d..33080fdca125 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,40 @@ 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;
-
- arm = zalloc(sizeof(*arm));
if (!arm)
- return ENOMEM;
+ 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;
/* 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..218207b52581 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;
+ return arch;
}
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..2f07bc7a56dd 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));
- return 0;
+ if (!arch)
+ return NULL;
+
+ arch->name = "sparc";
+ arch->id = *id;
+ arch->associate_instruction_ops = sparc__associate_instruction_ops;
+ arch->objdump.comment_char = '#';
+ return arch;
}
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 @@ retry:
}
#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..4f60726247d6 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -1,5 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <ctype.h>
+#include <elf.h>
+#ifndef EF_CSKY_ABIMASK
+#define EF_CSKY_ABIMASK 0XF0000000
+#endif
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -102,112 +106,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);