[lld] 2b129da - [ELF] Optimize parseSymbolVersion

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 8 12:33:02 PST 2024


Author: Fangrui Song
Date: 2024-12-08T12:32:55-08:00
New Revision: 2b129dacdde667137b5012d52f1d96e0ab26c749

URL: https://github.com/llvm/llvm-project/commit/2b129dacdde667137b5012d52f1d96e0ab26c749
DIFF: https://github.com/llvm/llvm-project/commit/2b129dacdde667137b5012d52f1d96e0ab26c749.diff

LOG: [ELF] Optimize parseSymbolVersion

We can just scan objectFiles and sharedFiles that have versioned symbols
to skip scanning the global symtab. While we won't suggest __wrap_foo
for undefined __wrap_foo at v1 when --wrap=foo at v1 is specified
(internalFile isn't scanned), this edge case difference is acceptable.

Added: 
    

Modified: 
    lld/ELF/InputFiles.cpp
    lld/ELF/InputFiles.h
    lld/ELF/SymbolTable.cpp
    lld/test/ELF/symver.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 9ff6ed58688cef..2006b3ba352070 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1217,6 +1217,7 @@ template <class ELFT> void ObjFile<ELFT>::postParse() {
       Err(ctx) << "TLS attribute mismatch: " << &sym << "\n>>> in " << sym.file
                << "\n>>> in " << this;
 
+    hasVersionSyms |= sym.hasVersionSuffix;
     // Handle non-COMMON defined symbol below. !sym.file allows a symbol
     // assignment to redefine a symbol without an error.
     if (!sym.isDefined() || secIdx == SHN_UNDEF)
@@ -1432,6 +1433,9 @@ template <class ELFT> void SharedFile::parse() {
   const Elf_Shdr *verdefSec = nullptr;
   const Elf_Shdr *verneedSec = nullptr;
 
+  numSymbols = numELFSyms;
+  symbols = std::make_unique<Symbol *[]>(numSymbols);
+
   // Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d.
   for (const Elf_Shdr &sec : sections) {
     switch (sec.sh_type) {
@@ -1591,6 +1595,8 @@ template <class ELFT> void SharedFile::parse() {
     s->dsoDefined = true;
     if (s->file == this)
       s->versionId = idx;
+    symbols[firstGlobal + i] = s;
+    hasVersionSyms = true;
   }
 }
 

diff  --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index 79545c4bdeb5d0..f31256a4b516d7 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -242,6 +242,7 @@ class ELFFileBase : public InputFile {
   StringRef sourceFile;
   uint32_t andFeatures = 0;
   bool hasCommonSyms = false;
+  bool hasVersionSyms = false;
   ArrayRef<uint8_t> aarch64PauthAbiCoreInfo;
 };
 

diff  --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 648da94989d7a4..758ca882740e8d 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -353,9 +353,21 @@ void SymbolTable::scanVersionScript() {
   // Symbol themselves might know their versions because symbols
   // can contain versions in the form of <name>@<version>.
   // Let them parse and update their names to exclude version suffix.
-  for (Symbol *sym : symVector)
-    if (sym->hasVersionSuffix)
-      sym->parseSymbolVersion(ctx);
+  for (ELFFileBase *file : ctx.objectFiles) {
+    if (!file->hasVersionSyms)
+      continue;
+    for (Symbol *sym : file->getGlobalSymbols())
+      if (sym->hasVersionSuffix)
+        sym->parseSymbolVersion(ctx);
+  }
+  // Only used for undefined symbol suggestion.
+  for (ELFFileBase *file : ctx.sharedFiles) {
+    if (!file->hasVersionSyms)
+      continue;
+    for (Symbol *sym : file->getGlobalSymbols())
+      if (sym && sym->hasVersionSuffix)
+        sym->parseSymbolVersion(ctx);
+  }
 
   // isPreemptible is false at this point. To correctly compute the binding of a
   // Defined (which is used by includeInDynsym(ctx)), we need to know if it is

diff  --git a/lld/test/ELF/symver.s b/lld/test/ELF/symver.s
index d05fcc2a55d362..526fd2f2915948 100644
--- a/lld/test/ELF/symver.s
+++ b/lld/test/ELF/symver.s
@@ -139,8 +139,7 @@
 
 # W3:      error: undefined symbol: __wrap_foo at v1
 # W3-NEXT: >>> referenced by {{.*}}ref1.o:(.text+0x1)
-# W3-NEXT: >>> did you mean: __wrap_foo{{$}}
-# W3-NEXT: >>> defined in: {{.*}}wrap.o
+# W3-NOT:  {{.}}
 
 ## foo at v1 is correctly wrapped.
 # RUN: ld.lld -shared --soname=t --version-script=%t/ver --wrap=foo at v1 %t/ref.o %t/ref1.o %t/def1.o %t/wrap1.o -o %t.w4


        


More information about the llvm-commits mailing list