objtool: Cache instruction relocs
authorPeter Zijlstra <peterz@infradead.org>
Fri, 26 Mar 2021 15:12:13 +0000 (16:12 +0100)
committerIngo Molnar <mingo@kernel.org>
Fri, 2 Apr 2021 10:46:15 +0000 (12:46 +0200)
Track the reloc of instructions in the new instruction->reloc field
to avoid having to look them up again later.

( Technically x86 instructions can have two relocations, but not jumps
  and calls, for which we're using this. )

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Link: https://lkml.kernel.org/r/20210326151300.195441549@infradead.org
tools/objtool/check.c
tools/objtool/include/objtool/check.h

index 77074db1fcda834e4aebb96b0827d47165307c30..1f4154f9b04b5dcc04b7f6b988a82a3a27438d8c 100644 (file)
@@ -797,6 +797,25 @@ __weak bool arch_is_retpoline(struct symbol *sym)
        return false;
 }
 
+#define NEGATIVE_RELOC ((void *)-1L)
+
+static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn)
+{
+       if (insn->reloc == NEGATIVE_RELOC)
+               return NULL;
+
+       if (!insn->reloc) {
+               insn->reloc = find_reloc_by_dest_range(file->elf, insn->sec,
+                                                      insn->offset, insn->len);
+               if (!insn->reloc) {
+                       insn->reloc = NEGATIVE_RELOC;
+                       return NULL;
+               }
+       }
+
+       return insn->reloc;
+}
+
 /*
  * Find the destination instructions for all jumps.
  */
@@ -811,8 +830,7 @@ static int add_jump_destinations(struct objtool_file *file)
                if (!is_static_jump(insn))
                        continue;
 
-               reloc = find_reloc_by_dest_range(file->elf, insn->sec,
-                                                insn->offset, insn->len);
+               reloc = insn_reloc(file, insn);
                if (!reloc) {
                        dest_sec = insn->sec;
                        dest_off = arch_jump_destination(insn);
@@ -944,8 +962,7 @@ static int add_call_destinations(struct objtool_file *file)
                if (insn->type != INSN_CALL)
                        continue;
 
-               reloc = find_reloc_by_dest_range(file->elf, insn->sec,
-                                              insn->offset, insn->len);
+               reloc = insn_reloc(file, insn);
                if (!reloc) {
                        dest_off = arch_jump_destination(insn);
                        insn->call_dest = find_call_destination(insn->sec, dest_off);
@@ -1144,8 +1161,7 @@ static int handle_group_alt(struct objtool_file *file,
                 * alternatives code can adjust the relative offsets
                 * accordingly.
                 */
-               alt_reloc = find_reloc_by_dest_range(file->elf, insn->sec,
-                                                  insn->offset, insn->len);
+               alt_reloc = insn_reloc(file, insn);
                if (alt_reloc &&
                    !arch_support_alt_relocation(special_alt, insn, alt_reloc)) {
 
index e5528ce3961a8d67ef01f9b19228b14190a41b34..56d50bc50c10c54354668714874382007127705e 100644 (file)
@@ -56,6 +56,7 @@ struct instruction {
        struct instruction *jump_dest;
        struct instruction *first_jump_src;
        struct reloc *jump_table;
+       struct reloc *reloc;
        struct list_head alts;
        struct symbol *func;
        struct list_head stack_ops;