1bdd1243dSDimitry Andric //===------- COFFPlatform.cpp - Utilities for executing COFF in Orc -------===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric
9bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
10bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
11bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
12bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
1306c3fb27SDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
14bdd1243dSDimitry Andric
15bdd1243dSDimitry Andric #include "llvm/Object/COFF.h"
16bdd1243dSDimitry Andric
17bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
18bdd1243dSDimitry Andric
19bdd1243dSDimitry Andric #include "llvm/ExecutionEngine/JITLink/x86_64.h"
20bdd1243dSDimitry Andric
21bdd1243dSDimitry Andric #define DEBUG_TYPE "orc"
22bdd1243dSDimitry Andric
23bdd1243dSDimitry Andric using namespace llvm;
24bdd1243dSDimitry Andric using namespace llvm::orc;
25bdd1243dSDimitry Andric using namespace llvm::orc::shared;
26bdd1243dSDimitry Andric
27bdd1243dSDimitry Andric namespace llvm {
28bdd1243dSDimitry Andric namespace orc {
29bdd1243dSDimitry Andric namespace shared {
30bdd1243dSDimitry Andric
31bdd1243dSDimitry Andric using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>;
32bdd1243dSDimitry Andric using SPSCOFFJITDylibDepInfoMap =
33bdd1243dSDimitry Andric SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>;
34bdd1243dSDimitry Andric using SPSCOFFObjectSectionsMap =
35bdd1243dSDimitry Andric SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
36bdd1243dSDimitry Andric using SPSCOFFRegisterObjectSectionsArgs =
37bdd1243dSDimitry Andric SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap, bool>;
38bdd1243dSDimitry Andric using SPSCOFFDeregisterObjectSectionsArgs =
39bdd1243dSDimitry Andric SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap>;
40bdd1243dSDimitry Andric
41bdd1243dSDimitry Andric } // namespace shared
42bdd1243dSDimitry Andric } // namespace orc
43bdd1243dSDimitry Andric } // namespace llvm
44bdd1243dSDimitry Andric namespace {
45bdd1243dSDimitry Andric
46bdd1243dSDimitry Andric class COFFHeaderMaterializationUnit : public MaterializationUnit {
47bdd1243dSDimitry Andric public:
COFFHeaderMaterializationUnit(COFFPlatform & CP,const SymbolStringPtr & HeaderStartSymbol)48bdd1243dSDimitry Andric COFFHeaderMaterializationUnit(COFFPlatform &CP,
49bdd1243dSDimitry Andric const SymbolStringPtr &HeaderStartSymbol)
50bdd1243dSDimitry Andric : MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)),
51bdd1243dSDimitry Andric CP(CP) {}
52bdd1243dSDimitry Andric
getName() const53bdd1243dSDimitry Andric StringRef getName() const override { return "COFFHeaderMU"; }
54bdd1243dSDimitry Andric
materialize(std::unique_ptr<MaterializationResponsibility> R)55bdd1243dSDimitry Andric void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
56bdd1243dSDimitry Andric unsigned PointerSize;
57*5f757f3fSDimitry Andric llvm::endianness Endianness;
5806c3fb27SDimitry Andric const auto &TT = CP.getExecutionSession().getTargetTriple();
59bdd1243dSDimitry Andric
60bdd1243dSDimitry Andric switch (TT.getArch()) {
61bdd1243dSDimitry Andric case Triple::x86_64:
62bdd1243dSDimitry Andric PointerSize = 8;
63*5f757f3fSDimitry Andric Endianness = llvm::endianness::little;
64bdd1243dSDimitry Andric break;
65bdd1243dSDimitry Andric default:
66bdd1243dSDimitry Andric llvm_unreachable("Unrecognized architecture");
67bdd1243dSDimitry Andric }
68bdd1243dSDimitry Andric
69bdd1243dSDimitry Andric auto G = std::make_unique<jitlink::LinkGraph>(
70bdd1243dSDimitry Andric "<COFFHeaderMU>", TT, PointerSize, Endianness,
71bdd1243dSDimitry Andric jitlink::getGenericEdgeKindName);
72bdd1243dSDimitry Andric auto &HeaderSection = G->createSection("__header", MemProt::Read);
73bdd1243dSDimitry Andric auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
74bdd1243dSDimitry Andric
75bdd1243dSDimitry Andric // Init symbol is __ImageBase symbol.
76bdd1243dSDimitry Andric auto &ImageBaseSymbol = G->addDefinedSymbol(
77bdd1243dSDimitry Andric HeaderBlock, 0, *R->getInitializerSymbol(), HeaderBlock.getSize(),
78bdd1243dSDimitry Andric jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
79bdd1243dSDimitry Andric
80bdd1243dSDimitry Andric addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol);
81bdd1243dSDimitry Andric
82bdd1243dSDimitry Andric CP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
83bdd1243dSDimitry Andric }
84bdd1243dSDimitry Andric
discard(const JITDylib & JD,const SymbolStringPtr & Sym)85bdd1243dSDimitry Andric void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
86bdd1243dSDimitry Andric
87bdd1243dSDimitry Andric private:
88bdd1243dSDimitry Andric struct HeaderSymbol {
89bdd1243dSDimitry Andric const char *Name;
90bdd1243dSDimitry Andric uint64_t Offset;
91bdd1243dSDimitry Andric };
92bdd1243dSDimitry Andric
93bdd1243dSDimitry Andric struct NTHeader {
94bdd1243dSDimitry Andric support::ulittle32_t PEMagic;
95bdd1243dSDimitry Andric object::coff_file_header FileHeader;
96bdd1243dSDimitry Andric struct PEHeader {
97bdd1243dSDimitry Andric object::pe32plus_header Header;
98bdd1243dSDimitry Andric object::data_directory DataDirectory[COFF::NUM_DATA_DIRECTORIES + 1];
99bdd1243dSDimitry Andric } OptionalHeader;
100bdd1243dSDimitry Andric };
101bdd1243dSDimitry Andric
102bdd1243dSDimitry Andric struct HeaderBlockContent {
103bdd1243dSDimitry Andric object::dos_header DOSHeader;
104bdd1243dSDimitry Andric COFFHeaderMaterializationUnit::NTHeader NTHeader;
105bdd1243dSDimitry Andric };
106bdd1243dSDimitry Andric
createHeaderBlock(jitlink::LinkGraph & G,jitlink::Section & HeaderSection)107bdd1243dSDimitry Andric static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
108bdd1243dSDimitry Andric jitlink::Section &HeaderSection) {
109bdd1243dSDimitry Andric HeaderBlockContent Hdr = {};
110bdd1243dSDimitry Andric
111bdd1243dSDimitry Andric // Set up magic
112bdd1243dSDimitry Andric Hdr.DOSHeader.Magic[0] = 'M';
113bdd1243dSDimitry Andric Hdr.DOSHeader.Magic[1] = 'Z';
114bdd1243dSDimitry Andric Hdr.DOSHeader.AddressOfNewExeHeader =
115bdd1243dSDimitry Andric offsetof(HeaderBlockContent, NTHeader);
116bdd1243dSDimitry Andric uint32_t PEMagic = *reinterpret_cast<const uint32_t *>(COFF::PEMagic);
117bdd1243dSDimitry Andric Hdr.NTHeader.PEMagic = PEMagic;
118bdd1243dSDimitry Andric Hdr.NTHeader.OptionalHeader.Header.Magic = COFF::PE32Header::PE32_PLUS;
119bdd1243dSDimitry Andric
120bdd1243dSDimitry Andric switch (G.getTargetTriple().getArch()) {
121bdd1243dSDimitry Andric case Triple::x86_64:
122bdd1243dSDimitry Andric Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
123bdd1243dSDimitry Andric break;
124bdd1243dSDimitry Andric default:
125bdd1243dSDimitry Andric llvm_unreachable("Unrecognized architecture");
126bdd1243dSDimitry Andric }
127bdd1243dSDimitry Andric
12806c3fb27SDimitry Andric auto HeaderContent = G.allocateContent(
12906c3fb27SDimitry Andric ArrayRef<char>(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
130bdd1243dSDimitry Andric
131bdd1243dSDimitry Andric return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
132bdd1243dSDimitry Andric 0);
133bdd1243dSDimitry Andric }
134bdd1243dSDimitry Andric
addImageBaseRelocationEdge(jitlink::Block & B,jitlink::Symbol & ImageBase)135bdd1243dSDimitry Andric static void addImageBaseRelocationEdge(jitlink::Block &B,
136bdd1243dSDimitry Andric jitlink::Symbol &ImageBase) {
137bdd1243dSDimitry Andric auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader) +
138bdd1243dSDimitry Andric offsetof(NTHeader, OptionalHeader) +
139bdd1243dSDimitry Andric offsetof(object::pe32plus_header, ImageBase);
140bdd1243dSDimitry Andric B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0);
141bdd1243dSDimitry Andric }
142bdd1243dSDimitry Andric
143bdd1243dSDimitry Andric static MaterializationUnit::Interface
createHeaderInterface(COFFPlatform & MOP,const SymbolStringPtr & HeaderStartSymbol)144bdd1243dSDimitry Andric createHeaderInterface(COFFPlatform &MOP,
145bdd1243dSDimitry Andric const SymbolStringPtr &HeaderStartSymbol) {
146bdd1243dSDimitry Andric SymbolFlagsMap HeaderSymbolFlags;
147bdd1243dSDimitry Andric
148bdd1243dSDimitry Andric HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
149bdd1243dSDimitry Andric
150bdd1243dSDimitry Andric return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
151bdd1243dSDimitry Andric HeaderStartSymbol);
152bdd1243dSDimitry Andric }
153bdd1243dSDimitry Andric
154bdd1243dSDimitry Andric COFFPlatform &CP;
155bdd1243dSDimitry Andric };
156bdd1243dSDimitry Andric
157bdd1243dSDimitry Andric } // end anonymous namespace
158bdd1243dSDimitry Andric
159bdd1243dSDimitry Andric namespace llvm {
160bdd1243dSDimitry Andric namespace orc {
161bdd1243dSDimitry Andric
Create(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,LoadDynamicLibrary LoadDynLibrary,bool StaticVCRuntime,const char * VCRuntimePath,std::optional<SymbolAliasMap> RuntimeAliases)16206c3fb27SDimitry Andric Expected<std::unique_ptr<COFFPlatform>> COFFPlatform::Create(
16306c3fb27SDimitry Andric ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
16406c3fb27SDimitry Andric JITDylib &PlatformJD, std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,
165bdd1243dSDimitry Andric LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
16606c3fb27SDimitry Andric const char *VCRuntimePath, std::optional<SymbolAliasMap> RuntimeAliases) {
167bdd1243dSDimitry Andric
168bdd1243dSDimitry Andric // If the target is not supported then bail out immediately.
16906c3fb27SDimitry Andric if (!supportedTarget(ES.getTargetTriple()))
170bdd1243dSDimitry Andric return make_error<StringError>("Unsupported COFFPlatform triple: " +
17106c3fb27SDimitry Andric ES.getTargetTriple().str(),
172bdd1243dSDimitry Andric inconvertibleErrorCode());
173bdd1243dSDimitry Andric
17406c3fb27SDimitry Andric auto &EPC = ES.getExecutorProcessControl();
17506c3fb27SDimitry Andric
17606c3fb27SDimitry Andric auto GeneratorArchive =
17706c3fb27SDimitry Andric object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef());
17806c3fb27SDimitry Andric if (!GeneratorArchive)
17906c3fb27SDimitry Andric return GeneratorArchive.takeError();
18006c3fb27SDimitry Andric
18106c3fb27SDimitry Andric auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Create(
18206c3fb27SDimitry Andric ObjLinkingLayer, nullptr, std::move(*GeneratorArchive));
18306c3fb27SDimitry Andric if (!OrcRuntimeArchiveGenerator)
18406c3fb27SDimitry Andric return OrcRuntimeArchiveGenerator.takeError();
18506c3fb27SDimitry Andric
18606c3fb27SDimitry Andric // We need a second instance of the archive (for now) for the Platform. We
18706c3fb27SDimitry Andric // can `cantFail` this call, since if it were going to fail it would have
18806c3fb27SDimitry Andric // failed above.
18906c3fb27SDimitry Andric auto RuntimeArchive = cantFail(
19006c3fb27SDimitry Andric object::Archive::create(OrcRuntimeArchiveBuffer->getMemBufferRef()));
19106c3fb27SDimitry Andric
192bdd1243dSDimitry Andric // Create default aliases if the caller didn't supply any.
193bdd1243dSDimitry Andric if (!RuntimeAliases)
194bdd1243dSDimitry Andric RuntimeAliases = standardPlatformAliases(ES);
195bdd1243dSDimitry Andric
196bdd1243dSDimitry Andric // Define the aliases.
197bdd1243dSDimitry Andric if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
198bdd1243dSDimitry Andric return std::move(Err);
199bdd1243dSDimitry Andric
200bdd1243dSDimitry Andric auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");
201bdd1243dSDimitry Andric
202bdd1243dSDimitry Andric // Add JIT-dispatch function support symbols.
20306c3fb27SDimitry Andric if (auto Err = HostFuncJD.define(
20406c3fb27SDimitry Andric absoluteSymbols({{ES.intern("__orc_rt_jit_dispatch"),
20506c3fb27SDimitry Andric {EPC.getJITDispatchInfo().JITDispatchFunction,
206bdd1243dSDimitry Andric JITSymbolFlags::Exported}},
207bdd1243dSDimitry Andric {ES.intern("__orc_rt_jit_dispatch_ctx"),
20806c3fb27SDimitry Andric {EPC.getJITDispatchInfo().JITDispatchContext,
209bdd1243dSDimitry Andric JITSymbolFlags::Exported}}})))
210bdd1243dSDimitry Andric return std::move(Err);
211bdd1243dSDimitry Andric
212bdd1243dSDimitry Andric PlatformJD.addToLinkOrder(HostFuncJD);
213bdd1243dSDimitry Andric
214bdd1243dSDimitry Andric // Create the instance.
215bdd1243dSDimitry Andric Error Err = Error::success();
216bdd1243dSDimitry Andric auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(
21706c3fb27SDimitry Andric ES, ObjLinkingLayer, PlatformJD, std::move(*OrcRuntimeArchiveGenerator),
21806c3fb27SDimitry Andric std::move(OrcRuntimeArchiveBuffer), std::move(RuntimeArchive),
219bdd1243dSDimitry Andric std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));
220bdd1243dSDimitry Andric if (Err)
221bdd1243dSDimitry Andric return std::move(Err);
222bdd1243dSDimitry Andric return std::move(P);
223bdd1243dSDimitry Andric }
224bdd1243dSDimitry Andric
22506c3fb27SDimitry Andric Expected<std::unique_ptr<COFFPlatform>>
Create(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,const char * OrcRuntimePath,LoadDynamicLibrary LoadDynLibrary,bool StaticVCRuntime,const char * VCRuntimePath,std::optional<SymbolAliasMap> RuntimeAliases)22606c3fb27SDimitry Andric COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
22706c3fb27SDimitry Andric JITDylib &PlatformJD, const char *OrcRuntimePath,
22806c3fb27SDimitry Andric LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
22906c3fb27SDimitry Andric const char *VCRuntimePath,
23006c3fb27SDimitry Andric std::optional<SymbolAliasMap> RuntimeAliases) {
23106c3fb27SDimitry Andric
23206c3fb27SDimitry Andric auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
23306c3fb27SDimitry Andric if (!ArchiveBuffer)
23406c3fb27SDimitry Andric return createFileError(OrcRuntimePath, ArchiveBuffer.getError());
23506c3fb27SDimitry Andric
23606c3fb27SDimitry Andric return Create(ES, ObjLinkingLayer, PlatformJD, std::move(*ArchiveBuffer),
23706c3fb27SDimitry Andric std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath,
23806c3fb27SDimitry Andric std::move(RuntimeAliases));
23906c3fb27SDimitry Andric }
24006c3fb27SDimitry Andric
getPerJDObjectFile()241bdd1243dSDimitry Andric Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
242bdd1243dSDimitry Andric auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
243bdd1243dSDimitry Andric if (!PerJDObj)
244bdd1243dSDimitry Andric return PerJDObj.takeError();
245bdd1243dSDimitry Andric
246bdd1243dSDimitry Andric if (!*PerJDObj)
247bdd1243dSDimitry Andric return make_error<StringError>("Could not find per jd object file",
248bdd1243dSDimitry Andric inconvertibleErrorCode());
249bdd1243dSDimitry Andric
250bdd1243dSDimitry Andric auto Buffer = (*PerJDObj)->getAsBinary();
251bdd1243dSDimitry Andric if (!Buffer)
252bdd1243dSDimitry Andric return Buffer.takeError();
253bdd1243dSDimitry Andric
254bdd1243dSDimitry Andric return (*Buffer)->getMemoryBufferRef();
255bdd1243dSDimitry Andric }
256bdd1243dSDimitry Andric
addAliases(ExecutionSession & ES,SymbolAliasMap & Aliases,ArrayRef<std::pair<const char *,const char * >> AL)257bdd1243dSDimitry Andric static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
258bdd1243dSDimitry Andric ArrayRef<std::pair<const char *, const char *>> AL) {
259bdd1243dSDimitry Andric for (auto &KV : AL) {
260bdd1243dSDimitry Andric auto AliasName = ES.intern(KV.first);
261bdd1243dSDimitry Andric assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
262bdd1243dSDimitry Andric Aliases[std::move(AliasName)] = {ES.intern(KV.second),
263bdd1243dSDimitry Andric JITSymbolFlags::Exported};
264bdd1243dSDimitry Andric }
265bdd1243dSDimitry Andric }
266bdd1243dSDimitry Andric
setupJITDylib(JITDylib & JD)267bdd1243dSDimitry Andric Error COFFPlatform::setupJITDylib(JITDylib &JD) {
268bdd1243dSDimitry Andric if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>(
269bdd1243dSDimitry Andric *this, COFFHeaderStartSymbol)))
270bdd1243dSDimitry Andric return Err;
271bdd1243dSDimitry Andric
272bdd1243dSDimitry Andric if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError())
273bdd1243dSDimitry Andric return Err;
274bdd1243dSDimitry Andric
275bdd1243dSDimitry Andric // Define the CXX aliases.
276bdd1243dSDimitry Andric SymbolAliasMap CXXAliases;
277bdd1243dSDimitry Andric addAliases(ES, CXXAliases, requiredCXXAliases());
278bdd1243dSDimitry Andric if (auto Err = JD.define(symbolAliases(std::move(CXXAliases))))
279bdd1243dSDimitry Andric return Err;
280bdd1243dSDimitry Andric
281bdd1243dSDimitry Andric auto PerJDObj = getPerJDObjectFile();
282bdd1243dSDimitry Andric if (!PerJDObj)
283bdd1243dSDimitry Andric return PerJDObj.takeError();
284bdd1243dSDimitry Andric
285bdd1243dSDimitry Andric auto I = getObjectFileInterface(ES, *PerJDObj);
286bdd1243dSDimitry Andric if (!I)
287bdd1243dSDimitry Andric return I.takeError();
288bdd1243dSDimitry Andric
289bdd1243dSDimitry Andric if (auto Err = ObjLinkingLayer.add(
290bdd1243dSDimitry Andric JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I)))
291bdd1243dSDimitry Andric return Err;
292bdd1243dSDimitry Andric
293bdd1243dSDimitry Andric if (!Bootstrapping) {
294bdd1243dSDimitry Andric auto ImportedLibs = StaticVCRuntime
295bdd1243dSDimitry Andric ? VCRuntimeBootstrap->loadStaticVCRuntime(JD)
296bdd1243dSDimitry Andric : VCRuntimeBootstrap->loadDynamicVCRuntime(JD);
297bdd1243dSDimitry Andric if (!ImportedLibs)
298bdd1243dSDimitry Andric return ImportedLibs.takeError();
299bdd1243dSDimitry Andric for (auto &Lib : *ImportedLibs)
300bdd1243dSDimitry Andric if (auto Err = LoadDynLibrary(JD, Lib))
301bdd1243dSDimitry Andric return Err;
302bdd1243dSDimitry Andric if (StaticVCRuntime)
303bdd1243dSDimitry Andric if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD))
304bdd1243dSDimitry Andric return Err;
305bdd1243dSDimitry Andric }
306bdd1243dSDimitry Andric
307bdd1243dSDimitry Andric JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer));
308bdd1243dSDimitry Andric return Error::success();
309bdd1243dSDimitry Andric }
310bdd1243dSDimitry Andric
teardownJITDylib(JITDylib & JD)311bdd1243dSDimitry Andric Error COFFPlatform::teardownJITDylib(JITDylib &JD) {
312bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex);
313bdd1243dSDimitry Andric auto I = JITDylibToHeaderAddr.find(&JD);
314bdd1243dSDimitry Andric if (I != JITDylibToHeaderAddr.end()) {
315bdd1243dSDimitry Andric assert(HeaderAddrToJITDylib.count(I->second) &&
316bdd1243dSDimitry Andric "HeaderAddrToJITDylib missing entry");
317bdd1243dSDimitry Andric HeaderAddrToJITDylib.erase(I->second);
318bdd1243dSDimitry Andric JITDylibToHeaderAddr.erase(I);
319bdd1243dSDimitry Andric }
320bdd1243dSDimitry Andric return Error::success();
321bdd1243dSDimitry Andric }
322bdd1243dSDimitry Andric
notifyAdding(ResourceTracker & RT,const MaterializationUnit & MU)323bdd1243dSDimitry Andric Error COFFPlatform::notifyAdding(ResourceTracker &RT,
324bdd1243dSDimitry Andric const MaterializationUnit &MU) {
325bdd1243dSDimitry Andric auto &JD = RT.getJITDylib();
326bdd1243dSDimitry Andric const auto &InitSym = MU.getInitializerSymbol();
327bdd1243dSDimitry Andric if (!InitSym)
328bdd1243dSDimitry Andric return Error::success();
329bdd1243dSDimitry Andric
330bdd1243dSDimitry Andric RegisteredInitSymbols[&JD].add(InitSym,
331bdd1243dSDimitry Andric SymbolLookupFlags::WeaklyReferencedSymbol);
332bdd1243dSDimitry Andric
333bdd1243dSDimitry Andric LLVM_DEBUG({
334bdd1243dSDimitry Andric dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU "
335bdd1243dSDimitry Andric << MU.getName() << "\n";
336bdd1243dSDimitry Andric });
337bdd1243dSDimitry Andric return Error::success();
338bdd1243dSDimitry Andric }
339bdd1243dSDimitry Andric
notifyRemoving(ResourceTracker & RT)340bdd1243dSDimitry Andric Error COFFPlatform::notifyRemoving(ResourceTracker &RT) {
341bdd1243dSDimitry Andric llvm_unreachable("Not supported yet");
342bdd1243dSDimitry Andric }
343bdd1243dSDimitry Andric
standardPlatformAliases(ExecutionSession & ES)344bdd1243dSDimitry Andric SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) {
345bdd1243dSDimitry Andric SymbolAliasMap Aliases;
346bdd1243dSDimitry Andric addAliases(ES, Aliases, standardRuntimeUtilityAliases());
347bdd1243dSDimitry Andric return Aliases;
348bdd1243dSDimitry Andric }
349bdd1243dSDimitry Andric
350bdd1243dSDimitry Andric ArrayRef<std::pair<const char *, const char *>>
requiredCXXAliases()351bdd1243dSDimitry Andric COFFPlatform::requiredCXXAliases() {
352bdd1243dSDimitry Andric static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
353bdd1243dSDimitry Andric {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},
354bdd1243dSDimitry Andric {"_onexit", "__orc_rt_coff_onexit_per_jd"},
355bdd1243dSDimitry Andric {"atexit", "__orc_rt_coff_atexit_per_jd"}};
356bdd1243dSDimitry Andric
357bdd1243dSDimitry Andric return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
358bdd1243dSDimitry Andric }
359bdd1243dSDimitry Andric
360bdd1243dSDimitry Andric ArrayRef<std::pair<const char *, const char *>>
standardRuntimeUtilityAliases()361bdd1243dSDimitry Andric COFFPlatform::standardRuntimeUtilityAliases() {
362bdd1243dSDimitry Andric static const std::pair<const char *, const char *>
363bdd1243dSDimitry Andric StandardRuntimeUtilityAliases[] = {
364bdd1243dSDimitry Andric {"__orc_rt_run_program", "__orc_rt_coff_run_program"},
365bdd1243dSDimitry Andric {"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"},
366bdd1243dSDimitry Andric {"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"},
367bdd1243dSDimitry Andric {"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"},
368bdd1243dSDimitry Andric {"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"},
369bdd1243dSDimitry Andric {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
370bdd1243dSDimitry Andric
371bdd1243dSDimitry Andric return ArrayRef<std::pair<const char *, const char *>>(
372bdd1243dSDimitry Andric StandardRuntimeUtilityAliases);
373bdd1243dSDimitry Andric }
374bdd1243dSDimitry Andric
supportedTarget(const Triple & TT)375bdd1243dSDimitry Andric bool COFFPlatform::supportedTarget(const Triple &TT) {
376bdd1243dSDimitry Andric switch (TT.getArch()) {
377bdd1243dSDimitry Andric case Triple::x86_64:
378bdd1243dSDimitry Andric return true;
379bdd1243dSDimitry Andric default:
380bdd1243dSDimitry Andric return false;
381bdd1243dSDimitry Andric }
382bdd1243dSDimitry Andric }
383bdd1243dSDimitry Andric
COFFPlatform(ExecutionSession & ES,ObjectLinkingLayer & ObjLinkingLayer,JITDylib & PlatformJD,std::unique_ptr<StaticLibraryDefinitionGenerator> OrcRuntimeGenerator,std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,std::unique_ptr<object::Archive> OrcRuntimeArchive,LoadDynamicLibrary LoadDynLibrary,bool StaticVCRuntime,const char * VCRuntimePath,Error & Err)38406c3fb27SDimitry Andric COFFPlatform::COFFPlatform(
38506c3fb27SDimitry Andric ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
38606c3fb27SDimitry Andric JITDylib &PlatformJD,
38706c3fb27SDimitry Andric std::unique_ptr<StaticLibraryDefinitionGenerator> OrcRuntimeGenerator,
38806c3fb27SDimitry Andric std::unique_ptr<MemoryBuffer> OrcRuntimeArchiveBuffer,
38906c3fb27SDimitry Andric std::unique_ptr<object::Archive> OrcRuntimeArchive,
39006c3fb27SDimitry Andric LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
39106c3fb27SDimitry Andric const char *VCRuntimePath, Error &Err)
392bdd1243dSDimitry Andric : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
393bdd1243dSDimitry Andric LoadDynLibrary(std::move(LoadDynLibrary)),
39406c3fb27SDimitry Andric OrcRuntimeArchiveBuffer(std::move(OrcRuntimeArchiveBuffer)),
39506c3fb27SDimitry Andric OrcRuntimeArchive(std::move(OrcRuntimeArchive)),
396bdd1243dSDimitry Andric StaticVCRuntime(StaticVCRuntime),
397bdd1243dSDimitry Andric COFFHeaderStartSymbol(ES.intern("__ImageBase")) {
398bdd1243dSDimitry Andric ErrorAsOutParameter _(&Err);
399bdd1243dSDimitry Andric
400bdd1243dSDimitry Andric Bootstrapping.store(true);
401bdd1243dSDimitry Andric ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));
402bdd1243dSDimitry Andric
403bdd1243dSDimitry Andric // Load vc runtime
404bdd1243dSDimitry Andric auto VCRT =
405bdd1243dSDimitry Andric COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath);
406bdd1243dSDimitry Andric if (!VCRT) {
407bdd1243dSDimitry Andric Err = VCRT.takeError();
408bdd1243dSDimitry Andric return;
409bdd1243dSDimitry Andric }
410bdd1243dSDimitry Andric VCRuntimeBootstrap = std::move(*VCRT);
411bdd1243dSDimitry Andric
41206c3fb27SDimitry Andric for (auto &Lib : OrcRuntimeGenerator->getImportedDynamicLibraries())
413bdd1243dSDimitry Andric DylibsToPreload.insert(Lib);
414bdd1243dSDimitry Andric
415bdd1243dSDimitry Andric auto ImportedLibs =
416bdd1243dSDimitry Andric StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD)
417bdd1243dSDimitry Andric : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD);
418bdd1243dSDimitry Andric if (!ImportedLibs) {
419bdd1243dSDimitry Andric Err = ImportedLibs.takeError();
420bdd1243dSDimitry Andric return;
421bdd1243dSDimitry Andric }
422bdd1243dSDimitry Andric
423bdd1243dSDimitry Andric for (auto &Lib : *ImportedLibs)
424bdd1243dSDimitry Andric DylibsToPreload.insert(Lib);
425bdd1243dSDimitry Andric
42606c3fb27SDimitry Andric PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
427bdd1243dSDimitry Andric
428bdd1243dSDimitry Andric // PlatformJD hasn't been set up by the platform yet (since we're creating
429bdd1243dSDimitry Andric // the platform now), so set it up.
430bdd1243dSDimitry Andric if (auto E2 = setupJITDylib(PlatformJD)) {
431bdd1243dSDimitry Andric Err = std::move(E2);
432bdd1243dSDimitry Andric return;
433bdd1243dSDimitry Andric }
434bdd1243dSDimitry Andric
435bdd1243dSDimitry Andric for (auto& Lib : DylibsToPreload)
43606c3fb27SDimitry Andric if (auto E2 = this->LoadDynLibrary(PlatformJD, Lib)) {
437bdd1243dSDimitry Andric Err = std::move(E2);
438bdd1243dSDimitry Andric return;
439bdd1243dSDimitry Andric }
440bdd1243dSDimitry Andric
441bdd1243dSDimitry Andric if (StaticVCRuntime)
442bdd1243dSDimitry Andric if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {
443bdd1243dSDimitry Andric Err = std::move(E2);
444bdd1243dSDimitry Andric return;
445bdd1243dSDimitry Andric }
446bdd1243dSDimitry Andric
447bdd1243dSDimitry Andric // Associate wrapper function tags with JIT-side function implementations.
448bdd1243dSDimitry Andric if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
449bdd1243dSDimitry Andric Err = std::move(E2);
450bdd1243dSDimitry Andric return;
451bdd1243dSDimitry Andric }
452bdd1243dSDimitry Andric
453bdd1243dSDimitry Andric // Lookup addresses of runtime functions callable by the platform,
454bdd1243dSDimitry Andric // call the platform bootstrap function to initialize the platform-state
455bdd1243dSDimitry Andric // object in the executor.
456bdd1243dSDimitry Andric if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) {
457bdd1243dSDimitry Andric Err = std::move(E2);
458bdd1243dSDimitry Andric return;
459bdd1243dSDimitry Andric }
460bdd1243dSDimitry Andric
461bdd1243dSDimitry Andric Bootstrapping.store(false);
462bdd1243dSDimitry Andric JDBootstrapStates.clear();
463bdd1243dSDimitry Andric }
464bdd1243dSDimitry Andric
465bdd1243dSDimitry Andric Expected<COFFPlatform::JITDylibDepMap>
buildJDDepMap(JITDylib & JD)466bdd1243dSDimitry Andric COFFPlatform::buildJDDepMap(JITDylib &JD) {
467bdd1243dSDimitry Andric return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> {
468bdd1243dSDimitry Andric JITDylibDepMap JDDepMap;
469bdd1243dSDimitry Andric
470bdd1243dSDimitry Andric SmallVector<JITDylib *, 16> Worklist({&JD});
471bdd1243dSDimitry Andric while (!Worklist.empty()) {
472bdd1243dSDimitry Andric auto CurJD = Worklist.back();
473bdd1243dSDimitry Andric Worklist.pop_back();
474bdd1243dSDimitry Andric
475bdd1243dSDimitry Andric auto &DM = JDDepMap[CurJD];
476bdd1243dSDimitry Andric CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
477bdd1243dSDimitry Andric DM.reserve(O.size());
478bdd1243dSDimitry Andric for (auto &KV : O) {
479bdd1243dSDimitry Andric if (KV.first == CurJD)
480bdd1243dSDimitry Andric continue;
481bdd1243dSDimitry Andric {
482bdd1243dSDimitry Andric // Bare jitdylibs not known to the platform
483bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex);
484bdd1243dSDimitry Andric if (!JITDylibToHeaderAddr.count(KV.first)) {
485bdd1243dSDimitry Andric LLVM_DEBUG({
486bdd1243dSDimitry Andric dbgs() << "JITDylib unregistered to COFFPlatform detected in "
487bdd1243dSDimitry Andric "LinkOrder: "
488bdd1243dSDimitry Andric << CurJD->getName() << "\n";
489bdd1243dSDimitry Andric });
490bdd1243dSDimitry Andric continue;
491bdd1243dSDimitry Andric }
492bdd1243dSDimitry Andric }
493bdd1243dSDimitry Andric DM.push_back(KV.first);
494bdd1243dSDimitry Andric // Push unvisited entry.
495bdd1243dSDimitry Andric if (!JDDepMap.count(KV.first)) {
496bdd1243dSDimitry Andric Worklist.push_back(KV.first);
497bdd1243dSDimitry Andric JDDepMap[KV.first] = {};
498bdd1243dSDimitry Andric }
499bdd1243dSDimitry Andric }
500bdd1243dSDimitry Andric });
501bdd1243dSDimitry Andric }
502bdd1243dSDimitry Andric return std::move(JDDepMap);
503bdd1243dSDimitry Andric });
504bdd1243dSDimitry Andric }
505bdd1243dSDimitry Andric
pushInitializersLoop(PushInitializersSendResultFn SendResult,JITDylibSP JD,JITDylibDepMap & JDDepMap)506bdd1243dSDimitry Andric void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult,
507bdd1243dSDimitry Andric JITDylibSP JD,
508bdd1243dSDimitry Andric JITDylibDepMap &JDDepMap) {
509bdd1243dSDimitry Andric SmallVector<JITDylib *, 16> Worklist({JD.get()});
510bdd1243dSDimitry Andric DenseSet<JITDylib *> Visited({JD.get()});
511bdd1243dSDimitry Andric DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
512bdd1243dSDimitry Andric ES.runSessionLocked([&]() {
513bdd1243dSDimitry Andric while (!Worklist.empty()) {
514bdd1243dSDimitry Andric auto CurJD = Worklist.back();
515bdd1243dSDimitry Andric Worklist.pop_back();
516bdd1243dSDimitry Andric
517bdd1243dSDimitry Andric auto RISItr = RegisteredInitSymbols.find(CurJD);
518bdd1243dSDimitry Andric if (RISItr != RegisteredInitSymbols.end()) {
519bdd1243dSDimitry Andric NewInitSymbols[CurJD] = std::move(RISItr->second);
520bdd1243dSDimitry Andric RegisteredInitSymbols.erase(RISItr);
521bdd1243dSDimitry Andric }
522bdd1243dSDimitry Andric
523bdd1243dSDimitry Andric for (auto *DepJD : JDDepMap[CurJD])
524bdd1243dSDimitry Andric if (!Visited.count(DepJD)) {
525bdd1243dSDimitry Andric Worklist.push_back(DepJD);
526bdd1243dSDimitry Andric Visited.insert(DepJD);
527bdd1243dSDimitry Andric }
528bdd1243dSDimitry Andric }
529bdd1243dSDimitry Andric });
530bdd1243dSDimitry Andric
531bdd1243dSDimitry Andric // If there are no further init symbols to look up then send the link order
532bdd1243dSDimitry Andric // (as a list of header addresses) to the caller.
533bdd1243dSDimitry Andric if (NewInitSymbols.empty()) {
534bdd1243dSDimitry Andric // Build the dep info map to return.
535bdd1243dSDimitry Andric COFFJITDylibDepInfoMap DIM;
536bdd1243dSDimitry Andric DIM.reserve(JDDepMap.size());
537bdd1243dSDimitry Andric for (auto &KV : JDDepMap) {
538bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex);
539bdd1243dSDimitry Andric COFFJITDylibDepInfo DepInfo;
540bdd1243dSDimitry Andric DepInfo.reserve(KV.second.size());
541bdd1243dSDimitry Andric for (auto &Dep : KV.second) {
542bdd1243dSDimitry Andric DepInfo.push_back(JITDylibToHeaderAddr[Dep]);
543bdd1243dSDimitry Andric }
544bdd1243dSDimitry Andric auto H = JITDylibToHeaderAddr[KV.first];
545bdd1243dSDimitry Andric DIM.push_back(std::make_pair(H, std::move(DepInfo)));
546bdd1243dSDimitry Andric }
547bdd1243dSDimitry Andric SendResult(DIM);
548bdd1243dSDimitry Andric return;
549bdd1243dSDimitry Andric }
550bdd1243dSDimitry Andric
551bdd1243dSDimitry Andric // Otherwise issue a lookup and re-run this phase when it completes.
552bdd1243dSDimitry Andric lookupInitSymbolsAsync(
553bdd1243dSDimitry Andric [this, SendResult = std::move(SendResult), &JD,
554bdd1243dSDimitry Andric JDDepMap = std::move(JDDepMap)](Error Err) mutable {
555bdd1243dSDimitry Andric if (Err)
556bdd1243dSDimitry Andric SendResult(std::move(Err));
557bdd1243dSDimitry Andric else
558bdd1243dSDimitry Andric pushInitializersLoop(std::move(SendResult), JD, JDDepMap);
559bdd1243dSDimitry Andric },
560bdd1243dSDimitry Andric ES, std::move(NewInitSymbols));
561bdd1243dSDimitry Andric }
562bdd1243dSDimitry Andric
rt_pushInitializers(PushInitializersSendResultFn SendResult,ExecutorAddr JDHeaderAddr)563bdd1243dSDimitry Andric void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
564bdd1243dSDimitry Andric ExecutorAddr JDHeaderAddr) {
565bdd1243dSDimitry Andric JITDylibSP JD;
566bdd1243dSDimitry Andric {
567bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex);
568bdd1243dSDimitry Andric auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
569bdd1243dSDimitry Andric if (I != HeaderAddrToJITDylib.end())
570bdd1243dSDimitry Andric JD = I->second;
571bdd1243dSDimitry Andric }
572bdd1243dSDimitry Andric
573bdd1243dSDimitry Andric LLVM_DEBUG({
574bdd1243dSDimitry Andric dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
575bdd1243dSDimitry Andric if (JD)
576bdd1243dSDimitry Andric dbgs() << "pushing initializers for " << JD->getName() << "\n";
577bdd1243dSDimitry Andric else
578bdd1243dSDimitry Andric dbgs() << "No JITDylib for header address.\n";
579bdd1243dSDimitry Andric });
580bdd1243dSDimitry Andric
581bdd1243dSDimitry Andric if (!JD) {
58206c3fb27SDimitry Andric SendResult(make_error<StringError>("No JITDylib with header addr " +
58306c3fb27SDimitry Andric formatv("{0:x}", JDHeaderAddr),
584bdd1243dSDimitry Andric inconvertibleErrorCode()));
585bdd1243dSDimitry Andric return;
586bdd1243dSDimitry Andric }
587bdd1243dSDimitry Andric
588bdd1243dSDimitry Andric auto JDDepMap = buildJDDepMap(*JD);
589bdd1243dSDimitry Andric if (!JDDepMap) {
590bdd1243dSDimitry Andric SendResult(JDDepMap.takeError());
591bdd1243dSDimitry Andric return;
592bdd1243dSDimitry Andric }
593bdd1243dSDimitry Andric
594bdd1243dSDimitry Andric pushInitializersLoop(std::move(SendResult), JD, *JDDepMap);
595bdd1243dSDimitry Andric }
596bdd1243dSDimitry Andric
rt_lookupSymbol(SendSymbolAddressFn SendResult,ExecutorAddr Handle,StringRef SymbolName)597bdd1243dSDimitry Andric void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
598bdd1243dSDimitry Andric ExecutorAddr Handle, StringRef SymbolName) {
59906c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "COFFPlatform::rt_lookupSymbol(\"" << Handle << "\")\n");
600bdd1243dSDimitry Andric
601bdd1243dSDimitry Andric JITDylib *JD = nullptr;
602bdd1243dSDimitry Andric
603bdd1243dSDimitry Andric {
604bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PlatformMutex);
605bdd1243dSDimitry Andric auto I = HeaderAddrToJITDylib.find(Handle);
606bdd1243dSDimitry Andric if (I != HeaderAddrToJITDylib.end())
607bdd1243dSDimitry Andric JD = I->second;
608bdd1243dSDimitry Andric }
609bdd1243dSDimitry Andric
610bdd1243dSDimitry Andric if (!JD) {
61106c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << " No JITDylib for handle " << Handle << "\n");
612bdd1243dSDimitry Andric SendResult(make_error<StringError>("No JITDylib associated with handle " +
61306c3fb27SDimitry Andric formatv("{0:x}", Handle),
614bdd1243dSDimitry Andric inconvertibleErrorCode()));
615bdd1243dSDimitry Andric return;
616bdd1243dSDimitry Andric }
617bdd1243dSDimitry Andric
618bdd1243dSDimitry Andric // Use functor class to work around XL build compiler issue on AIX.
619bdd1243dSDimitry Andric class RtLookupNotifyComplete {
620bdd1243dSDimitry Andric public:
621bdd1243dSDimitry Andric RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
622bdd1243dSDimitry Andric : SendResult(std::move(SendResult)) {}
623bdd1243dSDimitry Andric void operator()(Expected<SymbolMap> Result) {
624bdd1243dSDimitry Andric if (Result) {
625bdd1243dSDimitry Andric assert(Result->size() == 1 && "Unexpected result map count");
62606c3fb27SDimitry Andric SendResult(Result->begin()->second.getAddress());
627bdd1243dSDimitry Andric } else {
628bdd1243dSDimitry Andric SendResult(Result.takeError());
629bdd1243dSDimitry Andric }
630bdd1243dSDimitry Andric }
631bdd1243dSDimitry Andric
632bdd1243dSDimitry Andric private:
633bdd1243dSDimitry Andric SendSymbolAddressFn SendResult;
634bdd1243dSDimitry Andric };
635bdd1243dSDimitry Andric
636bdd1243dSDimitry Andric ES.lookup(
637bdd1243dSDimitry Andric LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
638bdd1243dSDimitry Andric SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
639bdd1243dSDimitry Andric RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
640bdd1243dSDimitry Andric }
641bdd1243dSDimitry Andric
associateRuntimeSupportFunctions(JITDylib & PlatformJD)642bdd1243dSDimitry Andric Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
643bdd1243dSDimitry Andric ExecutionSession::JITDispatchHandlerAssociationMap WFs;
644bdd1243dSDimitry Andric
645bdd1243dSDimitry Andric using LookupSymbolSPSSig =
646bdd1243dSDimitry Andric SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
647bdd1243dSDimitry Andric WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] =
648bdd1243dSDimitry Andric ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
649bdd1243dSDimitry Andric &COFFPlatform::rt_lookupSymbol);
650bdd1243dSDimitry Andric using PushInitializersSPSSig =
651bdd1243dSDimitry Andric SPSExpected<SPSCOFFJITDylibDepInfoMap>(SPSExecutorAddr);
652bdd1243dSDimitry Andric WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] =
653bdd1243dSDimitry Andric ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
654bdd1243dSDimitry Andric this, &COFFPlatform::rt_pushInitializers);
655bdd1243dSDimitry Andric
656bdd1243dSDimitry Andric return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
657bdd1243dSDimitry Andric }
658bdd1243dSDimitry Andric
runBootstrapInitializers(JDBootstrapState & BState)659bdd1243dSDimitry Andric Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {
660bdd1243dSDimitry Andric llvm::sort(BState.Initializers);
661bdd1243dSDimitry Andric if (auto Err =
662bdd1243dSDimitry Andric runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ"))
663bdd1243dSDimitry Andric return Err;
664bdd1243dSDimitry Andric
665bdd1243dSDimitry Andric if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init"))
666bdd1243dSDimitry Andric return Err;
667bdd1243dSDimitry Andric
668bdd1243dSDimitry Andric if (auto Err =
669bdd1243dSDimitry Andric runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ"))
670bdd1243dSDimitry Andric return Err;
671bdd1243dSDimitry Andric return Error::success();
672bdd1243dSDimitry Andric }
673bdd1243dSDimitry Andric
runBootstrapSubsectionInitializers(JDBootstrapState & BState,StringRef Start,StringRef End)674bdd1243dSDimitry Andric Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
675bdd1243dSDimitry Andric StringRef Start,
676bdd1243dSDimitry Andric StringRef End) {
677bdd1243dSDimitry Andric for (auto &Initializer : BState.Initializers)
678bdd1243dSDimitry Andric if (Initializer.first >= Start && Initializer.first <= End &&
679bdd1243dSDimitry Andric Initializer.second) {
680bdd1243dSDimitry Andric auto Res =
681bdd1243dSDimitry Andric ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second);
682bdd1243dSDimitry Andric if (!Res)
683bdd1243dSDimitry Andric return Res.takeError();
684bdd1243dSDimitry Andric }
685bdd1243dSDimitry Andric return Error::success();
686bdd1243dSDimitry Andric }
687bdd1243dSDimitry Andric
bootstrapCOFFRuntime(JITDylib & PlatformJD)688bdd1243dSDimitry Andric Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
689bdd1243dSDimitry Andric // Lookup of runtime symbols causes the collection of initializers if
690bdd1243dSDimitry Andric // it's static linking setting.
691bdd1243dSDimitry Andric if (auto Err = lookupAndRecordAddrs(
692bdd1243dSDimitry Andric ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
693bdd1243dSDimitry Andric {
694bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_platform_bootstrap"),
695bdd1243dSDimitry Andric &orc_rt_coff_platform_bootstrap},
696bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_platform_shutdown"),
697bdd1243dSDimitry Andric &orc_rt_coff_platform_shutdown},
698bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_register_jitdylib"),
699bdd1243dSDimitry Andric &orc_rt_coff_register_jitdylib},
700bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_deregister_jitdylib"),
701bdd1243dSDimitry Andric &orc_rt_coff_deregister_jitdylib},
702bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_register_object_sections"),
703bdd1243dSDimitry Andric &orc_rt_coff_register_object_sections},
704bdd1243dSDimitry Andric {ES.intern("__orc_rt_coff_deregister_object_sections"),
705bdd1243dSDimitry Andric &orc_rt_coff_deregister_object_sections},
706bdd1243dSDimitry Andric }))
707bdd1243dSDimitry Andric return Err;
708bdd1243dSDimitry Andric
709bdd1243dSDimitry Andric // Call bootstrap functions
710bdd1243dSDimitry Andric if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap))
711bdd1243dSDimitry Andric return Err;
712bdd1243dSDimitry Andric
713bdd1243dSDimitry Andric // Do the pending jitdylib registration actions that we couldn't do
714bdd1243dSDimitry Andric // because orc runtime was not linked fully.
715bdd1243dSDimitry Andric for (auto KV : JDBootstrapStates) {
716bdd1243dSDimitry Andric auto &JDBState = KV.second;
717bdd1243dSDimitry Andric if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>(
718bdd1243dSDimitry Andric orc_rt_coff_register_jitdylib, JDBState.JDName,
719bdd1243dSDimitry Andric JDBState.HeaderAddr))
720bdd1243dSDimitry Andric return Err;
721bdd1243dSDimitry Andric
722bdd1243dSDimitry Andric for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps)
723bdd1243dSDimitry Andric if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr,
724bdd1243dSDimitry Andric SPSCOFFObjectSectionsMap, bool)>(
725bdd1243dSDimitry Andric orc_rt_coff_register_object_sections, JDBState.HeaderAddr,
726bdd1243dSDimitry Andric ObjSectionMap, false))
727bdd1243dSDimitry Andric return Err;
728bdd1243dSDimitry Andric }
729bdd1243dSDimitry Andric
730bdd1243dSDimitry Andric // Run static initializers collected in bootstrap stage.
731bdd1243dSDimitry Andric for (auto KV : JDBootstrapStates) {
732bdd1243dSDimitry Andric auto &JDBState = KV.second;
733bdd1243dSDimitry Andric if (auto Err = runBootstrapInitializers(JDBState))
734bdd1243dSDimitry Andric return Err;
735bdd1243dSDimitry Andric }
736bdd1243dSDimitry Andric
737bdd1243dSDimitry Andric return Error::success();
738bdd1243dSDimitry Andric }
739bdd1243dSDimitry Andric
runSymbolIfExists(JITDylib & PlatformJD,StringRef SymbolName)740bdd1243dSDimitry Andric Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
741bdd1243dSDimitry Andric StringRef SymbolName) {
742bdd1243dSDimitry Andric ExecutorAddr jit_function;
743bdd1243dSDimitry Andric auto AfterCLookupErr = lookupAndRecordAddrs(
744bdd1243dSDimitry Andric ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
745bdd1243dSDimitry Andric {{ES.intern(SymbolName), &jit_function}});
746bdd1243dSDimitry Andric if (!AfterCLookupErr) {
747bdd1243dSDimitry Andric auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function);
748bdd1243dSDimitry Andric if (!Res)
749bdd1243dSDimitry Andric return Res.takeError();
750bdd1243dSDimitry Andric return Error::success();
751bdd1243dSDimitry Andric }
752bdd1243dSDimitry Andric if (!AfterCLookupErr.isA<SymbolsNotFound>())
753bdd1243dSDimitry Andric return AfterCLookupErr;
754bdd1243dSDimitry Andric consumeError(std::move(AfterCLookupErr));
755bdd1243dSDimitry Andric return Error::success();
756bdd1243dSDimitry Andric }
757bdd1243dSDimitry Andric
modifyPassConfig(MaterializationResponsibility & MR,jitlink::LinkGraph & LG,jitlink::PassConfiguration & Config)758bdd1243dSDimitry Andric void COFFPlatform::COFFPlatformPlugin::modifyPassConfig(
759bdd1243dSDimitry Andric MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
760bdd1243dSDimitry Andric jitlink::PassConfiguration &Config) {
761bdd1243dSDimitry Andric
762bdd1243dSDimitry Andric bool IsBootstrapping = CP.Bootstrapping.load();
763bdd1243dSDimitry Andric
764bdd1243dSDimitry Andric if (auto InitSymbol = MR.getInitializerSymbol()) {
765bdd1243dSDimitry Andric if (InitSymbol == CP.COFFHeaderStartSymbol) {
766bdd1243dSDimitry Andric Config.PostAllocationPasses.push_back(
767bdd1243dSDimitry Andric [this, &MR, IsBootstrapping](jitlink::LinkGraph &G) {
768bdd1243dSDimitry Andric return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping);
769bdd1243dSDimitry Andric });
770bdd1243dSDimitry Andric return;
771bdd1243dSDimitry Andric }
772bdd1243dSDimitry Andric Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
773bdd1243dSDimitry Andric return preserveInitializerSections(G, MR);
774bdd1243dSDimitry Andric });
775bdd1243dSDimitry Andric }
776bdd1243dSDimitry Andric
777bdd1243dSDimitry Andric if (!IsBootstrapping)
778bdd1243dSDimitry Andric Config.PostFixupPasses.push_back(
779bdd1243dSDimitry Andric [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
780bdd1243dSDimitry Andric return registerObjectPlatformSections(G, JD);
781bdd1243dSDimitry Andric });
782bdd1243dSDimitry Andric else
783bdd1243dSDimitry Andric Config.PostFixupPasses.push_back(
784bdd1243dSDimitry Andric [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
785bdd1243dSDimitry Andric return registerObjectPlatformSectionsInBootstrap(G, JD);
786bdd1243dSDimitry Andric });
787bdd1243dSDimitry Andric }
788bdd1243dSDimitry Andric
789bdd1243dSDimitry Andric ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
getSyntheticSymbolDependencies(MaterializationResponsibility & MR)790bdd1243dSDimitry Andric COFFPlatform::COFFPlatformPlugin::getSyntheticSymbolDependencies(
791bdd1243dSDimitry Andric MaterializationResponsibility &MR) {
792bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PluginMutex);
793bdd1243dSDimitry Andric auto I = InitSymbolDeps.find(&MR);
794bdd1243dSDimitry Andric if (I != InitSymbolDeps.end()) {
795bdd1243dSDimitry Andric SyntheticSymbolDependenciesMap Result;
796bdd1243dSDimitry Andric Result[MR.getInitializerSymbol()] = std::move(I->second);
797bdd1243dSDimitry Andric InitSymbolDeps.erase(&MR);
798bdd1243dSDimitry Andric return Result;
799bdd1243dSDimitry Andric }
800bdd1243dSDimitry Andric return SyntheticSymbolDependenciesMap();
801bdd1243dSDimitry Andric }
802bdd1243dSDimitry Andric
associateJITDylibHeaderSymbol(jitlink::LinkGraph & G,MaterializationResponsibility & MR,bool IsBootstraping)803bdd1243dSDimitry Andric Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol(
804bdd1243dSDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR,
805bdd1243dSDimitry Andric bool IsBootstraping) {
806bdd1243dSDimitry Andric auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
807bdd1243dSDimitry Andric return Sym->getName() == *CP.COFFHeaderStartSymbol;
808bdd1243dSDimitry Andric });
809bdd1243dSDimitry Andric assert(I != G.defined_symbols().end() && "Missing COFF header start symbol");
810bdd1243dSDimitry Andric
811bdd1243dSDimitry Andric auto &JD = MR.getTargetJITDylib();
812bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
813bdd1243dSDimitry Andric auto HeaderAddr = (*I)->getAddress();
814bdd1243dSDimitry Andric CP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
815bdd1243dSDimitry Andric CP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
816bdd1243dSDimitry Andric if (!IsBootstraping) {
817bdd1243dSDimitry Andric G.allocActions().push_back(
818bdd1243dSDimitry Andric {cantFail(WrapperFunctionCall::Create<
819bdd1243dSDimitry Andric SPSArgList<SPSString, SPSExecutorAddr>>(
820bdd1243dSDimitry Andric CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)),
821bdd1243dSDimitry Andric cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
822bdd1243dSDimitry Andric CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
823bdd1243dSDimitry Andric } else {
824bdd1243dSDimitry Andric G.allocActions().push_back(
825bdd1243dSDimitry Andric {{},
826bdd1243dSDimitry Andric cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
827bdd1243dSDimitry Andric CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
828bdd1243dSDimitry Andric JDBootstrapState BState;
829bdd1243dSDimitry Andric BState.JD = &JD;
830bdd1243dSDimitry Andric BState.JDName = JD.getName();
831bdd1243dSDimitry Andric BState.HeaderAddr = HeaderAddr;
832bdd1243dSDimitry Andric CP.JDBootstrapStates.emplace(&JD, BState);
833bdd1243dSDimitry Andric }
834bdd1243dSDimitry Andric
835bdd1243dSDimitry Andric return Error::success();
836bdd1243dSDimitry Andric }
837bdd1243dSDimitry Andric
registerObjectPlatformSections(jitlink::LinkGraph & G,JITDylib & JD)838bdd1243dSDimitry Andric Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections(
839bdd1243dSDimitry Andric jitlink::LinkGraph &G, JITDylib &JD) {
840bdd1243dSDimitry Andric COFFObjectSectionsMap ObjSecs;
841bdd1243dSDimitry Andric auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
842bdd1243dSDimitry Andric assert(HeaderAddr && "Must be registered jitdylib");
843bdd1243dSDimitry Andric for (auto &S : G.sections()) {
844bdd1243dSDimitry Andric jitlink::SectionRange Range(S);
845bdd1243dSDimitry Andric if (Range.getSize())
846bdd1243dSDimitry Andric ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
847bdd1243dSDimitry Andric }
848bdd1243dSDimitry Andric
849bdd1243dSDimitry Andric G.allocActions().push_back(
850bdd1243dSDimitry Andric {cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>(
851bdd1243dSDimitry Andric CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)),
852bdd1243dSDimitry Andric cantFail(
853bdd1243dSDimitry Andric WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
854bdd1243dSDimitry Andric CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
855bdd1243dSDimitry Andric ObjSecs))});
856bdd1243dSDimitry Andric
857bdd1243dSDimitry Andric return Error::success();
858bdd1243dSDimitry Andric }
859bdd1243dSDimitry Andric
preserveInitializerSections(jitlink::LinkGraph & G,MaterializationResponsibility & MR)860bdd1243dSDimitry Andric Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(
861bdd1243dSDimitry Andric jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
862bdd1243dSDimitry Andric JITLinkSymbolSet InitSectionSymbols;
863bdd1243dSDimitry Andric for (auto &Sec : G.sections())
86406c3fb27SDimitry Andric if (isCOFFInitializerSection(Sec.getName()))
865bdd1243dSDimitry Andric for (auto *B : Sec.blocks())
866bdd1243dSDimitry Andric if (!B->edges_empty())
867bdd1243dSDimitry Andric InitSectionSymbols.insert(
868bdd1243dSDimitry Andric &G.addAnonymousSymbol(*B, 0, 0, false, true));
869bdd1243dSDimitry Andric
870bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(PluginMutex);
871bdd1243dSDimitry Andric InitSymbolDeps[&MR] = InitSectionSymbols;
872bdd1243dSDimitry Andric return Error::success();
873bdd1243dSDimitry Andric }
874bdd1243dSDimitry Andric
875bdd1243dSDimitry Andric Error COFFPlatform::COFFPlatformPlugin::
registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph & G,JITDylib & JD)876bdd1243dSDimitry Andric registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,
877bdd1243dSDimitry Andric JITDylib &JD) {
878bdd1243dSDimitry Andric std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
879bdd1243dSDimitry Andric auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
880bdd1243dSDimitry Andric COFFObjectSectionsMap ObjSecs;
881bdd1243dSDimitry Andric for (auto &S : G.sections()) {
882bdd1243dSDimitry Andric jitlink::SectionRange Range(S);
883bdd1243dSDimitry Andric if (Range.getSize())
884bdd1243dSDimitry Andric ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
885bdd1243dSDimitry Andric }
886bdd1243dSDimitry Andric
887bdd1243dSDimitry Andric G.allocActions().push_back(
888bdd1243dSDimitry Andric {{},
889bdd1243dSDimitry Andric cantFail(
890bdd1243dSDimitry Andric WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
891bdd1243dSDimitry Andric CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
892bdd1243dSDimitry Andric ObjSecs))});
893bdd1243dSDimitry Andric
894bdd1243dSDimitry Andric auto &BState = CP.JDBootstrapStates[&JD];
895bdd1243dSDimitry Andric BState.ObjectSectionsMaps.push_back(std::move(ObjSecs));
896bdd1243dSDimitry Andric
897bdd1243dSDimitry Andric // Collect static initializers
898bdd1243dSDimitry Andric for (auto &S : G.sections())
89906c3fb27SDimitry Andric if (isCOFFInitializerSection(S.getName()))
900bdd1243dSDimitry Andric for (auto *B : S.blocks()) {
901bdd1243dSDimitry Andric if (B->edges_empty())
902bdd1243dSDimitry Andric continue;
903bdd1243dSDimitry Andric for (auto &E : B->edges())
904bdd1243dSDimitry Andric BState.Initializers.push_back(std::make_pair(
90506c3fb27SDimitry Andric S.getName().str(), E.getTarget().getAddress() + E.getAddend()));
906bdd1243dSDimitry Andric }
907bdd1243dSDimitry Andric
908bdd1243dSDimitry Andric return Error::success();
909bdd1243dSDimitry Andric }
910bdd1243dSDimitry Andric
911bdd1243dSDimitry Andric } // End namespace orc.
912bdd1243dSDimitry Andric } // End namespace llvm.
913