Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

objtool: Add abstraction for destination offsets

The jump and call destination relocation offsets are x86-specific.
Abstract them by calling arch-specific implementations.

[ jthierry: Remove superfluous comment; replace other addend offsets
with arch_dest_rela_offset() ]

Signed-off-by: Raphael Gault <raphael.gault@arm.com>
Signed-off-by: Julien Thierry <jthierry@redhat.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Raphael Gault and committed by
Ingo Molnar
bfb08f22 aff5e169

+27 -8
+6
tools/objtool/arch.h
··· 66 66 struct op_src src; 67 67 }; 68 68 69 + struct instruction; 70 + 69 71 void arch_initial_func_cfi_state(struct cfi_state *state); 70 72 71 73 int arch_decode_instruction(struct elf *elf, struct section *sec, ··· 76 74 unsigned long *immediate, struct stack_op *op); 77 75 78 76 bool arch_callee_saved_reg(unsigned char reg); 77 + 78 + unsigned long arch_jump_destination(struct instruction *insn); 79 + 80 + unsigned long arch_dest_rela_offset(int addend); 79 81 80 82 #endif /* _ARCH_H */
+11
tools/objtool/arch/x86/decode.c
··· 11 11 #include "../../../arch/x86/lib/inat.c" 12 12 #include "../../../arch/x86/lib/insn.c" 13 13 14 + #include "../../check.h" 14 15 #include "../../elf.h" 15 16 #include "../../arch.h" 16 17 #include "../../warn.h" ··· 65 64 default: 66 65 return false; 67 66 } 67 + } 68 + 69 + unsigned long arch_dest_rela_offset(int addend) 70 + { 71 + return addend + 4; 72 + } 73 + 74 + unsigned long arch_jump_destination(struct instruction *insn) 75 + { 76 + return insn->offset + insn->len + insn->immediate; 68 77 } 69 78 70 79 int arch_decode_instruction(struct elf *elf, struct section *sec,
+10 -8
tools/objtool/check.c
··· 574 574 insn->offset, insn->len); 575 575 if (!rela) { 576 576 dest_sec = insn->sec; 577 - dest_off = insn->offset + insn->len + insn->immediate; 577 + dest_off = arch_jump_destination(insn); 578 578 } else if (rela->sym->type == STT_SECTION) { 579 579 dest_sec = rela->sym->sec; 580 - dest_off = rela->addend + 4; 580 + dest_off = arch_dest_rela_offset(rela->addend); 581 581 } else if (rela->sym->sec->idx) { 582 582 dest_sec = rela->sym->sec; 583 - dest_off = rela->sym->sym.st_value + rela->addend + 4; 583 + dest_off = rela->sym->sym.st_value + 584 + arch_dest_rela_offset(rela->addend); 584 585 } else if (strstr(rela->sym->name, "_indirect_thunk_")) { 585 586 /* 586 587 * Retpoline jumps are really dynamic jumps in ··· 671 670 rela = find_rela_by_dest_range(file->elf, insn->sec, 672 671 insn->offset, insn->len); 673 672 if (!rela) { 674 - dest_off = insn->offset + insn->len + insn->immediate; 673 + dest_off = arch_jump_destination(insn); 675 674 insn->call_dest = find_func_by_offset(insn->sec, dest_off); 676 675 if (!insn->call_dest) 677 676 insn->call_dest = find_symbol_by_offset(insn->sec, dest_off); ··· 694 693 } 695 694 696 695 } else if (rela->sym->type == STT_SECTION) { 696 + dest_off = arch_dest_rela_offset(rela->addend); 697 697 insn->call_dest = find_func_by_offset(rela->sym->sec, 698 - rela->addend+4); 698 + dest_off); 699 699 if (!insn->call_dest) { 700 - WARN_FUNC("can't find call dest symbol at %s+0x%x", 700 + WARN_FUNC("can't find call dest symbol at %s+0x%lx", 701 701 insn->sec, insn->offset, 702 702 rela->sym->sec->name, 703 - rela->addend + 4); 703 + dest_off); 704 704 return -1; 705 705 } 706 706 } else ··· 812 810 if (!insn->immediate) 813 811 continue; 814 812 815 - dest_off = insn->offset + insn->len + insn->immediate; 813 + dest_off = arch_jump_destination(insn); 816 814 if (dest_off == special_alt->new_off + special_alt->new_len) { 817 815 if (!fake_jump) { 818 816 WARN("%s: alternative jump to end of section",