diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h --- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -223,6 +223,35 @@ DenseMap> EHFrameRanges; }; +class LinkGraphMaterializationUnit : public MaterializationUnit { +public: + static std::unique_ptr + Create(ObjectLinkingLayer &ObjLinkingLayer, + std::unique_ptr G); + + StringRef getName() const override { return G->getName(); } + void materialize(std::unique_ptr MR) override { + ObjLinkingLayer.emit(std::move(MR), std::move(G)); + } + +private: + LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer, + std::unique_ptr G, + Interface LGI); + + static Interface scanLinkGraph(ExecutionSession &ES, jitlink::LinkGraph &G); + static bool hasMachOInitSection(jitlink::LinkGraph &G); + static bool hasELFInitSection(jitlink::LinkGraph &G); + + static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, + jitlink::LinkGraph &G); + void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; + + ObjectLinkingLayer &ObjLinkingLayer; + std::unique_ptr G; + static std::atomic Counter; +}; + } // end namespace orc } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp --- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp @@ -20,107 +20,97 @@ using namespace llvm::jitlink; using namespace llvm::orc; -namespace { - -class LinkGraphMaterializationUnit : public MaterializationUnit { -public: - static std::unique_ptr - Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr G) { - auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G); - return std::unique_ptr( - new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G), - std::move(LGI))); - } - - StringRef getName() const override { return G->getName(); } - void materialize(std::unique_ptr MR) override { - ObjLinkingLayer.emit(std::move(MR), std::move(G)); - } - -private: - static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) { - - Interface LGI; - - for (auto *Sym : G.defined_symbols()) { - // Skip local symbols. - if (Sym->getScope() == Scope::Local) - continue; - assert(Sym->hasName() && "Anonymous non-local symbol?"); - - JITSymbolFlags Flags; - if (Sym->getScope() == Scope::Default) - Flags |= JITSymbolFlags::Exported; - - if (Sym->isCallable()) - Flags |= JITSymbolFlags::Callable; - - LGI.SymbolFlags[ES.intern(Sym->getName())] = Flags; - } - - if ((G.getTargetTriple().isOSBinFormatMachO() && hasMachOInitSection(G)) || - (G.getTargetTriple().isOSBinFormatELF() && hasELFInitSection(G))) - LGI.InitSymbol = makeInitSymbol(ES, G); - - return LGI; - } - - static bool hasMachOInitSection(LinkGraph &G) { - for (auto &Sec : G.sections()) - if (Sec.getName() == "__DATA,__objc_selrefs" || - Sec.getName() == "__DATA,__objc_classlist" || - Sec.getName() == "__TEXT,__swift5_protos" || - Sec.getName() == "__TEXT,__swift5_proto" || - Sec.getName() == "__TEXT,__swift5_types" || - Sec.getName() == "__DATA,__mod_init_func") - return true; - return false; - } - - static bool hasELFInitSection(LinkGraph &G) { - for (auto &Sec : G.sections()) { - auto SecName = Sec.getName(); - if (SecName.consume_front(".init_array") && - (SecName.empty() || SecName[0] == '.')) - return true; - } - return false; - } - - static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) { - std::string InitSymString; - raw_string_ostream(InitSymString) - << "$." << G.getName() << ".__inits" << Counter++; - return ES.intern(InitSymString); - } - - LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer, - std::unique_ptr G, Interface LGI) - : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer), - G(std::move(G)) {} - - void discard(const JITDylib &JD, const SymbolStringPtr &Name) override { - for (auto *Sym : G->defined_symbols()) - if (Sym->getName() == *Name) { - assert(Sym->getLinkage() == Linkage::Weak && - "Discarding non-weak definition"); - G->makeExternal(*Sym); - break; - } - } - - ObjectLinkingLayer &ObjLinkingLayer; - std::unique_ptr G; - static std::atomic Counter; -}; - -std::atomic LinkGraphMaterializationUnit::Counter{0}; - -} // end anonymous namespace - namespace llvm { namespace orc { +std::unique_ptr +LinkGraphMaterializationUnit::Create(ObjectLinkingLayer &ObjLinkingLayer, + std::unique_ptr G) { + auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G); + return std::unique_ptr( + new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G), + std::move(LGI))); +} + +AbsoluteSymbolsMaterializationUnit::Interface +LinkGraphMaterializationUnit::scanLinkGraph(ExecutionSession &ES, + LinkGraph &G) { + + Interface LGI; + + for (auto *Sym : G.defined_symbols()) { + // Skip local symbols. + if (Sym->getScope() == Scope::Local) + continue; + assert(Sym->hasName() && "Anonymous non-local symbol?"); + + JITSymbolFlags Flags; + if (Sym->getScope() == Scope::Default) + Flags |= JITSymbolFlags::Exported; + + if (Sym->isCallable()) + Flags |= JITSymbolFlags::Callable; + + LGI.SymbolFlags[ES.intern(Sym->getName())] = Flags; + } + + if ((G.getTargetTriple().isOSBinFormatMachO() && hasMachOInitSection(G)) || + (G.getTargetTriple().isOSBinFormatELF() && hasELFInitSection(G))) + LGI.InitSymbol = makeInitSymbol(ES, G); + + return LGI; +} + +bool LinkGraphMaterializationUnit::hasMachOInitSection(LinkGraph &G) { + for (auto &Sec : G.sections()) + if (Sec.getName() == "__DATA,__objc_selrefs" || + Sec.getName() == "__DATA,__objc_classlist" || + Sec.getName() == "__TEXT,__swift5_protos" || + Sec.getName() == "__TEXT,__swift5_proto" || + Sec.getName() == "__TEXT,__swift5_types" || + Sec.getName() == "__DATA,__mod_init_func") + return true; + return false; +} + +bool LinkGraphMaterializationUnit::hasELFInitSection(LinkGraph &G) { + for (auto &Sec : G.sections()) { + auto SecName = Sec.getName(); + if (SecName.consume_front(".init_array") && + (SecName.empty() || SecName[0] == '.')) + return true; + } + return false; +} + +SymbolStringPtr +LinkGraphMaterializationUnit::makeInitSymbol(ExecutionSession &ES, + LinkGraph &G) { + std::string InitSymString; + raw_string_ostream(InitSymString) + << "$." << G.getName() << ".__inits" << Counter++; + return ES.intern(InitSymString); +} + +LinkGraphMaterializationUnit::LinkGraphMaterializationUnit( + ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr G, + Interface LGI) + : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer), + G(std::move(G)) {} + +void LinkGraphMaterializationUnit::discard(const JITDylib &JD, + const SymbolStringPtr &Name) { + for (auto *Sym : G->defined_symbols()) + if (Sym->getName() == *Name) { + assert(Sym->getLinkage() == Linkage::Weak && + "Discarding non-weak definition"); + G->makeExternal(*Sym); + break; + } +} + +std::atomic LinkGraphMaterializationUnit::Counter{0}; + class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { public: ObjectLinkingLayerJITLinkContext( diff --git a/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp --- a/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp @@ -6,10 +6,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "OrcTestCommon.h" + #include "llvm/ExecutionEngine/JITLink/JITLink.h" #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" #include "llvm/ExecutionEngine/JITLink/x86_64.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" @@ -54,4 +56,29 @@ EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_X"), Succeeded()); } +TEST_F(ObjectLinkingLayerTest, MachOInitSymbol) { + { + auto Graph = + std::make_unique("foo", Triple("x86_64-apple-darwin"), 8, + support::little, x86_64::getEdgeKindName); + Graph->createSection("__DATA,__objc_selrefs", + orc::MemProt::Read | orc::MemProt::Write); + auto Unit = + LinkGraphMaterializationUnit::Create(ObjLinkingLayer, std::move(Graph)); + SymbolStringPtr Expected = ES.intern("$.foo.__inits0"); + EXPECT_EQ(Unit->getInitializerSymbol(), Expected); + } + + { + auto Graph = + std::make_unique("foo", Triple("x86_64-apple-darwin"), 8, + support::little, x86_64::getEdgeKindName); + Graph->createSection("__DATA,__not_an_init_sec", + orc::MemProt::Read | orc::MemProt::Write); + auto Unit = + LinkGraphMaterializationUnit::Create(ObjLinkingLayer, std::move(Graph)); + EXPECT_EQ(Unit->getInitializerSymbol(), nullptr); + } +} + } // end anonymous namespace