@@ -188,3 +188,65 @@ static int arm64__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
free(arm);
return SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP;
}
+
+
+/*
+ * Get the base register number and access offset in load/store instructions.
+ * At present, only the following two addressing modes are supported:
+ *
+ * 1. Base register only (no offset): [base{, #0}]
+ * 2. Base plus offset (immediate): [base{, #imm}]
+ *
+ * For addressing modes where the offset needs to be calculated from the
+ * register value, it is difficult to know the specific value of the offset
+ * register, making it impossible to calculate the offset.
+ *
+ * Fills @reg and @offset when return 0.
+ */
+static int
+extract_reg_offset_arm64(struct arch *arch __maybe_unused,
+ struct disasm_line *dl __maybe_unused,
+ const char *insn_str, int insn_ops __maybe_unused,
+ struct annotated_op_loc *op_loc)
+{
+ char *str;
+ regmatch_t match[4];
+ static regex_t reg_off_regex;
+ static bool regex_compiled;
+
+ if (!regex_compiled) {
+ regcomp(®_off_regex, "^\\[(sp|[xw][0-9]{1,2})(, #(-?[0-9]+))?\\].*",
+ REG_EXTENDED);
+ regex_compiled = true;
+ }
+
+ if (!op_loc->mem_ref)
+ return 0;
+
+ if (regexec(®_off_regex, insn_str, 4, match, 0))
+ return -1;
+
+ str = strdup(insn_str);
+ if (!str)
+ return -1;
+
+ /* Get the base register number. */
+ str[match[1].rm_eo] = '\0';
+ op_loc->reg1 = get_arm64_regnum(str + match[1].rm_so);
+
+ /*
+ * If there is an immediate offset, match[2] records the start and end
+ * positions of "#imm".
+ */
+ if (match[2].rm_so == -1) {
+ free(str);
+ return 0;
+ }
+
+ /* Get the immediate offset. */
+ str[match[3].rm_eo] = '\0';
+ op_loc->offset = strtol(str + match[3].rm_so, NULL, 0);
+
+ free(str);
+ return 0;
+}
@@ -210,6 +210,7 @@ perf-util-$(CONFIG_LIBDW) += dwarf-regs.o
perf-util-$(CONFIG_LIBDW) += dwarf-regs-csky.o
perf-util-$(CONFIG_LIBDW) += dwarf-regs-powerpc.o
perf-util-$(CONFIG_LIBDW) += dwarf-regs-x86.o
+perf-util-$(CONFIG_LIBDW) += dwarf-regs-arm64.o
perf-util-$(CONFIG_LIBDW) += debuginfo.o
perf-util-$(CONFIG_LIBDW) += annotate-data.o
@@ -128,6 +128,7 @@ static struct arch architectures[] = {
{
.name = "arm64",
.init = arm64__annotate_init,
+ .extract_reg_offset = extract_reg_offset_arm64,
},
{
.name = "csky",
new file mode 100644
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mapping of DWARF debug register numbers into register names.
+ *
+ * Copyright (c) 2025 Huawei Inc, Li Huafei <lihuafei1@huawei.com>
+ */
+#include <errno.h>
+#include <string.h>
+#include <dwarf-regs.h>
+
+int get_arm64_regnum(const char *name)
+{
+ int reg;
+
+ if (!strcmp(name, "sp"))
+ return 31;
+
+ if (*name != 'x' && *name != 'w')
+ return -EINVAL;
+
+ name++;
+ reg = strtol(name, NULL, 0);
+
+ return reg >= 0 && reg <= 30 ? reg : -EINVAL;
+}
@@ -101,6 +101,8 @@ const char *get_dwarf_regstr(unsigned int n, unsigned int machine, unsigned int
int get_x86_regnum(const char *name);
+int get_arm64_regnum(const char *name);
+
#if !defined(__x86_64__) && !defined(__i386__)
int get_arch_regnum(const char *name);
#endif
@@ -128,6 +130,11 @@ static inline void get_powerpc_regs(u32 raw_insn __maybe_unused, int is_source _
{
return;
}
+
+static inline int get_arm64_regnum(const char *name __maybe_unused)
+{
+ return -1;
+}
#endif
#endif
At present, only the following two addressing modes are supported: 1. Base register only (no offset): [base{, #0}] 2. Base plus offset (immediate): [base{, #imm}] For addressing modes where the offset needs to be calculated from the register value, it is difficult to know the specific value of the offset register, making it impossible to calculate the offset. Signed-off-by: Li Huafei <lihuafei1@huawei.com> --- tools/perf/arch/arm64/annotate/instructions.c | 62 +++++++++++++++++++ tools/perf/util/Build | 1 + tools/perf/util/disasm.c | 1 + tools/perf/util/dwarf-regs-arm64.c | 25 ++++++++ tools/perf/util/include/dwarf-regs.h | 7 +++ 5 files changed, 96 insertions(+) create mode 100644 tools/perf/util/dwarf-regs-arm64.c