[PATCH] objtool: Fix GCC 8 cold function processing without -freorder-functions

From: Allan Xavier
Date: Tue Jun 26 2018 - 12:22:04 EST


As of commit 13810435b9a7 ("objtool: Support GCC 8's cold subfunctions")
objtool can get stuck in an infinite loop when processing cold functions
compiled without -freorder-functions. Using v4.17.2 and "gcc version
8.1.1 20180502 (Red Hat 8.1.1-1) (GCC)" from Fedora, this can be
reproduced trivially with make EXTRA_CFLAGS='-fno-reorder-functions'.

When -freorder-functions is used (enabled by default for -O2 in GCC 8)
cold functions are emitted in the .text.unlikely section.

0000000000000230 g F .text 000000000000002c nmi_panic
00000000000002df l F .text.unlikely 000000000000000c nmi_panic.cold.7

Without -freorder-functions, cold functions are emitted in the .text
section within the range of their parent function.

0000000000000500 g F .text 0000000000000034 nmi_panic
0000000000000528 l F .text 000000000000000c nmi_panic.cold.7

When objtool processes the second case it associates all of the
instructions in the parent function range 0x500-0x534 with nmi_panic
since that symbol is processed first. No instructions are associated
with nmi_panic.cold.7.

Later on, 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.

This doesn't happen with -freorder-functions in the first example as the
symbols don't overlap. So when 0x25c in .text is reached objtool will
jump to 0x2df in .text.unlikely where the instructions are correctly
associated with nmi_panic.cold.7.

Fix this issue by modifying decode_instructions to check whether an
instruction is associated with the parent function of the cold function
currently being processed. If so, reference the cold function rather
than the parent.

Signed-off-by: Allan Xavier <allan.x.xavier@xxxxxxxxxx>
---
tools/objtool/check.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 3a31b238f8856..2a5eea534ab3e 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -314,7 +314,7 @@ static int decode_instructions(struct objtool_file *file)
}

func_for_each_insn(file, func, insn)
- if (!insn->func)
+ if (!insn->func || insn->func == func->pfunc)
insn->func = func;
}
}
--
2.14.1