//===- InputFiles.cpp -----------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "InputFiles.h" #include "Driver.h" #include "ELFCreator.h" #include "Error.h" #include "InputSection.h" #include "LinkerScript.h" #include "SymbolTable.h" #include "Symbols.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/LTO/LTO.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; using namespace llvm::sys::fs; using namespace lld; using namespace lld::elf; std::vector InputFile::Pool; // Deletes all InputFile instances created so far. void InputFile::freePool() { // Files are freed in reverse order so that files created // from other files (e.g. object files extracted from archives) // are freed in the proper order. for (int I = Pool.size() - 1; I >= 0; --I) delete Pool[I]; } // Returns "(internal)", "foo.a(bar.o)" or "baz.o". std::string elf::getFilename(const InputFile *F) { if (!F) return "(internal)"; if (!F->ArchiveName.empty()) return (F->ArchiveName + "(" + F->getName() + ")").str(); return F->getName(); } template static ELFFile createELFObj(MemoryBufferRef MB) { std::error_code EC; ELFFile F(MB.getBuffer(), EC); if (EC) fatal(EC, "failed to read " + MB.getBufferIdentifier()); return F; } template static ELFKind getELFKind() { if (ELFT::TargetEndianness == support::little) return ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind; return ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind; } template ELFFileBase::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB), ELFObj(createELFObj(MB)) { EKind = getELFKind(); EMachine = ELFObj.getHeader()->e_machine; } template typename ELFT::SymRange ELFFileBase::getElfSymbols(bool OnlyGlobals) { if (!Symtab) return Elf_Sym_Range(nullptr, nullptr); Elf_Sym_Range Syms = ELFObj.symbols(Symtab); uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); uint32_t FirstNonLocal = Symtab->sh_info; if (FirstNonLocal == 0 || FirstNonLocal > NumSymbols) fatal(getFilename(this) + ": invalid sh_info in symbol table"); if (OnlyGlobals) return makeArrayRef(Syms.begin() + FirstNonLocal, Syms.end()); return makeArrayRef(Syms.begin(), Syms.end()); } template uint32_t ELFFileBase::getSectionIndex(const Elf_Sym &Sym) const { uint32_t I = Sym.st_shndx; if (I == ELF::SHN_XINDEX) return ELFObj.getExtendedSymbolTableIndex(&Sym, Symtab, SymtabSHNDX); if (I >= ELF::SHN_LORESERVE) return 0; return I; } template void ELFFileBase::initStringTable() { if (!Symtab) return; StringTable = check(ELFObj.getStringTableForSymtab(*Symtab)); } template elf::ObjectFile::ObjectFile(MemoryBufferRef M) : ELFFileBase(Base::ObjectKind, M) {} template ArrayRef elf::ObjectFile::getNonLocalSymbols() { if (!this->Symtab) return this->SymbolBodies; uint32_t FirstNonLocal = this->Symtab->sh_info; return makeArrayRef(this->SymbolBodies).slice(FirstNonLocal); } template ArrayRef elf::ObjectFile::getLocalSymbols() { if (!this->Symtab) return this->SymbolBodies; uint32_t FirstNonLocal = this->Symtab->sh_info; return makeArrayRef(this->SymbolBodies).slice(1, FirstNonLocal - 1); } template ArrayRef elf::ObjectFile::getSymbols() { if (!this->Symtab) return this->SymbolBodies; return makeArrayRef(this->SymbolBodies).slice(1); } template uint32_t elf::ObjectFile::getMipsGp0() const { if (ELFT::Is64Bits && MipsOptions && MipsOptions->Reginfo) return MipsOptions->Reginfo->ri_gp_value; if (!ELFT::Is64Bits && MipsReginfo && MipsReginfo->Reginfo) return MipsReginfo->Reginfo->ri_gp_value; return 0; } template void elf::ObjectFile::parse(DenseSet &ComdatGroups) { // Read section and symbol tables. initializeSections(ComdatGroups); initializeSymbols(); if (Config->GcSections && Config->EMachine == EM_ARM) initializeReverseDependencies(); } // Sections with SHT_GROUP and comdat bits define comdat section groups. // They are identified and deduplicated by group name. This function // returns a group name. template StringRef elf::ObjectFile::getShtGroupSignature(const Elf_Shdr &Sec) { const ELFFile &Obj = this->ELFObj; const Elf_Shdr *Symtab = check(Obj.getSection(Sec.sh_link)); const Elf_Sym *Sym = Obj.getSymbol(Symtab, Sec.sh_info); StringRef Strtab = check(Obj.getStringTableForSymtab(*Symtab)); return check(Sym->getName(Strtab)); } template ArrayRef::Elf_Word> elf::ObjectFile::getShtGroupEntries(const Elf_Shdr &Sec) { const ELFFile &Obj = this->ELFObj; ArrayRef Entries = check(Obj.template getSectionContentsAsArray(&Sec)); if (Entries.empty() || Entries[0] != GRP_COMDAT) fatal(getFilename(this) + ": unsupported SHT_GROUP format"); return Entries.slice(1); } template bool elf::ObjectFile::shouldMerge(const Elf_Shdr &Sec) { // We don't merge sections if -O0 (default is -O1). This makes sometimes // the linker significantly faster, although the output will be bigger. if (Config->Optimize == 0) return false; // Do not merge sections if generating a relocatable object. It makes // the code simpler because we do not need to update relocation addends // to reflect changes introduced by merging. Instead of that we write // such "merge" sections into separate OutputSections and keep SHF_MERGE // / SHF_STRINGS flags and sh_entsize value to be able to perform merging // later during a final linking. if (Config->Relocatable) return false; // A mergeable section with size 0 is useless because they don't have // any data to merge. A mergeable string section with size 0 can be // argued as invalid because it doesn't end with a null character. // We'll avoid a mess by handling them as if they were non-mergeable. if (Sec.sh_size == 0) return false; // Check for sh_entsize. The ELF spec is not clear about the zero // sh_entsize. It says that "the member [sh_entsize] contains 0 if // the section does not hold a table of fixed-size entries". We know // that Rust 1.13 produces a string mergeable section with a zero // sh_entsize. Here we just accept it rather than being picky about it. uintX_t EntSize = Sec.sh_entsize; if (EntSize == 0) return false; if (Sec.sh_size % EntSize) fatal(getFilename(this) + ": SHF_MERGE section size must be a multiple of sh_entsize"); uintX_t Flags = Sec.sh_flags; if (!(Flags & SHF_MERGE)) return false; if (Flags & SHF_WRITE) fatal(getFilename(this) + ": writable SHF_MERGE section is not supported"); // Don't try to merge if the alignment is larger than the sh_entsize and this // is not SHF_STRINGS. // // Since this is not a SHF_STRINGS, we would need to pad after every entity. // It would be equivalent for the producer of the .o to just set a larger // sh_entsize. if (Flags & SHF_STRINGS) return true; return Sec.sh_addralign <= EntSize; } template void elf::ObjectFile::initializeSections( DenseSet &ComdatGroups) { uint64_t Size = this->ELFObj.getNumSections(); Sections.resize(Size); unsigned I = -1; const ELFFile &Obj = this->ELFObj; for (const Elf_Shdr &Sec : Obj.sections()) { ++I; if (Sections[I] == &InputSection::Discarded) continue; // SHF_EXCLUDE'ed sections are discarded by the linker. However, // if -r is given, we'll let the final link discard such sections. // This is compatible with GNU. if ((Sec.sh_flags & SHF_EXCLUDE) && !Config->Relocatable) { Sections[I] = &InputSection::Discarded; continue; } switch (Sec.sh_type) { case SHT_GROUP: Sections[I] = &InputSection::Discarded; if (ComdatGroups.insert(getShtGroupSignature(Sec)).second) continue; for (uint32_t SecIndex : getShtGroupEntries(Sec)) { if (SecIndex >= Size) fatal(getFilename(this) + ": invalid section index in group: " + Twine(SecIndex)); Sections[SecIndex] = &InputSection::Discarded; } break; case SHT_SYMTAB: this->Symtab = &Sec; break; case SHT_SYMTAB_SHNDX: this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec)); break; case SHT_STRTAB: case SHT_NULL: break; default: Sections[I] = createInputSection(Sec); } } } // .ARM.exidx sections have a reverse dependency on the InputSection they // have a SHF_LINK_ORDER dependency, this is identified by the sh_link. template void elf::ObjectFile::initializeReverseDependencies() { unsigned I = -1; for (const Elf_Shdr &Sec : this->ELFObj.sections()) { ++I; if ((Sections[I] == &InputSection::Discarded) || !(Sec.sh_flags & SHF_LINK_ORDER)) continue; if (Sec.sh_link >= Sections.size()) fatal(getFilename(this) + ": invalid sh_link index: " + Twine(Sec.sh_link)); auto *IS = cast>(Sections[Sec.sh_link]); IS->DependentSection = Sections[I]; } } template InputSectionBase * elf::ObjectFile::getRelocTarget(const Elf_Shdr &Sec) { uint32_t Idx = Sec.sh_info; if (Idx >= Sections.size()) fatal(getFilename(this) + ": invalid relocated section index: " + Twine(Idx)); InputSectionBase *Target = Sections[Idx]; // Strictly speaking, a relocation section must be included in the // group of the section it relocates. However, LLVM 3.3 and earlier // would fail to do so, so we gracefully handle that case. if (Target == &InputSection::Discarded) return nullptr; if (!Target) fatal(getFilename(this) + ": unsupported relocation reference"); return Target; } template InputSectionBase * elf::ObjectFile::createInputSection(const Elf_Shdr &Sec) { StringRef Name = check(this->ELFObj.getSectionName(&Sec)); switch (Sec.sh_type) { case SHT_ARM_ATTRIBUTES: // FIXME: ARM meta-data section. At present attributes are ignored, // they can be used to reason about object compatibility. return &InputSection::Discarded; case SHT_MIPS_REGINFO: if (MipsReginfo) fatal(getFilename(this) + ": multiple SHT_MIPS_REGINFO sections are not allowed"); MipsReginfo.reset(new MipsReginfoInputSection(this, &Sec, Name)); return MipsReginfo.get(); case SHT_MIPS_OPTIONS: if (MipsOptions) fatal(getFilename(this) + ": multiple SHT_MIPS_OPTIONS sections are not allowed"); MipsOptions.reset(new MipsOptionsInputSection(this, &Sec, Name)); return MipsOptions.get(); case SHT_MIPS_ABIFLAGS: if (MipsAbiFlags) fatal(getFilename(this) + ": multiple SHT_MIPS_ABIFLAGS sections are not allowed"); MipsAbiFlags.reset(new MipsAbiFlagsInputSection(this, &Sec, Name)); return MipsAbiFlags.get(); case SHT_RELA: case SHT_REL: { // This section contains relocation information. // If -r is given, we do not interpret or apply relocation // but just copy relocation sections to output. if (Config->Relocatable) return new (IAlloc.Allocate()) InputSection(this, &Sec, Name); // Find the relocation target section and associate this // section with it. InputSectionBase *Target = getRelocTarget(Sec); if (!Target) return nullptr; if (auto *S = dyn_cast>(Target)) { S->RelocSections.push_back(&Sec); return nullptr; } if (auto *S = dyn_cast>(Target)) { if (S->RelocSection) fatal(getFilename(this) + ": multiple relocation sections to .eh_frame are not supported"); S->RelocSection = &Sec; return nullptr; } fatal(getFilename(this) + ": relocations pointing to SHF_MERGE are not supported"); } } // .note.GNU-stack is a marker section to control the presence of // PT_GNU_STACK segment in outputs. Since the presence of the segment // is controlled only by the command line option (-z execstack) in LLD, // .note.GNU-stack is ignored. if (Name == ".note.GNU-stack") return &InputSection::Discarded; if (Name == ".note.GNU-split-stack") { error("objects using splitstacks are not supported"); return &InputSection::Discarded; } if (Config->Strip != StripPolicy::None && Name.startswith(".debug")) return &InputSection::Discarded; // The linker merges EH (exception handling) frames and creates a // .eh_frame_hdr section for runtime. So we handle them with a special // class. For relocatable outputs, they are just passed through. if (Name == ".eh_frame" && !Config->Relocatable) return new (EHAlloc.Allocate()) EhInputSection(this, &Sec, Name); if (shouldMerge(Sec)) return new (MAlloc.Allocate()) MergeInputSection(this, &Sec, Name); return new (IAlloc.Allocate()) InputSection(this, &Sec, Name); } template void elf::ObjectFile::initializeSymbols() { this->initStringTable(); Elf_Sym_Range Syms = this->getElfSymbols(false); uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); SymbolBodies.reserve(NumSymbols); for (const Elf_Sym &Sym : Syms) SymbolBodies.push_back(createSymbolBody(&Sym)); } template InputSectionBase * elf::ObjectFile::getSection(const Elf_Sym &Sym) const { uint32_t Index = this->getSectionIndex(Sym); if (Index >= Sections.size()) fatal(getFilename(this) + ": invalid section index: " + Twine(Index)); InputSectionBase *S = Sections[Index]; // We found that GNU assembler 2.17.50 [FreeBSD] 2007-07-03 // could generate broken objects. STT_SECTION symbols can be // associated with SHT_REL[A]/SHT_SYMTAB/SHT_STRTAB sections. // In this case it is fine for section to be null here as we // do not allocate sections of these types. if (!S) { if (Index == 0 || Sym.getType() == STT_SECTION) return nullptr; fatal(getFilename(this) + ": invalid section index: " + Twine(Index)); } if (S == &InputSectionBase::Discarded) return S; return S->Repl; } template SymbolBody *elf::ObjectFile::createSymbolBody(const Elf_Sym *Sym) { int Binding = Sym->getBinding(); InputSectionBase *Sec = getSection(*Sym); if (Binding == STB_LOCAL) { if (Sym->st_shndx == SHN_UNDEF) return new (this->Alloc) Undefined(Sym->st_name, Sym->st_other, Sym->getType(), this); return new (this->Alloc) DefinedRegular(*Sym, Sec); } StringRef Name = check(Sym->getName(this->StringTable)); switch (Sym->st_shndx) { case SHN_UNDEF: return elf::Symtab::X->addUndefined(Name, Binding, Sym->st_other, Sym->getType(), /*CanOmitFromDynSym*/ false, this) ->body(); case SHN_COMMON: if (Sym->st_value == 0 || Sym->st_value >= UINT32_MAX) fatal(getFilename(this) + ": common symbol '" + Name + "' has invalid alignment: " + Twine(Sym->st_value)); return elf::Symtab::X->addCommon(Name, Sym->st_size, Sym->st_value, Binding, Sym->st_other, Sym->getType(), this) ->body(); } switch (Binding) { default: fatal(getFilename(this) + ": unexpected binding: " + Twine(Binding)); case STB_GLOBAL: case STB_WEAK: case STB_GNU_UNIQUE: if (Sec == &InputSection::Discarded) return elf::Symtab::X->addUndefined(Name, Binding, Sym->st_other, Sym->getType(), /*CanOmitFromDynSym*/ false, this) ->body(); return elf::Symtab::X->addRegular(Name, *Sym, Sec)->body(); } } template void ArchiveFile::parse() { File = check(Archive::create(MB), "failed to parse archive"); // Read the symbol table to construct Lazy objects. for (const Archive::Symbol &Sym : File->symbols()) Symtab::X->addLazyArchive(this, Sym); } // Returns a buffer pointing to a member file containing a given symbol. std::pair ArchiveFile::getMember(const Archive::Symbol *Sym) { Archive::Child C = check(Sym->getMember(), "could not get the member for symbol " + Sym->getName()); if (!Seen.insert(C.getChildOffset()).second) return {MemoryBufferRef(), 0}; MemoryBufferRef Ret = check(C.getMemoryBufferRef(), "could not get the buffer for the member defining symbol " + Sym->getName()); if (C.getParent()->isThin() && Driver->Cpio) Driver->Cpio->append(relativeToRoot(check(C.getFullName())), Ret.getBuffer()); if (C.getParent()->isThin()) return {Ret, 0}; return {Ret, C.getChildOffset()}; } template SharedFile::SharedFile(MemoryBufferRef M) : ELFFileBase(Base::SharedKind, M), AsNeeded(Config->AsNeeded) {} template const typename ELFT::Shdr * SharedFile::getSection(const Elf_Sym &Sym) const { uint32_t Index = this->getSectionIndex(Sym); if (Index == 0) return nullptr; return check(this->ELFObj.getSection(Index)); } // Partially parse the shared object file so that we can call // getSoName on this object. template void SharedFile::parseSoName() { typedef typename ELFT::Dyn Elf_Dyn; typedef typename ELFT::uint uintX_t; const Elf_Shdr *DynamicSec = nullptr; const ELFFile Obj = this->ELFObj; for (const Elf_Shdr &Sec : Obj.sections()) { switch (Sec.sh_type) { default: continue; case SHT_DYNSYM: this->Symtab = &Sec; break; case SHT_DYNAMIC: DynamicSec = &Sec; break; case SHT_SYMTAB_SHNDX: this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec)); break; case SHT_GNU_versym: this->VersymSec = &Sec; break; case SHT_GNU_verdef: this->VerdefSec = &Sec; break; } } this->initStringTable(); // DSOs are identified by soname, and they usually contain // DT_SONAME tag in their header. But if they are missing, // filenames are used as default sonames. SoName = sys::path::filename(this->getName()); if (!DynamicSec) return; ArrayRef Arr = check(Obj.template getSectionContentsAsArray(DynamicSec), getFilename(this) + ": getSectionContentsAsArray failed"); for (const Elf_Dyn &Dyn : Arr) { if (Dyn.d_tag == DT_SONAME) { uintX_t Val = Dyn.getVal(); if (Val >= this->StringTable.size()) fatal(getFilename(this) + ": invalid DT_SONAME entry"); SoName = StringRef(this->StringTable.data() + Val); return; } } } // Parse the version definitions in the object file if present. Returns a vector // whose nth element contains a pointer to the Elf_Verdef for version identifier // n. Version identifiers that are not definitions map to nullptr. The array // always has at least length 1. template std::vector SharedFile::parseVerdefs(const Elf_Versym *&Versym) { std::vector Verdefs(1); // We only need to process symbol versions for this DSO if it has both a // versym and a verdef section, which indicates that the DSO contains symbol // version definitions. if (!VersymSec || !VerdefSec) return Verdefs; // The location of the first global versym entry. Versym = reinterpret_cast(this->ELFObj.base() + VersymSec->sh_offset) + this->Symtab->sh_info; // We cannot determine the largest verdef identifier without inspecting // every Elf_Verdef, but both bfd and gold assign verdef identifiers // sequentially starting from 1, so we predict that the largest identifier // will be VerdefCount. unsigned VerdefCount = VerdefSec->sh_info; Verdefs.resize(VerdefCount + 1); // Build the Verdefs array by following the chain of Elf_Verdef objects // from the start of the .gnu.version_d section. const uint8_t *Verdef = this->ELFObj.base() + VerdefSec->sh_offset; for (unsigned I = 0; I != VerdefCount; ++I) { auto *CurVerdef = reinterpret_cast(Verdef); Verdef += CurVerdef->vd_next; unsigned VerdefIndex = CurVerdef->vd_ndx; if (Verdefs.size() <= VerdefIndex) Verdefs.resize(VerdefIndex + 1); Verdefs[VerdefIndex] = CurVerdef; } return Verdefs; } // Fully parse the shared object file. This must be called after parseSoName(). template void SharedFile::parseRest() { // Create mapping from version identifiers to Elf_Verdef entries. const Elf_Versym *Versym = nullptr; std::vector Verdefs = parseVerdefs(Versym); Elf_Sym_Range Syms = this->getElfSymbols(true); for (const Elf_Sym &Sym : Syms) { unsigned VersymIndex = 0; if (Versym) { VersymIndex = Versym->vs_index; ++Versym; } StringRef Name = check(Sym.getName(this->StringTable)); if (Sym.isUndefined()) { Undefs.push_back(Name); continue; } if (Versym) { // Ignore local symbols and non-default versions. if (VersymIndex == VER_NDX_LOCAL || (VersymIndex & VERSYM_HIDDEN)) continue; } const Elf_Verdef *V = VersymIndex == VER_NDX_GLOBAL ? nullptr : Verdefs[VersymIndex]; elf::Symtab::X->addShared(this, Name, Sym, V); } } static ELFKind getBitcodeELFKind(MemoryBufferRef MB) { Triple T(getBitcodeTargetTriple(MB, Driver->Context)); if (T.isLittleEndian()) return T.isArch64Bit() ? ELF64LEKind : ELF32LEKind; return T.isArch64Bit() ? ELF64BEKind : ELF32BEKind; } static uint8_t getBitcodeMachineKind(MemoryBufferRef MB) { Triple T(getBitcodeTargetTriple(MB, Driver->Context)); switch (T.getArch()) { case Triple::aarch64: return EM_AARCH64; case Triple::arm: return EM_ARM; case Triple::mips: case Triple::mipsel: case Triple::mips64: case Triple::mips64el: return EM_MIPS; case Triple::ppc: return EM_PPC; case Triple::ppc64: return EM_PPC64; case Triple::x86: return T.isOSIAMCU() ? EM_IAMCU : EM_386; case Triple::x86_64: return EM_X86_64; default: fatal(MB.getBufferIdentifier() + ": could not infer e_machine from bitcode target triple " + T.str()); } } BitcodeFile::BitcodeFile(MemoryBufferRef MB) : InputFile(BitcodeKind, MB) { EKind = getBitcodeELFKind(MB); EMachine = getBitcodeMachineKind(MB); } static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) { switch (GvVisibility) { case GlobalValue::DefaultVisibility: return STV_DEFAULT; case GlobalValue::HiddenVisibility: return STV_HIDDEN; case GlobalValue::ProtectedVisibility: return STV_PROTECTED; } llvm_unreachable("unknown visibility"); } template static Symbol *createBitcodeSymbol(DenseSet &KeptComdats, DenseSet &ComdatGroups, const lto::InputFile::Symbol &ObjSym, StringSaver &Saver, BitcodeFile *F) { StringRef NameRef = Saver.save(ObjSym.getName()); uint32_t Flags = ObjSym.getFlags(); uint32_t Binding = (Flags & BasicSymbolRef::SF_Weak) ? STB_WEAK : STB_GLOBAL; uint8_t Type = ObjSym.isTLS() ? STT_TLS : STT_NOTYPE; uint8_t Visibility = mapVisibility(ObjSym.getVisibility()); bool CanOmitFromDynSym = ObjSym.canBeOmittedFromSymbolTable(); StringRef C = check(ObjSym.getComdat()); if (!C.empty()) { bool Keep = KeptComdats.count(C); if (!Keep) { StringRef N = Saver.save(C); if (ComdatGroups.insert(N).second) { Keep = true; KeptComdats.insert(C); } } if (!Keep) return Symtab::X->addUndefined(NameRef, Binding, Visibility, Type, CanOmitFromDynSym, F); } if (Flags & BasicSymbolRef::SF_Undefined) return Symtab::X->addUndefined(NameRef, Binding, Visibility, Type, CanOmitFromDynSym, F); if (Flags & BasicSymbolRef::SF_Common) return Symtab::X->addCommon(NameRef, ObjSym.getCommonSize(), ObjSym.getCommonAlignment(), Binding, Visibility, STT_OBJECT, F); return Symtab::X->addBitcode(NameRef, Binding, Visibility, Type, CanOmitFromDynSym, F); } template void BitcodeFile::parse(DenseSet &ComdatGroups) { // Here we pass a new MemoryBufferRef which is identified by ArchiveName // (the fully resolved path of the archive) + member name + offset of the // member in the archive. // ThinLTO uses the MemoryBufferRef identifier to access its internal // data structures and if two archives define two members with the same name, // this causes a collision which result in only one of the objects being // taken into consideration at LTO time (which very likely causes undefined // symbols later in the link stage). Obj = check(lto::InputFile::create(MemoryBufferRef( MB.getBuffer(), Saver.save(ArchiveName + MB.getBufferIdentifier() + utostr(OffsetInArchive))))); DenseSet KeptComdats; for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) Symbols.push_back(createBitcodeSymbol(KeptComdats, ComdatGroups, ObjSym, Saver, this)); } template