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

From: madvenka
Date: Thu Feb 02 2023 - 02:43:12 EST


From: "Madhavan T. Venkataraman" <madvenka@xxxxxxxxxxxxxxxxxxx>

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

Signed-off-by: Madhavan T. Venkataraman <madvenka@xxxxxxxxxxxxxxxxxxx>
---
tools/objtool/arch/arm64/decode.c | 12 ++++++++
tools/objtool/dcheck.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 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;
}
--
2.25.1