Skip to content

Commit cce622a

Browse files
committed
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
2 parents 6be5f58 + 44f6a7c commit cce622a

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)