diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp | 124 |
1 files changed, 74 insertions, 50 deletions
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp index dc07eaeaf615..3a6162db75c4 100644 --- a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp +++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp @@ -18,13 +18,19 @@ static const char *CommonSectionName = "__common"; namespace llvm { namespace jitlink { +static Triple createTripleWithCOFFFormat(Triple T) { + T.setObjectFormat(Triple::COFF); + return T; +} + COFFLinkGraphBuilder::COFFLinkGraphBuilder( const object::COFFObjectFile &Obj, Triple TT, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName) : Obj(Obj), - G(std::make_unique<LinkGraph>( - Obj.getFileName().str(), Triple(std::move(TT)), getPointerSize(Obj), - getEndianness(Obj), std::move(GetEdgeKindName))) { + G(std::make_unique<LinkGraph>(Obj.getFileName().str(), + createTripleWithCOFFFormat(TT), + getPointerSize(Obj), getEndianness(Obj), + std::move(GetEdgeKindName))) { LLVM_DEBUG({ dbgs() << "Created COFFLinkGraphBuilder for \"" << Obj.getFileName() << "\"\n"; @@ -128,16 +134,6 @@ Error COFFLinkGraphBuilder::graphifySections() { if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(*Sec)) SectionName = *SecNameOrErr; - bool IsDiscardable = - (*Sec)->Characteristics & - (COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_LNK_INFO); - if (IsDiscardable) { - LLVM_DEBUG(dbgs() << " " << SecIndex << ": \"" << SectionName - << "\" is discardable: " - "No graph section will be created.\n"); - continue; - } - // FIXME: Skip debug info sections LLVM_DEBUG({ @@ -145,6 +141,8 @@ Error COFFLinkGraphBuilder::graphifySections() { << "Creating section for \"" << SectionName << "\"\n"; }); + // FIXME: Revisit crash when dropping IMAGE_SCN_MEM_DISCARDABLE sections + // Get the section's memory protection flags. MemProt Prot = MemProt::None; if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE) @@ -190,6 +188,7 @@ Error COFFLinkGraphBuilder::graphifySymbols() { LLVM_DEBUG(dbgs() << " Creating graph symbols...\n"); SymbolSets.resize(Obj.getNumberOfSections() + 1); + PendingComdatExports.resize(Obj.getNumberOfSections() + 1); GraphSymbols.resize(Obj.getNumberOfSymbols()); for (COFFSymbolIndex SymIndex = 0; @@ -232,18 +231,16 @@ Error COFFLinkGraphBuilder::graphifySymbols() { << getCOFFSectionName(SectionIndex, Sec, *Sym) << " (index: " << SectionIndex << ") \n"; }); - GSym = - &G->addExternalSymbol(SymbolName, Sym->getValue(), Linkage::Strong); + if (!ExternalSymbols.count(SymbolName)) + ExternalSymbols[SymbolName] = + &G->addExternalSymbol(SymbolName, Sym->getValue(), Linkage::Strong); + GSym = ExternalSymbols[SymbolName]; } else if (Sym->isWeakExternal()) { - COFFSymbolIndex TagIndex = - Sym->getAux<object::coff_aux_weak_external>()->TagIndex; - assert(Sym->getAux<object::coff_aux_weak_external>()->Characteristics != - COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY && - "IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY is not supported."); - assert(Sym->getAux<object::coff_aux_weak_external>()->Characteristics != - COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY && - "IMAGE_WEAK_EXTERN_SEARCH_LIBRARY is not supported."); - WeakAliasRequests.push_back({SymIndex, TagIndex, SymbolName}); + auto *WeakExternal = Sym->getAux<object::coff_aux_weak_external>(); + COFFSymbolIndex TagIndex = WeakExternal->TagIndex; + uint32_t Characteristics = WeakExternal->Characteristics; + WeakExternalRequests.push_back( + {SymIndex, TagIndex, Characteristics, SymbolName}); } else { Expected<jitlink::Symbol *> NewGSym = createDefinedSymbol(SymIndex, SymbolName, *Sym, Sec); @@ -279,35 +276,41 @@ Error COFFLinkGraphBuilder::graphifySymbols() { Error COFFLinkGraphBuilder::flushWeakAliasRequests() { // Export the weak external symbols and alias it - for (auto &WeakAlias : WeakAliasRequests) { - if (auto *Target = getGraphSymbol(WeakAlias.Target)) { + for (auto &WeakExternal : WeakExternalRequests) { + if (auto *Target = getGraphSymbol(WeakExternal.Target)) { Expected<object::COFFSymbolRef> AliasSymbol = - Obj.getSymbol(WeakAlias.Alias); + Obj.getSymbol(WeakExternal.Alias); if (!AliasSymbol) return AliasSymbol.takeError(); + // FIXME: IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY and + // IMAGE_WEAK_EXTERN_SEARCH_LIBRARY are handled in the same way. + Scope S = + WeakExternal.Characteristics == COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS + ? Scope::Default + : Scope::Local; + // FIXME: Support this when there's a way to handle this. if (!Target->isDefined()) return make_error<JITLinkError>("Weak external symbol with external " "symbol as alternative not supported."); jitlink::Symbol *NewSymbol = &G->addDefinedSymbol( - Target->getBlock(), Target->getOffset(), WeakAlias.SymbolName, - Target->getSize(), Linkage::Weak, Scope::Default, - Target->isCallable(), false); - setGraphSymbol(AliasSymbol->getSectionNumber(), WeakAlias.Alias, + Target->getBlock(), Target->getOffset(), WeakExternal.SymbolName, + Target->getSize(), Linkage::Weak, S, Target->isCallable(), false); + setGraphSymbol(AliasSymbol->getSectionNumber(), WeakExternal.Alias, *NewSymbol); LLVM_DEBUG({ - dbgs() << " " << WeakAlias.Alias + dbgs() << " " << WeakExternal.Alias << ": Creating weak external symbol for COFF symbol \"" - << WeakAlias.SymbolName << "\" in section " + << WeakExternal.SymbolName << "\" in section " << AliasSymbol->getSectionNumber() << "\n"; dbgs() << " " << *NewSymbol << "\n"; }); } else return make_error<JITLinkError>("Weak symbol alias requested but actual " "symbol not found for symbol " + - formatv("{0:d}", WeakAlias.Alias)); + formatv("{0:d}", WeakExternal.Alias)); } return Error::success(); } @@ -324,6 +327,8 @@ Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() { SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections()); SecIndex++) { auto &SymbolSet = SymbolSets[SecIndex]; + if (SymbolSet.empty()) + continue; jitlink::Block *B = getGraphBlock(SecIndex); orc::ExecutorAddrDiff LastOffset = B->getSize(); orc::ExecutorAddrDiff LastDifferentOffset = B->getSize(); @@ -394,25 +399,35 @@ Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol( formatv("{0:d}", SymIndex)); Block *B = getGraphBlock(Symbol.getSectionNumber()); + if (!B) { + LLVM_DEBUG({ + dbgs() << " " << SymIndex + << ": Skipping graph symbol since section was not created for " + "COFF symbol \"" + << SymbolName << "\" in section " << Symbol.getSectionNumber() + << "\n"; + }); + return nullptr; + } + if (Symbol.isExternal()) { // This is not a comdat sequence, export the symbol as it is - if (!isComdatSection(Section)) + if (!isComdatSection(Section)) { + return &G->addDefinedSymbol( *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Default, Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false); - else { - if (!PendingComdatExport) + } else { + if (!PendingComdatExports[Symbol.getSectionNumber()]) return make_error<JITLinkError>("No pending COMDAT export for symbol " + formatv("{0:d}", SymIndex)); - if (PendingComdatExport->SectionIndex != Symbol.getSectionNumber()) - return make_error<JITLinkError>( - "COMDAT export section number mismatch for symbol " + - formatv("{0:d}", SymIndex)); + return exportCOMDATSymbol(SymIndex, SymbolName, Symbol); } } - if (Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC) { + if (Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC || + Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_LABEL) { const object::coff_aux_section_definition *Definition = Symbol.getSectionDefinition(); if (!Definition || !isComdatSection(Section)) { @@ -422,12 +437,14 @@ Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol( Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false); } if (Definition->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - // FIXME: don't dead strip this when parent section is alive - return &G->addDefinedSymbol( + auto Target = Definition->getNumber(Symbol.isBigObj()); + auto GSym = &G->addDefinedSymbol( *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local, Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false); + getGraphBlock(Target)->addEdge(Edge::KeepAlive, 0, *GSym, 0); + return GSym; } - if (PendingComdatExport) + if (PendingComdatExports[Symbol.getSectionNumber()]) return make_error<JITLinkError>( "COMDAT export request already exists before symbol " + formatv("{0:d}", SymIndex)); @@ -474,10 +491,16 @@ Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest( break; } case COFF::IMAGE_COMDAT_SELECT_LARGEST: { - // FIXME: Support IMAGE_COMDAT_SELECT_LARGEST when LinkGraph is able to - // handle this. - return make_error<JITLinkError>( - "IMAGE_COMDAT_SELECT_LARGEST is not supported."); + // FIXME: Support IMAGE_COMDAT_SELECT_LARGEST properly when LinkGraph is + // able to handle this. + LLVM_DEBUG({ + dbgs() << " " << SymIndex + << ": Partially supported IMAGE_COMDAT_SELECT_LARGEST was used" + " in section " + << Symbol.getSectionNumber() << "\n"; + }); + L = Linkage::Weak; + break; } case COFF::IMAGE_COMDAT_SELECT_NEWEST: { // Even link.exe doesn't support this selection properly. @@ -489,7 +512,7 @@ Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest( formatv("{0:d}", Definition->Selection)); } } - PendingComdatExport = {SymIndex, Symbol.getSectionNumber(), L}; + PendingComdatExports[Symbol.getSectionNumber()] = {SymIndex, L}; return &G->addAnonymousSymbol(*B, Symbol.getValue(), Definition->Length, false, false); } @@ -499,6 +522,7 @@ Expected<Symbol *> COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex, StringRef SymbolName, object::COFFSymbolRef Symbol) { + auto &PendingComdatExport = PendingComdatExports[Symbol.getSectionNumber()]; COFFSymbolIndex TargetIndex = PendingComdatExport->SymbolIndex; Linkage L = PendingComdatExport->Linkage; jitlink::Symbol *Target = getGraphSymbol(TargetIndex); |