diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2287,25 +2287,6 @@ parseFile(files[i]); } } - - parallelForEach(objectFiles, [](ELFFileBase *file) { - switch (config->ekind) { - case ELF32LEKind: - cast>(file)->postParse(); - break; - case ELF32BEKind: - cast>(file)->postParse(); - break; - case ELF64LEKind: - cast>(file)->postParse(); - break; - case ELF64BEKind: - cast>(file)->postParse(); - break; - default: - llvm_unreachable(""); - } - }); for (BitcodeFile *file : bitcodeFiles) file->postParse(); @@ -2427,6 +2408,26 @@ if (skipLinkedOutput) return; + parallelForEach(objectFiles, initializeLocalSymbols); + parallelForEach(objectFiles, [](ELFFileBase *file) { + switch (config->ekind) { + case ELF32LEKind: + cast>(file)->postParse(); + break; + case ELF32BEKind: + cast>(file)->postParse(); + break; + case ELF64LEKind: + cast>(file)->postParse(); + break; + case ELF64BEKind: + cast>(file)->postParse(); + break; + default: + llvm_unreachable(""); + } + }); + // Handle --exclude-libs again because lto.tmp may reference additional // libcalls symbols defined in an excluded archive. This may override // versionId set by scanVersionScript(). diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -273,6 +273,7 @@ // Get cached DWARF information. DWARFCache *getDwarf(); + void initializeLocalSymbols(); void postParse(); private: @@ -377,6 +378,8 @@ std::string replaceThinLTOSuffix(StringRef path); +void initializeLocalSymbols(ELFFileBase *file); + extern SmallVector> memoryBuffers; extern SmallVector binaryFiles; extern SmallVector bitcodeFiles; diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1021,40 +1021,6 @@ ArrayRef eSyms = this->getELFSyms(); symbols.resize(eSyms.size()); - SymbolUnion *locals = - firstGlobal == 0 - ? nullptr - : getSpecificAllocSingleton().Allocate(firstGlobal); - - for (size_t i = 0, end = firstGlobal; i != end; ++i) { - const Elf_Sym &eSym = eSyms[i]; - uint32_t secIdx = eSym.st_shndx; - if (LLVM_UNLIKELY(secIdx == SHN_XINDEX)) - secIdx = check(getExtendedSymbolTableIndex(eSym, i, shndxTable)); - else if (secIdx >= SHN_LORESERVE) - secIdx = 0; - if (LLVM_UNLIKELY(secIdx >= sections.size())) - fatal(toString(this) + ": invalid section index: " + Twine(secIdx)); - if (LLVM_UNLIKELY(eSym.getBinding() != STB_LOCAL)) - error(toString(this) + ": non-local symbol (" + Twine(i) + - ") found at index < .symtab's sh_info (" + Twine(end) + ")"); - - InputSectionBase *sec = sections[secIdx]; - uint8_t type = eSym.getType(); - if (type == STT_FILE) - sourceFile = CHECK(eSym.getName(stringTable), this); - if (LLVM_UNLIKELY(stringTable.size() <= eSym.st_name)) - fatal(toString(this) + ": invalid symbol name offset"); - StringRef name(stringTable.data() + eSym.st_name); - - symbols[i] = reinterpret_cast(locals + i); - if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded) - new (symbols[i]) Undefined(this, name, STB_LOCAL, eSym.st_other, type, - /*discardedSecIdx=*/secIdx); - else - new (symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type, - eSym.st_value, eSym.st_size, sec); - } // Some entries have been filled by LazyObjFile. for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) @@ -1149,6 +1115,67 @@ } } +template void ObjFile::initializeLocalSymbols() { + if (!firstGlobal) + return; + SymbolUnion *locals; + { + static std::mutex mu; + std::lock_guard lock(mu); + locals = getSpecificAllocSingleton().Allocate(firstGlobal); + } + + ArrayRef eSyms = this->getELFSyms(); + for (size_t i = 0, end = firstGlobal; i != end; ++i) { + const Elf_Sym &eSym = eSyms[i]; + uint32_t secIdx = eSym.st_shndx; + if (LLVM_UNLIKELY(secIdx == SHN_XINDEX)) + secIdx = check(getExtendedSymbolTableIndex(eSym, i, shndxTable)); + else if (secIdx >= SHN_LORESERVE) + secIdx = 0; + if (LLVM_UNLIKELY(secIdx >= sections.size())) + fatal(toString(this) + ": invalid section index: " + Twine(secIdx)); + if (LLVM_UNLIKELY(eSym.getBinding() != STB_LOCAL)) + error(toString(this) + ": non-local symbol (" + Twine(i) + + ") found at index < .symtab's sh_info (" + Twine(end) + ")"); + + InputSectionBase *sec = sections[secIdx]; + uint8_t type = eSym.getType(); + if (type == STT_FILE) + sourceFile = CHECK(eSym.getName(stringTable), this); + if (LLVM_UNLIKELY(stringTable.size() <= eSym.st_name)) + fatal(toString(this) + ": invalid symbol name offset"); + StringRef name(stringTable.data() + eSym.st_name); + + symbols[i] = reinterpret_cast(locals + i); + if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded) + new (symbols[i]) Undefined(this, name, STB_LOCAL, eSym.st_other, type, + /*discardedSecIdx=*/secIdx); + else + new (symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type, + eSym.st_value, eSym.st_size, sec); + } +} + +void elf::initializeLocalSymbols(ELFFileBase *file) { + switch (config->ekind) { + case ELF32LEKind: + cast>(file)->initializeLocalSymbols(); + break; + case ELF32BEKind: + cast>(file)->initializeLocalSymbols(); + break; + case ELF64LEKind: + cast>(file)->initializeLocalSymbols(); + break; + case ELF64BEKind: + cast>(file)->initializeLocalSymbols(); + break; + default: + llvm_unreachable(""); + } +} + // Called after all ObjFile::parse is called for all ObjFiles. This checks // duplicate symbols and may do symbol property merge in the future. template void ObjFile::postParse() { diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -297,9 +297,10 @@ if (!file->archiveName.empty()) archive = (" in archive " + file->archiveName).str(); - // Find a symbol that encloses a given location. + // Find a symbol that encloses a given location. getObjMsg may be called + // before ObjFile::initializeLocalSymbols where local symbols are initialized. for (Symbol *b : file->getSymbols()) - if (auto *d = dyn_cast(b)) + if (auto *d = dyn_cast_or_null(b)) if (d->section == this && d->value <= off && off < d->value + d->size) return filename + ":(" + toString(*d) + ")" + archive; diff --git a/lld/test/ELF/invalid/symtab-sh-info-dup.test b/lld/test/ELF/invalid/symtab-sh-info-dup.test --- a/lld/test/ELF/invalid/symtab-sh-info-dup.test +++ b/lld/test/ELF/invalid/symtab-sh-info-dup.test @@ -10,9 +10,7 @@ # CHECK: error: {{.*}}.o: STB_LOCAL symbol (2) found at index >= .symtab's sh_info (1) # CHECK-NEXT: error: {{.*}}.o: STB_LOCAL symbol (2) found at index >= .symtab's sh_info (1) -# CHECK-NEXT: error: duplicate symbol: _start -# CHECK-NEXT: >>> defined at {{.*}}.o:(.text+0x0) -# CHECK-NEXT: >>> defined at {{.*}}.o:(.text+0x0) +# CHECK-EMPTY: # RUN: ld.lld --noinhibit-exec %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN # WARN: warning: {{.*}}.o: STB_LOCAL symbol (2) found at index >= .symtab's sh_info (1)