diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-27 20:11:54 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-08 19:04:48 +0000 |
| commit | 972a253a57b6f144b0e4a3e2080a2a0076ec55a0 (patch) | |
| tree | a8aeeb0997a0a52500f1fa0644244206cf71df94 /contrib/llvm-project/llvm/lib/ExecutionEngine | |
| parent | fcaf7f8644a9988098ac6be2165bce3ea4786e91 (diff) | |
| parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) | |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ExecutionEngine')
6 files changed, 286 insertions, 128 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); diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h index 4dc1b14dc4a2..f925f6d7aeef 100644 --- a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h +++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h @@ -111,19 +111,19 @@ private: // COMDAT sequence. struct ComdatExportRequest { COFFSymbolIndex SymbolIndex; - COFFSectionIndex SectionIndex; jitlink::Linkage Linkage; }; - Optional<ComdatExportRequest> PendingComdatExport; + std::vector<Optional<ComdatExportRequest>> PendingComdatExports; // This represents a pending request to create a weak external symbol with a // name. - struct WeakAliasRequest { + struct WeakExternalRequest { COFFSymbolIndex Alias; COFFSymbolIndex Target; + uint32_t Characteristics; StringRef SymbolName; }; - std::vector<WeakAliasRequest> WeakAliasRequests; + std::vector<WeakExternalRequest> WeakExternalRequests; // Per COFF section jitlink symbol set sorted by offset. // Used for calculating implicit size of defined symbols. @@ -162,6 +162,8 @@ private: Section *CommonSection = nullptr; std::vector<Block *> GraphBlocks; std::vector<Symbol *> GraphSymbols; + + DenseMap<StringRef, Symbol *> ExternalSymbols; }; template <typename RelocHandlerFunction> diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp index 3d36ad1ed767..e2040dc95acc 100644 --- a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp +++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp @@ -12,8 +12,8 @@ #include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h" #include "COFFLinkGraphBuilder.h" -#include "EHFrameSupportImpl.h" #include "JITLinkGeneric.h" +#include "SEHFrameSupport.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/ExecutionEngine/JITLink/x86_64.h" #include "llvm/Object/COFF.h" @@ -26,6 +26,11 @@ using namespace llvm::jitlink; namespace { +enum EdgeKind_coff_x86_64 : Edge::Kind { + PCRel32 = x86_64::FirstPlatformRelocation, + Pointer32NB, +}; + class COFFJITLinker_x86_64 : public JITLinker<COFFJITLinker_x86_64> { friend class JITLinker<COFFJITLinker_x86_64>; @@ -43,27 +48,7 @@ private: class COFFLinkGraphBuilder_x86_64 : public COFFLinkGraphBuilder { private: - uint64_t ImageBase = 0; - enum COFFX86RelocationKind { - COFFAddr32NB, - COFFRel32, - }; - - static Expected<COFFX86RelocationKind> - getRelocationKind(const uint32_t Type) { - switch (Type) { - case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_ADDR32NB: - return COFFAddr32NB; - case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32: - return COFFRel32; - } - - return make_error<JITLinkError>("Unsupported x86_64 relocation:" + - formatv("{0:d}", Type)); - } - Error addRelocations() override { - LLVM_DEBUG(dbgs() << "Processing relocations:\n"); for (const auto &RelSect : sections()) @@ -74,21 +59,9 @@ private: return Error::success(); } - uint64_t getImageBase() { - if (!ImageBase) { - ImageBase = std::numeric_limits<uint64_t>::max(); - for (const auto &Block : getGraph().blocks()) { - if (Block->getAddress().getValue()) - ImageBase = std::min(ImageBase, Block->getAddress().getValue()); - } - } - return ImageBase; - } - Error addSingleRelocation(const object::RelocationRef &Rel, const object::SectionRef &FixupSect, Block &BlockToFix) { - const object::coff_relocation *COFFRel = getObject().getCOFFRelocation(Rel); auto SymbolIt = Rel.getSymbol(); if (SymbolIt == getObject().symbol_end()) { @@ -110,62 +83,122 @@ private: SymIndex, FixupSect.getIndex()), inconvertibleErrorCode()); - Expected<COFFX86RelocationKind> RelocKind = - getRelocationKind(Rel.getType()); - if (!RelocKind) - return RelocKind.takeError(); - int64_t Addend = 0; orc::ExecutorAddr FixupAddress = orc::ExecutorAddr(FixupSect.getAddress()) + Rel.getOffset(); Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); Edge::Kind Kind = Edge::Invalid; + const char *FixupPtr = BlockToFix.getContent().data() + Offset; - switch (*RelocKind) { - case COFFAddr32NB: { - Kind = x86_64::Pointer32; - Offset -= getImageBase(); + switch (Rel.getType()) { + case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_ADDR32NB: { + Kind = EdgeKind_coff_x86_64::Pointer32NB; + Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr); break; } - case COFFRel32: { - Kind = x86_64::BranchPCRel32; + case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32: { + Kind = EdgeKind_coff_x86_64::PCRel32; + Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr); break; } + case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_1: { + Kind = EdgeKind_coff_x86_64::PCRel32; + Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr); + Addend -= 1; + break; + } + default: { + return make_error<JITLinkError>("Unsupported x86_64 relocation:" + + formatv("{0:d}", Rel.getType())); + } }; Edge GE(Kind, Offset, *GraphSymbol, Addend); LLVM_DEBUG({ dbgs() << " "; - printEdge(dbgs(), BlockToFix, GE, x86_64::getEdgeKindName(Kind)); + printEdge(dbgs(), BlockToFix, GE, getCOFFX86RelocationKindName(Kind)); dbgs() << "\n"; }); BlockToFix.addEdge(std::move(GE)); + return Error::success(); } - /// Return the string name of the given COFF x86_64 edge kind. - const char *getCOFFX86RelocationKindName(COFFX86RelocationKind R) { - switch (R) { - case COFFAddr32NB: - return "COFFAddr32NB"; - case COFFRel32: - return "COFFRel32"; +public: + COFFLinkGraphBuilder_x86_64(const object::COFFObjectFile &Obj, const Triple T) + : COFFLinkGraphBuilder(Obj, std::move(T), getCOFFX86RelocationKindName) {} +}; + +class COFFLinkGraphLowering_x86_64 { +public: + // Lowers COFF x86_64 specific edges to generic x86_64 edges. + Error lowerCOFFRelocationEdges(LinkGraph &G, JITLinkContext &Ctx) { + for (auto *B : G.blocks()) { + for (auto &E : B->edges()) { + switch (E.getKind()) { + case EdgeKind_coff_x86_64::Pointer32NB: { + auto ImageBase = getImageBaseAddress(G, Ctx); + if (!ImageBase) + return ImageBase.takeError(); + E.setAddend(E.getAddend() - *ImageBase); + E.setKind(x86_64::Pointer32); + break; + } + case EdgeKind_coff_x86_64::PCRel32: { + E.setKind(x86_64::PCRel32); + break; + } + default: + break; + } + } } + return Error::success(); } -public: - COFFLinkGraphBuilder_x86_64(const object::COFFObjectFile &Obj, const Triple T) - : COFFLinkGraphBuilder(Obj, std::move(T), x86_64::getEdgeKindName) {} +private: + static StringRef getImageBaseSymbolName() { return "__ImageBase"; } + Expected<JITTargetAddress> getImageBaseAddress(LinkGraph &G, + JITLinkContext &Ctx) { + if (this->ImageBase) + return this->ImageBase; + for (auto *S : G.defined_symbols()) + if (S->getName() == getImageBaseSymbolName()) { + this->ImageBase = S->getAddress().getValue(); + return this->ImageBase; + } + + JITLinkContext::LookupMap Symbols; + Symbols[getImageBaseSymbolName()] = SymbolLookupFlags::RequiredSymbol; + JITTargetAddress ImageBase; + Error Err = Error::success(); + Ctx.lookup(Symbols, + createLookupContinuation([&](Expected<AsyncLookupResult> LR) { + ErrorAsOutParameter EAO(&Err); + if (!LR) { + Err = LR.takeError(); + return; + } + auto &ImageBaseSymbol = LR->begin()->second; + ImageBase = ImageBaseSymbol.getAddress(); + })); + if (Err) + return std::move(Err); + this->ImageBase = ImageBase; + return ImageBase; + } + JITTargetAddress ImageBase = 0; }; -Error buildTables_COFF_x86_64(LinkGraph &G) { - LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); +Error lowerEdges_COFF_x86_64(LinkGraph &G, JITLinkContext *Ctx) { + LLVM_DEBUG(dbgs() << "Lowering COFF x86_64 edges:\n"); + COFFLinkGraphLowering_x86_64 GraphLowering; + + if (auto Err = GraphLowering.lowerCOFFRelocationEdges(G, *Ctx)) + return Err; - x86_64::GOTTableManager GOT; - x86_64::PLTTableManager PLT(GOT); - visitExistingEdges(G, GOT, PLT); return Error::success(); } } // namespace @@ -173,6 +206,18 @@ Error buildTables_COFF_x86_64(LinkGraph &G) { namespace llvm { namespace jitlink { +/// Return the string name of the given COFF x86_64 edge kind. +const char *getCOFFX86RelocationKindName(Edge::Kind R) { + switch (R) { + case PCRel32: + return "PCRel32"; + case Pointer32NB: + return "Pointer32NB"; + default: + return x86_64::getEdgeKindName(R); + } +} + Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromCOFFObject_x86_64(MemoryBufferRef ObjectBuffer) { LLVM_DEBUG({ @@ -194,16 +239,16 @@ void link_COFF_x86_64(std::unique_ptr<LinkGraph> G, const Triple &TT = G->getTargetTriple(); if (Ctx->shouldAddDefaultTargetPasses(TT)) { // Add a mark-live pass. - if (auto MarkLive = Ctx->getMarkLivePass(TT)) + if (auto MarkLive = Ctx->getMarkLivePass(TT)) { Config.PrePrunePasses.push_back(std::move(MarkLive)); - else + Config.PrePrunePasses.push_back(SEHFrameKeepAlivePass(".pdata")); + } else Config.PrePrunePasses.push_back(markAllSymbolsLive); - // Add an in-place GOT/Stubs/TLSInfoEntry build pass. - Config.PostPrunePasses.push_back(buildTables_COFF_x86_64); - - // Add GOT/Stubs optimizer pass. - Config.PreFixupPasses.push_back(x86_64::optimizeGOTAndStubAccesses); + // Add COFF edge lowering passes. + JITLinkContext *CtxPtr = Ctx.get(); + Config.PreFixupPasses.push_back( + [CtxPtr](LinkGraph &G) { return lowerEdges_COFF_x86_64(G, CtxPtr); }); } if (auto Err = Ctx->modifyPassConfig(*G, Config)) diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h new file mode 100644 index 000000000000..f7689e4e4043 --- /dev/null +++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h @@ -0,0 +1,61 @@ +//===------- SEHFrameSupport.h - JITLink seh-frame utils --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// SEHFrame utils for JITLink. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITLINK_SEHFRAMESUPPORT_H +#define LLVM_EXECUTIONENGINE_JITLINK_SEHFRAMESUPPORT_H + +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/JITLink/JITLink.h" +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace jitlink { +/// This pass adds keep-alive edge from SEH frame sections +/// to the parent function content block. +class SEHFrameKeepAlivePass { +public: + SEHFrameKeepAlivePass(StringRef SEHFrameSectionName) + : SEHFrameSectionName(SEHFrameSectionName) {} + + Error operator()(LinkGraph &G) { + auto *S = G.findSectionByName(SEHFrameSectionName); + if (!S) + return Error::success(); + + // Simply consider every block pointed by seh frame block as parants. + // This adds some unnecessary keep-alive edges to unwind info blocks, + // (xdata) but these blocks are usually dead by default, so they wouldn't + // count for the fate of seh frame block. + for (auto *B : S->blocks()) { + auto &DummySymbol = G.addAnonymousSymbol(*B, 0, 0, false, false); + DenseSet<Block *> Children; + for (auto &E : B->edges()) { + auto &Sym = E.getTarget(); + if (!Sym.isDefined()) + continue; + Children.insert(&Sym.getBlock()); + } + for (auto *Child : Children) + Child->addEdge(Edge(Edge::KeepAlive, 0, DummySymbol, 0)); + } + return Error::success(); + } + +private: + StringRef SEHFrameSectionName; +}; + +} // end namespace jitlink +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_JITLINK_SEHFRAMESUPPORT_H
\ No newline at end of file diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp index df9979b47e88..393250a5578b 100644 --- a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp +++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp @@ -36,6 +36,8 @@ const char *getEdgeKindName(Edge::Kind K) { return "NegDelta32"; case Delta64FromGOT: return "Delta64FromGOT"; + case PCRel32: + return "PCRel32"; case BranchPCRel32: return "BranchPCRel32"; case BranchPCRel32ToPtrJumpStub: diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp index 356b81b4f1c5..3de15db3f1c6 100644 --- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp +++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp @@ -150,16 +150,39 @@ static Expected<MaterializationUnit::Interface> getCOFFObjectFileSymbolInfo(ExecutionSession &ES, const object::COFFObjectFile &Obj) { MaterializationUnit::Interface I; - + std::vector<Optional<object::coff_aux_section_definition>> ComdatDefs( + Obj.getNumberOfSections() + 1); for (auto &Sym : Obj.symbols()) { Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); if (!SymFlagsOrErr) // TODO: Test this error. return SymFlagsOrErr.takeError(); - // Skip symbols not defined in this object file. - if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) - continue; + // Handle comdat symbols + auto COFFSym = Obj.getCOFFSymbol(Sym); + bool IsWeak = false; + if (auto *Def = COFFSym.getSectionDefinition()) { + auto Sec = Obj.getSection(COFFSym.getSectionNumber()); + if (!Sec) + return Sec.takeError(); + if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) && + Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { + ComdatDefs[COFFSym.getSectionNumber()] = *Def; + continue; + } + } + if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) && + ComdatDefs[COFFSym.getSectionNumber()]) { + auto Def = ComdatDefs[COFFSym.getSectionNumber()]; + if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) { + IsWeak = true; + } + ComdatDefs[COFFSym.getSectionNumber()] = None; + } else { + // Skip symbols not defined in this object file. + if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) + continue; + } // Skip symbols that are not global. if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) @@ -180,12 +203,13 @@ getCOFFObjectFileSymbolInfo(ExecutionSession &ES, if (!SymFlags) return SymFlags.takeError(); *SymFlags |= JITSymbolFlags::Exported; - auto COFFSym = Obj.getCOFFSymbol(Sym); // Weak external is always a function - if (COFFSym.isWeakExternal()) { + if (COFFSym.isWeakExternal()) *SymFlags |= JITSymbolFlags::Callable; - } + + if (IsWeak) + *SymFlags |= JITSymbolFlags::Weak; I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags); } |
