Skip to content

Commit 44f6a7c

Browse files
jpoimboePeter Zijlstra
authored andcommitted
objtool: Fix seg fault with Clang non-section symbols
The Clang assembler likes to strip section symbols, which means objtool can't reference some text code by its section. This confuses objtool greatly, causing it to seg fault. The fix is similar to what was done before, for ORC reloc generation: e81e072 ("objtool: Support Clang non-section symbols in ORC generation") Factor out that code into a common helper and use it for static call reloc generation as well. Reported-by: Arnd Bergmann <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Nick Desaulniers <[email protected]> Reviewed-by: Miroslav Benes <[email protected]> Link: ClangBuiltLinux#1207 Link: https://lkml.kernel.org/r/ba6b6c0f0dd5acbba66e403955a967d9fdd1726a.1607983452.git.jpoimboe@redhat.com
1 parent 2c85ebc commit 44f6a7c

File tree

4 files changed

+42
-26
lines changed

4 files changed

+42
-26
lines changed

tools/objtool/check.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,13 +467,20 @@ static int create_static_call_sections(struct objtool_file *file)
467467

468468
/* populate reloc for 'addr' */
469469
reloc = malloc(sizeof(*reloc));
470+
470471
if (!reloc) {
471472
perror("malloc");
472473
return -1;
473474
}
474475
memset(reloc, 0, sizeof(*reloc));
475-
reloc->sym = insn->sec->sym;
476-
reloc->addend = insn->offset;
476+
477+
insn_to_reloc_sym_addend(insn->sec, insn->offset, reloc);
478+
if (!reloc->sym) {
479+
WARN_FUNC("static call tramp: missing containing symbol",
480+
insn->sec, insn->offset);
481+
return -1;
482+
}
483+
477484
reloc->type = R_X86_64_PC32;
478485
reloc->offset = idx * sizeof(struct static_call_site);
479486
reloc->sec = reloc_sec;

tools/objtool/elf.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,32 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
262262
return find_reloc_by_dest_range(elf, sec, offset, 1);
263263
}
264264

265+
void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset,
266+
struct reloc *reloc)
267+
{
268+
if (sec->sym) {
269+
reloc->sym = sec->sym;
270+
reloc->addend = offset;
271+
return;
272+
}
273+
274+
/*
275+
* The Clang assembler strips section symbols, so we have to reference
276+
* the function symbol instead:
277+
*/
278+
reloc->sym = find_symbol_containing(sec, offset);
279+
if (!reloc->sym) {
280+
/*
281+
* Hack alert. This happens when we need to reference the NOP
282+
* pad insn immediately after the function.
283+
*/
284+
reloc->sym = find_symbol_containing(sec, offset - 1);
285+
}
286+
287+
if (reloc->sym)
288+
reloc->addend = offset - reloc->sym->offset;
289+
}
290+
265291
static int read_sections(struct elf *elf)
266292
{
267293
Elf_Scn *s = NULL;

tools/objtool/elf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
140140
struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
141141
unsigned long offset, unsigned int len);
142142
struct symbol *find_func_containing(struct section *sec, unsigned long offset);
143+
void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset,
144+
struct reloc *reloc);
143145
int elf_rebuild_reloc_section(struct elf *elf, struct section *sec);
144146

145147
#define for_each_sec(file, sec) \

tools/objtool/orc_gen.c

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -105,30 +105,11 @@ static int create_orc_entry(struct elf *elf, struct section *u_sec, struct secti
105105
}
106106
memset(reloc, 0, sizeof(*reloc));
107107

108-
if (insn_sec->sym) {
109-
reloc->sym = insn_sec->sym;
110-
reloc->addend = insn_off;
111-
} else {
112-
/*
113-
* The Clang assembler doesn't produce section symbols, so we
114-
* have to reference the function symbol instead:
115-
*/
116-
reloc->sym = find_symbol_containing(insn_sec, insn_off);
117-
if (!reloc->sym) {
118-
/*
119-
* Hack alert. This happens when we need to reference
120-
* the NOP pad insn immediately after the function.
121-
*/
122-
reloc->sym = find_symbol_containing(insn_sec,
123-
insn_off - 1);
124-
}
125-
if (!reloc->sym) {
126-
WARN("missing symbol for insn at offset 0x%lx\n",
127-
insn_off);
128-
return -1;
129-
}
130-
131-
reloc->addend = insn_off - reloc->sym->offset;
108+
insn_to_reloc_sym_addend(insn_sec, insn_off, reloc);
109+
if (!reloc->sym) {
110+
WARN("missing symbol for insn at offset 0x%lx",
111+
insn_off);
112+
return -1;
132113
}
133114

134115
reloc->type = R_X86_64_PC32;

0 commit comments

Comments
 (0)