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 warnings like:

  vmlinux.o: warning: objtool: no correlation: __irf_start
  vmlinux.o: warning: objtool: no correlation: __irf_end

The problem is that Clang LTO is stripping the initramfs_data.o FILE
symbol, causing those two symbols to be orphaned and not noticed by
klp-diff's correlation logic.  Add a loop to correlate any symbols found
before the first FILE symbol.

Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing 
object files")
Reported-by: Song Liu <[email protected]>
Signed-off-by: Josh Poimboeuf <[email protected]>
---
 tools/objtool/klp-diff.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 1e649a3eb4cd..9f1f4011eb9c 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);
-- 
2.52.0


Reply via email to