1 //===------- COFFPlatform.cpp - Utilities for executing COFF in Orc -------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
10 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
11 #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
12 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
14 #include "llvm/Object/COFF.h"
16 #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
18 #include "llvm/ExecutionEngine/JITLink/x86_64.h"
20 #define DEBUG_TYPE "orc"
23 using namespace llvm::orc;
24 using namespace llvm::orc::shared;
30 using SPSCOFFJITDylibDepInfo = SPSSequence<SPSExecutorAddr>;
31 using SPSCOFFJITDylibDepInfoMap =
32 SPSSequence<SPSTuple<SPSExecutorAddr, SPSCOFFJITDylibDepInfo>>;
33 using SPSCOFFObjectSectionsMap =
34 SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
35 using SPSCOFFRegisterObjectSectionsArgs =
36 SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap, bool>;
37 using SPSCOFFDeregisterObjectSectionsArgs =
38 SPSArgList<SPSExecutorAddr, SPSCOFFObjectSectionsMap>;
45 class COFFHeaderMaterializationUnit : public MaterializationUnit {
47 COFFHeaderMaterializationUnit(COFFPlatform &CP,
48 const SymbolStringPtr &HeaderStartSymbol)
49 : MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)),
52 StringRef getName() const override { return "COFFHeaderMU"; }
54 void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
56 support::endianness Endianness;
58 CP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
60 switch (TT.getArch()) {
63 Endianness = support::endianness::little;
66 llvm_unreachable("Unrecognized architecture");
69 auto G = std::make_unique<jitlink::LinkGraph>(
70 "<COFFHeaderMU>", TT, PointerSize, Endianness,
71 jitlink::getGenericEdgeKindName);
72 auto &HeaderSection = G->createSection("__header", MemProt::Read);
73 auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
75 // Init symbol is __ImageBase symbol.
76 auto &ImageBaseSymbol = G->addDefinedSymbol(
77 HeaderBlock, 0, *R->getInitializerSymbol(), HeaderBlock.getSize(),
78 jitlink::Linkage::Strong, jitlink::Scope::Default, false, true);
80 addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol);
82 CP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
85 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
94 support::ulittle32_t PEMagic;
95 object::coff_file_header FileHeader;
97 object::pe32plus_header Header;
98 object::data_directory DataDirectory[COFF::NUM_DATA_DIRECTORIES + 1];
102 struct HeaderBlockContent {
103 object::dos_header DOSHeader;
104 COFFHeaderMaterializationUnit::NTHeader NTHeader;
107 static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
108 jitlink::Section &HeaderSection) {
109 HeaderBlockContent Hdr = {};
112 Hdr.DOSHeader.Magic[0] = 'M';
113 Hdr.DOSHeader.Magic[1] = 'Z';
114 Hdr.DOSHeader.AddressOfNewExeHeader =
115 offsetof(HeaderBlockContent, NTHeader);
116 uint32_t PEMagic = *reinterpret_cast<const uint32_t *>(COFF::PEMagic);
117 Hdr.NTHeader.PEMagic = PEMagic;
118 Hdr.NTHeader.OptionalHeader.Header.Magic = COFF::PE32Header::PE32_PLUS;
120 switch (G.getTargetTriple().getArch()) {
122 Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
125 llvm_unreachable("Unrecognized architecture");
128 auto HeaderContent = G.allocateString(
129 StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
131 return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
135 static void addImageBaseRelocationEdge(jitlink::Block &B,
136 jitlink::Symbol &ImageBase) {
137 auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader) +
138 offsetof(NTHeader, OptionalHeader) +
139 offsetof(object::pe32plus_header, ImageBase);
140 B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0);
143 static MaterializationUnit::Interface
144 createHeaderInterface(COFFPlatform &MOP,
145 const SymbolStringPtr &HeaderStartSymbol) {
146 SymbolFlagsMap HeaderSymbolFlags;
148 HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
150 return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
157 } // end anonymous namespace
162 Expected<std::unique_ptr<COFFPlatform>>
163 COFFPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
164 JITDylib &PlatformJD, const char *OrcRuntimePath,
165 LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
166 const char *VCRuntimePath,
167 std::optional<SymbolAliasMap> RuntimeAliases) {
168 auto &EPC = ES.getExecutorProcessControl();
170 // If the target is not supported then bail out immediately.
171 if (!supportedTarget(EPC.getTargetTriple()))
172 return make_error<StringError>("Unsupported COFFPlatform triple: " +
173 EPC.getTargetTriple().str(),
174 inconvertibleErrorCode());
176 // Create default aliases if the caller didn't supply any.
178 RuntimeAliases = standardPlatformAliases(ES);
180 // Define the aliases.
181 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
182 return std::move(Err);
184 auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");
186 // Add JIT-dispatch function support symbols.
187 if (auto Err = HostFuncJD.define(absoluteSymbols(
188 {{ES.intern("__orc_rt_jit_dispatch"),
189 {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
190 JITSymbolFlags::Exported}},
191 {ES.intern("__orc_rt_jit_dispatch_ctx"),
192 {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
193 JITSymbolFlags::Exported}}})))
194 return std::move(Err);
196 PlatformJD.addToLinkOrder(HostFuncJD);
198 // Create the instance.
199 Error Err = Error::success();
200 auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(
201 ES, ObjLinkingLayer, PlatformJD, OrcRuntimePath,
202 std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));
204 return std::move(Err);
208 Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
209 auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
211 return PerJDObj.takeError();
214 return make_error<StringError>("Could not find per jd object file",
215 inconvertibleErrorCode());
217 auto Buffer = (*PerJDObj)->getAsBinary();
219 return Buffer.takeError();
221 return (*Buffer)->getMemoryBufferRef();
224 static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
225 ArrayRef<std::pair<const char *, const char *>> AL) {
226 for (auto &KV : AL) {
227 auto AliasName = ES.intern(KV.first);
228 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
229 Aliases[std::move(AliasName)] = {ES.intern(KV.second),
230 JITSymbolFlags::Exported};
234 Error COFFPlatform::setupJITDylib(JITDylib &JD) {
235 if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>(
236 *this, COFFHeaderStartSymbol)))
239 if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError())
242 // Define the CXX aliases.
243 SymbolAliasMap CXXAliases;
244 addAliases(ES, CXXAliases, requiredCXXAliases());
245 if (auto Err = JD.define(symbolAliases(std::move(CXXAliases))))
248 auto PerJDObj = getPerJDObjectFile();
250 return PerJDObj.takeError();
252 auto I = getObjectFileInterface(ES, *PerJDObj);
254 return I.takeError();
256 if (auto Err = ObjLinkingLayer.add(
257 JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I)))
260 if (!Bootstrapping) {
261 auto ImportedLibs = StaticVCRuntime
262 ? VCRuntimeBootstrap->loadStaticVCRuntime(JD)
263 : VCRuntimeBootstrap->loadDynamicVCRuntime(JD);
265 return ImportedLibs.takeError();
266 for (auto &Lib : *ImportedLibs)
267 if (auto Err = LoadDynLibrary(JD, Lib))
270 if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD))
274 JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer));
275 return Error::success();
278 Error COFFPlatform::teardownJITDylib(JITDylib &JD) {
279 std::lock_guard<std::mutex> Lock(PlatformMutex);
280 auto I = JITDylibToHeaderAddr.find(&JD);
281 if (I != JITDylibToHeaderAddr.end()) {
282 assert(HeaderAddrToJITDylib.count(I->second) &&
283 "HeaderAddrToJITDylib missing entry");
284 HeaderAddrToJITDylib.erase(I->second);
285 JITDylibToHeaderAddr.erase(I);
287 return Error::success();
290 Error COFFPlatform::notifyAdding(ResourceTracker &RT,
291 const MaterializationUnit &MU) {
292 auto &JD = RT.getJITDylib();
293 const auto &InitSym = MU.getInitializerSymbol();
295 return Error::success();
297 RegisteredInitSymbols[&JD].add(InitSym,
298 SymbolLookupFlags::WeaklyReferencedSymbol);
301 dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU "
302 << MU.getName() << "\n";
304 return Error::success();
307 Error COFFPlatform::notifyRemoving(ResourceTracker &RT) {
308 llvm_unreachable("Not supported yet");
311 SymbolAliasMap COFFPlatform::standardPlatformAliases(ExecutionSession &ES) {
312 SymbolAliasMap Aliases;
313 addAliases(ES, Aliases, standardRuntimeUtilityAliases());
317 ArrayRef<std::pair<const char *, const char *>>
318 COFFPlatform::requiredCXXAliases() {
319 static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
320 {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},
321 {"_onexit", "__orc_rt_coff_onexit_per_jd"},
322 {"atexit", "__orc_rt_coff_atexit_per_jd"}};
324 return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
327 ArrayRef<std::pair<const char *, const char *>>
328 COFFPlatform::standardRuntimeUtilityAliases() {
329 static const std::pair<const char *, const char *>
330 StandardRuntimeUtilityAliases[] = {
331 {"__orc_rt_run_program", "__orc_rt_coff_run_program"},
332 {"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"},
333 {"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"},
334 {"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"},
335 {"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"},
336 {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
338 return ArrayRef<std::pair<const char *, const char *>>(
339 StandardRuntimeUtilityAliases);
342 bool COFFPlatform::supportedTarget(const Triple &TT) {
343 switch (TT.getArch()) {
351 COFFPlatform::COFFPlatform(ExecutionSession &ES,
352 ObjectLinkingLayer &ObjLinkingLayer,
353 JITDylib &PlatformJD, const char *OrcRuntimePath,
354 LoadDynamicLibrary LoadDynLibrary,
355 bool StaticVCRuntime, const char *VCRuntimePath,
357 : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
358 LoadDynLibrary(std::move(LoadDynLibrary)),
359 StaticVCRuntime(StaticVCRuntime),
360 COFFHeaderStartSymbol(ES.intern("__ImageBase")) {
361 ErrorAsOutParameter _(&Err);
363 // Create a generator for the ORC runtime archive.
364 auto OrcRuntimeArchiveGenerator =
365 StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
366 if (!OrcRuntimeArchiveGenerator) {
367 Err = OrcRuntimeArchiveGenerator.takeError();
371 auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
372 if (!ArchiveBuffer) {
373 Err = createFileError(OrcRuntimePath, ArchiveBuffer.getError());
376 OrcRuntimeArchiveBuffer = std::move(*ArchiveBuffer);
378 std::make_unique<object::Archive>(*OrcRuntimeArchiveBuffer, Err);
382 Bootstrapping.store(true);
383 ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));
387 COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath);
389 Err = VCRT.takeError();
392 VCRuntimeBootstrap = std::move(*VCRT);
394 for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries())
395 DylibsToPreload.insert(Lib);
398 StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD)
399 : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD);
401 Err = ImportedLibs.takeError();
405 for (auto &Lib : *ImportedLibs)
406 DylibsToPreload.insert(Lib);
408 PlatformJD.addGenerator(std::move(*OrcRuntimeArchiveGenerator));
410 // PlatformJD hasn't been set up by the platform yet (since we're creating
411 // the platform now), so set it up.
412 if (auto E2 = setupJITDylib(PlatformJD)) {
417 for (auto& Lib : DylibsToPreload)
418 if (auto E2 = LoadDynLibrary(PlatformJD, Lib)) {
424 if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {
429 // Associate wrapper function tags with JIT-side function implementations.
430 if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
435 // Lookup addresses of runtime functions callable by the platform,
436 // call the platform bootstrap function to initialize the platform-state
437 // object in the executor.
438 if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) {
443 Bootstrapping.store(false);
444 JDBootstrapStates.clear();
447 Expected<COFFPlatform::JITDylibDepMap>
448 COFFPlatform::buildJDDepMap(JITDylib &JD) {
449 return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> {
450 JITDylibDepMap JDDepMap;
452 SmallVector<JITDylib *, 16> Worklist({&JD});
453 while (!Worklist.empty()) {
454 auto CurJD = Worklist.back();
457 auto &DM = JDDepMap[CurJD];
458 CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
459 DM.reserve(O.size());
461 if (KV.first == CurJD)
464 // Bare jitdylibs not known to the platform
465 std::lock_guard<std::mutex> Lock(PlatformMutex);
466 if (!JITDylibToHeaderAddr.count(KV.first)) {
468 dbgs() << "JITDylib unregistered to COFFPlatform detected in "
470 << CurJD->getName() << "\n";
475 DM.push_back(KV.first);
476 // Push unvisited entry.
477 if (!JDDepMap.count(KV.first)) {
478 Worklist.push_back(KV.first);
479 JDDepMap[KV.first] = {};
484 return std::move(JDDepMap);
488 void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult,
490 JITDylibDepMap &JDDepMap) {
491 SmallVector<JITDylib *, 16> Worklist({JD.get()});
492 DenseSet<JITDylib *> Visited({JD.get()});
493 DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
494 ES.runSessionLocked([&]() {
495 while (!Worklist.empty()) {
496 auto CurJD = Worklist.back();
499 auto RISItr = RegisteredInitSymbols.find(CurJD);
500 if (RISItr != RegisteredInitSymbols.end()) {
501 NewInitSymbols[CurJD] = std::move(RISItr->second);
502 RegisteredInitSymbols.erase(RISItr);
505 for (auto *DepJD : JDDepMap[CurJD])
506 if (!Visited.count(DepJD)) {
507 Worklist.push_back(DepJD);
508 Visited.insert(DepJD);
513 // If there are no further init symbols to look up then send the link order
514 // (as a list of header addresses) to the caller.
515 if (NewInitSymbols.empty()) {
516 // Build the dep info map to return.
517 COFFJITDylibDepInfoMap DIM;
518 DIM.reserve(JDDepMap.size());
519 for (auto &KV : JDDepMap) {
520 std::lock_guard<std::mutex> Lock(PlatformMutex);
521 COFFJITDylibDepInfo DepInfo;
522 DepInfo.reserve(KV.second.size());
523 for (auto &Dep : KV.second) {
524 DepInfo.push_back(JITDylibToHeaderAddr[Dep]);
526 auto H = JITDylibToHeaderAddr[KV.first];
527 DIM.push_back(std::make_pair(H, std::move(DepInfo)));
533 // Otherwise issue a lookup and re-run this phase when it completes.
534 lookupInitSymbolsAsync(
535 [this, SendResult = std::move(SendResult), &JD,
536 JDDepMap = std::move(JDDepMap)](Error Err) mutable {
538 SendResult(std::move(Err));
540 pushInitializersLoop(std::move(SendResult), JD, JDDepMap);
542 ES, std::move(NewInitSymbols));
545 void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
546 ExecutorAddr JDHeaderAddr) {
549 std::lock_guard<std::mutex> Lock(PlatformMutex);
550 auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
551 if (I != HeaderAddrToJITDylib.end())
556 dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
558 dbgs() << "pushing initializers for " << JD->getName() << "\n";
560 dbgs() << "No JITDylib for header address.\n";
565 make_error<StringError>("No JITDylib with header addr " +
566 formatv("{0:x}", JDHeaderAddr.getValue()),
567 inconvertibleErrorCode()));
571 auto JDDepMap = buildJDDepMap(*JD);
573 SendResult(JDDepMap.takeError());
577 pushInitializersLoop(std::move(SendResult), JD, *JDDepMap);
580 void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
581 ExecutorAddr Handle, StringRef SymbolName) {
583 dbgs() << "COFFPlatform::rt_lookupSymbol(\""
584 << formatv("{0:x}", Handle.getValue()) << "\")\n";
587 JITDylib *JD = nullptr;
590 std::lock_guard<std::mutex> Lock(PlatformMutex);
591 auto I = HeaderAddrToJITDylib.find(Handle);
592 if (I != HeaderAddrToJITDylib.end())
598 dbgs() << " No JITDylib for handle "
599 << formatv("{0:x}", Handle.getValue()) << "\n";
601 SendResult(make_error<StringError>("No JITDylib associated with handle " +
602 formatv("{0:x}", Handle.getValue()),
603 inconvertibleErrorCode()));
607 // Use functor class to work around XL build compiler issue on AIX.
608 class RtLookupNotifyComplete {
610 RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
611 : SendResult(std::move(SendResult)) {}
612 void operator()(Expected<SymbolMap> Result) {
614 assert(Result->size() == 1 && "Unexpected result map count");
615 SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
617 SendResult(Result.takeError());
622 SendSymbolAddressFn SendResult;
626 LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
627 SymbolLookupSet(ES.intern(SymbolName)), SymbolState::Ready,
628 RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
631 Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
632 ExecutionSession::JITDispatchHandlerAssociationMap WFs;
634 using LookupSymbolSPSSig =
635 SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
636 WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] =
637 ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
638 &COFFPlatform::rt_lookupSymbol);
639 using PushInitializersSPSSig =
640 SPSExpected<SPSCOFFJITDylibDepInfoMap>(SPSExecutorAddr);
641 WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] =
642 ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
643 this, &COFFPlatform::rt_pushInitializers);
645 return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
648 Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {
649 llvm::sort(BState.Initializers);
651 runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ"))
654 if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init"))
658 runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ"))
660 return Error::success();
663 Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
666 for (auto &Initializer : BState.Initializers)
667 if (Initializer.first >= Start && Initializer.first <= End &&
668 Initializer.second) {
670 ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second);
672 return Res.takeError();
674 return Error::success();
677 Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
678 // Lookup of runtime symbols causes the collection of initializers if
679 // it's static linking setting.
680 if (auto Err = lookupAndRecordAddrs(
681 ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
683 {ES.intern("__orc_rt_coff_platform_bootstrap"),
684 &orc_rt_coff_platform_bootstrap},
685 {ES.intern("__orc_rt_coff_platform_shutdown"),
686 &orc_rt_coff_platform_shutdown},
687 {ES.intern("__orc_rt_coff_register_jitdylib"),
688 &orc_rt_coff_register_jitdylib},
689 {ES.intern("__orc_rt_coff_deregister_jitdylib"),
690 &orc_rt_coff_deregister_jitdylib},
691 {ES.intern("__orc_rt_coff_register_object_sections"),
692 &orc_rt_coff_register_object_sections},
693 {ES.intern("__orc_rt_coff_deregister_object_sections"),
694 &orc_rt_coff_deregister_object_sections},
698 // Call bootstrap functions
699 if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap))
702 // Do the pending jitdylib registration actions that we couldn't do
703 // because orc runtime was not linked fully.
704 for (auto KV : JDBootstrapStates) {
705 auto &JDBState = KV.second;
706 if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>(
707 orc_rt_coff_register_jitdylib, JDBState.JDName,
708 JDBState.HeaderAddr))
711 for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps)
712 if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr,
713 SPSCOFFObjectSectionsMap, bool)>(
714 orc_rt_coff_register_object_sections, JDBState.HeaderAddr,
715 ObjSectionMap, false))
719 // Run static initializers collected in bootstrap stage.
720 for (auto KV : JDBootstrapStates) {
721 auto &JDBState = KV.second;
722 if (auto Err = runBootstrapInitializers(JDBState))
726 return Error::success();
729 Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
730 StringRef SymbolName) {
731 ExecutorAddr jit_function;
732 auto AfterCLookupErr = lookupAndRecordAddrs(
733 ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
734 {{ES.intern(SymbolName), &jit_function}});
735 if (!AfterCLookupErr) {
736 auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function);
738 return Res.takeError();
739 return Error::success();
741 if (!AfterCLookupErr.isA<SymbolsNotFound>())
742 return AfterCLookupErr;
743 consumeError(std::move(AfterCLookupErr));
744 return Error::success();
747 void COFFPlatform::COFFPlatformPlugin::modifyPassConfig(
748 MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
749 jitlink::PassConfiguration &Config) {
751 bool IsBootstrapping = CP.Bootstrapping.load();
753 if (auto InitSymbol = MR.getInitializerSymbol()) {
754 if (InitSymbol == CP.COFFHeaderStartSymbol) {
755 Config.PostAllocationPasses.push_back(
756 [this, &MR, IsBootstrapping](jitlink::LinkGraph &G) {
757 return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping);
761 Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
762 return preserveInitializerSections(G, MR);
766 if (!IsBootstrapping)
767 Config.PostFixupPasses.push_back(
768 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
769 return registerObjectPlatformSections(G, JD);
772 Config.PostFixupPasses.push_back(
773 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
774 return registerObjectPlatformSectionsInBootstrap(G, JD);
778 ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
779 COFFPlatform::COFFPlatformPlugin::getSyntheticSymbolDependencies(
780 MaterializationResponsibility &MR) {
781 std::lock_guard<std::mutex> Lock(PluginMutex);
782 auto I = InitSymbolDeps.find(&MR);
783 if (I != InitSymbolDeps.end()) {
784 SyntheticSymbolDependenciesMap Result;
785 Result[MR.getInitializerSymbol()] = std::move(I->second);
786 InitSymbolDeps.erase(&MR);
789 return SyntheticSymbolDependenciesMap();
792 Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol(
793 jitlink::LinkGraph &G, MaterializationResponsibility &MR,
794 bool IsBootstraping) {
795 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
796 return Sym->getName() == *CP.COFFHeaderStartSymbol;
798 assert(I != G.defined_symbols().end() && "Missing COFF header start symbol");
800 auto &JD = MR.getTargetJITDylib();
801 std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
802 auto HeaderAddr = (*I)->getAddress();
803 CP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
804 CP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
805 if (!IsBootstraping) {
806 G.allocActions().push_back(
807 {cantFail(WrapperFunctionCall::Create<
808 SPSArgList<SPSString, SPSExecutorAddr>>(
809 CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)),
810 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
811 CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
813 G.allocActions().push_back(
815 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
816 CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
817 JDBootstrapState BState;
819 BState.JDName = JD.getName();
820 BState.HeaderAddr = HeaderAddr;
821 CP.JDBootstrapStates.emplace(&JD, BState);
824 return Error::success();
827 Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections(
828 jitlink::LinkGraph &G, JITDylib &JD) {
829 COFFObjectSectionsMap ObjSecs;
830 auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
831 assert(HeaderAddr && "Must be registered jitdylib");
832 for (auto &S : G.sections()) {
833 jitlink::SectionRange Range(S);
835 ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
838 G.allocActions().push_back(
839 {cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>(
840 CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)),
842 WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
843 CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
846 return Error::success();
849 Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(
850 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
851 JITLinkSymbolSet InitSectionSymbols;
852 for (auto &Sec : G.sections())
853 if (COFFPlatform::isInitializerSection(Sec.getName()))
854 for (auto *B : Sec.blocks())
855 if (!B->edges_empty())
856 InitSectionSymbols.insert(
857 &G.addAnonymousSymbol(*B, 0, 0, false, true));
859 std::lock_guard<std::mutex> Lock(PluginMutex);
860 InitSymbolDeps[&MR] = InitSectionSymbols;
861 return Error::success();
864 Error COFFPlatform::COFFPlatformPlugin::
865 registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,
867 std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
868 auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
869 COFFObjectSectionsMap ObjSecs;
870 for (auto &S : G.sections()) {
871 jitlink::SectionRange Range(S);
873 ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
876 G.allocActions().push_back(
879 WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
880 CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
883 auto &BState = CP.JDBootstrapStates[&JD];
884 BState.ObjectSectionsMaps.push_back(std::move(ObjSecs));
886 // Collect static initializers
887 for (auto &S : G.sections())
888 if (COFFPlatform::isInitializerSection(S.getName()))
889 for (auto *B : S.blocks()) {
890 if (B->edges_empty())
892 for (auto &E : B->edges())
893 BState.Initializers.push_back(std::make_pair(
895 ExecutorAddr(E.getTarget().getAddress() + E.getAddend())));
898 return Error::success();
901 } // End namespace orc.
902 } // End namespace llvm.