[RFC PATCH v2 10/20] objtool: arm64: Compute destinations for call and jump instructions

madvenka@linux.microsoft.com posted 20 patches 2 months, 4 weeks ago
[RFC PATCH v2 10/20] objtool: arm64: Compute destinations for call and jump instructions
Posted by madvenka@linux.microsoft.com 2 months, 4 weeks ago
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/fpv.c               | 47 ++++++++++++++++++++++++++++++-
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index 8a9ff030085d..f9df8b321659 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -33,6 +33,18 @@ struct decode {
 				s64 *imm, struct list_head *stack_ops);
 };
 
+/* --------------------- 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;
+}
+
 /* --------------------- miscellaneous functions --------------------------- */
 
 static void reg_check(unsigned int sp_check, unsigned int fp_check,
diff --git a/tools/objtool/fpv.c b/tools/objtool/fpv.c
index 76f0f2e611a8..92ad0d0aac8e 100644
--- a/tools/objtool/fpv.c
+++ b/tools/objtool/fpv.c
@@ -13,7 +13,52 @@
 #include <objtool/insn.h>
 #include <objtool/warn.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 fpv_decode(struct objtool_file *file)
 {
-	return decode_instructions(file);
+	int ret;
+
+	ret = decode_instructions(file);
+	if (ret)
+		return ret;
+
+	add_jump_destinations(file);
+
+	return 0;
 }
-- 
2.25.1