@@ -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,
@@ -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;
}