Skip to content

Commit

Permalink
objtool: Support GCC 8 '-fnoreorder-functions'
Browse files Browse the repository at this point in the history
Since the following commit:

  cd77849 ("objtool: Fix GCC 8 cold subfunction detection for aliased functions")

... if the kernel is built with EXTRA_CFLAGS='-fno-reorder-functions',
objtool can get stuck in an infinite loop.

That flag causes the new GCC 8 cold subfunctions to be placed in .text
instead of .text.unlikely.  But it also has an unfortunate quirk: in the
symbol table, the subfunction (e.g., nmi_panic.cold.7) is nested inside
the parent (nmi_panic).

That function overlap confuses objtool, and causes it to get into an
infinite loop in next_insn_same_func().  Here's Allan's description of
the loop:

  "Objtool iterates through the instructions in nmi_panic using
  next_insn_same_func. Once it reaches the end of nmi_panic at 0x534 it
  jumps to 0x528 as that's the start of nmi_panic.cold.7. However, since
  the instructions starting at 0x528 are still associated with nmi_panic
  objtool will get stuck in a loop, continually jumping back to 0x528
  after reaching 0x534."

Fix it by shortening the length of the parent function so that the
functions no longer overlap.

Reported-and-analyzed-by: Allan Xavier <[email protected]>
Signed-off-by: Josh Poimboeuf <[email protected]>
Cc: Allan Xavier <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Brian Gerst <[email protected]>
Cc: Denys Vlasenko <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Link: http://lkml.kernel.org/r/9e704c52bee651129b036be14feda317ae5606ae.1530136978.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
jpoimboe authored and Ingo Molnar committed Jul 2, 2018
1 parent 021c917 commit 08b393d
Showing 1 changed file with 28 additions and 13 deletions.
41 changes: 28 additions & 13 deletions tools/objtool/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,19 +302,34 @@ static int read_symbols(struct elf *elf)
continue;
sym->pfunc = sym->cfunc = sym;
coldstr = strstr(sym->name, ".cold.");
if (coldstr) {
coldstr[0] = '\0';
pfunc = find_symbol_by_name(elf, sym->name);
coldstr[0] = '.';

if (!pfunc) {
WARN("%s(): can't find parent function",
sym->name);
goto err;
}

sym->pfunc = pfunc;
pfunc->cfunc = sym;
if (!coldstr)
continue;

coldstr[0] = '\0';
pfunc = find_symbol_by_name(elf, sym->name);
coldstr[0] = '.';

if (!pfunc) {
WARN("%s(): can't find parent function",
sym->name);
goto err;
}

sym->pfunc = pfunc;
pfunc->cfunc = sym;

/*
* Unfortunately, -fnoreorder-functions puts the child
* inside the parent. Remove the overlap so we can
* have sane assumptions.
*
* Note that pfunc->len now no longer matches
* pfunc->sym.st_size.
*/
if (sym->sec == pfunc->sec &&
sym->offset >= pfunc->offset &&
sym->offset + sym->len == pfunc->offset + pfunc->len) {
pfunc->len -= sym->len;
}
}
}
Expand Down

0 comments on commit 08b393d

Please sign in to comment.