[tip:core/urgent] objtool: Fix "noreturn" detection for recursive sibling calls

From: tip-bot for Josh Poimboeuf
Date: Mon May 14 2018 - 08:38:31 EST


Commit-ID: 0afd0d9e0e7879d666c1df2fa1bea4d8716909fe
Gitweb: https://git.kernel.org/tip/0afd0d9e0e7879d666c1df2fa1bea4d8716909fe
Author: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
AuthorDate: Wed, 9 May 2018 22:39:14 -0500
Committer: Ingo Molnar <mingo@xxxxxxxxxx>
CommitDate: Mon, 14 May 2018 10:20:53 +0200

objtool: Fix "noreturn" detection for recursive sibling calls

Objtool has some crude logic for detecting static "noreturn" functions
(aka "dead ends"). This is necessary for being able to correctly follow
GCC code flow when such functions are called.

It's remotely possible for two functions to call each other via sibling
calls. If they don't have RET instructions, objtool's noreturn
detection logic goes into a recursive loop:

drivers/char/ipmi/ipmi_ssif.o: warning: objtool: return_hosed_msg()+0x0: infinite recursion (objtool bug!)
drivers/char/ipmi/ipmi_ssif.o: warning: objtool: deliver_recv_msg()+0x0: infinite recursion (objtool bug!)

Instead of reporting an error in this case, consider the functions to be
non-dead-ends.

Reported-and-tested-by: Randy Dunlap <rdunlap@xxxxxxxxxxxxx>
Signed-off-by: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
Acked-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Cc: Arnd Bergmann <arnd@xxxxxxxx>
Cc: David Laight <David.Laight@xxxxxxxxxx>
Cc: Greg KH <gregkh@xxxxxxxxxxxxxxxxxxx>
Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Cc: damian <damian.tometzki@xxxxxxxxxx>
Link: http://lkml.kernel.org/r/7cc156408c5781a1f62085d352ced1fe39fe2f91.1525923412.git.jpoimboe@xxxxxxxxxx
Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx>
---
tools/objtool/check.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 5409f6f6c48d..264522d4e4af 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -190,9 +190,13 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
continue;

if (recursion == 5) {
- WARN_FUNC("infinite recursion (objtool bug!)",
- dest->sec, dest->offset);
- return -1;
+ /*
+ * Infinite recursion: two functions
+ * have sibling calls to each other.
+ * This is a very rare case. It means
+ * they aren't dead ends.
+ */
+ return 0;
}

return __dead_end_function(file, dest_func,