]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
perf capstone: Determine architecture from e_machine
authorIan Rogers <irogers@google.com>
Tue, 2 Jun 2026 15:25:01 +0000 (08:25 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 3 Jun 2026 19:45:43 +0000 (16:45 -0300)
Avoid the use of arch string that is imprecise and use the
e_machine. Do more e_machine to capstone machine translations adding
MIPS and RISCV. Remove unnecessary maybe_unused annotations.

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Honglei Wang <jameshongleiwang@126.com>
Cc: Jan Polensky <japo@linux.ibm.com>
Cc: Sumanth Korikkar <sumanthk@linux.ibm.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/capstone.c

index 25cf6e15ec2728fd640b44b6444a83c947a380dd..5ad537fea4360e3100a8d0723e81d9f80a97d4c6 100644 (file)
@@ -1,7 +1,19 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "capstone.h"
-#include "annotate.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include <dlfcn.h>
+#include <elf.h>
+#include <fcntl.h>
+#include <linux/ctype.h>
+
+#include <capstone/capstone.h>
+
 #include "addr_location.h"
+#include "annotate.h"
 #include "debug.h"
 #include "disasm.h"
 #include "dso.h"
 #include "print_insn.h"
 #include "symbol.h"
 #include "thread.h"
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <string.h>
-
-#include <capstone/capstone.h>
 
 #ifdef LIBCAPSTONE_DLOPEN
 static void *perf_cs_dll_handle(void)
@@ -137,37 +142,70 @@ static enum cs_err perf_cs_close(csh *handle)
 #endif
 }
 
