summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorRong Xu <xur@google.com>2024-11-02 10:51:09 -0700
committerMasahiro Yamada <masahiroy@kernel.org>2024-11-06 22:41:10 +0900
commit18e885099f1c52755f054202525cb60d3edcda44 (patch)
tree1692f0625004ba80e3ae6dd9efbc406b7215daff /tools
parent315ad8780a129e82e2c5c65ee6e970d91a577acb (diff)
downloadlwn-18e885099f1c52755f054202525cb60d3edcda44.tar.gz
lwn-18e885099f1c52755f054202525cb60d3edcda44.zip
objtool: Fix unreachable instruction warnings for weak functions
In the presence of both weak and strong function definitions, the linker drops the weak symbol in favor of a strong symbol, but leaves the code in place. Code in ignore_unreachable_insn() has some heuristics to suppress the warning, but it does not work when -ffunction-sections is enabled. Suppose function foo has both strong and weak definitions. Case 1: The strong definition has an annotated section name, like .init.text. Only the weak definition will be placed into .text.foo. But since the section has no symbols, there will be no "hole" in the section. Case 2: Both sections are without an annotated section name. Both will be placed into .text.foo section, but there will be only one symbol (the strong one). If the weak code is before the strong code, there is no "hole" as it fails to find the right-most symbol before the offset. The fix is to use the first node to compute the hole if hole.sym is empty. If there is no symbol in the section, the first node will be NULL, in which case, -1 is returned to skip the whole section. Co-developed-by: Han Shen <shenhan@google.com> Signed-off-by: Han Shen <shenhan@google.com> Signed-off-by: Rong Xu <xur@google.com> Suggested-by: Sriraman Tallam <tmsriram@google.com> Suggested-by: Krzysztof Pszeniczny <kpszeniczny@google.com> Tested-by: Yonghong Song <yonghong.song@linux.dev> Tested-by: Yabin Cui <yabinc@google.com> Tested-by: Nathan Chancellor <nathan@kernel.org> Reviewed-by: Kees Cook <kees@kernel.org> Acked-by: Josh Poimboeuf <jpoimboe@kernel.org> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/objtool/elf.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 3d27983dc908..6f64d611faea 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -224,12 +224,17 @@ int find_symbol_hole_containing(const struct section *sec, unsigned long offset)
if (n)
return 0; /* not a hole */
- /* didn't find a symbol for which @offset is after it */
- if (!hole.sym)
- return 0; /* not a hole */
+ /*
+ * @offset >= sym->offset + sym->len, find symbol after it.
+ * When hole.sym is empty, use the first node to compute the hole.
+ * If there is no symbol in the section, the first node will be NULL,
+ * in which case, -1 is returned to skip the whole section.
+ */
+ if (hole.sym)
+ n = rb_next(&hole.sym->node);
+ else
+ n = rb_first_cached(&sec->symbol_tree);
- /* @offset >= sym->offset + sym->len, find symbol after it */
- n = rb_next(&hole.sym->node);
if (!n)
return -1; /* until end of address space */