Skip to content

Commit 2b129da

Browse files
committed
[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@v1 when --wrap=foo@v1 is specified (internalFile isn't scanned), this edge case difference is acceptable.
1 parent b6dfdd2 commit 2b129da

File tree

4 files changed

+23
-5
lines changed

4 files changed

+23
-5
lines changed

lld/ELF/InputFiles.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,7 @@ template <class ELFT> void ObjFile<ELFT>::postParse() {
12171217
Err(ctx) << "TLS attribute mismatch: " << &sym << "\n>>> in " << sym.file
12181218
<< "\n>>> in " << this;
12191219

1220+
hasVersionSyms |= sym.hasVersionSuffix;
12201221
// Handle non-COMMON defined symbol below. !sym.file allows a symbol
12211222
// assignment to redefine a symbol without an error.
12221223
if (!sym.isDefined() || secIdx == SHN_UNDEF)
@@ -1432,6 +1433,9 @@ template <class ELFT> void SharedFile::parse() {
14321433
const Elf_Shdr *verdefSec = nullptr;
14331434
const Elf_Shdr *verneedSec = nullptr;
14341435

1436+
numSymbols = numELFSyms;
1437+
symbols = std::make_unique<Symbol *[]>(numSymbols);
1438+
14351439
// Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d.
14361440
for (const Elf_Shdr &sec : sections) {
14371441
switch (sec.sh_type) {
@@ -1591,6 +1595,8 @@ template <class ELFT> void SharedFile::parse() {
15911595
s->dsoDefined = true;
15921596
if (s->file == this)
15931597
s->versionId = idx;
1598+
symbols[firstGlobal + i] = s;
1599+
hasVersionSyms = true;
15941600
}
15951601
}
15961602

lld/ELF/InputFiles.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ class ELFFileBase : public InputFile {
242242
StringRef sourceFile;
243243
uint32_t andFeatures = 0;
244244
bool hasCommonSyms = false;
245+
bool hasVersionSyms = false;
245246
ArrayRef<uint8_t> aarch64PauthAbiCoreInfo;
246247
};
247248

lld/ELF/SymbolTable.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,9 +353,21 @@ void SymbolTable::scanVersionScript() {
353353
// Symbol themselves might know their versions because symbols
354354
// can contain versions in the form of <name>@<version>.
355355
// Let them parse and update their names to exclude version suffix.
356-
for (Symbol *sym : symVector)
357-
if (sym->hasVersionSuffix)
358-
sym->parseSymbolVersion(ctx);
356+
for (ELFFileBase *file : ctx.objectFiles) {
357+
if (!file->hasVersionSyms)
358+
continue;
359+
for (Symbol *sym : file->getGlobalSymbols())
360+
if (sym->hasVersionSuffix)
361+
sym->parseSymbolVersion(ctx);
362+
}
363+
// Only used for undefined symbol suggestion.
364+
for (ELFFileBase *file : ctx.sharedFiles) {
365+
if (!file->hasVersionSyms)
366+
continue;
367+
for (Symbol *sym : file->getGlobalSymbols())
368+
if (sym && sym->hasVersionSuffix)
369+
sym->parseSymbolVersion(ctx);
370+
}
359371

360372
// isPreemptible is false at this point. To correctly compute the binding of a
361373
// Defined (which is used by includeInDynsym(ctx)), we need to know if it is

lld/test/ELF/symver.s

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,7 @@
139139

140140
# W3: error: undefined symbol: __wrap_foo@v1
141141
# W3-NEXT: >>> referenced by {{.*}}ref1.o:(.text+0x1)
142-
# W3-NEXT: >>> did you mean: __wrap_foo{{$}}
143-
# W3-NEXT: >>> defined in: {{.*}}wrap.o
142+
# W3-NOT: {{.}}
144143

145144
## foo@v1 is correctly wrapped.
146145
# RUN: ld.lld -shared --soname=t --version-script=%t/ver --wrap=foo@v1 %t/ref.o %t/ref1.o %t/def1.o %t/wrap1.o -o %t.w4

0 commit comments

Comments
 (0)