[lld] [lld] Merge equivalent symbols found during ICF (PR #134342)

James Y Knight via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 15 03:23:54 PDT 2025


================
@@ -535,14 +557,35 @@ template <class ELFT> void ICF<ELFT>::run() {
   auto print = [&ctx = ctx]() -> ELFSyncStream {
     return {ctx, ctx.arg.printIcfSections ? DiagLevel::Msg : DiagLevel::None};
   };
+
+  DenseMap<Symbol *, Symbol *> symbolMap;
   // Merge sections by the equivalence class.
+  // Merge symbols identified as equivalent during ICF
   forEachClassRange(0, sections.size(), [&](size_t begin, size_t end) {
     if (end - begin == 1)
       return;
     print() << "selected section " << sections[begin];
+    SmallVector<Symbol *> syms = getRelocTargetSyms<ELFT>(sections[begin]);
     for (size_t i = begin + 1; i < end; ++i) {
       print() << "  removing identical section " << sections[i];
       sections[begin]->replace(sections[i]);
+      SmallVector<Symbol *> replacedSyms =
+          getRelocTargetSyms<ELFT>(sections[i]);
+      assert(syms.size() == replacedSyms.size() &&
+             "Should have same number of syms!");
+      for (size_t i = 0; i < syms.size(); i++) {
+        if (syms[i] == replacedSyms[i] || !syms[i]->isGlobal() ||
+            !replacedSyms[i]->isGlobal())
+          continue;
+        auto [it, inserted] =
----------------
jyknight wrote:

I think this code doesn't resolve transitively to a _single_ canonical symbol. (My original proposed code also had this bug)

For example:

- functions f1, f2, which have relocs pointing, respectively, to symbols s1, s2 (which are equivalent), ICF will merge f2 into f1 and this will mark s2 as being replaced by s1.
- functions g2, g3 which have relocs pointing at symbols s2, s3, ICF will merge g3 into g2, and mark s3 as being replaced by s2.

But, nothing follows the chain s3 -> s2 -> s1, so, in the end, we have an output file which still has references to both s1 and s2, despite that we are supposed to replace s2 with s1. So I think this can still cause a miscompile.


https://github.com/llvm/llvm-project/pull/134342


More information about the llvm-commits mailing list