Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 08b393d0 authored by Josh Poimboeuf's avatar Josh Poimboeuf Committed by Ingo Molnar
Browse files

objtool: Support GCC 8 '-fnoreorder-functions'



Since the following commit:

  cd77849a ("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: default avatarAllan Xavier <allan.x.xavier@oracle.com>
Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Cc: Allan Xavier <allan.x.xavier@oracle.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/9e704c52bee651129b036be14feda317ae5606ae.1530136978.git.jpoimboe@redhat.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 021c9179
Loading
Loading
Loading
Loading
+28 −13
Original line number Diff line number Diff line
@@ -302,7 +302,9 @@ static int read_symbols(struct elf *elf)
				continue;
			sym->pfunc = sym->cfunc = sym;
			coldstr = strstr(sym->name, ".cold.");
			if (coldstr) {
			if (!coldstr)
				continue;

			coldstr[0] = '\0';
			pfunc = find_symbol_by_name(elf, sym->name);
			coldstr[0] = '.';
@@ -315,6 +317,19 @@ static int read_symbols(struct elf *elf)

			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;
			}
		}
	}