LLVM 17.0.0git
COFFPlatform.cpp
Go to the documentation of this file.
1//===------- COFFPlatform.cpp - Utilities for executing COFF in Orc -------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
14
15#include "llvm/Object/COFF.h"
16
18
20
21#define DEBUG_TYPE "orc"
22
23using namespace llvm;
24using namespace llvm::orc;
25using namespace llvm::orc::shared;
26
27namespace llvm {
28namespace orc {
29namespace shared {
30
40
41} // namespace shared
42} // namespace orc
43} // namespace llvm
44namespace {
45
46class COFFHeaderMaterializationUnit : public MaterializationUnit {
47public:
48 COFFHeaderMaterializationUnit(COFFPlatform &CP,
49 const SymbolStringPtr &HeaderStartSymbol)
50 : MaterializationUnit(createHeaderInterface(CP, HeaderStartSymbol)),
51 CP(CP) {}
52
53 StringRef getName() const override { return "COFFHeaderMU"; }
54
55 void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
56 unsigned PointerSize;
58 const auto &TT = CP.getExecutionSession().getTargetTriple();
59
60 switch (TT.getArch()) {
61 case Triple::x86_64:
62 PointerSize = 8;
63 Endianness = support::endianness::little;
64 break;
65 default:
66 llvm_unreachable("Unrecognized architecture");
67 }
68
69 auto G = std::make_unique<jitlink::LinkGraph>(
70 "<COFFHeaderMU>", TT, PointerSize, Endianness,
72 auto &HeaderSection = G->createSection("__header", MemProt::Read);
73 auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
74
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);
79
80 addImageBaseRelocationEdge(HeaderBlock, ImageBaseSymbol);
81
82 CP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
83 }
84
85 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
86
87private:
88 struct HeaderSymbol {
89 const char *Name;
91 };
92
93 struct NTHeader {
95 object::coff_file_header FileHeader;
96 struct PEHeader {
99 } OptionalHeader;
100 };
101
102 struct HeaderBlockContent {
103 object::dos_header DOSHeader;
104 COFFHeaderMaterializationUnit::NTHeader NTHeader;
105 };
106
107 static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
108 jitlink::Section &HeaderSection) {
109 HeaderBlockContent Hdr = {};
110
111 // Set up magic
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;
119
120 switch (G.getTargetTriple().getArch()) {
121 case Triple::x86_64:
122 Hdr.NTHeader.FileHeader.Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
123 break;
124 default:
125 llvm_unreachable("Unrecognized architecture");
126 }
127
128 auto HeaderContent = G.allocateContent(
129 ArrayRef<char>(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
130
131 return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
132 0);
133 }
134
135 static void addImageBaseRelocationEdge(jitlink::Block &B,
136 jitlink::Symbol &ImageBase) {
137 auto ImageBaseOffset = offsetof(HeaderBlockContent, NTHeader) +
138 offsetof(NTHeader, OptionalHeader) +
140 B.addEdge(jitlink::x86_64::Pointer64, ImageBaseOffset, ImageBase, 0);
141 }
142
144 createHeaderInterface(COFFPlatform &MOP,
145 const SymbolStringPtr &HeaderStartSymbol) {
146 SymbolFlagsMap HeaderSymbolFlags;
147
148 HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
149
150 return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
151 HeaderStartSymbol);
152 }
153
155};
156
157} // end anonymous namespace
158
159namespace llvm {
160namespace orc {
161
164 JITDylib &PlatformJD, const char *OrcRuntimePath,
165 LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime,
166 const char *VCRuntimePath,
167 std::optional<SymbolAliasMap> RuntimeAliases) {
168
169 // If the target is not supported then bail out immediately.
170 if (!supportedTarget(ES.getTargetTriple()))
171 return make_error<StringError>("Unsupported COFFPlatform triple: " +
172 ES.getTargetTriple().str(),
174
175 auto &EPC = ES.getExecutorProcessControl();
176
177 // Create default aliases if the caller didn't supply any.
178 if (!RuntimeAliases)
179 RuntimeAliases = standardPlatformAliases(ES);
180
181 // Define the aliases.
182 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
183 return std::move(Err);
184
185 auto &HostFuncJD = ES.createBareJITDylib("$<PlatformRuntimeHostFuncJD>");
186
187 // Add JIT-dispatch function support symbols.
188 if (auto Err = HostFuncJD.define(absoluteSymbols(
189 {{ES.intern("__orc_rt_jit_dispatch"),
190 {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
192 {ES.intern("__orc_rt_jit_dispatch_ctx"),
193 {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
195 return std::move(Err);
196
197 PlatformJD.addToLinkOrder(HostFuncJD);
198
199 // Create the instance.
200 Error Err = Error::success();
201 auto P = std::unique_ptr<COFFPlatform>(new COFFPlatform(
202 ES, ObjLinkingLayer, PlatformJD, OrcRuntimePath,
203 std::move(LoadDynLibrary), StaticVCRuntime, VCRuntimePath, Err));
204 if (Err)
205 return std::move(Err);
206 return std::move(P);
207}
208
209Expected<MemoryBufferRef> COFFPlatform::getPerJDObjectFile() {
210 auto PerJDObj = OrcRuntimeArchive->findSym("__orc_rt_coff_per_jd_marker");
211 if (!PerJDObj)
212 return PerJDObj.takeError();
213
214 if (!*PerJDObj)
215 return make_error<StringError>("Could not find per jd object file",
217
218 auto Buffer = (*PerJDObj)->getAsBinary();
219 if (!Buffer)
220 return Buffer.takeError();
221
222 return (*Buffer)->getMemoryBufferRef();
223}
224
226 ArrayRef<std::pair<const char *, const char *>> AL) {
227 for (auto &KV : AL) {
228 auto AliasName = ES.intern(KV.first);
229 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
230 Aliases[std::move(AliasName)] = {ES.intern(KV.second),
232 }
233}
234
236 if (auto Err = JD.define(std::make_unique<COFFHeaderMaterializationUnit>(
237 *this, COFFHeaderStartSymbol)))
238 return Err;
239
240 if (auto Err = ES.lookup({&JD}, COFFHeaderStartSymbol).takeError())
241 return Err;
242
243 // Define the CXX aliases.
244 SymbolAliasMap CXXAliases;
245 addAliases(ES, CXXAliases, requiredCXXAliases());
246 if (auto Err = JD.define(symbolAliases(std::move(CXXAliases))))
247 return Err;
248
249 auto PerJDObj = getPerJDObjectFile();
250 if (!PerJDObj)
251 return PerJDObj.takeError();
252
253 auto I = getObjectFileInterface(ES, *PerJDObj);
254 if (!I)
255 return I.takeError();
256
257 if (auto Err = ObjLinkingLayer.add(
258 JD, MemoryBuffer::getMemBuffer(*PerJDObj, false), std::move(*I)))
259 return Err;
260
261 if (!Bootstrapping) {
262 auto ImportedLibs = StaticVCRuntime
263 ? VCRuntimeBootstrap->loadStaticVCRuntime(JD)
264 : VCRuntimeBootstrap->loadDynamicVCRuntime(JD);
265 if (!ImportedLibs)
266 return ImportedLibs.takeError();
267 for (auto &Lib : *ImportedLibs)
268 if (auto Err = LoadDynLibrary(JD, Lib))
269 return Err;
270 if (StaticVCRuntime)
271 if (auto Err = VCRuntimeBootstrap->initializeStaticVCRuntime(JD))
272 return Err;
273 }
274
275 JD.addGenerator(DLLImportDefinitionGenerator::Create(ES, ObjLinkingLayer));
276 return Error::success();
277}
278
280 std::lock_guard<std::mutex> Lock(PlatformMutex);
281 auto I = JITDylibToHeaderAddr.find(&JD);
282 if (I != JITDylibToHeaderAddr.end()) {
283 assert(HeaderAddrToJITDylib.count(I->second) &&
284 "HeaderAddrToJITDylib missing entry");
285 HeaderAddrToJITDylib.erase(I->second);
286 JITDylibToHeaderAddr.erase(I);
287 }
288 return Error::success();
289}
290
292 const MaterializationUnit &MU) {
293 auto &JD = RT.getJITDylib();
294 const auto &InitSym = MU.getInitializerSymbol();
295 if (!InitSym)
296 return Error::success();
297
298 RegisteredInitSymbols[&JD].add(InitSym,
300
301 LLVM_DEBUG({
302 dbgs() << "COFFPlatform: Registered init symbol " << *InitSym << " for MU "
303 << MU.getName() << "\n";
304 });
305 return Error::success();
306}
307
309 llvm_unreachable("Not supported yet");
310}
311
313 SymbolAliasMap Aliases;
315 return Aliases;
316}
317
320 static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
321 {"_CxxThrowException", "__orc_rt_coff_cxx_throw_exception"},
322 {"_onexit", "__orc_rt_coff_onexit_per_jd"},
323 {"atexit", "__orc_rt_coff_atexit_per_jd"}};
324
325 return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
326}
327
330 static const std::pair<const char *, const char *>
331 StandardRuntimeUtilityAliases[] = {
332 {"__orc_rt_run_program", "__orc_rt_coff_run_program"},
333 {"__orc_rt_jit_dlerror", "__orc_rt_coff_jit_dlerror"},
334 {"__orc_rt_jit_dlopen", "__orc_rt_coff_jit_dlopen"},
335 {"__orc_rt_jit_dlclose", "__orc_rt_coff_jit_dlclose"},
336 {"__orc_rt_jit_dlsym", "__orc_rt_coff_jit_dlsym"},
337 {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
338
340 StandardRuntimeUtilityAliases);
341}
342
343bool COFFPlatform::supportedTarget(const Triple &TT) {
344 switch (TT.getArch()) {
345 case Triple::x86_64:
346 return true;
347 default:
348 return false;
349 }
350}
351
352COFFPlatform::COFFPlatform(ExecutionSession &ES,
353 ObjectLinkingLayer &ObjLinkingLayer,
354 JITDylib &PlatformJD, const char *OrcRuntimePath,
355 LoadDynamicLibrary LoadDynamicLibrary,
356 bool StaticVCRuntime, const char *VCRuntimePath,
357 Error &Err)
358 : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
359 LoadDynLibrary(std::move(LoadDynamicLibrary)),
360 StaticVCRuntime(StaticVCRuntime),
361 COFFHeaderStartSymbol(ES.intern("__ImageBase")) {
363
364 // Create a generator for the ORC runtime archive.
365 auto OrcRuntimeArchiveGenerator =
366 StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
367 if (!OrcRuntimeArchiveGenerator) {
368 Err = OrcRuntimeArchiveGenerator.takeError();
369 return;
370 }
371
372 auto ArchiveBuffer = MemoryBuffer::getFile(OrcRuntimePath);
373 if (!ArchiveBuffer) {
374 Err = createFileError(OrcRuntimePath, ArchiveBuffer.getError());
375 return;
376 }
377 OrcRuntimeArchiveBuffer = std::move(*ArchiveBuffer);
378 OrcRuntimeArchive =
379 std::make_unique<object::Archive>(*OrcRuntimeArchiveBuffer, Err);
380 if (Err)
381 return;
382
383 Bootstrapping.store(true);
384 ObjLinkingLayer.addPlugin(std::make_unique<COFFPlatformPlugin>(*this));
385
386 // Load vc runtime
387 auto VCRT =
388 COFFVCRuntimeBootstrapper::Create(ES, ObjLinkingLayer, VCRuntimePath);
389 if (!VCRT) {
390 Err = VCRT.takeError();
391 return;
392 }
393 VCRuntimeBootstrap = std::move(*VCRT);
394
395 for (auto &Lib : (*OrcRuntimeArchiveGenerator)->getImportedDynamicLibraries())
396 DylibsToPreload.insert(Lib);
397
398 auto ImportedLibs =
399 StaticVCRuntime ? VCRuntimeBootstrap->loadStaticVCRuntime(PlatformJD)
400 : VCRuntimeBootstrap->loadDynamicVCRuntime(PlatformJD);
401 if (!ImportedLibs) {
402 Err = ImportedLibs.takeError();
403 return;
404 }
405
406 for (auto &Lib : *ImportedLibs)
407 DylibsToPreload.insert(Lib);
408
409 PlatformJD.addGenerator(std::move(*OrcRuntimeArchiveGenerator));
410
411 // PlatformJD hasn't been set up by the platform yet (since we're creating
412 // the platform now), so set it up.
413 if (auto E2 = setupJITDylib(PlatformJD)) {
414 Err = std::move(E2);
415 return;
416 }
417
418 for (auto& Lib : DylibsToPreload)
419 if (auto E2 = LoadDynLibrary(PlatformJD, Lib)) {
420 Err = std::move(E2);
421 return;
422 }
423
424 if (StaticVCRuntime)
425 if (auto E2 = VCRuntimeBootstrap->initializeStaticVCRuntime(PlatformJD)) {
426 Err = std::move(E2);
427 return;
428 }
429
430 // Associate wrapper function tags with JIT-side function implementations.
431 if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
432 Err = std::move(E2);
433 return;
434 }
435
436 // Lookup addresses of runtime functions callable by the platform,
437 // call the platform bootstrap function to initialize the platform-state
438 // object in the executor.
439 if (auto E2 = bootstrapCOFFRuntime(PlatformJD)) {
440 Err = std::move(E2);
441 return;
442 }
443
444 Bootstrapping.store(false);
445 JDBootstrapStates.clear();
446}
447
449COFFPlatform::buildJDDepMap(JITDylib &JD) {
450 return ES.runSessionLocked([&]() -> Expected<JITDylibDepMap> {
451 JITDylibDepMap JDDepMap;
452
453 SmallVector<JITDylib *, 16> Worklist({&JD});
454 while (!Worklist.empty()) {
455 auto CurJD = Worklist.back();
456 Worklist.pop_back();
457
458 auto &DM = JDDepMap[CurJD];
459 CurJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
460 DM.reserve(O.size());
461 for (auto &KV : O) {
462 if (KV.first == CurJD)
463 continue;
464 {
465 // Bare jitdylibs not known to the platform
466 std::lock_guard<std::mutex> Lock(PlatformMutex);
467 if (!JITDylibToHeaderAddr.count(KV.first)) {
468 LLVM_DEBUG({
469 dbgs() << "JITDylib unregistered to COFFPlatform detected in "
470 "LinkOrder: "
471 << CurJD->getName() << "\n";
472 });
473 continue;
474 }
475 }
476 DM.push_back(KV.first);
477 // Push unvisited entry.
478 if (!JDDepMap.count(KV.first)) {
479 Worklist.push_back(KV.first);
480 JDDepMap[KV.first] = {};
481 }
482 }
483 });
484 }
485 return std::move(JDDepMap);
486 });
487}
488
489void COFFPlatform::pushInitializersLoop(PushInitializersSendResultFn SendResult,
490 JITDylibSP JD,
491 JITDylibDepMap &JDDepMap) {
492 SmallVector<JITDylib *, 16> Worklist({JD.get()});
493 DenseSet<JITDylib *> Visited({JD.get()});
495 ES.runSessionLocked([&]() {
496 while (!Worklist.empty()) {
497 auto CurJD = Worklist.back();
498 Worklist.pop_back();
499
500 auto RISItr = RegisteredInitSymbols.find(CurJD);
501 if (RISItr != RegisteredInitSymbols.end()) {
502 NewInitSymbols[CurJD] = std::move(RISItr->second);
503 RegisteredInitSymbols.erase(RISItr);
504 }
505
506 for (auto *DepJD : JDDepMap[CurJD])
507 if (!Visited.count(DepJD)) {
508 Worklist.push_back(DepJD);
509 Visited.insert(DepJD);
510 }
511 }
512 });
513
514 // If there are no further init symbols to look up then send the link order
515 // (as a list of header addresses) to the caller.
516 if (NewInitSymbols.empty()) {
517 // Build the dep info map to return.
518 COFFJITDylibDepInfoMap DIM;
519 DIM.reserve(JDDepMap.size());
520 for (auto &KV : JDDepMap) {
521 std::lock_guard<std::mutex> Lock(PlatformMutex);
522 COFFJITDylibDepInfo DepInfo;
523 DepInfo.reserve(KV.second.size());
524 for (auto &Dep : KV.second) {
525 DepInfo.push_back(JITDylibToHeaderAddr[Dep]);
526 }
527 auto H = JITDylibToHeaderAddr[KV.first];
528 DIM.push_back(std::make_pair(H, std::move(DepInfo)));
529 }
530 SendResult(DIM);
531 return;
532 }
533
534 // Otherwise issue a lookup and re-run this phase when it completes.
535 lookupInitSymbolsAsync(
536 [this, SendResult = std::move(SendResult), &JD,
537 JDDepMap = std::move(JDDepMap)](Error Err) mutable {
538 if (Err)
539 SendResult(std::move(Err));
540 else
541 pushInitializersLoop(std::move(SendResult), JD, JDDepMap);
542 },
543 ES, std::move(NewInitSymbols));
544}
545
546void COFFPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
547 ExecutorAddr JDHeaderAddr) {
548 JITDylibSP JD;
549 {
550 std::lock_guard<std::mutex> Lock(PlatformMutex);
551 auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
552 if (I != HeaderAddrToJITDylib.end())
553 JD = I->second;
554 }
555
556 LLVM_DEBUG({
557 dbgs() << "COFFPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
558 if (JD)
559 dbgs() << "pushing initializers for " << JD->getName() << "\n";
560 else
561 dbgs() << "No JITDylib for header address.\n";
562 });
563
564 if (!JD) {
565 SendResult(
566 make_error<StringError>("No JITDylib with header addr " +
567 formatv("{0:x}", JDHeaderAddr.getValue()),
569 return;
570 }
571
572 auto JDDepMap = buildJDDepMap(*JD);
573 if (!JDDepMap) {
574 SendResult(JDDepMap.takeError());
575 return;
576 }
577
578 pushInitializersLoop(std::move(SendResult), JD, *JDDepMap);
579}
580
581void COFFPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
582 ExecutorAddr Handle, StringRef SymbolName) {
583 LLVM_DEBUG({
584 dbgs() << "COFFPlatform::rt_lookupSymbol(\""
585 << formatv("{0:x}", Handle.getValue()) << "\")\n";
586 });
587
588 JITDylib *JD = nullptr;
589
590 {
591 std::lock_guard<std::mutex> Lock(PlatformMutex);
592 auto I = HeaderAddrToJITDylib.find(Handle);
593 if (I != HeaderAddrToJITDylib.end())
594 JD = I->second;
595 }
596
597 if (!JD) {
598 LLVM_DEBUG({
599 dbgs() << " No JITDylib for handle "
600 << formatv("{0:x}", Handle.getValue()) << "\n";
601 });
602 SendResult(make_error<StringError>("No JITDylib associated with handle " +
603 formatv("{0:x}", Handle.getValue()),
605 return;
606 }
607
608 // Use functor class to work around XL build compiler issue on AIX.
609 class RtLookupNotifyComplete {
610 public:
611 RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
612 : SendResult(std::move(SendResult)) {}
613 void operator()(Expected<SymbolMap> Result) {
614 if (Result) {
615 assert(Result->size() == 1 && "Unexpected result map count");
616 SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
617 } else {
618 SendResult(Result.takeError());
619 }
620 }
621
622 private:
623 SendSymbolAddressFn SendResult;
624 };
625
626 ES.lookup(
629 RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
630}
631
632Error COFFPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
634
635 using LookupSymbolSPSSig =
637 WFs[ES.intern("__orc_rt_coff_symbol_lookup_tag")] =
638 ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
639 &COFFPlatform::rt_lookupSymbol);
640 using PushInitializersSPSSig =
642 WFs[ES.intern("__orc_rt_coff_push_initializers_tag")] =
643 ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
644 this, &COFFPlatform::rt_pushInitializers);
645
646 return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
647}
648
649Error COFFPlatform::runBootstrapInitializers(JDBootstrapState &BState) {
650 llvm::sort(BState.Initializers);
651 if (auto Err =
652 runBootstrapSubsectionInitializers(BState, ".CRT$XIA", ".CRT$XIZ"))
653 return Err;
654
655 if (auto Err = runSymbolIfExists(*BState.JD, "__run_after_c_init"))
656 return Err;
657
658 if (auto Err =
659 runBootstrapSubsectionInitializers(BState, ".CRT$XCA", ".CRT$XCZ"))
660 return Err;
661 return Error::success();
662}
663
664Error COFFPlatform::runBootstrapSubsectionInitializers(JDBootstrapState &BState,
665 StringRef Start,
666 StringRef End) {
667 for (auto &Initializer : BState.Initializers)
668 if (Initializer.first >= Start && Initializer.first <= End &&
669 Initializer.second) {
670 auto Res =
671 ES.getExecutorProcessControl().runAsVoidFunction(Initializer.second);
672 if (!Res)
673 return Res.takeError();
674 }
675 return Error::success();
676}
677
678Error COFFPlatform::bootstrapCOFFRuntime(JITDylib &PlatformJD) {
679 // Lookup of runtime symbols causes the collection of initializers if
680 // it's static linking setting.
681 if (auto Err = lookupAndRecordAddrs(
683 {
684 {ES.intern("__orc_rt_coff_platform_bootstrap"),
685 &orc_rt_coff_platform_bootstrap},
686 {ES.intern("__orc_rt_coff_platform_shutdown"),
687 &orc_rt_coff_platform_shutdown},
688 {ES.intern("__orc_rt_coff_register_jitdylib"),
689 &orc_rt_coff_register_jitdylib},
690 {ES.intern("__orc_rt_coff_deregister_jitdylib"),
691 &orc_rt_coff_deregister_jitdylib},
692 {ES.intern("__orc_rt_coff_register_object_sections"),
693 &orc_rt_coff_register_object_sections},
694 {ES.intern("__orc_rt_coff_deregister_object_sections"),
695 &orc_rt_coff_deregister_object_sections},
696 }))
697 return Err;
698
699 // Call bootstrap functions
700 if (auto Err = ES.callSPSWrapper<void()>(orc_rt_coff_platform_bootstrap))
701 return Err;
702
703 // Do the pending jitdylib registration actions that we couldn't do
704 // because orc runtime was not linked fully.
705 for (auto KV : JDBootstrapStates) {
706 auto &JDBState = KV.second;
707 if (auto Err = ES.callSPSWrapper<void(SPSString, SPSExecutorAddr)>(
708 orc_rt_coff_register_jitdylib, JDBState.JDName,
709 JDBState.HeaderAddr))
710 return Err;
711
712 for (auto &ObjSectionMap : JDBState.ObjectSectionsMaps)
713 if (auto Err = ES.callSPSWrapper<void(SPSExecutorAddr,
715 orc_rt_coff_register_object_sections, JDBState.HeaderAddr,
716 ObjSectionMap, false))
717 return Err;
718 }
719
720 // Run static initializers collected in bootstrap stage.
721 for (auto KV : JDBootstrapStates) {
722 auto &JDBState = KV.second;
723 if (auto Err = runBootstrapInitializers(JDBState))
724 return Err;
725 }
726
727 return Error::success();
728}
729
730Error COFFPlatform::runSymbolIfExists(JITDylib &PlatformJD,
731 StringRef SymbolName) {
732 ExecutorAddr jit_function;
733 auto AfterCLookupErr = lookupAndRecordAddrs(
735 {{ES.intern(SymbolName), &jit_function}});
736 if (!AfterCLookupErr) {
737 auto Res = ES.getExecutorProcessControl().runAsVoidFunction(jit_function);
738 if (!Res)
739 return Res.takeError();
740 return Error::success();
741 }
742 if (!AfterCLookupErr.isA<SymbolsNotFound>())
743 return AfterCLookupErr;
744 consumeError(std::move(AfterCLookupErr));
745 return Error::success();
746}
747
748void COFFPlatform::COFFPlatformPlugin::modifyPassConfig(
751
752 bool IsBootstrapping = CP.Bootstrapping.load();
753
754 if (auto InitSymbol = MR.getInitializerSymbol()) {
755 if (InitSymbol == CP.COFFHeaderStartSymbol) {
756 Config.PostAllocationPasses.push_back(
757 [this, &MR, IsBootstrapping](jitlink::LinkGraph &G) {
758 return associateJITDylibHeaderSymbol(G, MR, IsBootstrapping);
759 });
760 return;
761 }
762 Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
763 return preserveInitializerSections(G, MR);
764 });
765 }
766
767 if (!IsBootstrapping)
768 Config.PostFixupPasses.push_back(
769 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
770 return registerObjectPlatformSections(G, JD);
771 });
772 else
773 Config.PostFixupPasses.push_back(
774 [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
775 return registerObjectPlatformSectionsInBootstrap(G, JD);
776 });
777}
778
780COFFPlatform::COFFPlatformPlugin::getSyntheticSymbolDependencies(
782 std::lock_guard<std::mutex> Lock(PluginMutex);
783 auto I = InitSymbolDeps.find(&MR);
784 if (I != InitSymbolDeps.end()) {
785 SyntheticSymbolDependenciesMap Result;
786 Result[MR.getInitializerSymbol()] = std::move(I->second);
787 InitSymbolDeps.erase(&MR);
788 return Result;
789 }
790 return SyntheticSymbolDependenciesMap();
791}
792
793Error COFFPlatform::COFFPlatformPlugin::associateJITDylibHeaderSymbol(
795 bool IsBootstraping) {
796 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
797 return Sym->getName() == *CP.COFFHeaderStartSymbol;
798 });
799 assert(I != G.defined_symbols().end() && "Missing COFF header start symbol");
800
801 auto &JD = MR.getTargetJITDylib();
802 std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
803 auto HeaderAddr = (*I)->getAddress();
804 CP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
805 CP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
806 if (!IsBootstraping) {
807 G.allocActions().push_back(
810 CP.orc_rt_coff_register_jitdylib, JD.getName(), HeaderAddr)),
812 CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
813 } else {
814 G.allocActions().push_back(
815 {{},
817 CP.orc_rt_coff_deregister_jitdylib, HeaderAddr))});
818 JDBootstrapState BState;
819 BState.JD = &JD;
820 BState.JDName = JD.getName();
821 BState.HeaderAddr = HeaderAddr;
822 CP.JDBootstrapStates.emplace(&JD, BState);
823 }
824
825 return Error::success();
826}
827
828Error COFFPlatform::COFFPlatformPlugin::registerObjectPlatformSections(
830 COFFObjectSectionsMap ObjSecs;
831 auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
832 assert(HeaderAddr && "Must be registered jitdylib");
833 for (auto &S : G.sections()) {
835 if (Range.getSize())
836 ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
837 }
838
839 G.allocActions().push_back(
840 {cantFail(WrapperFunctionCall::Create<SPSCOFFRegisterObjectSectionsArgs>(
841 CP.orc_rt_coff_register_object_sections, HeaderAddr, ObjSecs, true)),
842 cantFail(
843 WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
844 CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
845 ObjSecs))});
846
847 return Error::success();
848}
849
850Error COFFPlatform::COFFPlatformPlugin::preserveInitializerSections(
852 JITLinkSymbolSet InitSectionSymbols;
853 for (auto &Sec : G.sections())
854 if (isCOFFInitializerSection(Sec.getName()))
855 for (auto *B : Sec.blocks())
856 if (!B->edges_empty())
857 InitSectionSymbols.insert(
858 &G.addAnonymousSymbol(*B, 0, 0, false, true));
859
860 std::lock_guard<std::mutex> Lock(PluginMutex);
861 InitSymbolDeps[&MR] = InitSectionSymbols;
862 return Error::success();
863}
864
865Error COFFPlatform::COFFPlatformPlugin::
866 registerObjectPlatformSectionsInBootstrap(jitlink::LinkGraph &G,
867 JITDylib &JD) {
868 std::lock_guard<std::mutex> Lock(CP.PlatformMutex);
869 auto HeaderAddr = CP.JITDylibToHeaderAddr[&JD];
870 COFFObjectSectionsMap ObjSecs;
871 for (auto &S : G.sections()) {
873 if (Range.getSize())
874 ObjSecs.push_back(std::make_pair(S.getName().str(), Range.getRange()));
875 }
876
877 G.allocActions().push_back(
878 {{},
879 cantFail(
880 WrapperFunctionCall::Create<SPSCOFFDeregisterObjectSectionsArgs>(
881 CP.orc_rt_coff_deregister_object_sections, HeaderAddr,
882 ObjSecs))});
883
884 auto &BState = CP.JDBootstrapStates[&JD];
885 BState.ObjectSectionsMaps.push_back(std::move(ObjSecs));
886
887 // Collect static initializers
888 for (auto &S : G.sections())
889 if (isCOFFInitializerSection(S.getName()))
890 for (auto *B : S.blocks()) {
891 if (B->edges_empty())
892 continue;
893 for (auto &E : B->edges())
894 BState.Initializers.push_back(std::make_pair(
895 S.getName().str(),
896 ExecutorAddr(E.getTarget().getAddress() + E.getAddend())));
897 }
898
899 return Error::success();
900}
901
902} // End namespace orc.
903} // End namespace llvm.
#define offsetof(TYPE, MEMBER)
for(auto &MBB :MF)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DEBUG(X)
Definition: Debug.h:101
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
#define _
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
#define H(x, y, z)
Definition: MD5.cpp:57
#define P(N)
if(VerifyEach)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:151
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
Helper for Errors used as out-parameters.
Definition: Error.h:1104
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
bool empty() const
Definition: SmallVector.h:94
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
const std::string & str() const
Definition: Triple.h:415
Mediates between COFF initialization and ExecutionSession state.
Definition: COFFPlatform.h:33
Error setupJITDylib(JITDylib &JD) override
This method will be called outside the session lock each time a JITDylib is created (unless it is cre...
static ArrayRef< std::pair< const char *, const char * > > standardRuntimeUtilityAliases()
Returns the array of standard runtime utility aliases for COFF.
Error teardownJITDylib(JITDylib &JD) override
This method will be called outside the session lock each time a JITDylib is removed to allow the Plat...
static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES)
Returns an AliasMap containing the default aliases for the COFFPlatform.
Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) override
This method will be called under the ExecutionSession lock each time a MaterializationUnit is added t...
static ArrayRef< std::pair< const char *, const char * > > requiredCXXAliases()
Returns the array of required CXX aliases.
static Expected< std::unique_ptr< COFFPlatform > > Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, const char *OrcRuntimePath, LoadDynamicLibrary LoadDynLibrary, bool StaticVCRuntime=false, const char *VCRuntimePath=nullptr, std::optional< SymbolAliasMap > RuntimeAliases=std::nullopt)
Try to create a COFFPlatform instance, adding the ORC runtime to the given JITDylib.
Error notifyRemoving(ResourceTracker &RT) override
This method will be called under the ExecutionSession lock when a ResourceTracker is removed.
static Expected< std::unique_ptr< COFFVCRuntimeBootstrapper > > Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, const char *RuntimePath=nullptr)
Try to create a COFFVCRuntimeBootstrapper instance.
static std::unique_ptr< DLLImportDefinitionGenerator > Create(ExecutionSession &ES, ObjectLinkingLayer &L)
Creates a DLLImportDefinitionGenerator instance.
An ExecutionSession represents a running JIT program.
Definition: Core.h:1373
ExecutorProcessControl & getExecutorProcessControl()
Get the ExecutorProcessControl object associated with this ExecutionSession.
Definition: Core.h:1416
const Triple & getTargetTriple() const
Return the triple for the executor.
Definition: Core.h:1419
Error callSPSWrapper(ExecutorAddr WrapperFnAddr, WrapperCallArgTs &&...WrapperCallArgs)
Run a wrapper function using SPS to serialize the arguments and deserialize the results.
Definition: Core.h:1621
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:1427
JITDylib & createBareJITDylib(std::string Name)
Add a new bare JITDylib to this ExecutionSession.
Definition: Core.cpp:1948
static JITDispatchHandlerFunction wrapAsyncWithSPS(HandlerT &&H)
Wrap a handler that takes concrete argument types (and a sender for a concrete return type) to produc...
Definition: Core.h:1635
void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder, SymbolLookupSet Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies)
Search the given JITDylibs for the given symbols.
Definition: Core.cpp:2084
Error registerJITDispatchHandlers(JITDylib &JD, JITDispatchHandlerAssociationMap WFs)
For each tag symbol name, associate the corresponding AsyncHandlerWrapperFunction with the address of...
Definition: Core.cpp:2193
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
Definition: Core.h:1437
Represents an address in the executor process.
uint64_t getValue() const
virtual Expected< int32_t > runAsVoidFunction(ExecutorAddr VoidFnAddr)=0
Run function with a int (*)(void) signature.
Represents a JIT'd dynamic library.
Definition: Core.h:962
Error define(std::unique_ptr< MaterializationUnitType > &&MU, ResourceTrackerSP RT=nullptr)
Define all symbols provided by the materialization unit to be part of this JITDylib.
Definition: Core.h:1816
void addToLinkOrder(JITDylib &JD, JITDylibLookupFlags JDLookupFlags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Add the given JITDylib to the link order for definitions in this JITDylib.
Definition: Core.cpp:1332
GeneratorT & addGenerator(std::unique_ptr< GeneratorT > DefGenerator)
Adds a definition generator to this JITDylib and returns a referenece to it.
Definition: Core.h:1799
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:524
const SymbolStringPtr & getInitializerSymbol() const
Returns the initialization pseudo-symbol, if any.
Definition: Core.h:560
JITDylib & getTargetJITDylib() const
Returns the target JITDylib that these symbols are being materialized into.
Definition: Core.h:546
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Definition: Core.h:673
virtual StringRef getName() const =0
Return the name of this materialization unit.
virtual void materialize(std::unique_ptr< MaterializationResponsibility > R)=0
Implementations of this method should materialize all symbols in the materialzation unit,...
const SymbolStringPtr & getInitializerSymbol() const
Returns the initialization symbol for this MaterializationUnit (if any).
Definition: Core.h:706
An ObjectLayer implementation built on JITLink.
ObjectLinkingLayer & addPlugin(std::unique_ptr< Plugin > P)
Add a pass-config modifier.
Error add(ResourceTrackerSP, std::unique_ptr< jitlink::LinkGraph > G)
Add a LinkGraph to the JITDylib targeted by the given tracker.
API to remove / transfer ownership of JIT resources.
Definition: Core.h:53
JITDylib & getJITDylib() const
Return the JITDylib targeted by this tracker.
Definition: Core.h:68
static Expected< std::unique_ptr< StaticLibraryDefinitionGenerator > > Load(ObjectLayer &L, const char *FileName, GetObjectFileInterface GetObjFileInterface=GetObjectFileInterface())
Try to create a StaticLibraryDefinitionGenerator from the given path.
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Definition: Core.h:180
Pointer to a pooled string representing a symbol name.
Used to notify clients when symbols can not be found during a lookup.
Definition: Core.h:437
A utility class for serializing to a blob from a variadic list.
SPS tag type for expecteds, which are either a T or a string representing an error.
static Expected< WrapperFunctionCall > Create(ExecutorAddr FnAddr, const ArgTs &...Args)
Create a WrapperFunctionCall using the given SPS serializer to serialize the arguments.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ IMAGE_FILE_MACHINE_AMD64
Definition: COFF.h:97
@ NUM_DATA_DIRECTORIES
Definition: COFF.h:599
static const char PEMagic[]
Definition: COFF.h:35
constexpr support::endianness Endianness
The endianness of all multi-byte encoded values in MessagePack.
Definition: MsgPack.h:24
JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib * > JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...
Definition: Core.h:163
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
Definition: Core.h:159
std::unique_ptr< ReExportsMaterializationUnit > symbolAliases(SymbolAliasMap Aliases)
Create a ReExportsMaterializationUnit with the given aliases.
Definition: Core.h:817
std::unique_ptr< AbsoluteSymbolsMaterializationUnit > absoluteSymbols(SymbolMap Symbols)
Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
Definition: Core.h:771
void lookupAndRecordAddrs(unique_function< void(Error)> OnRecorded, ExecutionSession &ES, LookupKind K, const JITDylibSearchOrder &SearchOrder, std::vector< std::pair< SymbolStringPtr, ExecutorAddr * > > Pairs, SymbolLookupFlags LookupFlags=SymbolLookupFlags::RequiredSymbol)
Record addresses of the given symbols in the given ExecutorAddrs.
static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, ArrayRef< std::pair< const char *, const char * > > AL)
Expected< MaterializationUnit::Interface > getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer)
Returns a MaterializationUnit::Interface for the object file contained in the given buffer,...
RegisterDependenciesFunction NoDependenciesToRegister
This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...
Definition: Core.cpp:35
bool isCOFFInitializerSection(StringRef Name)
@ Ready
Emitted to memory, but waiting on transitive dependencies.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition: Error.h:1327
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1744
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:745
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1946
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1846
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
Definition: BitVector.h:858
The DOS compatible header at the front of all PE/COFF executables.
Definition: COFF.h:53
The 64-bit PE header that follows the COFF header.
Definition: COFF.h:140