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

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 10 10:35:13 PST 2021


MaskRay updated this revision to Diff 322742.
MaskRay added a comment.

Increase inline element number for unds
Improve comment


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D95985/new/

https://reviews.llvm.org/D95985

Files:
  lld/ELF/InputFiles.cpp
  lld/test/ELF/interconnected-lazy.s


Index: lld/test/ELF/interconnected-lazy.s
===================================================================
--- /dev/null
+++ lld/test/ELF/interconnected-lazy.s
@@ -0,0 +1,42 @@
+# REQUIRES: x86
+
+# RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/main.s -o %t/main.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/a.s -o %t/a.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/b.s -o %t/b.o
+
+## foo and __foo are interconnected and defined in two lazy object files.
+## Test we resolve both to the same file.
+# RUN: ld.lld -y a -y foo -y __foo %t/main.o --start-lib %t/a.o %t/b.o --end-lib -o /dev/null | FileCheck %s
+
+# CHECK:      a.o: lazy definition of __foo
+# CHECK-NEXT: a.o: lazy definition of a
+# CHECK-NEXT: a.o: lazy definition of foo
+# CHECK-NEXT: b.o: definition of __foo
+# CHECK-NEXT: b.o: definition of foo
+# CHECK-NEXT: b.o: reference to a
+# CHECK-NEXT: a.o: definition of a
+
+#--- main.s
+.globl _start
+_start:
+  call b
+
+#--- a.s
+.globl a
+.weak foo
+a:
+foo:
+
+.weak __foo
+__foo:
+
+#--- b.s
+.globl b
+.weak foo
+b:
+  call a
+foo:
+
+.weak __foo
+__foo:
Index: lld/ELF/InputFiles.cpp
===================================================================
--- lld/ELF/InputFiles.cpp
+++ lld/ELF/InputFiles.cpp
@@ -1138,6 +1138,7 @@
   }
 
   // Symbol resolution of non-local symbols.
+  SmallVector<unsigned, 32> unds;
   for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) {
     const Elf_Sym &eSym = eSyms[i];
     uint8_t binding = eSym.getBinding();
@@ -1154,8 +1155,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;
     }
 
@@ -1202,6 +1202,20 @@
 
     fatal(toString(this) + ": unexpected binding: " + Twine((int)binding));
   }
+
+  // Undefined symbols (excluding those defined relative to non-prevailing
+  // sections) can trigger recursive fetch. Process defined symbols first so
+  // that the relative order between a defined symbol and an undefined symbol
+  // does not change the symbol resolution behavior. In addition, a set of
+  // interconnected symbols will all be resolved to the same file, instead of
+  // being resolved to different files.
+  for (unsigned i : unds) {
+    const Elf_Sym &eSym = eSyms[i];
+    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.322742.patch
Type: text/x-patch
Size: 2733 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210210/7aaaad7f/attachment.bin>


More information about the llvm-commits mailing list