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);

Reply via email to