[PATCH] D95985: [ELF] Resolve defined symbols before undefined symbols

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 3 15:50:12 PST 2021


MaskRay created this revision.
Herald added subscribers: arichardson, emaste.
MaskRay requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

If both `a.a(a.o)` and `a.a(b.o)` define foo (in COMDAT group `foo`) and `__profd_foo` (in COMDAT group `__profd_foo`).
LLD may select `foo` from `a.a(a.o)` as the prevailing definition while `__profd_foo` from `b.a(b.o)` as the prevailing definition.

  parse ArchiveFile a.a
    entry fetches a.a(a.o)
    parse ObjectFile a.o
      define entry
      define foo
      reference b
      b fetches a.a(b.o)
      parse ObjectFile b.o
        define prevailing __profd_foo
      define non-prevailing __profd_foo

This can happen with interconnected weak symbols not-in COMDAT groups as well.

Assuming a set of interconnected symbols are defined all or none, in several lazy objects.
Arguably making them resolve to the same lazy object is preferable than making them come from different lazy objects.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D95985

Files:
  lld/ELF/InputFiles.cpp


Index: lld/ELF/InputFiles.cpp
===================================================================
--- lld/ELF/InputFiles.cpp
+++ lld/ELF/InputFiles.cpp
@@ -1134,6 +1134,7 @@
   }
 
   // Symbol resolution of non-local symbols.
+  SmallVector<size_t, 8> unds;
   for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) {
     const Elf_Sym &eSym = eSyms[i];
     uint8_t binding = eSym.getBinding();
@@ -1150,8 +1151,7 @@
 
     // Handle global undefined symbols.
     if (eSym.st_shndx == SHN_UNDEF) {
-      this->symbols[i]->resolve(Undefined{this, name, binding, stOther, type});
-      this->symbols[i]->referenced = true;
+      unds.push_back(i);
       continue;
     }
 
@@ -1198,6 +1198,15 @@
 
     fatal(toString(this) + ": unexpected binding: " + Twine((int)binding));
   }
+
+  for (size_t i : unds) {
+    const Elf_Sym &eSym = eSyms[i];
+    uint8_t binding = eSym.getBinding();
+    StringRefZ name = this->stringTable.data() + eSym.st_name;
+    this->symbols[i]->resolve(Undefined{this, name, eSym.getBinding(),
+                                        eSym.st_other, eSym.getType()});
+    this->symbols[i]->referenced = true;
+  }
 }
 
 ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&file)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D95985.321250.patch
Type: text/x-patch
Size: 1224 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210203/93bca126/attachment.bin>


More information about the llvm-commits mailing list