LLVM 17.0.0git
MachOPlatform.cpp
Go to the documentation of this file.
1//===------ MachOPlatform.cpp - Utilities for executing MachO 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
10
17#include "llvm/Support/Debug.h"
18#include <optional>
19
20#define DEBUG_TYPE "orc"
21
22using namespace llvm;
23using namespace llvm::orc;
24using namespace llvm::orc::shared;
25
26namespace llvm {
27namespace orc {
28namespace shared {
29
33
34template <>
36 MachOPlatform::MachOJITDylibDepInfo> {
37public:
38 static size_t size(const MachOPlatform::MachOJITDylibDepInfo &DDI) {
39 return SPSMachOJITDylibDepInfo::AsArgList::size(DDI.Sealed, DDI.DepHeaders);
40 }
41
42 static bool serialize(SPSOutputBuffer &OB,
44 return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, DDI.Sealed,
45 DDI.DepHeaders);
46 }
47
48 static bool deserialize(SPSInputBuffer &IB,
50 return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, DDI.Sealed,
51 DDI.DepHeaders);
52 }
53};
54
55} // namespace shared
56} // namespace orc
57} // namespace llvm
58
59namespace {
60
61std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP,
62 std::string Name) {
63 unsigned PointerSize;
65 const auto &TT =
67
68 switch (TT.getArch()) {
69 case Triple::aarch64:
70 case Triple::x86_64:
71 PointerSize = 8;
72 Endianness = support::endianness::little;
73 break;
74 default:
75 llvm_unreachable("Unrecognized architecture");
76 }
77
78 return std::make_unique<jitlink::LinkGraph>(std::move(Name), TT, PointerSize,
79 Endianness,
81}
82
83// Generates a MachO header.
84class MachOHeaderMaterializationUnit : public MaterializationUnit {
85public:
86 MachOHeaderMaterializationUnit(MachOPlatform &MOP,
87 const SymbolStringPtr &HeaderStartSymbol)
88 : MaterializationUnit(createHeaderInterface(MOP, HeaderStartSymbol)),
89 MOP(MOP) {}
90
91 StringRef getName() const override { return "MachOHeaderMU"; }
92
93 void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
94 auto G = createPlatformGraph(MOP, "<MachOHeaderMU>");
95 addMachOHeader(*G, MOP, R->getInitializerSymbol());
96 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
97 }
98
99 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
100
101 static void addMachOHeader(jitlink::LinkGraph &G, MachOPlatform &MOP,
102 const SymbolStringPtr &InitializerSymbol) {
103 auto &HeaderSection = G.createSection("__header", MemProt::Read);
104 auto &HeaderBlock = createHeaderBlock(G, HeaderSection);
105
106 // Init symbol is header-start symbol.
107 G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol,
108 HeaderBlock.getSize(), jitlink::Linkage::Strong,
109 jitlink::Scope::Default, false, true);
110 for (auto &HS : AdditionalHeaderSymbols)
111 G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(),
112 jitlink::Linkage::Strong, jitlink::Scope::Default,
113 false, true);
114 }
115
116private:
117 struct HeaderSymbol {
118 const char *Name;
120 };
121
122 static constexpr HeaderSymbol AdditionalHeaderSymbols[] = {
123 {"___mh_executable_header", 0}};
124
125 static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
126 jitlink::Section &HeaderSection) {
129 switch (G.getTargetTriple().getArch()) {
130 case Triple::aarch64:
133 break;
134 case Triple::x86_64:
137 break;
138 default:
139 llvm_unreachable("Unrecognized architecture");
140 }
141 Hdr.filetype = MachO::MH_DYLIB; // Custom file type?
142 Hdr.ncmds = 0;
143 Hdr.sizeofcmds = 0;
144 Hdr.flags = 0;
145 Hdr.reserved = 0;
146
147 if (G.getEndianness() != support::endian::system_endianness())
149
150 auto HeaderContent = G.allocateString(
151 StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
152
153 return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
154 0);
155 }
156
158 createHeaderInterface(MachOPlatform &MOP,
159 const SymbolStringPtr &HeaderStartSymbol) {
160 SymbolFlagsMap HeaderSymbolFlags;
161
162 HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
163 for (auto &HS : AdditionalHeaderSymbols)
164 HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] =
166
167 return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
168 HeaderStartSymbol);
169 }
170
171 MachOPlatform &MOP;
172};
173
174constexpr MachOHeaderMaterializationUnit::HeaderSymbol
175 MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[];
176
177// Creates a Bootstrap-Complete LinkGraph to run deferred actions.
178class MachOPlatformCompleteBootstrapMaterializationUnit
179 : public MaterializationUnit {
180public:
181 MachOPlatformCompleteBootstrapMaterializationUnit(
182 MachOPlatform &MOP, StringRef PlatformJDName,
183 SymbolStringPtr CompleteBootstrapSymbol, shared::AllocActions DeferredAAs,
184 ExecutorAddr PlatformBootstrap, ExecutorAddr PlatformShutdown,
185 ExecutorAddr RegisterJITDylib, ExecutorAddr DeregisterJITDylib,
186 ExecutorAddr MachOHeaderAddr)
188 {{{CompleteBootstrapSymbol, JITSymbolFlags::None}}, nullptr}),
189 MOP(MOP), PlatformJDName(PlatformJDName),
190 CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)),
191 DeferredAAs(std::move(DeferredAAs)),
192 PlatformBootstrap(PlatformBootstrap),
193 PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib),
194 DeregisterJITDylib(DeregisterJITDylib),
195 MachOHeaderAddr(MachOHeaderAddr) {}
196
197 StringRef getName() const override {
198 return "MachOPlatformCompleteBootstrap";
199 }
200
201 void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
202 using namespace jitlink;
203 auto G = createPlatformGraph(MOP, "<OrcRTCompleteBootstrap>");
204 auto &PlaceholderSection =
205 G->createSection("__orc_rt_cplt_bs", MemProt::Read);
206 auto &PlaceholderBlock =
207 G->createZeroFillBlock(PlaceholderSection, 1, ExecutorAddr(), 1, 0);
208 G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1,
209 Linkage::Strong, Scope::Hidden, false, true);
210
211 // Reserve space for the stolen actions, plus two extras.
212 G->allocActions().reserve(DeferredAAs.size() + 2);
213
214 // 1. Bootstrap the platform support code.
215 G->allocActions().push_back(
217 cantFail(
218 WrapperFunctionCall::Create<SPSArgList<>>(PlatformShutdown))});
219
220 // 2. Register the platform JITDylib.
221 G->allocActions().push_back(
224 RegisterJITDylib, PlatformJDName, MachOHeaderAddr)),
226 DeregisterJITDylib, MachOHeaderAddr))});
227
228 // 3. Add the deferred actions to the graph.
229 std::move(DeferredAAs.begin(), DeferredAAs.end(),
230 std::back_inserter(G->allocActions()));
231
232 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
233 }
234
235 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
236
237private:
238 MachOPlatform &MOP;
239 StringRef PlatformJDName;
240 SymbolStringPtr CompleteBootstrapSymbol;
241 shared::AllocActions DeferredAAs;
242 ExecutorAddr PlatformBootstrap;
243 ExecutorAddr PlatformShutdown;
244 ExecutorAddr RegisterJITDylib;
245 ExecutorAddr DeregisterJITDylib;
246 ExecutorAddr MachOHeaderAddr;
247};
248
249StringRef DataCommonSectionName = "__DATA,__common";
250StringRef DataDataSectionName = "__DATA,__data";
251StringRef EHFrameSectionName = "__TEXT,__eh_frame";
252StringRef CompactUnwindInfoSectionName = "__TEXT,__unwind_info";
253StringRef ModInitFuncSectionName = "__DATA,__mod_init_func";
254StringRef ObjCClassListSectionName = "__DATA,__objc_classlist";
255StringRef ObjCImageInfoSectionName = "__DATA,__objc_image_info";
256StringRef ObjCSelRefsSectionName = "__DATA,__objc_selrefs";
257StringRef Swift5ProtoSectionName = "__TEXT,__swift5_proto";
258StringRef Swift5ProtosSectionName = "__TEXT,__swift5_protos";
259StringRef Swift5TypesSectionName = "__TEXT,__swift5_types";
260StringRef ThreadBSSSectionName = "__DATA,__thread_bss";
261StringRef ThreadDataSectionName = "__DATA,__thread_data";
262StringRef ThreadVarsSectionName = "__DATA,__thread_vars";
263
264StringRef InitSectionNames[] = {
265 ModInitFuncSectionName, ObjCSelRefsSectionName, ObjCClassListSectionName,
266 Swift5ProtosSectionName, Swift5ProtoSectionName, Swift5TypesSectionName};
267
268} // end anonymous namespace
269
270namespace llvm {
271namespace orc {
272
275 JITDylib &PlatformJD, const char *OrcRuntimePath,
276 std::optional<SymbolAliasMap> RuntimeAliases) {
277
278 auto &EPC = ES.getExecutorProcessControl();
279
280 // If the target is not supported then bail out immediately.
281 if (!supportedTarget(EPC.getTargetTriple()))
282 return make_error<StringError>("Unsupported MachOPlatform triple: " +
283 EPC.getTargetTriple().str(),
285
286 // Create default aliases if the caller didn't supply any.
287 if (!RuntimeAliases)
288 RuntimeAliases = standardPlatformAliases(ES);
289
290 // Define the aliases.
291 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
292 return std::move(Err);
293
294 // Add JIT-dispatch function support symbols.
295 if (auto Err = PlatformJD.define(absoluteSymbols(
296 {{ES.intern("___orc_rt_jit_dispatch"),
297 {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
299 {ES.intern("___orc_rt_jit_dispatch_ctx"),
300 {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
302 return std::move(Err);
303
304 // Create a generator for the ORC runtime archive.
305 auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load(
306 ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple());
307 if (!OrcRuntimeArchiveGenerator)
308 return OrcRuntimeArchiveGenerator.takeError();
309
310 // Create the instance.
311 Error Err = Error::success();
312 auto P = std::unique_ptr<MachOPlatform>(
313 new MachOPlatform(ES, ObjLinkingLayer, PlatformJD,
314 std::move(*OrcRuntimeArchiveGenerator), Err));
315 if (Err)
316 return std::move(Err);
317 return std::move(P);
318}
319
321 if (auto Err = JD.define(std::make_unique<MachOHeaderMaterializationUnit>(
322 *this, MachOHeaderStartSymbol)))
323 return Err;
324
325 return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError();
326}
327
329 std::lock_guard<std::mutex> Lock(PlatformMutex);
330 auto I = JITDylibToHeaderAddr.find(&JD);
331 if (I != JITDylibToHeaderAddr.end()) {
332 assert(HeaderAddrToJITDylib.count(I->second) &&
333 "HeaderAddrToJITDylib missing entry");
334 HeaderAddrToJITDylib.erase(I->second);
335 JITDylibToHeaderAddr.erase(I);
336 }
337 JITDylibToPThreadKey.erase(&JD);
338 return Error::success();
339}
340
342 const MaterializationUnit &MU) {
343 auto &JD = RT.getJITDylib();
344 const auto &InitSym = MU.getInitializerSymbol();
345 if (!InitSym)
346 return Error::success();
347
348 RegisteredInitSymbols[&JD].add(InitSym,
350 LLVM_DEBUG({
351 dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU "
352 << MU.getName() << "\n";
353 });
354 return Error::success();
355}
356
358 llvm_unreachable("Not supported yet");
359}
360
362 ArrayRef<std::pair<const char *, const char *>> AL) {
363 for (auto &KV : AL) {
364 auto AliasName = ES.intern(KV.first);
365 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
366 Aliases[std::move(AliasName)] = {ES.intern(KV.second),
368 }
369}
370
372 SymbolAliasMap Aliases;
373 addAliases(ES, Aliases, requiredCXXAliases());
375 return Aliases;
376}
377
380 static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
381 {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}};
382
383 return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
384}
385
388 static const std::pair<const char *, const char *>
389 StandardRuntimeUtilityAliases[] = {
390 {"___orc_rt_run_program", "___orc_rt_macho_run_program"},
391 {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"},
392 {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"},
393 {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"},
394 {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"},
395 {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};
396
398 StandardRuntimeUtilityAliases);
399}
400
402 StringRef SectName) {
403 for (auto &Name : InitSectionNames) {
404 if (Name.startswith(SegName) && Name.substr(7) == SectName)
405 return true;
406 }
407 return false;
408}
409
410bool MachOPlatform::supportedTarget(const Triple &TT) {
411 switch (TT.getArch()) {
412 case Triple::aarch64:
413 case Triple::x86_64:
414 return true;
415 default:
416 return false;
417 }
418}
419
420MachOPlatform::MachOPlatform(
421 ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
422 JITDylib &PlatformJD,
423 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
424 : ES(ES), PlatformJD(PlatformJD), ObjLinkingLayer(ObjLinkingLayer) {
426 ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this));
427 PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
428
429 BootstrapInfo BI;
430 Bootstrap = &BI;
431
432 // Bootstrap process -- here be phase-ordering dragons.
433 //
434 // The MachOPlatform class uses allocation actions to register metadata
435 // sections with the ORC runtime, however the runtime contains metadata
436 // registration functions that have their own metadata that they need to
437 // register (e.g. the frame-info registration functions have frame-info).
438 // We can't use an ordinary lookup to find these registration functions
439 // because their address is needed during the link of the containing graph
440 // itself (to build the allocation actions that will call the registration
441 // functions). Further complicating the situation (a) the graph containing
442 // the registration functions is allowed to depend on other graphs (e.g. the
443 // graph containing the ORC runtime RTTI support) so we need to handle with
444 // an unknown set of dependencies during bootstrap, and (b) these graphs may
445 // be linked concurrently if the user has installed a concurrent dispatcher.
446 //
447 // We satisfy these constraint by implementing a bootstrap phase during which
448 // allocation actions generated by MachOPlatform are appended to a list of
449 // deferred allocation actions, rather than to the graphs themselves. At the
450 // end of the bootstrap process the deferred actions are attached to a final
451 // "complete-bootstrap" graph that causes them to be run.
452 //
453 // The bootstrap steps are as follows:
454 //
455 // 1. Request the graph containing the mach header. This graph is guaranteed
456 // not to have any metadata so the fact that the registration functions
457 // are not available yet is not a problem.
458 //
459 // 2. Look up the registration functions and discard the results. This will
460 // trigger linking of the graph containing these functions, and
461 // consequently any graphs that it depends on. We do not use the lookup
462 // result to find the addresses of the functions requested (as described
463 // above the lookup will return too late for that), instead we capture the
464 // addresses in a post-allocation pass injected by the platform runtime
465 // during bootstrap only.
466 //
467 // 3. During bootstrap the MachOPlatformPlugin keeps a count of the number of
468 // graphs being linked (potentially concurrently), and we block until all
469 // of these graphs have completed linking. This is to avoid a race on the
470 // deferred-actions vector: the lookup for the runtime registration
471 // functions may return while some functions (those that are being
472 // incidentally linked in, but aren't reachable via the runtime functions)
473 // are still being linked, and we need to capture any allocation actions
474 // for this incidental code before we proceed.
475 //
476 // 4. Once all active links are complete we transfer the deferred actions to
477 // a newly added CompleteBootstrap graph and then request a symbol from
478 // the CompleteBootstrap graph to trigger materialization. This will cause
479 // all deferred actions to be run, and once this lookup returns we can
480 // proceed.
481 //
482 // 5. Finally, we associate runtime support methods in MachOPlatform with
483 // the corresponding jit-dispatch tag variables in the ORC runtime to make
484 // the support methods callable. The bootstrap is now complete.
485
486 // Step (1) Add header materialization unit and request.
487 if ((Err = PlatformJD.define(std::make_unique<MachOHeaderMaterializationUnit>(
488 *this, MachOHeaderStartSymbol))))
489 return;
490 if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError()))
491 return;
492
493 // Step (2) Request runtime registration functions to trigger
494 // materialization..
495 if ((Err = ES.lookup(makeJITDylibSearchOrder(&PlatformJD),
497 {PlatformBootstrap.Name, PlatformShutdown.Name,
498 RegisterJITDylib.Name, DeregisterJITDylib.Name,
499 RegisterObjectPlatformSections.Name,
500 DeregisterObjectPlatformSections.Name,
501 CreatePThreadKey.Name}))
502 .takeError()))
503 return;
504
505 // Step (3) Wait for any incidental linker work to complete.
506 {
507 std::unique_lock<std::mutex> Lock(BI.Mutex);
508 BI.CV.wait(Lock, [&]() { return BI.ActiveGraphs == 0; });
509 Bootstrap = nullptr;
510 }
511
512 // Step (4) Add complete-bootstrap materialization unit and request.
513 auto BootstrapCompleteSymbol = ES.intern("__orc_rt_macho_complete_bootstrap");
514 if ((Err = PlatformJD.define(
515 std::make_unique<MachOPlatformCompleteBootstrapMaterializationUnit>(
516 *this, PlatformJD.getName(), BootstrapCompleteSymbol,
517 std::move(BI.DeferredAAs), PlatformBootstrap.Addr,
518 PlatformShutdown.Addr, RegisterJITDylib.Addr,
519 DeregisterJITDylib.Addr, BI.MachOHeaderAddr))))
520 return;
521 if ((Err = ES.lookup(makeJITDylibSearchOrder(
523 std::move(BootstrapCompleteSymbol))
524 .takeError()))
525 return;
526
527 // (5) Associate runtime support functions.
528 if ((Err = associateRuntimeSupportFunctions()))
529 return;
530}
531
532Error MachOPlatform::associateRuntimeSupportFunctions() {
534
535 using PushInitializersSPSSig =
537 WFs[ES.intern("___orc_rt_macho_push_initializers_tag")] =
538 ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
539 this, &MachOPlatform::rt_pushInitializers);
540
541 using LookupSymbolSPSSig =
543 WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] =
544 ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
545 &MachOPlatform::rt_lookupSymbol);
546
547 return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
548}
549
550void MachOPlatform::pushInitializersLoop(
551 PushInitializersSendResultFn SendResult, JITDylibSP JD) {
554 SmallVector<JITDylib *, 16> Worklist({JD.get()});
555
556 ES.runSessionLocked([&]() {
557 while (!Worklist.empty()) {
558 // FIXME: Check for defunct dylibs.
559
560 auto DepJD = Worklist.back();
561 Worklist.pop_back();
562
563 // If we've already visited this JITDylib on this iteration then continue.
564 if (JDDepMap.count(DepJD))
565 continue;
566
567 // Add dep info.
568 auto &DM = JDDepMap[DepJD];
569 DepJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
570 for (auto &KV : O) {
571 if (KV.first == DepJD)
572 continue;
573 DM.push_back(KV.first);
574 Worklist.push_back(KV.first);
575 }
576 });
577
578 // Add any registered init symbols.
579 auto RISItr = RegisteredInitSymbols.find(DepJD);
580 if (RISItr != RegisteredInitSymbols.end()) {
581 NewInitSymbols[DepJD] = std::move(RISItr->second);
582 RegisteredInitSymbols.erase(RISItr);
583 }
584 }
585 });
586
587 // If there are no further init symbols to look up then send the link order
588 // (as a list of header addresses) to the caller.
589 if (NewInitSymbols.empty()) {
590
591 // To make the list intelligible to the runtime we need to convert all
592 // JITDylib pointers to their header addresses. Only include JITDylibs
593 // that appear in the JITDylibToHeaderAddr map (i.e. those that have been
594 // through setupJITDylib) -- bare JITDylibs aren't managed by the platform.
596 HeaderAddrs.reserve(JDDepMap.size());
597 {
598 std::lock_guard<std::mutex> Lock(PlatformMutex);
599 for (auto &KV : JDDepMap) {
600 auto I = JITDylibToHeaderAddr.find(KV.first);
601 if (I != JITDylibToHeaderAddr.end())
602 HeaderAddrs[KV.first] = I->second;
603 }
604 }
605
606 // Build the dep info map to return.
607 MachOJITDylibDepInfoMap DIM;
608 DIM.reserve(JDDepMap.size());
609 for (auto &KV : JDDepMap) {
610 auto HI = HeaderAddrs.find(KV.first);
611 // Skip unmanaged JITDylibs.
612 if (HI == HeaderAddrs.end())
613 continue;
614 auto H = HI->second;
615 MachOJITDylibDepInfo DepInfo;
616 for (auto &Dep : KV.second) {
617 auto HJ = HeaderAddrs.find(Dep);
618 if (HJ != HeaderAddrs.end())
619 DepInfo.DepHeaders.push_back(HJ->second);
620 }
621 DIM.push_back(std::make_pair(H, std::move(DepInfo)));
622 }
623 SendResult(DIM);
624 return;
625 }
626
627 // Otherwise issue a lookup and re-run this phase when it completes.
628 lookupInitSymbolsAsync(
629 [this, SendResult = std::move(SendResult), JD](Error Err) mutable {
630 if (Err)
631 SendResult(std::move(Err));
632 else
633 pushInitializersLoop(std::move(SendResult), JD);
634 },
635 ES, std::move(NewInitSymbols));
636}
637
638void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
639 ExecutorAddr JDHeaderAddr) {
640 JITDylibSP JD;
641 {
642 std::lock_guard<std::mutex> Lock(PlatformMutex);
643 auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
644 if (I != HeaderAddrToJITDylib.end())
645 JD = I->second;
646 }
647
648 LLVM_DEBUG({
649 dbgs() << "MachOPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
650 if (JD)
651 dbgs() << "pushing initializers for " << JD->getName() << "\n";
652 else
653 dbgs() << "No JITDylib for header address.\n";
654 });
655
656 if (!JD) {
657 SendResult(
658 make_error<StringError>("No JITDylib with header addr " +
659 formatv("{0:x}", JDHeaderAddr.getValue()),
661 return;
662 }
663
664 pushInitializersLoop(std::move(SendResult), JD);
665}
666
667void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
668 ExecutorAddr Handle, StringRef SymbolName) {
669 LLVM_DEBUG({
670 dbgs() << "MachOPlatform::rt_lookupSymbol(\""
671 << formatv("{0:x}", Handle.getValue()) << "\")\n";
672 });
673
674 JITDylib *JD = nullptr;
675
676 {
677 std::lock_guard<std::mutex> Lock(PlatformMutex);
678 auto I = HeaderAddrToJITDylib.find(Handle);
679 if (I != HeaderAddrToJITDylib.end())
680 JD = I->second;
681 }
682
683 if (!JD) {
684 LLVM_DEBUG({
685 dbgs() << " No JITDylib for handle "
686 << formatv("{0:x}", Handle.getValue()) << "\n";
687 });
688 SendResult(make_error<StringError>("No JITDylib associated with handle " +
689 formatv("{0:x}", Handle.getValue()),
691 return;
692 }
693
694 // Use functor class to work around XL build compiler issue on AIX.
695 class RtLookupNotifyComplete {
696 public:
697 RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
698 : SendResult(std::move(SendResult)) {}
699 void operator()(Expected<SymbolMap> Result) {
700 if (Result) {
701 assert(Result->size() == 1 && "Unexpected result map count");
702 SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
703 } else {
704 SendResult(Result.takeError());
705 }
706 }
707
708 private:
709 SendSymbolAddressFn SendResult;
710 };
711
712 // FIXME: Proper mangling.
713 auto MangledName = ("_" + SymbolName).str();
714 ES.lookup(
715 LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
716 SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready,
717 RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
718}
719
720Expected<uint64_t> MachOPlatform::createPThreadKey() {
721 if (!CreatePThreadKey.Addr)
722 return make_error<StringError>(
723 "Attempting to create pthread key in target, but runtime support has "
724 "not been loaded yet",
726
728 if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
729 CreatePThreadKey.Addr, Result))
730 return std::move(Err);
731 return Result;
732}
733
734void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
737
738 using namespace jitlink;
739
740 bool InBootstrapPhase =
741 &MR.getTargetJITDylib() == &MP.PlatformJD && MP.Bootstrap;
742
743 // If we're in the bootstrap phase then increment the active graphs.
744 if (InBootstrapPhase) {
745 Config.PrePrunePasses.push_back(
746 [this](LinkGraph &G) { return bootstrapPipelineStart(G); });
747 Config.PostAllocationPasses.push_back([this](LinkGraph &G) {
748 return bootstrapPipelineRecordRuntimeFunctions(G);
749 });
750 }
751
752 // --- Handle Initializers ---
753 if (auto InitSymbol = MR.getInitializerSymbol()) {
754
755 // If the initializer symbol is the MachOHeader start symbol then just
756 // register it and then bail out -- the header materialization unit
757 // definitely doesn't need any other passes.
758 if (InitSymbol == MP.MachOHeaderStartSymbol && !InBootstrapPhase) {
759 Config.PostAllocationPasses.push_back([this, &MR](LinkGraph &G) {
760 return associateJITDylibHeaderSymbol(G, MR);
761 });
762 return;
763 }
764
765 // If the object contains an init symbol other than the header start symbol
766 // then add passes to preserve, process and register the init
767 // sections/symbols.
768 Config.PrePrunePasses.push_back([this, &MR](LinkGraph &G) {
769 if (auto Err = preserveInitSections(G, MR))
770 return Err;
771 return processObjCImageInfo(G, MR);
772 });
773 }
774
775 // Insert TLV lowering at the start of the PostPrunePasses, since we want
776 // it to run before GOT/PLT lowering.
777 Config.PostPrunePasses.insert(
778 Config.PostPrunePasses.begin(),
779 [this, &JD = MR.getTargetJITDylib()](LinkGraph &G) {
780 return fixTLVSectionsAndEdges(G, JD);
781 });
782
783 // Add a pass to register the final addresses of any special sections in the
784 // object with the runtime.
785 Config.PostAllocationPasses.push_back(
786 [this, &JD = MR.getTargetJITDylib(), InBootstrapPhase](LinkGraph &G) {
787 return registerObjectPlatformSections(G, JD, InBootstrapPhase);
788 });
789
790 // If we're in the bootstrap phase then steal allocation actions and then
791 // decrement the active graphs.
792 if (InBootstrapPhase)
793 Config.PostFixupPasses.push_back(
794 [this](LinkGraph &G) { return bootstrapPipelineEnd(G); });
795}
796
798MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies(
800 std::lock_guard<std::mutex> Lock(PluginMutex);
801 auto I = InitSymbolDeps.find(&MR);
802 if (I != InitSymbolDeps.end()) {
803 SyntheticSymbolDependenciesMap Result;
804 Result[MR.getInitializerSymbol()] = std::move(I->second);
805 InitSymbolDeps.erase(&MR);
806 return Result;
807 }
808 return SyntheticSymbolDependenciesMap();
809}
810
811Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineStart(
813 // Increment the active graphs count in BootstrapInfo.
814 std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
815 ++MP.Bootstrap.load()->ActiveGraphs;
816 return Error::success();
817}
818
819Error MachOPlatform::MachOPlatformPlugin::
820 bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) {
821 // Record bootstrap function names.
822 std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = {
823 {*MP.MachOHeaderStartSymbol, &MP.Bootstrap.load()->MachOHeaderAddr},
824 {*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr},
825 {*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr},
826 {*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr},
827 {*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr},
828 {*MP.RegisterObjectPlatformSections.Name,
829 &MP.RegisterObjectPlatformSections.Addr},
830 {*MP.DeregisterObjectPlatformSections.Name,
831 &MP.DeregisterObjectPlatformSections.Addr},
832 {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr}};
833
834 bool RegisterMachOHeader = false;
835
836 for (auto *Sym : G.defined_symbols()) {
837 for (auto &RTSym : RuntimeSymbols) {
838 if (Sym->hasName() && Sym->getName() == RTSym.first) {
839 if (*RTSym.second)
840 return make_error<StringError>(
841 "Duplicate " + RTSym.first +
842 " detected during MachOPlatform bootstrap",
844
845 if (Sym->getName() == *MP.MachOHeaderStartSymbol)
846 RegisterMachOHeader = true;
847
848 *RTSym.second = Sym->getAddress();
849 }
850 }
851 }
852
853 if (RegisterMachOHeader) {
854 // If this graph defines the macho header symbol then create the internal
855 // mapping between it and PlatformJD.
856 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
857 MP.JITDylibToHeaderAddr[&MP.PlatformJD] =
858 MP.Bootstrap.load()->MachOHeaderAddr;
859 MP.HeaderAddrToJITDylib[MP.Bootstrap.load()->MachOHeaderAddr] =
860 &MP.PlatformJD;
861 }
862
863 return Error::success();
864}
865
866Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd(
868 std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
869 assert(MP.Bootstrap && "DeferredAAs reset before bootstrap completed");
870 --MP.Bootstrap.load()->ActiveGraphs;
871 // Notify Bootstrap->CV while holding the mutex because the mutex is
872 // also keeping Bootstrap->CV alive.
873 if (MP.Bootstrap.load()->ActiveGraphs == 0)
874 MP.Bootstrap.load()->CV.notify_all();
875 return Error::success();
876}
877
878Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
880 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
881 return Sym->getName() == *MP.MachOHeaderStartSymbol;
882 });
883 assert(I != G.defined_symbols().end() && "Missing MachO header start symbol");
884
885 auto &JD = MR.getTargetJITDylib();
886 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
887 auto HeaderAddr = (*I)->getAddress();
888 MP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
889 MP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
890 // We can unconditionally add these actions to the Graph because this pass
891 // isn't used during bootstrap.
892 G.allocActions().push_back(
893 {cantFail(
895 MP.RegisterJITDylib.Addr, JD.getName(), HeaderAddr)),
897 MP.DeregisterJITDylib.Addr, HeaderAddr))});
898 return Error::success();
899}
900
901Error MachOPlatform::MachOPlatformPlugin::preserveInitSections(
903
904 JITLinkSymbolSet InitSectionSymbols;
905 for (auto &InitSectionName : InitSectionNames) {
906 // Skip non-init sections.
907 auto *InitSection = G.findSectionByName(InitSectionName);
908 if (!InitSection)
909 continue;
910
911 // Make a pass over live symbols in the section: those blocks are already
912 // preserved.
913 DenseSet<jitlink::Block *> AlreadyLiveBlocks;
914 for (auto &Sym : InitSection->symbols()) {
915 auto &B = Sym->getBlock();
916 if (Sym->isLive() && Sym->getOffset() == 0 &&
917 Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) {
918 InitSectionSymbols.insert(Sym);
919 AlreadyLiveBlocks.insert(&B);
920 }
921 }
922
923 // Add anonymous symbols to preserve any not-already-preserved blocks.
924 for (auto *B : InitSection->blocks())
925 if (!AlreadyLiveBlocks.count(B))
926 InitSectionSymbols.insert(
927 &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true));
928 }
929
930 if (!InitSectionSymbols.empty()) {
931 std::lock_guard<std::mutex> Lock(PluginMutex);
932 InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
933 }
934
935 return Error::success();
936}
937
938Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
940
941 // If there's an ObjC imagine info then either
942 // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In
943 // this case we name and record it.
944 // OR
945 // (2) We already have a recorded __objc_imageinfo for this JITDylib,
946 // in which case we just verify it.
947 auto *ObjCImageInfo = G.findSectionByName(ObjCImageInfoSectionName);
948 if (!ObjCImageInfo)
949 return Error::success();
950
951 auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();
952
953 // Check that the section is not empty if present.
954 if (ObjCImageInfoBlocks.empty())
955 return make_error<StringError>("Empty " + ObjCImageInfoSectionName +
956 " section in " + G.getName(),
958
959 // Check that there's only one block in the section.
960 if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
961 return make_error<StringError>("Multiple blocks in " +
962 ObjCImageInfoSectionName +
963 " section in " + G.getName(),
965
966 // Check that the __objc_imageinfo section is unreferenced.
967 // FIXME: We could optimize this check if Symbols had a ref-count.
968 for (auto &Sec : G.sections()) {
969 if (&Sec != ObjCImageInfo)
970 for (auto *B : Sec.blocks())
971 for (auto &E : B->edges())
972 if (E.getTarget().isDefined() &&
973 &E.getTarget().getBlock().getSection() == ObjCImageInfo)
974 return make_error<StringError>(ObjCImageInfoSectionName +
975 " is referenced within file " +
976 G.getName(),
978 }
979
980 auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();
981 auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();
982 auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness());
983 auto Flags =
984 support::endian::read32(ObjCImageInfoData + 4, G.getEndianness());
985
986 // Lock the mutex while we verify / update the ObjCImageInfos map.
987 std::lock_guard<std::mutex> Lock(PluginMutex);
988
989 auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib());
990 if (ObjCImageInfoItr != ObjCImageInfos.end()) {
991 // We've already registered an __objc_imageinfo section. Verify the
992 // content of this new section matches, then delete it.
993 if (ObjCImageInfoItr->second.first != Version)
994 return make_error<StringError>(
995 "ObjC version in " + G.getName() +
996 " does not match first registered version",
998 if (ObjCImageInfoItr->second.second != Flags)
999 return make_error<StringError>("ObjC flags in " + G.getName() +
1000 " do not match first registered flags",
1002
1003 // __objc_imageinfo is valid. Delete the block.
1004 for (auto *S : ObjCImageInfo->symbols())
1005 G.removeDefinedSymbol(*S);
1006 G.removeBlock(ObjCImageInfoBlock);
1007 } else {
1008 // We haven't registered an __objc_imageinfo section yet. Register and
1009 // move on. The section should already be marked no-dead-strip.
1010 ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags);
1011 }
1012
1013 return Error::success();
1014}
1015
1016Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
1018
1019 // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr.
1020 for (auto *Sym : G.external_symbols())
1021 if (Sym->getName() == "__tlv_bootstrap") {
1022 Sym->setName("___orc_rt_macho_tlv_get_addr");
1023 break;
1024 }
1025
1026 // Store key in __thread_vars struct fields.
1027 if (auto *ThreadDataSec = G.findSectionByName(ThreadVarsSectionName)) {
1028 std::optional<uint64_t> Key;
1029 {
1030 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
1031 auto I = MP.JITDylibToPThreadKey.find(&JD);
1032 if (I != MP.JITDylibToPThreadKey.end())
1033 Key = I->second;
1034 }
1035
1036 if (!Key) {
1037 if (auto KeyOrErr = MP.createPThreadKey())
1038 Key = *KeyOrErr;
1039 else
1040 return KeyOrErr.takeError();
1041 }
1042
1043 uint64_t PlatformKeyBits =
1044 support::endian::byte_swap(*Key, G.getEndianness());
1045
1046 for (auto *B : ThreadDataSec->blocks()) {
1047 if (B->getSize() != 3 * G.getPointerSize())
1048 return make_error<StringError>("__thread_vars block at " +
1049 formatv("{0:x}", B->getAddress()) +
1050 " has unexpected size",
1052
1053 auto NewBlockContent = G.allocateBuffer(B->getSize());
1054 llvm::copy(B->getContent(), NewBlockContent.data());
1055 memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits,
1056 G.getPointerSize());
1057 B->setContent(NewBlockContent);
1058 }
1059 }
1060
1061 // Transform any TLV edges into GOT edges.
1062 for (auto *B : G.blocks())
1063 for (auto &E : B->edges())
1064 if (E.getKind() ==
1066 E.setKind(jitlink::x86_64::
1067 RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable);
1068
1069 return Error::success();
1070}
1071
1072std::optional<MachOPlatform::MachOPlatformPlugin::UnwindSections>
1073MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
1075 using namespace jitlink;
1076
1077 UnwindSections US;
1078
1079 // ScanSection records a section range and adds any executable blocks that
1080 // that section points to to the CodeBlocks vector.
1081 SmallVector<Block *> CodeBlocks;
1082 auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) {
1083 if (Sec.blocks().empty())
1084 return;
1085 SecRange = (*Sec.blocks().begin())->getRange();
1086 for (auto *B : Sec.blocks()) {
1087 auto R = B->getRange();
1088 SecRange.Start = std::min(SecRange.Start, R.Start);
1089 SecRange.End = std::max(SecRange.End, R.End);
1090 for (auto &E : B->edges()) {
1091 if (!E.getTarget().isDefined())
1092 continue;
1093 auto &TargetBlock = E.getTarget().getBlock();
1094 auto &TargetSection = TargetBlock.getSection();
1095 if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec)
1096 CodeBlocks.push_back(&TargetBlock);
1097 }
1098 }
1099 };
1100
1101 if (Section *EHFrameSec = G.findSectionByName(EHFrameSectionName))
1102 ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);
1103
1104 if (Section *CUInfoSec = G.findSectionByName(CompactUnwindInfoSectionName))
1105 ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);
1106
1107 // If we didn't find any pointed-to code-blocks then there's no need to
1108 // register any info.
1109 if (CodeBlocks.empty())
1110 return std::nullopt;
1111
1112 // We have info to register. Sort the code blocks into address order and
1113 // build a list of contiguous address ranges covering them all.
1114 llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) {
1115 return LHS->getAddress() < RHS->getAddress();
1116 });
1117 for (auto *B : CodeBlocks) {
1118 if (US.CodeRanges.empty() || US.CodeRanges.back().End != B->getAddress())
1119 US.CodeRanges.push_back(B->getRange());
1120 else
1121 US.CodeRanges.back().End = B->getRange().End;
1122 }
1123
1124 LLVM_DEBUG({
1125 dbgs() << "MachOPlatform identified unwind info in " << G.getName() << ":\n"
1126 << " DWARF: ";
1127 if (US.DwarfSection.Start)
1128 dbgs() << US.DwarfSection << "\n";
1129 else
1130 dbgs() << "none\n";
1131 dbgs() << " Compact-unwind: ";
1132 if (US.CompactUnwindSection.Start)
1133 dbgs() << US.CompactUnwindSection << "\n";
1134 else
1135 dbgs() << "none\n"
1136 << "for code ranges:\n";
1137 for (auto &CR : US.CodeRanges)
1138 dbgs() << " " << CR << "\n";
1139 if (US.CodeRanges.size() >= G.sections_size())
1140 dbgs() << "WARNING: High number of discontiguous code ranges! "
1141 "Padding may be interfering with coalescing.\n";
1142 });
1143
1144 return US;
1145}
1146
1147Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
1148 jitlink::LinkGraph &G, JITDylib &JD, bool InBootstrapPhase) {
1149
1150 // Get a pointer to the thread data section if there is one. It will be used
1151 // below.
1152 jitlink::Section *ThreadDataSection =
1153 G.findSectionByName(ThreadDataSectionName);
1154
1155 // Handle thread BSS section if there is one.
1156 if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
1157 // If there's already a thread data section in this graph then merge the
1158 // thread BSS section content into it, otherwise just treat the thread
1159 // BSS section as the thread data section.
1160 if (ThreadDataSection)
1161 G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
1162 else
1163 ThreadDataSection = ThreadBSSSection;
1164 }
1165
1167
1168 // Collect data sections to register.
1169 StringRef DataSections[] = {DataDataSectionName, DataCommonSectionName,
1170 EHFrameSectionName};
1171 for (auto &SecName : DataSections) {
1172 if (auto *Sec = G.findSectionByName(SecName)) {
1174 if (!R.empty())
1175 MachOPlatformSecs.push_back({SecName, R.getRange()});
1176 }
1177 }
1178
1179 // Having merged thread BSS (if present) and thread data (if present),
1180 // record the resulting section range.
1181 if (ThreadDataSection) {
1182 jitlink::SectionRange R(*ThreadDataSection);
1183 if (!R.empty())
1184 MachOPlatformSecs.push_back({ThreadDataSectionName, R.getRange()});
1185 }
1186
1187 // If any platform sections were found then add an allocation action to call
1188 // the registration function.
1189 StringRef PlatformSections[] = {
1190 ModInitFuncSectionName, ObjCClassListSectionName,
1191 ObjCImageInfoSectionName, ObjCSelRefsSectionName,
1192 Swift5ProtoSectionName, Swift5ProtosSectionName,
1193 Swift5TypesSectionName,
1194 };
1195
1196 for (auto &SecName : PlatformSections) {
1197 auto *Sec = G.findSectionByName(SecName);
1198 if (!Sec)
1199 continue;
1201 if (R.empty())
1202 continue;
1203
1204 MachOPlatformSecs.push_back({SecName, R.getRange()});
1205 }
1206
1207 std::optional<std::tuple<SmallVector<ExecutorAddrRange>, ExecutorAddrRange,
1209 UnwindInfo;
1210 if (auto UI = findUnwindSectionInfo(G))
1211 UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection,
1212 UI->CompactUnwindSection);
1213
1214 if (!MachOPlatformSecs.empty() || UnwindInfo) {
1215 ExecutorAddr HeaderAddr;
1216 {
1217 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
1218 auto I = MP.JITDylibToHeaderAddr.find(&JD);
1219 assert(I != MP.JITDylibToHeaderAddr.end() &&
1220 "Missing header for JITDylib");
1221 HeaderAddr = I->second;
1222 }
1223
1224 // Dump the scraped inits.
1225 LLVM_DEBUG({
1226 dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";
1227 for (auto &KV : MachOPlatformSecs)
1228 dbgs() << " " << KV.first << ": " << KV.second << "\n";
1229 });
1230
1231 using SPSRegisterObjectPlatformSectionsArgs = SPSArgList<
1236
1237 shared::AllocActions &allocActions = LLVM_LIKELY(!InBootstrapPhase)
1238 ? G.allocActions()
1239 : MP.Bootstrap.load()->DeferredAAs;
1240
1241 allocActions.push_back(
1242 {cantFail(
1243 WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
1244 MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo,
1245 MachOPlatformSecs)),
1246 cantFail(
1247 WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
1248 MP.DeregisterObjectPlatformSections.Addr, HeaderAddr,
1249 UnwindInfo, MachOPlatformSecs))});
1250 }
1251
1252 return Error::success();
1253}
1254
1255} // End namespace orc.
1256} // End namespace llvm.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:209
#define LLVM_DEBUG(X)
Definition: Debug.h:101
std::string Name
#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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Value * RHS
Value * LHS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
unsigned size() const
Definition: DenseMap.h:99
bool empty() const
Definition: DenseMap.h:98
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:145
iterator end()
Definition: DenseMap.h:84
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition: DenseMap.h:103
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...
bool empty() const
Definition: SmallVector.h:94
void push_back(const T &Elt)
Definition: SmallVector.h:416
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
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition: DenseSet.h:97
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
Error callSPSWrapper(ExecutorAddr WrapperFnAddr, WrapperCallArgTs &&...WrapperCallArgs)
Run a wrapper function using SPS to serialize the arguments and deserialize the results.
Definition: Core.h:1618
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:1424
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:1632
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:2077
Error registerJITDispatchHandlers(JITDylib &JD, JITDispatchHandlerAssociationMap WFs)
For each tag symbol name, associate the corresponding AsyncHandlerWrapperFunction with the address of...
Definition: Core.cpp:2186
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
Definition: Core.h:1434
Represents an address in the executor process.
uint64_t getValue() const
const Triple & getTargetTriple() const
Return the Triple for the target process.
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:1813
GeneratorT & addGenerator(std::unique_ptr< GeneratorT > DefGenerator)
Adds a definition generator to this JITDylib and returns a referenece to it.
Definition: Core.h:1796
Mediates between MachO initialization and ExecutionSession state.
Definition: MachOPlatform.h:30
ObjectLinkingLayer & getObjectLinkingLayer() const
Definition: MachOPlatform.h:86
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 bool isInitializerSection(StringRef SegName, StringRef SectName)
Returns true if the given section name is an initializer section.
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 MachO.
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 Expected< std::unique_ptr< MachOPlatform > > Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, const char *OrcRuntimePath, std::optional< SymbolAliasMap > RuntimeAliases=std::nullopt)
Try to create a MachOPlatform instance, adding the ORC runtime to the given JITDylib.
static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES)
Returns an AliasMap containing the default aliases for the MachOPlatform.
ExecutionSession & getExecutionSession() const
Definition: MachOPlatform.h:85
Error notifyRemoving(ResourceTracker &RT) override
This method will be called under the ExecutionSession lock when a ResourceTracker is removed.
static ArrayRef< std::pair< const char *, const char * > > requiredCXXAliases()
Returns the array of required CXX aliases.
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.
void emit(std::unique_ptr< MaterializationResponsibility > R, std::unique_ptr< MemoryBuffer > O) override
Emit an object file.
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.
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.
Input char buffer with underflow check.
Output char buffer with overflow check.
static bool serialize(SPSOutputBuffer &OB, const MachOPlatform::MachOJITDylibDepInfo &DDI)
static bool deserialize(SPSInputBuffer &IB, MachOPlatform::MachOJITDylibDepInfo &DDI)
Specialize to describe how to serialize/deserialize to/from the given concrete type.
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.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Key
PAL metadata keys.
const uint64_t Version
Definition: InstrProf.h:1058
@ MH_MAGIC_64
Definition: MachO.h:32
@ CPU_SUBTYPE_ARM64_ALL
Definition: MachO.h:1639
@ MH_DYLIB
Definition: MachO.h:48
void swapStruct(fat_header &mh)
Definition: MachO.h:1139
@ CPU_SUBTYPE_X86_64_ALL
Definition: MachO.h:1609
@ CPU_TYPE_ARM64
Definition: MachO.h:1568
@ CPU_TYPE_X86_64
Definition: MachO.h:1564
constexpr support::endianness Endianness
The endianness of all multi-byte encoded values in MessagePack.
Definition: MsgPack.h:24
SPSTuple< SPSExecutorAddr, SPSExecutorAddr > SPSExecutorAddrRange
std::vector< AllocActionCallPair > AllocActions
A vector of allocation actions to be run for this allocation.
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::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
static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, ArrayRef< std::pair< const char *, const char * > > AL)
RegisterDependenciesFunction NoDependenciesToRegister
This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...
Definition: Core.cpp:35
value_type byte_swap(value_type value, endianness endian)
Definition: Endian.h:49
uint32_t read32(const void *P, endianness E)
Definition: Endian.h:363
constexpr endianness system_endianness()
Definition: Endian.h:44
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))...))>
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:1683
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 copy(R &&Range, OutputIt Out)
Definition: STLExtras.h:1837
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:1862
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:1762
Definition: BitVector.h:851
Represents an address range in the exceutor process.