Skip to content

Commit

Permalink
objtool: Teach get_alt_entry() about more relocation types
Browse files Browse the repository at this point in the history
Occasionally objtool encounters symbol (as opposed to section)
relocations in .altinstructions. Typically they are the alternatives
written by elf_add_alternative() as encountered on a noinstr
validation run on vmlinux after having already ran objtool on the
individual .o files.

Basically this is the counterpart of commit 44f6a7c ("objtool:
Fix seg fault with Clang non-section symbols"), because when these new
assemblers (binutils now also does this) strip the section symbols,
elf_add_reloc_to_insn() is forced to emit symbol based relocations.

As such, teach get_alt_entry() about different relocation types.

Fixes: 9bc0bb5 ("objtool/x86: Rewrite retpoline thunk calls")
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Reported-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Link: https://lore.kernel.org/r/YVWUvknIEVNkPvnP@hirez.programming.kicks-ass.net
  • Loading branch information
Peter Zijlstra committed Oct 1, 2021
1 parent e4e737b commit 24ff652
Showing 1 changed file with 25 additions and 7 deletions.
32 changes: 25 additions & 7 deletions tools/objtool/special.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ void __weak arch_handle_alternative(unsigned short feature, struct special_alt *
{
}

static bool reloc2sec_off(struct reloc *reloc, struct section **sec, unsigned long *off)
{
switch (reloc->sym->type) {
case STT_FUNC:
*sec = reloc->sym->sec;
*off = reloc->sym->offset + reloc->addend;
return true;

case STT_SECTION:
*sec = reloc->sym->sec;
*off = reloc->addend;
return true;

default:
return false;
}
}

static int get_alt_entry(struct elf *elf, struct special_entry *entry,
struct section *sec, int idx,
struct special_alt *alt)
Expand Down Expand Up @@ -91,15 +109,12 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry,
WARN_FUNC("can't find orig reloc", sec, offset + entry->orig);
return -1;
}
if (orig_reloc->sym->type != STT_SECTION) {
WARN_FUNC("don't know how to handle non-section reloc symbol %s",
if (!reloc2sec_off(orig_reloc, &alt->orig_sec, &alt->orig_off)) {
WARN_FUNC("don't know how to handle reloc symbol type: %s",
sec, offset + entry->orig, orig_reloc->sym->name);
return -1;
}

alt->orig_sec = orig_reloc->sym->sec;
alt->orig_off = orig_reloc->addend;

if (!entry->group || alt->new_len) {
new_reloc = find_reloc_by_dest(elf, sec, offset + entry->new);
if (!new_reloc) {
Expand All @@ -116,8 +131,11 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry,
if (arch_is_retpoline(new_reloc->sym))
return 1;

alt->new_sec = new_reloc->sym->sec;
alt->new_off = (unsigned int)new_reloc->addend;
if (!reloc2sec_off(new_reloc, &alt->new_sec, &alt->new_off)) {
WARN_FUNC("don't know how to handle reloc symbol type: %s",
sec, offset + entry->new, new_reloc->sym->name);
return -1;
}

/* _ASM_EXTABLE_EX hack */
if (alt->new_off >= 0x7ffffff0)
Expand Down

0 comments on commit 24ff652

Please sign in to comment.