Fix a segfault that occurs when built with Clang.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAl/oU8URHG1pbmdvQGtl
 cm5lbC5vcmcACgkQEnMQ0APhK1iOgw//Rb7VwweTCbPXansvkw3/lCZdQ4EHhfw9
 kWwAd+fXyGgO4SL9Beu0LgH4IADmEmDBpG5tdX6F1fufRoJKOANc1yhKisWGfxhR
 WCx+ve+0gden6Ky2hPqog3hVOcZQnyrZSCHRSSvDqV9zasIDIqSJI9UNMVQ8lb6r
 fRCwbW6++8dwy0vQVN/yU78Gi/YTEPPyP5us3WATJuvyTQtD3P8PrQyJQWucULhB
 49Tup//M/NjZRC8p5Yyhyy7YXOngox+LEjw9S8Eztlu3f0YqGlMwYmKc6FOYyl3z
 R6zoO+vKbkakXZ2qwPBVTNINQOc/5HGKf5OPl2itollMtpQIlOCNwENULmjhisoK
 k/BOtBp699GjqvRMfWKEp3WC/xV3ujQa/RKA6bi7F54G2p5cZIV2qx+/nK+MNqEq
 pWg2yqvKQEWZbA4AAUGj3Ls1lsBgs1m1Uc9gZLVwM22gkwCut5xZczXHmANZGeZY
 AdkX/AAxM4/X+u1E7DbpCUmOeylT3ig8iDJxGr56Gr06kJEoyMocDdpk+T/KdRXL
 2paPZhMS3BJWLF1Z9W0a0fT36F9Q0FU9dvp3UXBv/iuslIHRfBw5PoNqUlDNGb6h
 rHHyAvlt210xsZrVTTcHbJzR+xzR0AkEd1C0/g2yUitp3yORC0BgsjYRmew20iEI
 aJ/vstOYgi4=
 =xfnP
 -----END PGP SIGNATURE-----

Merge tag 'objtool-urgent-2020-12-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull objtool fix from Ingo Molnar:
 "Fix a segfault that occurs when built with Clang"

* tag 'objtool-urgent-2020-12-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  objtool: Fix seg fault with Clang non-section symbols
This commit is contained in:
Linus Torvalds 2020-12-27 09:08:23 -08:00
commit cce622ab92
4 changed files with 42 additions and 26 deletions

View File

@ -467,13 +467,20 @@ static int create_static_call_sections(struct objtool_file *file)
/* populate reloc for 'addr' */
reloc = malloc(sizeof(*reloc));
if (!reloc) {
perror("malloc");
return -1;
}
memset(reloc, 0, sizeof(*reloc));
reloc->sym = insn->sec->sym;
reloc->addend = insn->offset;
insn_to_reloc_sym_addend(insn->sec, insn->offset, reloc);
if (!reloc->sym) {
WARN_FUNC("static call tramp: missing containing symbol",
insn->sec, insn->offset);
return -1;
}
reloc->type = R_X86_64_PC32;
reloc->offset = idx * sizeof(struct static_call_site);
reloc->sec = reloc_sec;

View File

@ -262,6 +262,32 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
return find_reloc_by_dest_range(elf, sec, offset, 1);
}
void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset,
struct reloc *reloc)
{
if (sec->sym) {
reloc->sym = sec->sym;
reloc->addend = offset;
return;
}
/*
* The Clang assembler strips section symbols, so we have to reference
* the function symbol instead:
*/
reloc->sym = find_symbol_containing(sec, offset);
if (!reloc->sym) {
/*
* Hack alert. This happens when we need to reference the NOP
* pad insn immediately after the function.
*/
reloc->sym = find_symbol_containing(sec, offset - 1);
}
if (reloc->sym)
reloc->addend = offset - reloc->sym->offset;
}
static int read_sections(struct elf *elf)
{
Elf_Scn *s = NULL;

View File

@ -140,6 +140,8 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
unsigned long offset, unsigned int len);
struct symbol *find_func_containing(struct section *sec, unsigned long offset);
void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset,
struct reloc *reloc);
int elf_rebuild_reloc_section(struct elf *elf, struct section *sec);
#define for_each_sec(file, sec) \

View File

@ -105,30 +105,11 @@ static int create_orc_entry(struct elf *elf, struct section *u_sec, struct secti
}
memset(reloc, 0, sizeof(*reloc));
if (insn_sec->sym) {
reloc->sym = insn_sec->sym;
reloc->addend = insn_off;
} else {
/*
* The Clang assembler doesn't produce section symbols, so we
* have to reference the function symbol instead:
*/
reloc->sym = find_symbol_containing(insn_sec, insn_off);
if (!reloc->sym) {
/*
* Hack alert. This happens when we need to reference
* the NOP pad insn immediately after the function.
*/
reloc->sym = find_symbol_containing(insn_sec,
insn_off - 1);
}
if (!reloc->sym) {
WARN("missing symbol for insn at offset 0x%lx\n",
insn_off);
return -1;
}
reloc->addend = insn_off - reloc->sym->offset;
insn_to_reloc_sym_addend(insn_sec, insn_off, reloc);
if (!reloc->sym) {
WARN("missing symbol for insn at offset 0x%lx",
insn_off);
return -1;
}
reloc->type = R_X86_64_PC32;