-static int capstone_init(struct machine *machine, csh *cs_handle, bool is64,
+static bool e_machine_to_capstone(uint16_t e_machine, bool is64, bool is_big_endian,
+                                 enum cs_arch *arch, enum cs_mode *mode)
+{
+       *mode = is_big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN;
+
+       switch (e_machine) {
+       case EM_X86_64:
+       case EM_386:
+               *arch = CS_ARCH_X86;
+               *mode |= is64 ? CS_MODE_64 : CS_MODE_32;
+               return true;
+       case EM_AARCH64:
+               *arch = CS_ARCH_ARM64;
+               *mode |= CS_MODE_ARM;
+               return true;
+       case EM_ARM:
+               *arch = CS_ARCH_ARM;
+               *mode |= CS_MODE_ARM | CS_MODE_V8;
+               return true;
+       case EM_S390:
+               *arch = CS_ARCH_SYSZ;
+               return true;
+       case EM_MIPS:
+               *arch = CS_ARCH_MIPS;
+               *mode |= is64 ? CS_MODE_MIPS64 : CS_MODE_MIPS32;
+               return true;
+       case EM_PPC:
+               *arch = CS_ARCH_PPC;
+               return true;
+       case EM_PPC64:
+               *arch = CS_ARCH_PPC;
+               *mode |= CS_MODE_64;
+               return true;
+       case EM_SPARC:
+               *arch = CS_ARCH_SPARC;
+               return true;
+       case EM_SPARCV9:
+               *arch = CS_ARCH_SPARC;
+               *mode |= CS_MODE_V9;
+               return true;
+       case EM_RISCV:
+               *arch = CS_ARCH_RISCV;
+               *mode |= (is64 ? CS_MODE_RISCV64 : CS_MODE_RISCV32) | CS_MODE_RISCVC;
+               return true;
+       default:
+               return false;
+       }
+}
+
+static int capstone_init(uint16_t e_machine, csh *cs_handle, bool is64, bool is_big_endian,
                         bool disassembler_style)
 {
        enum cs_arch arch;
        enum cs_mode mode;
 
-       if (machine__is(machine, "x86_64") && is64) {
-               arch = CS_ARCH_X86;
-               mode = CS_MODE_64;
-       } else if (machine__normalized_is(machine, "x86")) {
-               arch = CS_ARCH_X86;
-               mode = CS_MODE_32;
-       } else if (machine__normalized_is(machine, "arm64")) {
-               arch = CS_ARCH_ARM64;
-               mode = CS_MODE_ARM;
-       } else if (machine__normalized_is(machine, "arm")) {
-               arch = CS_ARCH_ARM;
-               mode = CS_MODE_ARM + CS_MODE_V8;
-       } else if (machine__normalized_is(machine, "s390")) {
-               arch = CS_ARCH_SYSZ;
-               mode = CS_MODE_BIG_ENDIAN;
-       } else {
+       if (!e_machine_to_capstone(e_machine, is64, is_big_endian, &arch, &mode))
                return -1;
-       }
 
        if (perf_cs_open(arch, mode, cs_handle) != CS_ERR_OK) {
                pr_warning_once("cs_open failed\n");
                return -1;
        }
 
-       if (machine__normalized_is(machine, "x86")) {
+       if (arch == CS_ARCH_X86) {
                /*
                 * In case of using capstone_init while symbol__disassemble
                 * setting CS_OPT_SYNTAX_ATT depends if disassembler_style opts
@@ -211,29 +249,28 @@ static size_t print_insn_x86(struct thread *thread, u8 cpumode, struct cs_insn *
        return printed;
 }
 
-
-ssize_t capstone__fprintf_insn_asm(struct machine *machine __maybe_unused,
-                                  struct thread *thread __maybe_unused,
-                                  u8 cpumode __maybe_unused, bool is64bit __maybe_unused,
-                                  const uint8_t *code __maybe_unused,
-                                  size_t code_size __maybe_unused,
-                                  uint64_t ip __maybe_unused, int *lenp __maybe_unused,
-                                  int print_opts __maybe_unused, FILE *fp __maybe_unused)
+ssize_t capstone__fprintf_insn_asm(struct machine *machine, struct thread *thread, u8 cpumode,
+                                  bool is64bit, const uint8_t *code, size_t code_size, uint64_t ip,
+                                  int *lenp, int print_opts, FILE *fp)
 {
        size_t printed;
        struct cs_insn *insn;
        csh cs_handle;
        size_t count;
+       bool is_big_endian = false;
+       uint16_t e_machine = thread__e_machine_endian(thread, machine,
+                                                     /*e_flags=*/NULL, &is_big_endian);
        int ret;
 
        /* TODO: Try to initiate capstone only once but need a proper place. */
-       ret = capstone_init(machine, &cs_handle, is64bit, true);
+       ret = capstone_init(e_machine, &cs_handle, is64bit, is_big_endian,
+                           /*disassembler_style=*/true);
        if (ret < 0)
                return ret;
 
        count = perf_cs_disasm(cs_handle, code, code_size, ip, 1, &insn);
        if (count > 0) {
-               if (machine__normalized_is(machine, "x86"))
+               if (e_machine == EM_X86_64 || e_machine == EM_386)
                        printed = print_insn_x86(thread, cpumode, &insn[0], print_opts, fp);
                else
                        printed = fprintf(fp, "%s %s", insn[0].mnemonic, insn[0].op_str);
@@ -322,9 +359,8 @@ static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg)
        return 0;
 }
 
-int symbol__disassemble_capstone(const char *filename __maybe_unused,
-                                struct symbol *sym __maybe_unused,
-                                struct annotate_args *args __maybe_unused)
+int symbol__disassemble_capstone(const char *filename, struct symbol *sym,
+                                struct annotate_args *args)
 {
        struct annotation *notes = symbol__annotation(sym);
        struct map *map = args->ms->map;
@@ -344,6 +380,8 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
        char disasm_buf[512];
        struct disasm_line *dl;
        bool disassembler_style = false;
+       uint16_t e_machine;
+       bool is_big_endian = false;
 
        if (args->options->objdump_path)
                return -1;
@@ -373,8 +411,10 @@ int symbol__disassemble_capstone(const char *filename __maybe_unused,
            !strcmp(args->options->disassembler_style, "att"))
                disassembler_style = true;
 
-       if (capstone_init(maps__machine(thread__maps(args->ms->thread)), &handle, is_64bit,
-                         disassembler_style) < 0)
+       e_machine = thread__e_machine_endian(args->ms->thread,
+                                            /*machine=*/NULL,
+                                            /*e_flags=*/NULL, &is_big_endian);
+       if (capstone_init(e_machine, &handle, is_64bit, is_big_endian, disassembler_style) < 0)
                goto err;
 
        needs_cs_close = true;
@@ -466,6 +506,8 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused,
        struct disasm_line *dl;
        u32 *line;
        bool disassembler_style = false;
+       uint16_t e_machine;
+       bool is_big_endian = false;
 
        if (args->options->objdump_path)
                return -1;
@@ -484,8 +526,10 @@ int symbol__disassemble_capstone_powerpc(const char *filename __maybe_unused,
            !strcmp(args->options->disassembler_style, "att"))
                disassembler_style = true;
 
-       if (capstone_init(maps__machine(thread__maps(args->ms->thread)), &handle, is_64bit,
-                         disassembler_style) < 0)
+       e_machine = thread__e_machine_endian(args->ms->thread,
+                                            /*machine=*/NULL,
+                                            /*e_flags=*/NULL, &is_big_endian);
+       if (capstone_init(e_machine, &handle, is_64bit, is_big_endian, disassembler_style) < 0)
                goto err;
 
        needs_cs_close = true;