diff mbox series

[RFC,v3,12/22] objtool: arm64: Compute destinations for call and jump instructions

Message ID 20230202074036.507249-13-madvenka@linux.microsoft.com (mailing list archive)
State New, archived
Headers show
Series arm64: livepatch: Use ORC for dynamic frame pointer validation | expand

Commit Message

Madhavan T. Venkataraman Feb. 2, 2023, 7:40 a.m. UTC
From: "Madhavan T. Venkataraman" <madvenka@linux.microsoft.com>

Compute the destination address of each call and jump instruction after
decoding all the instructions.

Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
---
 tools/objtool/arch/arm64/decode.c | 12 ++++++++
 tools/objtool/dcheck.c            | 47 ++++++++++++++++++++++++++++++-
 2 files changed, 58 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index aaae16791807..81653ed3c323 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -20,6 +20,18 @@ 
 /* ARM64 instructions are all 4 bytes wide. */
 #define INSN_SIZE	4
 
+/* --------------------- arch support functions ------------------------- */
+
+unsigned long arch_dest_reloc_offset(int addend)
+{
+	return addend;
+}
+
+unsigned long arch_jump_destination(struct instruction *insn)
+{
+	return insn->offset + insn->immediate;
+}
+
 /* --------------------- instruction decode structs ------------------------ */
 
 struct decode_var {
diff --git a/tools/objtool/dcheck.c b/tools/objtool/dcheck.c
index cd2700153408..eb806a032a32 100644
--- a/tools/objtool/dcheck.c
+++ b/tools/objtool/dcheck.c
@@ -12,10 +12,55 @@ 
 #include <objtool/builtin.h>
 #include <objtool/insn.h>
 
+/*
+ * Find the destination instructions for all jumps.
+ */
+static void add_jump_destinations(struct objtool_file *file)
+{
+	struct instruction *insn;
+	struct reloc *reloc;
+	struct section *dest_sec;
+	unsigned long dest_off;
+
+	for_each_insn(file, insn) {
+		if (insn->type != INSN_CALL &&
+		    insn->type != INSN_JUMP_CONDITIONAL &&
+		    insn->type != INSN_JUMP_UNCONDITIONAL) {
+			continue;
+		}
+
+		reloc = insn_reloc(file, insn);
+		if (!reloc) {
+			dest_sec = insn->sec;
+			dest_off = arch_jump_destination(insn);
+		} else if (reloc->sym->type == STT_SECTION) {
+			dest_sec = reloc->sym->sec;
+			dest_off = arch_dest_reloc_offset(reloc->addend);
+		} else if (reloc->sym->sec->idx) {
+			dest_sec = reloc->sym->sec;
+			dest_off = reloc->sym->sym.st_value +
+				   arch_dest_reloc_offset(reloc->addend);
+		} else {
+			/* non-func asm code jumping to another file */
+			continue;
+		}
+
+		insn->jump_dest = find_insn(file, dest_sec, dest_off);
+	}
+}
+
 int check(struct objtool_file *file)
 {
+	int ret;
+
 	if (!opts.stackval)
 		return 1;
 
-	return decode_instructions(file);
+	ret = decode_instructions(file);
+	if (ret)
+		return ret;
+
+	add_jump_destinations(file);
+
+	return 0;
 }