[PATCH 04/27] objtool: Fix dead end detection for sibling calls

Josh Poimboeuf <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.kernel.rust,gmane.linux.kbuild.devel
Message-ID <82b063dbeff61b78a4c42643ce5d4ebf8936c291.1787890035.git.jpoimboe@kernel.org>
The dead end detection for sibling calls has apparently always been
broken.  There are two issues: it checks jump_dest instead of call_dest,
and it only checks the first sibling call instead of all of them.  Fix
both issues.

No warnings were seen, this was only found by code inspection.

Signed-off-by: Josh Poimboeuf <[email protected]>
---
 tools/objtool/check.c | 37 +++++++++++++++++++------------------
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index a98d7589d8a48..01c50aa00b6dc 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -272,30 +272,31 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
 		return false;
 
 	/*
-	 * A function can have a sibling call instead of a return.  In that
-	 * case, the function's dead-end status depends on whether the target
-	 * of the sibling call returns.
+	 * A function can have sibling calls instead of a return.  It's only a
+	 * dead end if *all* the sibling call targets are dead ends.
 	 */
 	func_for_each_insn(file, func, insn) {
-		if (is_sibling_call(insn)) {
-			struct instruction *dest = insn->jump_dest;
+		struct symbol *dest;
 
-			if (!dest)
-				/* sibling call to another file */
-				return false;
+		if (!is_sibling_call(insn))
+			continue;
 
-			/* local sibling call */
-			if (recursion == 5) {
-				/*
-				 * Infinite recursion: two functions have
-				 * sibling calls to each other.  This is a very
-				 * rare case.  It means they aren't dead ends.
-				 */
-				return false;
-			}
+		dest = insn_call_dest(insn);
+		if (!dest)
+			/* call to another file */
+			return false;
 
-			return __dead_end_function(file, insn_func(dest), recursion+1);
+		if (recursion == 5) {
+			/*
+			 * Infinite recursion: two functions have sibling
+			 * calls to each other.  This is a very rare case.
+			 * It means they aren't dead ends.
+			 */
+			return false;
 		}
+
+		if (!__dead_end_function(file, dest, recursion+1))
+			return false;
 	}
 
 	return true;
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.