diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1680,7 +1680,7 @@ for (InputFile *file : lto->compile()) { auto *obj = cast>(file); - obj->parse(/*ignoreComdats=*/true); + obj->parse(/*isBitcodeFile=*/true); for (Symbol *sym : obj->getGlobalSymbols()) sym->parseSymbolVersion(); objectFiles.push_back(file); diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -201,7 +201,7 @@ this->archiveName = std::string(archiveName); } - void parse(bool ignoreComdats = false); + void parse(bool isBitcodeFile = false); StringRef getShtGroupSignature(ArrayRef sections, const Elf_Shdr &sec); @@ -252,7 +252,7 @@ DWARFCache *getDwarf(); private: - void initializeSections(bool ignoreComdats); + void initializeSections(bool isBitcodeFile); void initializeSymbols(); void initializeJustSymbols(); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -390,12 +390,12 @@ return makeArrayRef(this->symbols).slice(this->firstGlobal); } -template void ObjFile::parse(bool ignoreComdats) { +template void ObjFile::parse(bool isBitcodeFile) { // Read a section table. justSymbols is usually false. if (this->justSymbols) initializeJustSymbols(); else - initializeSections(ignoreComdats); + initializeSections(isBitcodeFile); // Read a symbol table. initializeSymbols(); @@ -546,7 +546,7 @@ } template -void ObjFile::initializeSections(bool ignoreComdats) { +void ObjFile::initializeSections(bool isBitcodeFile) { const ELFFile &obj = this->getObj(); ArrayRef objSections = CHECK(obj.sections(), this); @@ -607,10 +607,15 @@ if (entries[0] != GRP_COMDAT) fatal(toString(this) + ": unsupported SHT_GROUP format"); - bool isNew = - ignoreComdats || - symtab->comdatGroups.try_emplace(CachedHashStringRef(signature), this) - .second; + // If this is a bitcode file, ignore already proceed comdat groups. + // Else, check all comdat groups. + bool isNew = isBitcodeFile + ? symtab->bitcodeComdatGroups + .try_emplace(CachedHashStringRef(signature), this) + .second + : symtab->comdatGroups + .try_emplace(CachedHashStringRef(signature), this) + .second; if (isNew) { if (config->relocatable) this->sections[i] = createInputSection(sec); @@ -1561,9 +1566,10 @@ template void BitcodeFile::parse() { std::vector keptComdats; - for (StringRef s : obj->getComdatTable()) + for (StringRef s : obj->getComdatTable()) { keptComdats.push_back( symtab->comdatGroups.try_emplace(CachedHashStringRef(s), this).second); + } for (const lto::InputFile::Symbol &objSym : obj->symbols()) symbols.push_back(createBitcodeSymbol(keptComdats, objSym, *this)); diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -694,8 +694,12 @@ // If the discarded section is a COMDAT. StringRef signature = file->getShtGroupSignature(objSections, elfSec); - if (const InputFile *prevailing = - symtab->comdatGroups.lookup(CachedHashStringRef(signature))) + const InputFile *prevailing = + symtab->comdatGroups.lookup(CachedHashStringRef(signature)); + if (!prevailing) + prevailing = + symtab->bitcodeComdatGroups.lookup(CachedHashStringRef(signature)); + if (prevailing) msg += "\n>>> section group signature: " + signature.str() + "\n>>> prevailing definition is in " + toString(prevailing); return msg; diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -63,6 +63,12 @@ // is used to uniquify them. llvm::DenseMap comdatGroups; + // We link twice in thinlto. Define a separate map of comdat groups for + // bitcode files to make sure the symbols are distinct fromt the ones found + // in object files + llvm::DenseMap + bitcodeComdatGroups; + private: std::vector findByVersion(SymbolVersion ver); std::vector findAllByVersion(SymbolVersion ver);