lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250314162137.528204-5-lihuafei1@huawei.com>
Date: Sat, 15 Mar 2025 00:21:34 +0800
From: Li Huafei <lihuafei1@...wei.com>
To: <namhyung@...nel.org>, <acme@...nel.org>, <leo.yan@...ux.dev>,
	<james.clark@...aro.org>, <mark.rutland@....com>, <john.g.garry@...cle.com>,
	<will@...nel.org>, <irogers@...gle.com>
CC: <mike.leach@...aro.org>, <peterz@...radead.org>, <mingo@...hat.com>,
	<alexander.shishkin@...ux.intel.com>, <jolsa@...nel.org>,
	<kjain@...ux.ibm.com>, <mhiramat@...nel.org>, <atrajeev@...ux.vnet.ibm.com>,
	<sesse@...gle.com>, <adrian.hunter@...el.com>, <kan.liang@...ux.intel.com>,
	<linux-kernel@...r.kernel.org>, <linux-arm-kernel@...ts.infradead.org>,
	<linux-perf-users@...r.kernel.org>, <lihuafei1@...wei.com>
Subject: [PATCH 4/7] perf annotate: Support for the 'extract_reg_offset' callback function in arm64

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@...wei.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

diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index c212eb7341bd..54497b72a5c5 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -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(&reg_off_regex, "^\\[(sp|[xw][0-9]{1,2})(, #(-?[0-9]+))?\\].*",
+			REG_EXTENDED);
+		regex_compiled = true;
+	}
+
+	if (!op_loc->mem_ref)
+		return 0;
+
+	if (regexec(&reg_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;
+}
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 5ec97e8d6b6d..d408cbe94fdd 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -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
 
diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
index 905eceb824a4..1035c60a8545 100644
--- a/tools/perf/util/disasm.c
+++ b/tools/perf/util/disasm.c
@@ -128,6 +128,7 @@ static struct arch architectures[] = {
 	{
 		.name = "arm64",
 		.init = arm64__annotate_init,
+		.extract_reg_offset = extract_reg_offset_arm64,
 	},
 	{
 		.name = "csky",
diff --git a/tools/perf/util/dwarf-regs-arm64.c b/tools/perf/util/dwarf-regs-arm64.c
new file mode 100644
index 000000000000..edf41c059967
--- /dev/null
+++ b/tools/perf/util/dwarf-regs-arm64.c
@@ -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@...wei.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;
+}
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index 6f1b9f6b2466..81cc5f69a391 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -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
-- 
2.25.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