On Fri, Jan 30, 2026 at 12:39:12PM -0800, Song Liu wrote:
> When compiling with CONFIG_LTO_CLANG_THIN, vmlinux.o has
> __irf_[start|end] before the first FILE entry:
>
> $ readelf -sW vmlinux.o
> Symbol table '.symtab' contains 597706 entries:
> Num: Value Size Type Bind Vis Ndx Name
> 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
> 1: 0000000000000000 0 NOTYPE LOCAL DEFAULT 18 __irf_start
> 2: 0000000000000200 0 NOTYPE LOCAL DEFAULT 18 __irf_end
> 3: 0000000000000000 0 SECTION LOCAL DEFAULT 17 .text
> 4: 0000000000000000 0 SECTION LOCAL DEFAULT 18 .init.ramfs
>
> This causes klp-build throwing warnings like:
>
> vmlinux.o: warning: objtool: no correlation: __irf_start
> vmlinux.o: warning: objtool: no correlation: __irf_end
>
> Fix this by not warn for no correlation before seeing the first FILE
> entry.
>
> Signed-off-by: Song Liu <[email protected]>
> ---
> tools/objtool/klp-diff.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
> index d94531e3f64e..370e5c79ae66 100644
> --- a/tools/objtool/klp-diff.c
> +++ b/tools/objtool/klp-diff.c
> @@ -363,6 +363,7 @@ static int correlate_symbols(struct elfs *e)
> {
> struct symbol *file1_sym, *file2_sym;
> struct symbol *sym1, *sym2;
> + bool found_first_file = false;
>
> /* Correlate locals */
> for (file1_sym = first_file_symbol(e->orig),
> @@ -432,9 +433,12 @@ static int correlate_symbols(struct elfs *e)
> }
>
> for_each_sym(e->orig, sym1) {
> + if (!found_first_file && is_file_sym(sym1))
> + found_first_file = true;
> if (sym1->twin || dont_correlate(sym1))
> continue;
> - WARN("no correlation: %s", sym1->name);
> + if (found_first_file)
> + WARN("no correlation: %s", sym1->name);
It's a bit worrisome that Clang is stripping FILE entries and moving
symbols, but I looked at the symbol table for a thin LTO vmlinux.o and
it only seems to have stripped this one FILE symbol for initramfs_data.o
and made its symbols orphans. Presumably because this file only has
data and no code.
I actually think the warning is valid. We should try to correlate those
pre-FILE symbols, otherwise things like klp_reloc_needed() might not
work as intended.
Does the below patch work instead?
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index d94531e3f64e..ea292ebe217f 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -364,11 +364,40 @@ static int correlate_symbols(struct elfs *e)
struct symbol *file1_sym, *file2_sym;
struct symbol *sym1, *sym2;
- /* Correlate locals */
- for (file1_sym = first_file_symbol(e->orig),
- file2_sym = first_file_symbol(e->patched); ;
- file1_sym = next_file_symbol(e->orig, file1_sym),
- file2_sym = next_file_symbol(e->patched, file2_sym)) {
+ file1_sym = first_file_symbol(e->orig);
+ file2_sym = first_file_symbol(e->patched);
+
+ /*
+ * Correlate any locals before the first FILE symbol. This has been
+ * seen when LTO inexplicably strips the initramfs_data.o FILE symbol
+ * due to the file only containing data and no code.
+ */
+ for_each_sym(e->orig, sym1) {
+ if (sym1 == file1_sym || !is_local_sym(sym1))
+ break;
+
+ if (dont_correlate(sym1))
+ continue;
+
+ for_each_sym(e->patched, sym2) {
+ if (sym2 == file2_sym || !is_local_sym(sym2))
+ break;
+
+ if (sym2->twin || dont_correlate(sym2))
+ continue;
+
+ if (strcmp(sym1->demangled_name, sym2->demangled_name))
+ continue;
+
+ sym1->twin = sym2;
+ sym2->twin = sym1;
+ break;
+ }
+ }
+
+ /* Correlate locals after the first FILE symbol */
+ for (; ; file1_sym = next_file_symbol(e->orig, file1_sym),
+ file2_sym = next_file_symbol(e->patched, file2_sym)) {
if (!file1_sym && file2_sym) {
ERROR("FILE symbol mismatch: NULL != %s",
file2_sym->name);