|  | //===- 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 "Chunks.h" | 
|  | #include "Config.h" | 
|  | #include "Driver.h" | 
|  | #include "SymbolTable.h" | 
|  | #include "Symbols.h" | 
|  | #include "lld/Common/ErrorHandler.h" | 
|  | #include "lld/Common/Memory.h" | 
|  | #include "llvm-c/lto.h" | 
|  | #include "llvm/ADT/SmallVector.h" | 
|  | #include "llvm/ADT/Triple.h" | 
|  | #include "llvm/ADT/Twine.h" | 
|  | #include "llvm/BinaryFormat/COFF.h" | 
|  | #include "llvm/Object/Binary.h" | 
|  | #include "llvm/Object/COFF.h" | 
|  | #include "llvm/Support/Casting.h" | 
|  | #include "llvm/Support/Endian.h" | 
|  | #include "llvm/Support/Error.h" | 
|  | #include "llvm/Support/ErrorOr.h" | 
|  | #include "llvm/Support/FileSystem.h" | 
|  | #include "llvm/Support/Path.h" | 
|  | #include "llvm/Target/TargetOptions.h" | 
|  | #include <cstring> | 
|  | #include <system_error> | 
|  | #include <utility> | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::COFF; | 
|  | using namespace llvm::object; | 
|  | using namespace llvm::support::endian; | 
|  |  | 
|  | using llvm::Triple; | 
|  | using llvm::support::ulittle32_t; | 
|  |  | 
|  | namespace lld { | 
|  | namespace coff { | 
|  |  | 
|  | std::vector<ObjFile *> ObjFile::Instances; | 
|  | std::vector<ImportFile *> ImportFile::Instances; | 
|  | std::vector<BitcodeFile *> BitcodeFile::Instances; | 
|  |  | 
|  | /// Checks that Source is compatible with being a weak alias to Target. | 
|  | /// If Source is Undefined and has no weak alias set, makes it a weak | 
|  | /// alias to Target. | 
|  | static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F, | 
|  | Symbol *Source, Symbol *Target) { | 
|  | if (auto *U = dyn_cast<Undefined>(Source)) { | 
|  | if (U->WeakAlias && U->WeakAlias != Target) | 
|  | Symtab->reportDuplicate(Source, F); | 
|  | U->WeakAlias = Target; | 
|  | } | 
|  | } | 
|  |  | 
|  | ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} | 
|  |  | 
|  | void ArchiveFile::parse() { | 
|  | // Parse a MemoryBufferRef as an archive file. | 
|  | File = CHECK(Archive::create(MB), this); | 
|  |  | 
|  | // Read the symbol table to construct Lazy objects. | 
|  | for (const Archive::Symbol &Sym : File->symbols()) | 
|  | Symtab->addLazy(this, Sym); | 
|  | } | 
|  |  | 
|  | // Returns a buffer pointing to a member file containing a given symbol. | 
|  | void ArchiveFile::addMember(const Archive::Symbol *Sym) { | 
|  | const Archive::Child &C = | 
|  | CHECK(Sym->getMember(), | 
|  | "could not get the member for symbol " + Sym->getName()); | 
|  |  | 
|  | // Return an empty buffer if we have already returned the same buffer. | 
|  | if (!Seen.insert(C.getChildOffset()).second) | 
|  | return; | 
|  |  | 
|  | Driver->enqueueArchiveMember(C, Sym->getName(), getName()); | 
|  | } | 
|  |  | 
|  | std::vector<MemoryBufferRef> getArchiveMembers(Archive *File) { | 
|  | std::vector<MemoryBufferRef> V; | 
|  | Error Err = Error::success(); | 
|  | for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) { | 
|  | Archive::Child C = | 
|  | CHECK(COrErr, | 
|  | File->getFileName() + ": could not get the child of the archive"); | 
|  | MemoryBufferRef MBRef = | 
|  | CHECK(C.getMemoryBufferRef(), | 
|  | File->getFileName() + | 
|  | ": could not get the buffer for a child of the archive"); | 
|  | V.push_back(MBRef); | 
|  | } | 
|  | if (Err) | 
|  | fatal(File->getFileName() + | 
|  | ": Archive::children failed: " + toString(std::move(Err))); | 
|  | return V; | 
|  | } | 
|  |  | 
|  | void ObjFile::parse() { | 
|  | // Parse a memory buffer as a COFF file. | 
|  | std::unique_ptr<Binary> Bin = CHECK(createBinary(MB), this); | 
|  |  | 
|  | if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) { | 
|  | Bin.release(); | 
|  | COFFObj.reset(Obj); | 
|  | } else { | 
|  | fatal(toString(this) + " is not a COFF file"); | 
|  | } | 
|  |  | 
|  | // Read section and symbol tables. | 
|  | initializeChunks(); | 
|  | initializeSymbols(); | 
|  | } | 
|  |  | 
|  | // We set SectionChunk pointers in the SparseChunks vector to this value | 
|  | // temporarily to mark comdat sections as having an unknown resolution. As we | 
|  | // walk the object file's symbol table, once we visit either a leader symbol or | 
|  | // an associative section definition together with the parent comdat's leader, | 
|  | // we set the pointer to either nullptr (to mark the section as discarded) or a | 
|  | // valid SectionChunk for that section. | 
|  | static SectionChunk *const PendingComdat = reinterpret_cast<SectionChunk *>(1); | 
|  |  | 
|  | void ObjFile::initializeChunks() { | 
|  | uint32_t NumSections = COFFObj->getNumberOfSections(); | 
|  | Chunks.reserve(NumSections); | 
|  | SparseChunks.resize(NumSections + 1); | 
|  | for (uint32_t I = 1; I < NumSections + 1; ++I) { | 
|  | const coff_section *Sec; | 
|  | if (auto EC = COFFObj->getSection(I, Sec)) | 
|  | fatal("getSection failed: #" + Twine(I) + ": " + EC.message()); | 
|  |  | 
|  | if (Sec->Characteristics & IMAGE_SCN_LNK_COMDAT) | 
|  | SparseChunks[I] = PendingComdat; | 
|  | else | 
|  | SparseChunks[I] = readSection(I, nullptr, ""); | 
|  | } | 
|  | } | 
|  |  | 
|  | SectionChunk *ObjFile::readSection(uint32_t SectionNumber, | 
|  | const coff_aux_section_definition *Def, | 
|  | StringRef LeaderName) { | 
|  | const coff_section *Sec; | 
|  | StringRef Name; | 
|  | if (auto EC = COFFObj->getSection(SectionNumber, Sec)) | 
|  | fatal("getSection failed: #" + Twine(SectionNumber) + ": " + EC.message()); | 
|  | if (auto EC = COFFObj->getSectionName(Sec, Name)) | 
|  | fatal("getSectionName failed: #" + Twine(SectionNumber) + ": " + | 
|  | EC.message()); | 
|  |  | 
|  | if (Name == ".drectve") { | 
|  | ArrayRef<uint8_t> Data; | 
|  | COFFObj->getSectionContents(Sec, Data); | 
|  | Directives = std::string((const char *)Data.data(), Data.size()); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | // Object files may have DWARF debug info or MS CodeView debug info | 
|  | // (or both). | 
|  | // | 
|  | // DWARF sections don't need any special handling from the perspective | 
|  | // of the linker; they are just a data section containing relocations. | 
|  | // We can just link them to complete debug info. | 
|  | // | 
|  | // CodeView needs a linker support. We need to interpret and debug | 
|  | // info, and then write it to a separate .pdb file. | 
|  |  | 
|  | // Ignore DWARF debug info unless /debug is given. | 
|  | if (!Config->Debug && Name.startswith(".debug_")) | 
|  | return nullptr; | 
|  |  | 
|  | if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE) | 
|  | return nullptr; | 
|  | auto *C = make<SectionChunk>(this, Sec); | 
|  | if (Def) | 
|  | C->Checksum = Def->CheckSum; | 
|  |  | 
|  | // CodeView sections are stored to a different vector because they are not | 
|  | // linked in the regular manner. | 
|  | if (C->isCodeView()) | 
|  | DebugChunks.push_back(C); | 
|  | else if (Config->GuardCF != GuardCFLevel::Off && Name == ".gfids$y") | 
|  | GuardFidChunks.push_back(C); | 
|  | else if (Config->GuardCF != GuardCFLevel::Off && Name == ".gljmp$y") | 
|  | GuardLJmpChunks.push_back(C); | 
|  | else if (Name == ".sxdata") | 
|  | SXDataChunks.push_back(C); | 
|  | else if (Config->TailMerge && Sec->NumberOfRelocations == 0 && | 
|  | Name == ".rdata" && LeaderName.startswith("??_C@")) | 
|  | // COFF sections that look like string literal sections (i.e. no | 
|  | // relocations, in .rdata, leader symbol name matches the MSVC name mangling | 
|  | // for string literals) are subject to string tail merging. | 
|  | MergeChunk::addSection(C); | 
|  | else | 
|  | Chunks.push_back(C); | 
|  |  | 
|  | return C; | 
|  | } | 
|  |  | 
|  | void ObjFile::readAssociativeDefinition( | 
|  | COFFSymbolRef Sym, const coff_aux_section_definition *Def) { | 
|  | readAssociativeDefinition(Sym, Def, Def->getNumber(Sym.isBigObj())); | 
|  | } | 
|  |  | 
|  | void ObjFile::readAssociativeDefinition(COFFSymbolRef Sym, | 
|  | const coff_aux_section_definition *Def, | 
|  | uint32_t ParentSection) { | 
|  | SectionChunk *Parent = SparseChunks[ParentSection]; | 
|  |  | 
|  | // If the parent is pending, it probably means that its section definition | 
|  | // appears after us in the symbol table. Leave the associated section as | 
|  | // pending; we will handle it during the second pass in initializeSymbols(). | 
|  | if (Parent == PendingComdat) | 
|  | return; | 
|  |  | 
|  | // Check whether the parent is prevailing. If it is, so are we, and we read | 
|  | // the section; otherwise mark it as discarded. | 
|  | int32_t SectionNumber = Sym.getSectionNumber(); | 
|  | if (Parent) { | 
|  | SparseChunks[SectionNumber] = readSection(SectionNumber, Def, ""); | 
|  | if (SparseChunks[SectionNumber]) | 
|  | Parent->addAssociative(SparseChunks[SectionNumber]); | 
|  | } else { | 
|  | SparseChunks[SectionNumber] = nullptr; | 
|  | } | 
|  | } | 
|  |  | 
|  | void ObjFile::recordPrevailingSymbolForMingw( | 
|  | COFFSymbolRef Sym, DenseMap<StringRef, uint32_t> &PrevailingSectionMap) { | 
|  | // For comdat symbols in executable sections, where this is the copy | 
|  | // of the section chunk we actually include instead of discarding it, | 
|  | // add the symbol to a map to allow using it for implicitly | 
|  | // associating .[px]data$<func> sections to it. | 
|  | int32_t SectionNumber = Sym.getSectionNumber(); | 
|  | SectionChunk *SC = SparseChunks[SectionNumber]; | 
|  | if (SC && SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) { | 
|  | StringRef Name; | 
|  | COFFObj->getSymbolName(Sym, Name); | 
|  | PrevailingSectionMap[Name] = SectionNumber; | 
|  | } | 
|  | } | 
|  |  | 
|  | void ObjFile::maybeAssociateSEHForMingw( | 
|  | COFFSymbolRef Sym, const coff_aux_section_definition *Def, | 
|  | const DenseMap<StringRef, uint32_t> &PrevailingSectionMap) { | 
|  | StringRef Name; | 
|  | COFFObj->getSymbolName(Sym, Name); | 
|  | if (Name.consume_front(".pdata$") || Name.consume_front(".xdata$")) { | 
|  | // For MinGW, treat .[px]data$<func> as implicitly associative to | 
|  | // the symbol <func>. | 
|  | auto ParentSym = PrevailingSectionMap.find(Name); | 
|  | if (ParentSym != PrevailingSectionMap.end()) | 
|  | readAssociativeDefinition(Sym, Def, ParentSym->second); | 
|  | } | 
|  | } | 
|  |  | 
|  | Symbol *ObjFile::createRegular(COFFSymbolRef Sym) { | 
|  | SectionChunk *SC = SparseChunks[Sym.getSectionNumber()]; | 
|  | if (Sym.isExternal()) { | 
|  | StringRef Name; | 
|  | COFFObj->getSymbolName(Sym, Name); | 
|  | if (SC) | 
|  | return Symtab->addRegular(this, Name, Sym.getGeneric(), SC); | 
|  | return Symtab->addUndefined(Name, this, false); | 
|  | } | 
|  | if (SC) | 
|  | return make<DefinedRegular>(this, /*Name*/ "", false, | 
|  | /*IsExternal*/ false, Sym.getGeneric(), SC); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | void ObjFile::initializeSymbols() { | 
|  | uint32_t NumSymbols = COFFObj->getNumberOfSymbols(); | 
|  | Symbols.resize(NumSymbols); | 
|  |  | 
|  | SmallVector<std::pair<Symbol *, uint32_t>, 8> WeakAliases; | 
|  | std::vector<uint32_t> PendingIndexes; | 
|  | PendingIndexes.reserve(NumSymbols); | 
|  |  | 
|  | DenseMap<StringRef, uint32_t> PrevailingSectionMap; | 
|  | std::vector<const coff_aux_section_definition *> ComdatDefs( | 
|  | COFFObj->getNumberOfSections() + 1); | 
|  |  | 
|  | for (uint32_t I = 0; I < NumSymbols; ++I) { | 
|  | COFFSymbolRef COFFSym = check(COFFObj->getSymbol(I)); | 
|  | bool PrevailingComdat; | 
|  | if (COFFSym.isUndefined()) { | 
|  | Symbols[I] = createUndefined(COFFSym); | 
|  | } else if (COFFSym.isWeakExternal()) { | 
|  | Symbols[I] = createUndefined(COFFSym); | 
|  | uint32_t TagIndex = COFFSym.getAux<coff_aux_weak_external>()->TagIndex; | 
|  | WeakAliases.emplace_back(Symbols[I], TagIndex); | 
|  | } else if (Optional<Symbol *> OptSym = | 
|  | createDefined(COFFSym, ComdatDefs, PrevailingComdat)) { | 
|  | Symbols[I] = *OptSym; | 
|  | if (Config->MinGW && PrevailingComdat) | 
|  | recordPrevailingSymbolForMingw(COFFSym, PrevailingSectionMap); | 
|  | } else { | 
|  | // createDefined() returns None if a symbol belongs to a section that | 
|  | // was pending at the point when the symbol was read. This can happen in | 
|  | // two cases: | 
|  | // 1) section definition symbol for a comdat leader; | 
|  | // 2) symbol belongs to a comdat section associated with a section whose | 
|  | //    section definition symbol appears later in the symbol table. | 
|  | // In both of these cases, we can expect the section to be resolved by | 
|  | // the time we finish visiting the remaining symbols in the symbol | 
|  | // table. So we postpone the handling of this symbol until that time. | 
|  | PendingIndexes.push_back(I); | 
|  | } | 
|  | I += COFFSym.getNumberOfAuxSymbols(); | 
|  | } | 
|  |  | 
|  | for (uint32_t I : PendingIndexes) { | 
|  | COFFSymbolRef Sym = check(COFFObj->getSymbol(I)); | 
|  | if (auto *Def = Sym.getSectionDefinition()) { | 
|  | if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) | 
|  | readAssociativeDefinition(Sym, Def); | 
|  | else if (Config->MinGW) | 
|  | maybeAssociateSEHForMingw(Sym, Def, PrevailingSectionMap); | 
|  | } | 
|  | if (SparseChunks[Sym.getSectionNumber()] == PendingComdat) { | 
|  | StringRef Name; | 
|  | COFFObj->getSymbolName(Sym, Name); | 
|  | log("comdat section " + Name + | 
|  | " without leader and unassociated, discarding"); | 
|  | continue; | 
|  | } | 
|  | Symbols[I] = createRegular(Sym); | 
|  | } | 
|  |  | 
|  | for (auto &KV : WeakAliases) { | 
|  | Symbol *Sym = KV.first; | 
|  | uint32_t Idx = KV.second; | 
|  | checkAndSetWeakAlias(Symtab, this, Sym, Symbols[Idx]); | 
|  | } | 
|  | } | 
|  |  | 
|  | Symbol *ObjFile::createUndefined(COFFSymbolRef Sym) { | 
|  | StringRef Name; | 
|  | COFFObj->getSymbolName(Sym, Name); | 
|  | return Symtab->addUndefined(Name, this, Sym.isWeakExternal()); | 
|  | } | 
|  |  | 
|  | Optional<Symbol *> ObjFile::createDefined( | 
|  | COFFSymbolRef Sym, | 
|  | std::vector<const coff_aux_section_definition *> &ComdatDefs, | 
|  | bool &Prevailing) { | 
|  | Prevailing = false; | 
|  | auto GetName = [&]() { | 
|  | StringRef S; | 
|  | COFFObj->getSymbolName(Sym, S); | 
|  | return S; | 
|  | }; | 
|  |  | 
|  | if (Sym.isCommon()) { | 
|  | auto *C = make<CommonChunk>(Sym); | 
|  | Chunks.push_back(C); | 
|  | return Symtab->addCommon(this, GetName(), Sym.getValue(), Sym.getGeneric(), | 
|  | C); | 
|  | } | 
|  |  | 
|  | if (Sym.isAbsolute()) { | 
|  | StringRef Name = GetName(); | 
|  |  | 
|  | // Skip special symbols. | 
|  | if (Name == "@comp.id") | 
|  | return nullptr; | 
|  | if (Name == "@feat.00") { | 
|  | Feat00Flags = Sym.getValue(); | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | if (Sym.isExternal()) | 
|  | return Symtab->addAbsolute(Name, Sym); | 
|  | return make<DefinedAbsolute>(Name, Sym); | 
|  | } | 
|  |  | 
|  | int32_t SectionNumber = Sym.getSectionNumber(); | 
|  | if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG) | 
|  | return nullptr; | 
|  |  | 
|  | if (llvm::COFF::isReservedSectionNumber(SectionNumber)) | 
|  | fatal(toString(this) + ": " + GetName() + | 
|  | " should not refer to special section " + Twine(SectionNumber)); | 
|  |  | 
|  | if ((uint32_t)SectionNumber >= SparseChunks.size()) | 
|  | fatal(toString(this) + ": " + GetName() + | 
|  | " should not refer to non-existent section " + Twine(SectionNumber)); | 
|  |  | 
|  | // Handle comdat leader symbols. | 
|  | if (const coff_aux_section_definition *Def = ComdatDefs[SectionNumber]) { | 
|  | ComdatDefs[SectionNumber] = nullptr; | 
|  | Symbol *Leader; | 
|  | if (Sym.isExternal()) { | 
|  | std::tie(Leader, Prevailing) = | 
|  | Symtab->addComdat(this, GetName(), Sym.getGeneric()); | 
|  | } else { | 
|  | Leader = make<DefinedRegular>(this, /*Name*/ "", false, | 
|  | /*IsExternal*/ false, Sym.getGeneric()); | 
|  | Prevailing = true; | 
|  | } | 
|  |  | 
|  | if (Prevailing) { | 
|  | SectionChunk *C = readSection(SectionNumber, Def, GetName()); | 
|  | SparseChunks[SectionNumber] = C; | 
|  | C->Sym = cast<DefinedRegular>(Leader); | 
|  | cast<DefinedRegular>(Leader)->Data = &C->Repl; | 
|  | } else { | 
|  | SparseChunks[SectionNumber] = nullptr; | 
|  | } | 
|  | return Leader; | 
|  | } | 
|  |  | 
|  | // Read associative section definitions and prepare to handle the comdat | 
|  | // leader symbol by setting the section's ComdatDefs pointer if we encounter a | 
|  | // non-associative comdat. | 
|  | if (SparseChunks[SectionNumber] == PendingComdat) { | 
|  | if (auto *Def = Sym.getSectionDefinition()) { | 
|  | if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) | 
|  | readAssociativeDefinition(Sym, Def); | 
|  | else | 
|  | ComdatDefs[SectionNumber] = Def; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (SparseChunks[SectionNumber] == PendingComdat) | 
|  | return None; | 
|  | return createRegular(Sym); | 
|  | } | 
|  |  | 
|  | MachineTypes ObjFile::getMachineType() { | 
|  | if (COFFObj) | 
|  | return static_cast<MachineTypes>(COFFObj->getMachine()); | 
|  | return IMAGE_FILE_MACHINE_UNKNOWN; | 
|  | } | 
|  |  | 
|  | StringRef ltrim1(StringRef S, const char *Chars) { | 
|  | if (!S.empty() && strchr(Chars, S[0])) | 
|  | return S.substr(1); | 
|  | return S; | 
|  | } | 
|  |  | 
|  | void ImportFile::parse() { | 
|  | const char *Buf = MB.getBufferStart(); | 
|  | const char *End = MB.getBufferEnd(); | 
|  | const auto *Hdr = reinterpret_cast<const coff_import_header *>(Buf); | 
|  |  | 
|  | // Check if the total size is valid. | 
|  | if ((size_t)(End - Buf) != (sizeof(*Hdr) + Hdr->SizeOfData)) | 
|  | fatal("broken import library"); | 
|  |  | 
|  | // Read names and create an __imp_ symbol. | 
|  | StringRef Name = Saver.save(StringRef(Buf + sizeof(*Hdr))); | 
|  | StringRef ImpName = Saver.save("__imp_" + Name); | 
|  | const char *NameStart = Buf + sizeof(coff_import_header) + Name.size() + 1; | 
|  | DLLName = StringRef(NameStart); | 
|  | StringRef ExtName; | 
|  | switch (Hdr->getNameType()) { | 
|  | case IMPORT_ORDINAL: | 
|  | ExtName = ""; | 
|  | break; | 
|  | case IMPORT_NAME: | 
|  | ExtName = Name; | 
|  | break; | 
|  | case IMPORT_NAME_NOPREFIX: | 
|  | ExtName = ltrim1(Name, "?@_"); | 
|  | break; | 
|  | case IMPORT_NAME_UNDECORATE: | 
|  | ExtName = ltrim1(Name, "?@_"); | 
|  | ExtName = ExtName.substr(0, ExtName.find('@')); | 
|  | break; | 
|  | } | 
|  |  | 
|  | this->Hdr = Hdr; | 
|  | ExternalName = ExtName; | 
|  |  | 
|  | ImpSym = Symtab->addImportData(ImpName, this); | 
|  |  | 
|  | if (Hdr->getType() == llvm::COFF::IMPORT_CONST) | 
|  | static_cast<void>(Symtab->addImportData(Name, this)); | 
|  |  | 
|  | // If type is function, we need to create a thunk which jump to an | 
|  | // address pointed by the __imp_ symbol. (This allows you to call | 
|  | // DLL functions just like regular non-DLL functions.) | 
|  | if (Hdr->getType() == llvm::COFF::IMPORT_CODE) | 
|  | ThunkSym = Symtab->addImportThunk( | 
|  | Name, cast_or_null<DefinedImportData>(ImpSym), Hdr->Machine); | 
|  | } | 
|  |  | 
|  | void BitcodeFile::parse() { | 
|  | Obj = check(lto::InputFile::create(MemoryBufferRef( | 
|  | MB.getBuffer(), Saver.save(ParentName + MB.getBufferIdentifier())))); | 
|  | std::vector<std::pair<Symbol *, bool>> Comdat(Obj->getComdatTable().size()); | 
|  | for (size_t I = 0; I != Obj->getComdatTable().size(); ++I) | 
|  | Comdat[I] = Symtab->addComdat(this, Saver.save(Obj->getComdatTable()[I])); | 
|  | for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) { | 
|  | StringRef SymName = Saver.save(ObjSym.getName()); | 
|  | int ComdatIndex = ObjSym.getComdatIndex(); | 
|  | Symbol *Sym; | 
|  | if (ObjSym.isUndefined()) { | 
|  | Sym = Symtab->addUndefined(SymName, this, false); | 
|  | } else if (ObjSym.isCommon()) { | 
|  | Sym = Symtab->addCommon(this, SymName, ObjSym.getCommonSize()); | 
|  | } else if (ObjSym.isWeak() && ObjSym.isIndirect()) { | 
|  | // Weak external. | 
|  | Sym = Symtab->addUndefined(SymName, this, true); | 
|  | std::string Fallback = ObjSym.getCOFFWeakExternalFallback(); | 
|  | Symbol *Alias = Symtab->addUndefined(Saver.save(Fallback)); | 
|  | checkAndSetWeakAlias(Symtab, this, Sym, Alias); | 
|  | } else if (ComdatIndex != -1) { | 
|  | if (SymName == Obj->getComdatTable()[ComdatIndex]) | 
|  | Sym = Comdat[ComdatIndex].first; | 
|  | else if (Comdat[ComdatIndex].second) | 
|  | Sym = Symtab->addRegular(this, SymName); | 
|  | else | 
|  | Sym = Symtab->addUndefined(SymName, this, false); | 
|  | } else { | 
|  | Sym = Symtab->addRegular(this, SymName); | 
|  | } | 
|  | Symbols.push_back(Sym); | 
|  | } | 
|  | Directives = Obj->getCOFFLinkerOpts(); | 
|  | } | 
|  |  | 
|  | MachineTypes BitcodeFile::getMachineType() { | 
|  | switch (Triple(Obj->getTargetTriple()).getArch()) { | 
|  | case Triple::x86_64: | 
|  | return AMD64; | 
|  | case Triple::x86: | 
|  | return I386; | 
|  | case Triple::arm: | 
|  | return ARMNT; | 
|  | case Triple::aarch64: | 
|  | return ARM64; | 
|  | default: | 
|  | return IMAGE_FILE_MACHINE_UNKNOWN; | 
|  | } | 
|  | } | 
|  | } // namespace coff | 
|  | } // namespace lld | 
|  |  | 
|  | // Returns the last element of a path, which is supposed to be a filename. | 
|  | static StringRef getBasename(StringRef Path) { | 
|  | return sys::path::filename(Path, sys::path::Style::windows); | 
|  | } | 
|  |  | 
|  | // Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)". | 
|  | std::string lld::toString(const coff::InputFile *File) { | 
|  | if (!File) | 
|  | return "<internal>"; | 
|  | if (File->ParentName.empty()) | 
|  | return File->getName(); | 
|  |  | 
|  | return (getBasename(File->ParentName) + "(" + getBasename(File->getName()) + | 
|  | ")") | 
|  | .str(); | 
|  | } |