LLVM 24.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
11
22#include "llvm/Support/Debug.h"
23#include <optional>
24
25#define DEBUG_TYPE "orc"
26
27using namespace llvm;
28using namespace llvm::orc;
29using namespace llvm::orc::shared;
30
31namespace llvm {
32namespace orc {
33namespace shared {
34
38
39class SPSMachOExecutorSymbolFlags;
40
41template <>
43 MachOPlatform::MachOJITDylibDepInfo> {
44public:
45 static size_t size(const MachOPlatform::MachOJITDylibDepInfo &DDI) {
46 return SPSMachOJITDylibDepInfo::AsArgList::size(DDI.Sealed, DDI.DepHeaders);
47 }
48
49 static bool serialize(SPSOutputBuffer &OB,
51 return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, DDI.Sealed,
52 DDI.DepHeaders);
53 }
54
55 static bool deserialize(SPSInputBuffer &IB,
57 return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, DDI.Sealed,
58 DDI.DepHeaders);
59 }
60};
61
62template <>
63class SPSSerializationTraits<SPSMachOExecutorSymbolFlags,
64 MachOPlatform::MachOExecutorSymbolFlags> {
65private:
66 using UT = std::underlying_type_t<MachOPlatform::MachOExecutorSymbolFlags>;
67
68public:
70 return sizeof(UT);
71 }
72
73 static bool serialize(SPSOutputBuffer &OB,
75 return SPSArgList<UT>::serialize(OB, static_cast<UT>(SF));
76 }
77
78 static bool deserialize(SPSInputBuffer &IB,
80 UT Tmp;
81 if (!SPSArgList<UT>::deserialize(IB, Tmp))
82 return false;
83 SF = static_cast<MachOPlatform::MachOExecutorSymbolFlags>(Tmp);
84 return true;
85 }
86};
87
88} // namespace shared
89} // namespace orc
90} // namespace llvm
91
92// Controller-interface descriptors for the MachO platform runtime's SPS
93// wrapper calls.
96 static constexpr SymbolNameSpec Name =
97 SymbolNameSpec::c("__orc_rt_macho_create_pthread_key");
99};
100} // namespace llvm::orc::macho_sps_ci
101
102namespace {
103
104using SPSRegisterSymbolsArgs =
107 SPSMachOExecutorSymbolFlags>>>;
108
109std::unique_ptr<jitlink::LinkGraph> createPlatformGraph(MachOPlatform &MOP,
110 std::string Name) {
111 auto &ES = MOP.getExecutionSession();
112 return std::make_unique<jitlink::LinkGraph>(
113 std::move(Name), ES.getSymbolStringPool(), ES.getTargetTriple(),
114 ES.getTargetTriple().getArchPointerBitWidth() / 8, SubtargetFeatures(),
116}
117
118// Creates a Bootstrap-Complete LinkGraph to run deferred actions.
119class MachOPlatformCompleteBootstrapMaterializationUnit
120 : public MaterializationUnit {
121public:
122 using SymbolTableVector =
125
126 MachOPlatformCompleteBootstrapMaterializationUnit(
127 MachOPlatform &MOP, StringRef PlatformJDName,
128 SymbolStringPtr CompleteBootstrapSymbol, SymbolTableVector SymTab,
129 shared::AllocActions DeferredAAs, ExecutorAddr MachOHeaderAddr,
130 ExecutorAddr PlatformBootstrap, ExecutorAddr PlatformShutdown,
131 ExecutorAddr RegisterJITDylib, ExecutorAddr DeregisterJITDylib,
132 ExecutorAddr RegisterObjectSymbolTable,
133 ExecutorAddr DeregisterObjectSymbolTable)
135 {{{CompleteBootstrapSymbol, JITSymbolFlags::None}}, nullptr}),
136 MOP(MOP), PlatformJDName(PlatformJDName),
137 CompleteBootstrapSymbol(std::move(CompleteBootstrapSymbol)),
138 SymTab(std::move(SymTab)), DeferredAAs(std::move(DeferredAAs)),
139 MachOHeaderAddr(MachOHeaderAddr), PlatformBootstrap(PlatformBootstrap),
140 PlatformShutdown(PlatformShutdown), RegisterJITDylib(RegisterJITDylib),
141 DeregisterJITDylib(DeregisterJITDylib),
142 RegisterObjectSymbolTable(RegisterObjectSymbolTable),
143 DeregisterObjectSymbolTable(DeregisterObjectSymbolTable) {}
144
145 StringRef getName() const override {
146 return "MachOPlatformCompleteBootstrap";
147 }
148
149 void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
150 using namespace jitlink;
151 auto G = createPlatformGraph(MOP, "<OrcRTCompleteBootstrap>");
152 auto &PlaceholderSection =
153 G->createSection("__orc_rt_cplt_bs", MemProt::Read);
154 auto &PlaceholderBlock =
155 G->createZeroFillBlock(PlaceholderSection, 1, ExecutorAddr(), 1, 0);
156 G->addDefinedSymbol(PlaceholderBlock, 0, *CompleteBootstrapSymbol, 1,
157 Linkage::Strong, Scope::Hidden, false, true);
158
159 // Reserve space for the stolen actions, plus two extras.
160 G->allocActions().reserve(DeferredAAs.size() + 3);
161
162 // 1. Bootstrap the platform support code.
163 G->allocActions().push_back(
164 {cantFail(WrapperFunctionCall::Create<SPSArgList<>>(PlatformBootstrap)),
165 cantFail(
166 WrapperFunctionCall::Create<SPSArgList<>>(PlatformShutdown))});
167
168 // 2. Register the platform JITDylib.
169 G->allocActions().push_back(
171 SPSArgList<SPSString, SPSExecutorAddr>>(
172 RegisterJITDylib, PlatformJDName, MachOHeaderAddr)),
173 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
174 DeregisterJITDylib, MachOHeaderAddr))});
175
176 // 3. Register deferred symbols.
177 G->allocActions().push_back(
179 RegisterObjectSymbolTable, MachOHeaderAddr, SymTab)),
181 DeregisterObjectSymbolTable, MachOHeaderAddr, SymTab))});
182
183 // 4. Add the deferred actions to the graph.
184 std::move(DeferredAAs.begin(), DeferredAAs.end(),
185 std::back_inserter(G->allocActions()));
186
187 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
188 }
189
190 void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
191
192private:
193 MachOPlatform &MOP;
194 StringRef PlatformJDName;
195 SymbolStringPtr CompleteBootstrapSymbol;
196 SymbolTableVector SymTab;
197 shared::AllocActions DeferredAAs;
198 ExecutorAddr MachOHeaderAddr;
199 ExecutorAddr PlatformBootstrap;
200 ExecutorAddr PlatformShutdown;
201 ExecutorAddr RegisterJITDylib;
202 ExecutorAddr DeregisterJITDylib;
203 ExecutorAddr RegisterObjectSymbolTable;
204 ExecutorAddr DeregisterObjectSymbolTable;
205};
206
207static StringRef ObjCRuntimeObjectSectionsData[] = {
214
215static StringRef ObjCRuntimeObjectSectionsText[] = {
221
222static StringRef ObjCRuntimeObjectSectionName =
223 "__llvm_jitlink_ObjCRuntimeRegistrationObject";
224
225static StringRef ObjCImageInfoSymbolName =
226 "__llvm_jitlink_macho_objc_imageinfo";
227
228struct ObjCImageInfoFlags {
229 uint16_t SwiftABIVersion;
230 uint16_t SwiftVersion;
231 bool HasCategoryClassProperties;
232 bool HasSignedObjCClassROs;
233
234 static constexpr uint32_t SIGNED_CLASS_RO = (1 << 4);
235 static constexpr uint32_t HAS_CATEGORY_CLASS_PROPERTIES = (1 << 6);
236
237 explicit ObjCImageInfoFlags(uint32_t RawFlags) {
238 HasSignedObjCClassROs = RawFlags & SIGNED_CLASS_RO;
239 HasCategoryClassProperties = RawFlags & HAS_CATEGORY_CLASS_PROPERTIES;
240 SwiftABIVersion = (RawFlags >> 8) & 0xFF;
241 SwiftVersion = (RawFlags >> 16) & 0xFFFF;
242 }
243
244 uint32_t rawFlags() const {
245 uint32_t Result = 0;
246 if (HasCategoryClassProperties)
247 Result |= HAS_CATEGORY_CLASS_PROPERTIES;
248 if (HasSignedObjCClassROs)
249 Result |= SIGNED_CLASS_RO;
250 Result |= (SwiftABIVersion << 8);
251 Result |= (SwiftVersion << 16);
252 return Result;
253 }
254};
255} // end anonymous namespace
256
257namespace llvm {
258namespace orc {
259
260std::optional<MachOPlatform::HeaderOptions::BuildVersionOpts>
263 uint32_t SDK) {
264
266 switch (TT.getOS()) {
267 case Triple::IOS:
268 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR
269 : MachO::PLATFORM_IOS;
270 break;
271 case Triple::MacOSX:
272 Platform = MachO::PLATFORM_MACOS;
273 break;
274 case Triple::TvOS:
275 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR
276 : MachO::PLATFORM_TVOS;
277 break;
278 case Triple::WatchOS:
279 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR
280 : MachO::PLATFORM_WATCHOS;
281 break;
282 case Triple::XROS:
283 Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_XROS_SIMULATOR
284 : MachO::PLATFORM_XROS;
285 break;
286 default:
287 return std::nullopt;
288 }
289
291}
292
295 std::unique_ptr<DefinitionGenerator> OrcRuntime,
296 HeaderOptionsBuilder BuildHeaderOpts,
297 HeaderOptions PlatformJDOpts,
298 MachOHeaderMUBuilder BuildMachOHeaderMU,
299 std::optional<SymbolAliasMap> RuntimeAliases) {
300
301 auto &ES = ObjLinkingLayer.getExecutionSession();
302
303 // If the target is not supported then bail out immediately.
304 if (!supportedTarget(ES.getTargetTriple()))
305 return make_error<StringError>("Unsupported MachOPlatform triple: " +
306 ES.getTargetTriple().str(),
308
309 // Create default aliases if the caller didn't supply any.
310 if (!RuntimeAliases)
311 RuntimeAliases = standardPlatformAliases(ES);
312
313 // Define the aliases.
314 if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
315 return std::move(Err);
316
317 {
318 // Add JIT dispatch reexports from bootstrap JITDylib.
319 MangleAndInterner Mangle(ES);
320 if (auto Err = PlatformJD.define(reexports(
321 ES.getBootstrapJITDylib(),
322 {{ES.intern("___orc_rt_jit_dispatch"),
323 {Mangle(rt::DispatchName),
324 JITSymbolFlags::Exported | JITSymbolFlags::Callable}},
325 {ES.intern("___orc_rt_jit_dispatch_ctx"),
326 {Mangle(rt::DispatchCtxName), JITSymbolFlags::Exported}}})))
327 return Err;
328 }
329
330 // Create the instance.
331 Error Err = Error::success();
332 auto P = std::unique_ptr<MachOPlatform>(
333 new MachOPlatform(ObjLinkingLayer, PlatformJD, std::move(OrcRuntime),
334 std::move(BuildHeaderOpts), std::move(PlatformJDOpts),
335 std::move(BuildMachOHeaderMU), Err));
336 if (Err)
337 return std::move(Err);
338 return std::move(P);
339}
340
342 ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
343 const char *OrcRuntimePath, HeaderOptionsBuilder BuildHeaderOpts,
344 HeaderOptions PlatformJDOpts, MachOHeaderMUBuilder BuildMachOHeaderMU,
345 std::optional<SymbolAliasMap> RuntimeAliases) {
346
347 // Create a generator for the ORC runtime archive.
348 auto OrcRuntimeArchiveGenerator =
349 StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer, OrcRuntimePath);
350 if (!OrcRuntimeArchiveGenerator)
351 return OrcRuntimeArchiveGenerator.takeError();
352
353 return Create(ObjLinkingLayer, PlatformJD,
354 std::move(*OrcRuntimeArchiveGenerator),
355 std::move(BuildHeaderOpts), std::move(PlatformJDOpts),
356 std::move(BuildMachOHeaderMU), std::move(RuntimeAliases));
357}
358
360 return setupJITDylib(JD, BuildHeaderOpts(JD));
361}
362
364 if (auto Err = JD.define(BuildMachOHeaderMU(*this, std::move(Opts))))
365 return Err;
366
367 return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError();
368}
369
371 std::lock_guard<std::mutex> Lock(PlatformMutex);
372 auto I = JITDylibToHeaderAddr.find(&JD);
373 if (I != JITDylibToHeaderAddr.end()) {
374 assert(HeaderAddrToJITDylib.count(I->second) &&
375 "HeaderAddrToJITDylib missing entry");
376 HeaderAddrToJITDylib.erase(I->second);
377 JITDylibToHeaderAddr.erase(I);
378 }
379 JITDylibToPThreadKey.erase(&JD);
380 return Error::success();
381}
382
384 const MaterializationUnit &MU) {
385 auto &JD = RT.getJITDylib();
386 const auto &InitSym = MU.getInitializerSymbol();
387 if (!InitSym)
388 return Error::success();
389
390 RegisteredInitSymbols[&JD].add(InitSym,
392 LLVM_DEBUG({
393 dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU "
394 << MU.getName() << "\n";
395 });
396 return Error::success();
397}
398
402
404 ArrayRef<std::pair<const char *, const char *>> AL) {
405 for (auto &KV : AL) {
406 auto AliasName = ES.intern(KV.first);
407 assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
408 Aliases[std::move(AliasName)] = {ES.intern(KV.second),
410 }
411}
412
420
423 static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
424 {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}};
425
426 return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
427}
428
431 static const std::pair<const char *, const char *>
432 StandardRuntimeUtilityAliases[] = {
433 {"___orc_rt_run_program", "___orc_rt_macho_run_program"},
434 {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"},
435 {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"},
436 {"___orc_rt_jit_dlupdate", "___orc_rt_macho_jit_dlupdate"},
437 {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"},
438 {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"},
439 {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};
440
442 StandardRuntimeUtilityAliases);
443}
444
447 static const std::pair<const char *, const char *>
448 StandardLazyCompilationAliases[] = {
449 {"__orc_rt_reenter", "__orc_rt_sysv_reenter"}};
450
452 StandardLazyCompilationAliases);
453}
454
458
459bool MachOPlatform::supportedTarget(const Triple &TT) {
460 switch (TT.getArch()) {
461 case Triple::aarch64:
462 case Triple::x86_64:
463 return true;
464 default:
465 return false;
466 }
467}
468
469jitlink::Edge::Kind MachOPlatform::getPointerEdgeKind(jitlink::LinkGraph &G) {
470 switch (G.getTargetTriple().getArch()) {
471 case Triple::aarch64:
473 case Triple::x86_64:
475 default:
476 llvm_unreachable("Unsupported architecture");
477 }
478}
479
481MachOPlatform::flagsForSymbol(jitlink::Symbol &Sym) {
485
486 if (Sym.isCallable())
488
489 return Flags;
490}
491
492MachOPlatform::MachOPlatform(
493 ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD,
494 std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
495 HeaderOptionsBuilder BuildHeaderOpts, HeaderOptions PlatformJDOpts,
496 MachOHeaderMUBuilder BuildMachOHeaderMU, Error &Err)
497 : ES(ObjLinkingLayer.getExecutionSession()), PlatformJD(PlatformJD),
498 ObjLinkingLayer(ObjLinkingLayer),
499 BuildHeaderOpts(std::move(BuildHeaderOpts)),
500 BuildMachOHeaderMU(std::move(BuildMachOHeaderMU)) {
501 ErrorAsOutParameter _(Err);
502 ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this));
503 PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
504
505 {
506 // Check for force-eh-frame
507 std::optional<bool> ForceEHFrames;
508 if ((Err = ES.getBootstrapMapValue<bool, bool>("darwin-use-ehframes-only",
509 ForceEHFrames)))
510 return;
511 this->ForceEHFrames = ForceEHFrames.value_or(false);
512 }
513
514 BootstrapInfo BI;
515 Bootstrap = &BI;
516
517 // Bootstrap process -- here be phase-ordering dragons.
518 //
519 // The MachOPlatform class uses allocation actions to register metadata
520 // sections with the ORC runtime, however the runtime contains metadata
521 // registration functions that have their own metadata that they need to
522 // register (e.g. the frame-info registration functions have frame-info).
523 // We can't use an ordinary lookup to find these registration functions
524 // because their address is needed during the link of the containing graph
525 // itself (to build the allocation actions that will call the registration
526 // functions). Further complicating the situation (a) the graph containing
527 // the registration functions is allowed to depend on other graphs (e.g. the
528 // graph containing the ORC runtime RTTI support) so we need to handle an
529 // unknown set of dependencies during bootstrap, and (b) these graphs may
530 // be linked concurrently if the user has installed a concurrent dispatcher.
531 //
532 // We satisfy these constraints by implementing a bootstrap phase during which
533 // allocation actions generated by MachOPlatform are appended to a list of
534 // deferred allocation actions, rather than to the graphs themselves. At the
535 // end of the bootstrap process the deferred actions are attached to a final
536 // "complete-bootstrap" graph that causes them to be run.
537 //
538 // The bootstrap steps are as follows:
539 //
540 // 1. Request the graph containing the mach header. This graph is guaranteed
541 // not to have any metadata so the fact that the registration functions
542 // are not available yet is not a problem.
543 //
544 // 2. Look up the registration functions and discard the results. This will
545 // trigger linking of the graph containing these functions, and
546 // consequently any graphs that it depends on. We do not use the lookup
547 // result to find the addresses of the functions requested (as described
548 // above the lookup will return too late for that), instead we capture the
549 // addresses in a post-allocation pass injected by the platform runtime
550 // during bootstrap only.
551 //
552 // 3. During bootstrap the MachOPlatformPlugin keeps a count of the number of
553 // graphs being linked (potentially concurrently), and we block until all
554 // of these graphs have completed linking. This is to avoid a race on the
555 // deferred-actions vector: the lookup for the runtime registration
556 // functions may return while some functions (those that are being
557 // incidentally linked in, but aren't reachable via the runtime functions)
558 // are still being linked, and we need to capture any allocation actions
559 // for this incidental code before we proceed.
560 //
561 // 4. Once all active links are complete we transfer the deferred actions to
562 // a newly added CompleteBootstrap graph and then request a symbol from
563 // the CompleteBootstrap graph to trigger materialization. This will cause
564 // all deferred actions to be run, and once this lookup returns we can
565 // proceed.
566 //
567 // 5. Finally, we associate runtime support methods in MachOPlatform with
568 // the corresponding jit-dispatch tag variables in the ORC runtime to make
569 // the support methods callable. The bootstrap is now complete.
570
571 // Step (1) Add header materialization unit and request.
572 if ((Err = PlatformJD.define(
573 this->BuildMachOHeaderMU(*this, std::move(PlatformJDOpts)))))
574 return;
575 if ((Err = ES.lookup(&PlatformJD, MachOHeaderStartSymbol).takeError()))
576 return;
577
578 // Step (2) Request runtime registration functions to trigger
579 // materialization..
580 if ((Err = ES.lookup(makeJITDylibSearchOrder(&PlatformJD),
581 SymbolLookupSet(
582 {PlatformBootstrap.Name, PlatformShutdown.Name,
583 RegisterJITDylib.Name, DeregisterJITDylib.Name,
584 RegisterObjectSymbolTable.Name,
585 DeregisterObjectSymbolTable.Name,
586 RegisterObjectPlatformSections.Name,
587 DeregisterObjectPlatformSections.Name,
588 CreatePThreadKey.Name}))
589 .takeError()))
590 return;
591
592 // Step (3) Wait for any incidental linker work to complete.
593 {
594 std::unique_lock<std::mutex> Lock(PlatformMutex);
595 BI.CV.wait(Lock, [&]() { return BI.ActiveGraphs == 0; });
596 Bootstrap = nullptr;
597 }
598
599 // Step (4) Add complete-bootstrap materialization unit and request.
600 auto BootstrapCompleteSymbol = ES.intern("__orc_rt_macho_complete_bootstrap");
601 if ((Err = PlatformJD.define(
602 std::make_unique<MachOPlatformCompleteBootstrapMaterializationUnit>(
603 *this, PlatformJD.getName(), BootstrapCompleteSymbol,
604 std::move(BI.SymTab), std::move(BI.DeferredAAs),
605 BI.MachOHeaderAddr, PlatformBootstrap.Addr,
606 PlatformShutdown.Addr, RegisterJITDylib.Addr,
607 DeregisterJITDylib.Addr, RegisterObjectSymbolTable.Addr,
608 DeregisterObjectSymbolTable.Addr))))
609 return;
610 if ((Err = ES.lookup(makeJITDylibSearchOrder(
612 std::move(BootstrapCompleteSymbol))
613 .takeError()))
614 return;
615
616 // (5) Associate runtime support functions.
617 // TODO: Consider moving this above (4) to make runtime support functions
618 // available to the bootstrap completion graph. We'd just need to be
619 // sure that the runtime support functions are fully usable before any
620 // bootstrap completion actions use them (e.g. the ORC runtime
621 // macho_platform object would have to have been created and
622 // initialized).
623 if ((Err = associateRuntimeSupportFunctions()))
624 return;
625}
626
627Error MachOPlatform::associateRuntimeSupportFunctions() {
628 using PushInitializersSPSSig =
629 SPSExpected<SPSMachOJITDylibDepInfoMap>(SPSExecutorAddr);
630 using PushSymbolsSPSSig =
631 SPSError(SPSExecutorAddr, SPSSequence<SPSTuple<SPSString, bool>>);
632
633 return ES.registerCallControllerHandlers(
634 PlatformJD,
636 SymbolNameSpec::c("__orc_rt_macho_push_initializers_tag"), this,
637 &MachOPlatform::rt_pushInitializers),
639 SymbolNameSpec::c("__orc_rt_macho_push_symbols_tag"), this,
640 &MachOPlatform::rt_pushSymbols));
641}
642
643void MachOPlatform::pushInitializersLoop(
644 PushInitializersSendResultFn SendResult, JITDylibSP JD) {
645 DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
646 DenseMap<JITDylib *, SmallVector<JITDylib *>> JDDepMap;
647 SmallVector<JITDylib *, 16> Worklist({JD.get()});
648
649 ES.runSessionLocked([&]() {
650 while (!Worklist.empty()) {
651 // FIXME: Check for defunct dylibs.
652
653 auto DepJD = Worklist.back();
654 Worklist.pop_back();
655
656 // If we've already visited this JITDylib on this iteration then continue.
657 auto [It, Inserted] = JDDepMap.try_emplace(DepJD);
658 if (!Inserted)
659 continue;
660
661 // Add dep info.
662 auto &DM = It->second;
663 DepJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
664 for (auto &KV : O) {
665 if (KV.first == DepJD)
666 continue;
667 DM.push_back(KV.first);
668 Worklist.push_back(KV.first);
669 }
670 });
671
672 // Add any registered init symbols.
673 auto RISItr = RegisteredInitSymbols.find(DepJD);
674 if (RISItr != RegisteredInitSymbols.end()) {
675 NewInitSymbols[DepJD] = std::move(RISItr->second);
676 RegisteredInitSymbols.erase(RISItr);
677 }
678 }
679 });
680
681 // If there are no further init symbols to look up then send the link order
682 // (as a list of header addresses) to the caller.
683 if (NewInitSymbols.empty()) {
684
685 // To make the list intelligible to the runtime we need to convert all
686 // JITDylib pointers to their header addresses. Only include JITDylibs
687 // that appear in the JITDylibToHeaderAddr map (i.e. those that have been
688 // through setupJITDylib) -- bare JITDylibs aren't managed by the platform.
689 DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
690 HeaderAddrs.reserve(JDDepMap.size());
691 {
692 std::lock_guard<std::mutex> Lock(PlatformMutex);
693 for (auto &KV : JDDepMap) {
694 auto I = JITDylibToHeaderAddr.find(KV.first);
695 if (I != JITDylibToHeaderAddr.end())
696 HeaderAddrs[KV.first] = I->second;
697 }
698 }
699
700 // Build the dep info map to return.
702 DIM.reserve(JDDepMap.size());
703 for (auto &KV : JDDepMap) {
704 auto HI = HeaderAddrs.find(KV.first);
705 // Skip unmanaged JITDylibs.
706 if (HI == HeaderAddrs.end())
707 continue;
708 auto H = HI->second;
709 MachOJITDylibDepInfo DepInfo;
710 for (auto &Dep : KV.second) {
711 auto HJ = HeaderAddrs.find(Dep);
712 if (HJ != HeaderAddrs.end())
713 DepInfo.DepHeaders.push_back(HJ->second);
714 }
715 DIM.push_back(std::make_pair(H, std::move(DepInfo)));
716 }
717 SendResult(DIM);
718 return;
719 }
720
721 // Otherwise issue a lookup and re-run this phase when it completes.
723 [this, SendResult = std::move(SendResult), JD](Error Err) mutable {
724 if (Err)
725 SendResult(std::move(Err));
726 else
727 pushInitializersLoop(std::move(SendResult), JD);
728 },
729 ES, std::move(NewInitSymbols));
730}
731
732void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
733 ExecutorAddr JDHeaderAddr) {
734 JITDylibSP JD;
735 {
736 std::lock_guard<std::mutex> Lock(PlatformMutex);
737 auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
738 if (I != HeaderAddrToJITDylib.end())
739 JD = I->second;
740 }
741
742 LLVM_DEBUG({
743 dbgs() << "MachOPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
744 if (JD)
745 dbgs() << "pushing initializers for " << JD->getName() << "\n";
746 else
747 dbgs() << "No JITDylib for header address.\n";
748 });
749
750 if (!JD) {
751 SendResult(make_error<StringError>("No JITDylib with header addr " +
752 formatv("{0:x}", JDHeaderAddr),
754 return;
755 }
756
757 pushInitializersLoop(std::move(SendResult), JD);
758}
759
760void MachOPlatform::rt_pushSymbols(
761 PushSymbolsInSendResultFn SendResult, ExecutorAddr Handle,
762 const std::vector<std::pair<StringRef, bool>> &SymbolNames) {
763
764 JITDylib *JD = nullptr;
765
766 {
767 std::lock_guard<std::mutex> Lock(PlatformMutex);
768 auto I = HeaderAddrToJITDylib.find(Handle);
769 if (I != HeaderAddrToJITDylib.end())
770 JD = I->second;
771 }
772 LLVM_DEBUG({
773 dbgs() << "MachOPlatform::rt_pushSymbols(";
774 if (JD)
775 dbgs() << "\"" << JD->getName() << "\", [ ";
776 else
777 dbgs() << "<invalid handle " << Handle << ">, [ ";
778 for (auto &Name : SymbolNames)
779 dbgs() << "\"" << Name.first << "\" ";
780 dbgs() << "])\n";
781 });
782
783 if (!JD) {
784 SendResult(make_error<StringError>("No JITDylib associated with handle " +
785 formatv("{0:x}", Handle),
787 return;
788 }
789
790 SymbolLookupSet LS;
791 for (auto &[Name, Required] : SymbolNames)
792 LS.add(ES.intern(Name), Required
795
796 ES.lookup(
798 std::move(LS), SymbolState::Ready,
799 [SendResult = std::move(SendResult)](Expected<SymbolMap> Result) mutable {
800 SendResult(Result.takeError());
801 },
803}
804
805Expected<uint64_t> MachOPlatform::createPThreadKey() {
806 if (!CreatePThreadKey.Addr)
808 "Attempting to create pthread key in target, but runtime support has "
809 "not been loaded yet",
811
812 using CreatePThreadKeyProxy = Proxy<Expected<uint64_t>()>;
813 CreatePThreadKeyProxy CreateKey(
814 sps::ProxySpec<CreatePThreadKeyProxy,
815 macho_sps_ci::CreatePThreadKey>::dispatch,
816 CreatePThreadKey.Addr);
817 return CreateKey(ES);
818}
819
820void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
821 MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
822 jitlink::PassConfiguration &Config) {
823
824 using namespace jitlink;
825
826 bool InBootstrapPhase = false;
827
828 ExecutorAddr HeaderAddr;
829 {
830 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
831 if (LLVM_UNLIKELY(&MR.getTargetJITDylib() == &MP.PlatformJD)) {
832 if (MP.Bootstrap) {
833 InBootstrapPhase = true;
834 ++MP.Bootstrap->ActiveGraphs;
835 }
836 }
837
838 // Get the dso-base address if available.
839 auto I = MP.JITDylibToHeaderAddr.find(&MR.getTargetJITDylib());
840 if (I != MP.JITDylibToHeaderAddr.end())
841 HeaderAddr = I->second;
842 }
843
844 // If we're forcing eh-frame use then discard the compact-unwind section
845 // immediately to prevent FDEs from being stripped.
846 if (MP.ForceEHFrames)
848 LG.removeSection(*CUSec);
849
850 // Point the libunwind dso-base absolute symbol at the header for the
851 // JITDylib. This will prevent us from synthesizing a new header for
852 // every object.
853 if (HeaderAddr)
854 LG.addAbsoluteSymbol("__jitlink$libunwind_dso_base", HeaderAddr, 0,
855 Linkage::Strong, Scope::Local, true);
856
857 // If we're in the bootstrap phase then increment the active graphs.
858 if (LLVM_UNLIKELY(InBootstrapPhase))
859 Config.PostAllocationPasses.push_back([this](LinkGraph &G) {
860 return bootstrapPipelineRecordRuntimeFunctions(G);
861 });
862
863 // --- Handle Initializers ---
864 if (auto InitSymbol = MR.getInitializerSymbol()) {
865
866 // If the initializer symbol is the MachOHeader start symbol then just
867 // register it and then bail out -- the header materialization unit
868 // definitely doesn't need any other passes.
869 if (InitSymbol == MP.MachOHeaderStartSymbol && !InBootstrapPhase) {
870 Config.PostAllocationPasses.push_back([this, &MR](LinkGraph &G) {
871 return associateJITDylibHeaderSymbol(G, MR);
872 });
873 return;
874 }
875
876 // If the object contains an init symbol other than the header start symbol
877 // then add passes to preserve, process and register the init
878 // sections/symbols.
879 Config.PrePrunePasses.push_back([this, &MR](LinkGraph &G) {
880 if (auto Err = preserveImportantSections(G, MR))
881 return Err;
882 return processObjCImageInfo(G, MR);
883 });
884 Config.PostPrunePasses.push_back(
885 [this](LinkGraph &G) { return createObjCRuntimeObject(G); });
886 Config.PostAllocationPasses.push_back(
887 [this, &MR](LinkGraph &G) { return populateObjCRuntimeObject(G, MR); });
888 }
889
890 // Insert TLV lowering at the start of the PostPrunePasses, since we want
891 // it to run before GOT/PLT lowering.
892 Config.PostPrunePasses.insert(
893 Config.PostPrunePasses.begin(),
894 [this, &JD = MR.getTargetJITDylib()](LinkGraph &G) {
895 return fixTLVSectionsAndEdges(G, JD);
896 });
897
898 // Add symbol table prepare and register passes: These will add strings for
899 // all symbols to the c-strings section, and build a symbol table registration
900 // call.
901 auto JITSymTabInfo = std::make_shared<JITSymTabVector>();
902 Config.PostPrunePasses.push_back([this, JITSymTabInfo](LinkGraph &G) {
903 return prepareSymbolTableRegistration(G, *JITSymTabInfo);
904 });
905 Config.PostFixupPasses.push_back([this, &MR, JITSymTabInfo,
906 InBootstrapPhase](LinkGraph &G) {
907 return addSymbolTableRegistration(G, MR, *JITSymTabInfo, InBootstrapPhase);
908 });
909
910 // Add a pass to register the final addresses of any special sections in the
911 // object with the runtime.
912 Config.PostAllocationPasses.push_back([this, &JD = MR.getTargetJITDylib(),
913 HeaderAddr,
914 InBootstrapPhase](LinkGraph &G) {
915 return registerObjectPlatformSections(G, JD, HeaderAddr, InBootstrapPhase);
916 });
917
918 // If we're in the bootstrap phase then steal allocation actions and then
919 // decrement the active graphs.
920 if (InBootstrapPhase)
921 Config.PostFixupPasses.push_back(
922 [this](LinkGraph &G) { return bootstrapPipelineEnd(G); });
923}
924
925Error MachOPlatform::MachOPlatformPlugin::
926 bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) {
927 // Record bootstrap function names.
928 std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = {
929 {*MP.MachOHeaderStartSymbol, &MP.Bootstrap->MachOHeaderAddr},
930 {*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr},
931 {*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr},
932 {*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr},
933 {*MP.DeregisterJITDylib.Name, &MP.DeregisterJITDylib.Addr},
934 {*MP.RegisterObjectSymbolTable.Name, &MP.RegisterObjectSymbolTable.Addr},
935 {*MP.DeregisterObjectSymbolTable.Name,
936 &MP.DeregisterObjectSymbolTable.Addr},
937 {*MP.RegisterObjectPlatformSections.Name,
938 &MP.RegisterObjectPlatformSections.Addr},
939 {*MP.DeregisterObjectPlatformSections.Name,
940 &MP.DeregisterObjectPlatformSections.Addr},
941 {*MP.CreatePThreadKey.Name, &MP.CreatePThreadKey.Addr},
942 {*MP.RegisterObjCRuntimeObject.Name, &MP.RegisterObjCRuntimeObject.Addr},
943 {*MP.DeregisterObjCRuntimeObject.Name,
944 &MP.DeregisterObjCRuntimeObject.Addr}};
945
946 bool RegisterMachOHeader = false;
947
948 for (auto *Sym : G.defined_symbols()) {
949 for (auto &RTSym : RuntimeSymbols) {
950 if (Sym->hasName() && *Sym->getName() == RTSym.first) {
951 if (*RTSym.second)
953 "Duplicate " + RTSym.first +
954 " detected during MachOPlatform bootstrap",
956
957 if (Sym->getName() == MP.MachOHeaderStartSymbol)
958 RegisterMachOHeader = true;
959
960 *RTSym.second = Sym->getAddress();
961 }
962 }
963 }
964
965 if (RegisterMachOHeader) {
966 // If this graph defines the macho header symbol then create the internal
967 // mapping between it and PlatformJD.
968 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
969 MP.JITDylibToHeaderAddr[&MP.PlatformJD] = MP.Bootstrap->MachOHeaderAddr;
970 MP.HeaderAddrToJITDylib[MP.Bootstrap->MachOHeaderAddr] = &MP.PlatformJD;
971 }
972
973 return Error::success();
974}
975
976Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd(
977 jitlink::LinkGraph &G) {
978 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
979
980 --MP.Bootstrap->ActiveGraphs;
981 // Notify Bootstrap->CV while holding the mutex because the mutex is
982 // also keeping Bootstrap->CV alive.
983 if (MP.Bootstrap->ActiveGraphs == 0)
984 MP.Bootstrap->CV.notify_all();
985 return Error::success();
986}
987
988Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
989 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
990 auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
991 return Sym->getName() == MP.MachOHeaderStartSymbol;
992 });
993 assert(I != G.defined_symbols().end() && "Missing MachO header start symbol");
994
995 auto &JD = MR.getTargetJITDylib();
996 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
997 auto HeaderAddr = (*I)->getAddress();
998 MP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
999 MP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
1000 // We can unconditionally add these actions to the Graph because this pass
1001 // isn't used during bootstrap.
1002 G.allocActions().push_back(
1003 {cantFail(
1004 WrapperFunctionCall::Create<SPSArgList<SPSString, SPSExecutorAddr>>(
1005 MP.RegisterJITDylib.Addr, JD.getName(), HeaderAddr)),
1006 cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
1007 MP.DeregisterJITDylib.Addr, HeaderAddr))});
1008 return Error::success();
1009}
1010
1011Error MachOPlatform::MachOPlatformPlugin::preserveImportantSections(
1012 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
1013 // __objc_imageinfo is "important": we want to preserve it and record its
1014 // address in the first graph that it appears in, then verify and discard it
1015 // in all subsequent graphs. In this pass we preserve unconditionally -- we'll
1016 // manually throw it away in the processObjCImageInfo pass.
1017 if (auto *ObjCImageInfoSec =
1018 G.findSectionByName(MachOObjCImageInfoSectionName)) {
1019 if (ObjCImageInfoSec->blocks_size() != 1)
1021 "In " + G.getName() +
1022 "__DATA,__objc_imageinfo contains multiple blocks",
1024 G.addAnonymousSymbol(**ObjCImageInfoSec->blocks().begin(), 0, 0, false,
1025 true);
1026
1027 for (auto *B : ObjCImageInfoSec->blocks())
1028 if (!B->edges_empty())
1029 return make_error<StringError>("In " + G.getName() + ", " +
1031 " contains references to symbols",
1033 }
1034
1035 // Init sections are important: We need to preserve them and so that their
1036 // addresses can be captured and reported to the ORC runtime in
1037 // registerObjectPlatformSections.
1038 if (const auto &InitSymName = MR.getInitializerSymbol()) {
1039
1040 jitlink::Symbol *InitSym = nullptr;
1041 for (auto &InitSectionName : MachOInitSectionNames) {
1042 // Skip ObjCImageInfo -- this shouldn't have any dependencies, and we may
1043 // remove it later.
1044 if (InitSectionName == MachOObjCImageInfoSectionName)
1045 continue;
1046
1047 // Skip non-init sections.
1048 auto *InitSection = G.findSectionByName(InitSectionName);
1049 if (!InitSection || InitSection->empty())
1050 continue;
1051
1052 // Create the init symbol if it has not been created already and attach it
1053 // to the first block.
1054 if (!InitSym) {
1055 auto &B = **InitSection->blocks().begin();
1056 InitSym = &G.addDefinedSymbol(
1057 B, 0, *InitSymName, B.getSize(), jitlink::Linkage::Strong,
1058 jitlink::Scope::SideEffectsOnly, false, true);
1059 }
1060
1061 // Add keep-alive edges to anonymous symbols in all other init blocks.
1062 for (auto *B : InitSection->blocks()) {
1063 if (B == &InitSym->getBlock())
1064 continue;
1065
1066 auto &S = G.addAnonymousSymbol(*B, 0, B->getSize(), false, true);
1067 InitSym->getBlock().addEdge(jitlink::Edge::KeepAlive, 0, S, 0);
1068 }
1069 }
1070 }
1071
1072 return Error::success();
1073}
1074
1075Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
1076 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
1077
1078 // If there's an ObjC imagine info then either
1079 // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In
1080 // this case we name and record it.
1081 // OR
1082 // (2) We already have a recorded __objc_imageinfo for this JITDylib,
1083 // in which case we just verify it.
1084 auto *ObjCImageInfo = G.findSectionByName(MachOObjCImageInfoSectionName);
1085 if (!ObjCImageInfo)
1086 return Error::success();
1087
1088 auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();
1089
1090 // Check that the section is not empty if present.
1091 if (ObjCImageInfoBlocks.empty())
1093 " section in " + G.getName(),
1095
1096 // Check that there's only one block in the section.
1097 if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
1098 return make_error<StringError>("Multiple blocks in " +
1100 " section in " + G.getName(),
1102
1103 // Check that the __objc_imageinfo section is unreferenced.
1104 // FIXME: We could optimize this check if Symbols had a ref-count.
1105 for (auto &Sec : G.sections()) {
1106 if (&Sec != ObjCImageInfo)
1107 for (auto *B : Sec.blocks())
1108 for (auto &E : B->edges())
1109 if (E.getTarget().isDefined() &&
1110 &E.getTarget().getSection() == ObjCImageInfo)
1112 " is referenced within file " +
1113 G.getName(),
1115 }
1116
1117 auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();
1118 auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();
1119 auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness());
1120 auto Flags =
1121 support::endian::read32(ObjCImageInfoData + 4, G.getEndianness());
1122
1123 // Lock the mutex while we verify / update the ObjCImageInfos map.
1124 std::lock_guard<std::mutex> Lock(PluginMutex);
1125
1126 auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib());
1127 if (ObjCImageInfoItr != ObjCImageInfos.end()) {
1128 // We've already registered an __objc_imageinfo section. Verify the
1129 // content of this new section matches, then delete it.
1130 if (ObjCImageInfoItr->second.Version != Version)
1132 "ObjC version in " + G.getName() +
1133 " does not match first registered version",
1135 if (ObjCImageInfoItr->second.Flags != Flags)
1136 if (Error E = mergeImageInfoFlags(G, MR, ObjCImageInfoItr->second, Flags))
1137 return E;
1138
1139 // __objc_imageinfo is valid. Delete the block.
1140 while (ObjCImageInfo->symbols_size() != 0)
1141 G.removeDefinedSymbol(**ObjCImageInfo->symbols().begin());
1142 G.removeBlock(ObjCImageInfoBlock);
1143 } else {
1144 LLVM_DEBUG({
1145 dbgs() << "MachOPlatform: Registered __objc_imageinfo for "
1146 << MR.getTargetJITDylib().getName() << " in " << G.getName()
1147 << "; flags = " << formatv("{0:x4}", Flags) << "\n";
1148 });
1149 // We haven't registered an __objc_imageinfo section yet. Register and
1150 // move on. The section should already be marked no-dead-strip.
1151 G.addDefinedSymbol(ObjCImageInfoBlock, 0, ObjCImageInfoSymbolName,
1152 ObjCImageInfoBlock.getSize(), jitlink::Linkage::Strong,
1153 jitlink::Scope::Hidden, false, true);
1154 if (auto Err = MR.defineMaterializing(
1155 {{MR.getExecutionSession().intern(ObjCImageInfoSymbolName),
1156 JITSymbolFlags()}}))
1157 return Err;
1158 ObjCImageInfos[&MR.getTargetJITDylib()] = {Version, Flags, false};
1159 }
1160
1161 return Error::success();
1162}
1163
1164Error MachOPlatform::MachOPlatformPlugin::mergeImageInfoFlags(
1165 jitlink::LinkGraph &G, MaterializationResponsibility &MR,
1166 ObjCImageInfo &Info, uint32_t NewFlags) {
1167 if (Info.Flags == NewFlags)
1168 return Error::success();
1169
1170 ObjCImageInfoFlags Old(Info.Flags);
1171 ObjCImageInfoFlags New(NewFlags);
1172
1173 // Check for incompatible flags.
1174 if (Old.SwiftABIVersion && New.SwiftABIVersion &&
1175 Old.SwiftABIVersion != New.SwiftABIVersion)
1176 return make_error<StringError>("Swift ABI version in " + G.getName() +
1177 " does not match first registered flags",
1179
1180 // HasCategoryClassProperties and HasSignedObjCClassROs can be disabled before
1181 // they are registered, if necessary, but once they are in use must be
1182 // supported by subsequent objects.
1183 if (Info.Finalized && Old.HasCategoryClassProperties &&
1184 !New.HasCategoryClassProperties)
1185 return make_error<StringError>("ObjC category class property support in " +
1186 G.getName() +
1187 " does not match first registered flags",
1189 if (Info.Finalized && Old.HasSignedObjCClassROs && !New.HasSignedObjCClassROs)
1190 return make_error<StringError>("ObjC class_ro_t pointer signing in " +
1191 G.getName() +
1192 " does not match first registered flags",
1194
1195 // If we cannot change the flags, ignore any remaining differences. Adding
1196 // Swift or changing its version are unlikely to cause problems in practice.
1197 if (Info.Finalized)
1198 return Error::success();
1199
1200 // Use the minimum Swift version.
1201 if (Old.SwiftVersion && New.SwiftVersion)
1202 New.SwiftVersion = std::min(Old.SwiftVersion, New.SwiftVersion);
1203 else if (Old.SwiftVersion)
1204 New.SwiftVersion = Old.SwiftVersion;
1205 // Add a Swift ABI version if it was pure objc before.
1206 if (!New.SwiftABIVersion)
1207 New.SwiftABIVersion = Old.SwiftABIVersion;
1208 // Disable class properties if any object does not support it.
1209 if (Old.HasCategoryClassProperties != New.HasCategoryClassProperties)
1210 New.HasCategoryClassProperties = false;
1211 // Disable signed class ro data if any object does not support it.
1212 if (Old.HasSignedObjCClassROs != New.HasSignedObjCClassROs)
1213 New.HasSignedObjCClassROs = false;
1214
1215 LLVM_DEBUG({
1216 dbgs() << "MachOPlatform: Merging __objc_imageinfo flags for "
1217 << MR.getTargetJITDylib().getName() << " (was "
1218 << formatv("{0:x4}", Old.rawFlags()) << ")"
1219 << " with " << G.getName() << " (" << formatv("{0:x4}", NewFlags)
1220 << ")"
1221 << " -> " << formatv("{0:x4}", New.rawFlags()) << "\n";
1222 });
1223
1224 Info.Flags = New.rawFlags();
1225 return Error::success();
1226}
1227
1228Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
1229 jitlink::LinkGraph &G, JITDylib &JD) {
1230 auto TLVBootStrapSymbolName = G.intern("__tlv_bootstrap");
1231 // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr.
1232 for (auto *Sym : G.external_symbols())
1233 if (Sym->getName() == TLVBootStrapSymbolName) {
1234 auto TLSGetADDR =
1235 MP.getExecutionSession().intern("___orc_rt_macho_tlv_get_addr");
1236 Sym->setName(std::move(TLSGetADDR));
1237 break;
1238 }
1239
1240 // Store key in __thread_vars struct fields.
1241 if (auto *ThreadDataSec = G.findSectionByName(MachOThreadVarsSectionName)) {
1242 std::optional<uint64_t> Key;
1243 {
1244 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
1245 auto I = MP.JITDylibToPThreadKey.find(&JD);
1246 if (I != MP.JITDylibToPThreadKey.end())
1247 Key = I->second;
1248 }
1249
1250 if (!Key) {
1251 if (auto KeyOrErr = MP.createPThreadKey())
1252 Key = *KeyOrErr;
1253 else
1254 return KeyOrErr.takeError();
1255 }
1256
1257 uint64_t PlatformKeyBits =
1258 support::endian::byte_swap(*Key, G.getEndianness());
1259
1260 for (auto *B : ThreadDataSec->blocks()) {
1261 if (B->getSize() != 3 * G.getPointerSize())
1262 return make_error<StringError>("__thread_vars block at " +
1263 formatv("{0:x}", B->getAddress()) +
1264 " has unexpected size",
1266
1267 auto NewBlockContent = G.allocateBuffer(B->getSize());
1268 llvm::copy(B->getContent(), NewBlockContent.data());
1269 memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits,
1270 G.getPointerSize());
1271 B->setContent(NewBlockContent);
1272 }
1273 }
1274
1275 // Transform any TLV edges into GOT edges.
1276 for (auto *B : G.blocks())
1277 for (auto &E : B->edges())
1278 if (E.getKind() ==
1280 E.setKind(jitlink::x86_64::
1281 RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable);
1282
1283 return Error::success();
1284}
1285
1286std::optional<MachOPlatform::MachOPlatformPlugin::UnwindSections>
1287MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
1288 jitlink::LinkGraph &G) {
1289 using namespace jitlink;
1290
1291 UnwindSections US;
1292
1293 // ScanSection records a section range and adds any executable blocks that
1294 // that section points to to the CodeBlocks vector.
1295 SmallVector<Block *> CodeBlocks;
1296 auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange,
1297 auto AddCodeBlocks) {
1298 if (Sec.blocks().empty())
1299 return;
1300 SecRange = (*Sec.blocks().begin())->getRange();
1301 for (auto *B : Sec.blocks()) {
1302 auto R = B->getRange();
1303 SecRange.Start = std::min(SecRange.Start, R.Start);
1304 SecRange.End = std::max(SecRange.End, R.End);
1305 AddCodeBlocks(*B);
1306 }
1307 };
1308
1309 if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName)) {
1310 ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection, [&](Block &B) {
1311 if (auto *Fn = jitlink::EHFrameCFIBlockInspector::FromEdgeScan(B)
1312 .getPCBeginEdge())
1313 if (Fn->getTarget().isDefined())
1314 CodeBlocks.push_back(&Fn->getTarget().getBlock());
1315 });
1316 }
1317
1318 if (Section *CUInfoSec = G.findSectionByName(MachOUnwindInfoSectionName)) {
1319 ScanUnwindInfoSection(
1320 *CUInfoSec, US.CompactUnwindSection, [&](Block &B) {
1321 for (auto &E : B.edges()) {
1322 assert(E.getTarget().isDefined() &&
1323 "unwind-info record edge has external target");
1324 assert(E.getKind() == Edge::KeepAlive &&
1325 "unwind-info record has unexpected edge kind");
1326 CodeBlocks.push_back(&E.getTarget().getBlock());
1327 }
1328 });
1329 }
1330
1331 // If we didn't find any pointed-to code-blocks then there's no need to
1332 // register any info.
1333 if (CodeBlocks.empty())
1334 return std::nullopt;
1335
1336 // We have info to register. Sort the code blocks into address order and
1337 // build a list of contiguous address ranges covering them all.
1338 llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) {
1339 return LHS->getAddress() < RHS->getAddress();
1340 });
1341 for (auto *B : CodeBlocks) {
1342 if (US.CodeRanges.empty() || US.CodeRanges.back().End != B->getAddress())
1343 US.CodeRanges.push_back(B->getRange());
1344 else
1345 US.CodeRanges.back().End = B->getRange().End;
1346 }
1347
1348 LLVM_DEBUG({
1349 dbgs() << "MachOPlatform identified unwind info in " << G.getName() << ":\n"
1350 << " DWARF: ";
1351 if (US.DwarfSection.Start)
1352 dbgs() << US.DwarfSection << "\n";
1353 else
1354 dbgs() << "none\n";
1355 dbgs() << " Compact-unwind: ";
1356 if (US.CompactUnwindSection.Start)
1357 dbgs() << US.CompactUnwindSection << "\n";
1358 else
1359 dbgs() << "none\n"
1360 << "for code ranges:\n";
1361 for (auto &CR : US.CodeRanges)
1362 dbgs() << " " << CR << "\n";
1363 if (US.CodeRanges.size() >= G.sections_size())
1364 dbgs() << "WARNING: High number of discontiguous code ranges! "
1365 "Padding may be interfering with coalescing.\n";
1366 });
1367
1368 return US;
1369}
1370
1371Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
1372 jitlink::LinkGraph &G, JITDylib &JD, ExecutorAddr HeaderAddr,
1373 bool InBootstrapPhase) {
1374
1375 // Get a pointer to the thread data section if there is one. It will be used
1376 // below.
1377 jitlink::Section *ThreadDataSection =
1378 G.findSectionByName(MachOThreadDataSectionName);
1379
1380 // Handle thread BSS section if there is one.
1381 if (auto *ThreadBSSSection = G.findSectionByName(MachOThreadBSSSectionName)) {
1382 // If there's already a thread data section in this graph then merge the
1383 // thread BSS section content into it, otherwise just treat the thread
1384 // BSS section as the thread data section.
1385 if (ThreadDataSection)
1386 G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
1387 else
1388 ThreadDataSection = ThreadBSSSection;
1389 }
1390
1392
1393 // Collect data sections to register.
1394 StringRef DataSections[] = {MachODataDataSectionName,
1397 for (auto &SecName : DataSections) {
1398 if (auto *Sec = G.findSectionByName(SecName)) {
1399 jitlink::SectionRange R(*Sec);
1400 if (!R.empty())
1401 MachOPlatformSecs.push_back({SecName, R.getRange()});
1402 }
1403 }
1404
1405 // Having merged thread BSS (if present) and thread data (if present),
1406 // record the resulting section range.
1407 if (ThreadDataSection) {
1408 jitlink::SectionRange R(*ThreadDataSection);
1409 if (!R.empty())
1410 MachOPlatformSecs.push_back({MachOThreadDataSectionName, R.getRange()});
1411 }
1412
1413 // If any platform sections were found then add an allocation action to call
1414 // the registration function.
1415 StringRef PlatformSections[] = {MachOModInitFuncSectionName,
1416 ObjCRuntimeObjectSectionName};
1417
1418 for (auto &SecName : PlatformSections) {
1419 auto *Sec = G.findSectionByName(SecName);
1420 if (!Sec)
1421 continue;
1422 jitlink::SectionRange R(*Sec);
1423 if (R.empty())
1424 continue;
1425
1426 MachOPlatformSecs.push_back({SecName, R.getRange()});
1427 }
1428
1429 std::optional<std::tuple<SmallVector<ExecutorAddrRange>, ExecutorAddrRange,
1430 ExecutorAddrRange>>
1431 UnwindInfo;
1432 if (auto UI = findUnwindSectionInfo(G))
1433 UnwindInfo = std::make_tuple(std::move(UI->CodeRanges), UI->DwarfSection,
1434 UI->CompactUnwindSection);
1435
1436 if (!MachOPlatformSecs.empty() || UnwindInfo) {
1437 // Dump the scraped inits.
1438 LLVM_DEBUG({
1439 dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";
1440 for (auto &KV : MachOPlatformSecs)
1441 dbgs() << " " << KV.first << ": " << KV.second << "\n";
1442 });
1443
1444 assert(HeaderAddr && "Null header registered for JD");
1445 using SPSRegisterObjectPlatformSectionsArgs = SPSArgList<
1446 SPSExecutorAddr,
1447 SPSOptional<SPSTuple<SPSSequence<SPSExecutorAddrRange>,
1449 SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>;
1450
1451 AllocActionCallPair AllocActions = {
1452 cantFail(
1454 MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo,
1455 MachOPlatformSecs)),
1456 cantFail(
1458 MP.DeregisterObjectPlatformSections.Addr, HeaderAddr,
1459 UnwindInfo, MachOPlatformSecs))};
1460
1461 if (LLVM_LIKELY(!InBootstrapPhase))
1462 G.allocActions().push_back(std::move(AllocActions));
1463 else {
1464 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
1465 MP.Bootstrap->DeferredAAs.push_back(std::move(AllocActions));
1466 }
1467 }
1468
1469 return Error::success();
1470}
1471
1472Error MachOPlatform::MachOPlatformPlugin::createObjCRuntimeObject(
1473 jitlink::LinkGraph &G) {
1474
1475 bool NeedTextSegment = false;
1476 size_t NumRuntimeSections = 0;
1477
1478 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData)
1479 if (G.findSectionByName(ObjCRuntimeSectionName))
1480 ++NumRuntimeSections;
1481
1482 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) {
1483 if (G.findSectionByName(ObjCRuntimeSectionName)) {
1484 ++NumRuntimeSections;
1485 NeedTextSegment = true;
1486 }
1487 }
1488
1489 // Early out for no runtime sections.
1490 if (NumRuntimeSections == 0)
1491 return Error::success();
1492
1493 // If there were any runtime sections then we need to add an __objc_imageinfo
1494 // section.
1495 ++NumRuntimeSections;
1496
1497 size_t MachOSize = sizeof(MachO::mach_header_64) +
1498 (NeedTextSegment + 1) * sizeof(MachO::segment_command_64) +
1499 NumRuntimeSections * sizeof(MachO::section_64);
1500
1501 auto &Sec = G.createSection(ObjCRuntimeObjectSectionName,
1503 G.createMutableContentBlock(Sec, MachOSize, ExecutorAddr(), 16, 0, true);
1504
1505 return Error::success();
1506}
1507
1508Error MachOPlatform::MachOPlatformPlugin::populateObjCRuntimeObject(
1509 jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
1510
1511 auto *ObjCRuntimeObjectSec =
1512 G.findSectionByName(ObjCRuntimeObjectSectionName);
1513
1514 if (!ObjCRuntimeObjectSec)
1515 return Error::success();
1516
1517 switch (G.getTargetTriple().getArch()) {
1518 case Triple::aarch64:
1519 case Triple::x86_64:
1520 // Supported.
1521 break;
1522 default:
1523 return make_error<StringError>("Unrecognized MachO arch in triple " +
1524 G.getTargetTriple().str(),
1526 }
1527
1528 auto &SecBlock = **ObjCRuntimeObjectSec->blocks().begin();
1529
1530 struct SecDesc {
1531 MachO::section_64 Sec;
1532 unique_function<void(size_t RecordOffset)> AddFixups;
1533 };
1534
1535 std::vector<SecDesc> TextSections, DataSections;
1536 auto AddSection = [&](SecDesc &SD, jitlink::Section &GraphSec) {
1537 jitlink::SectionRange SR(GraphSec);
1538 StringRef FQName = GraphSec.getName();
1539 memset(&SD.Sec, 0, sizeof(MachO::section_64));
1540 memcpy(SD.Sec.sectname, FQName.drop_front(7).data(), FQName.size() - 7);
1541 memcpy(SD.Sec.segname, FQName.data(), 6);
1542 SD.Sec.addr = SR.getStart() - SecBlock.getAddress();
1543 SD.Sec.size = SR.getSize();
1544 SD.Sec.flags = MachO::S_REGULAR;
1545 };
1546
1547 // Add the __objc_imageinfo section.
1548 {
1549 DataSections.push_back({});
1550 auto &SD = DataSections.back();
1551 memset(&SD.Sec, 0, sizeof(SD.Sec));
1552 memcpy(SD.Sec.sectname, "__objc_imageinfo", 16);
1553 strcpy(SD.Sec.segname, "__DATA");
1554 SD.Sec.size = 8;
1555 jitlink::Symbol *ObjCImageInfoSym = nullptr;
1556 SD.AddFixups = [&, ObjCImageInfoSym](size_t RecordOffset) mutable {
1557 auto PointerEdge = getPointerEdgeKind(G);
1558
1559 // Look for an existing __objc_imageinfo symbol.
1560 if (!ObjCImageInfoSym) {
1561 auto Name = G.intern(ObjCImageInfoSymbolName);
1562 ObjCImageInfoSym = G.findExternalSymbolByName(Name);
1563 if (!ObjCImageInfoSym)
1564 ObjCImageInfoSym = G.findAbsoluteSymbolByName(Name);
1565 if (!ObjCImageInfoSym) {
1566 ObjCImageInfoSym = G.findDefinedSymbolByName(Name);
1567 if (ObjCImageInfoSym) {
1568 std::optional<uint32_t> Flags;
1569 {
1570 std::lock_guard<std::mutex> Lock(PluginMutex);
1571 auto It = ObjCImageInfos.find(&MR.getTargetJITDylib());
1572 if (It != ObjCImageInfos.end()) {
1573 It->second.Finalized = true;
1574 Flags = It->second.Flags;
1575 }
1576 }
1577
1578 if (Flags) {
1579 // We own the definition of __objc_image_info; write the final
1580 // merged flags value.
1581 auto Content = ObjCImageInfoSym->getBlock().getMutableContent(G);
1582 assert(
1583 Content.size() == 8 &&
1584 "__objc_image_info size should have been verified already");
1585 support::endian::write32(&Content[4], *Flags, G.getEndianness());
1586 }
1587 }
1588 }
1589 if (!ObjCImageInfoSym)
1590 ObjCImageInfoSym = &G.addExternalSymbol(std::move(Name), 8, false);
1591 }
1592
1593 SecBlock.addEdge(PointerEdge,
1594 RecordOffset + ((char *)&SD.Sec.addr - (char *)&SD.Sec),
1595 *ObjCImageInfoSym, -SecBlock.getAddress().getValue());
1596 };
1597 }
1598
1599 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsData) {
1600 if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) {
1601 DataSections.push_back({});
1602 AddSection(DataSections.back(), *GraphSec);
1603 }
1604 }
1605
1606 for (auto ObjCRuntimeSectionName : ObjCRuntimeObjectSectionsText) {
1607 if (auto *GraphSec = G.findSectionByName(ObjCRuntimeSectionName)) {
1608 TextSections.push_back({});
1609 AddSection(TextSections.back(), *GraphSec);
1610 }
1611 }
1612
1613 assert(ObjCRuntimeObjectSec->blocks_size() == 1 &&
1614 "Unexpected number of blocks in runtime sections object");
1615
1616 // Build the header struct up-front. This also gives us a chance to check
1617 // that the triple is supported, which we'll assume below.
1618 MachO::mach_header_64 Hdr;
1620 switch (G.getTargetTriple().getArch()) {
1621 case Triple::aarch64:
1624 break;
1625 case Triple::x86_64:
1628 break;
1629 default:
1630 llvm_unreachable("Unsupported architecture");
1631 }
1632
1634 Hdr.ncmds = 1 + !TextSections.empty();
1635 Hdr.sizeofcmds =
1636 Hdr.ncmds * sizeof(MachO::segment_command_64) +
1637 (TextSections.size() + DataSections.size()) * sizeof(MachO::section_64);
1638 Hdr.flags = 0;
1639 Hdr.reserved = 0;
1640
1641 auto SecContent = SecBlock.getAlreadyMutableContent();
1642 char *P = SecContent.data();
1643 auto WriteMachOStruct = [&](auto S) {
1644 if (G.getEndianness() != llvm::endianness::native)
1646 memcpy(P, &S, sizeof(S));
1647 P += sizeof(S);
1648 };
1649
1650 auto WriteSegment = [&](StringRef Name, std::vector<SecDesc> &Secs) {
1651 MachO::segment_command_64 SegLC;
1652 memset(&SegLC, 0, sizeof(SegLC));
1653 memcpy(SegLC.segname, Name.data(), Name.size());
1654 SegLC.cmd = MachO::LC_SEGMENT_64;
1655 SegLC.cmdsize = sizeof(MachO::segment_command_64) +
1656 Secs.size() * sizeof(MachO::section_64);
1657 SegLC.nsects = Secs.size();
1658 WriteMachOStruct(SegLC);
1659 for (auto &SD : Secs) {
1660 if (SD.AddFixups)
1661 SD.AddFixups(P - SecContent.data());
1662 WriteMachOStruct(SD.Sec);
1663 }
1664 };
1665
1666 WriteMachOStruct(Hdr);
1667 if (!TextSections.empty())
1668 WriteSegment("__TEXT", TextSections);
1669 if (!DataSections.empty())
1670 WriteSegment("__DATA", DataSections);
1671
1672 assert(P == SecContent.end() && "Underflow writing ObjC runtime object");
1673 return Error::success();
1674}
1675
1676Error MachOPlatform::MachOPlatformPlugin::prepareSymbolTableRegistration(
1677 jitlink::LinkGraph &G, JITSymTabVector &JITSymTabInfo) {
1678
1679 auto *CStringSec = G.findSectionByName(MachOCStringSectionName);
1680 if (!CStringSec)
1681 CStringSec = &G.createSection(MachOCStringSectionName,
1683
1684 // Make a map of existing strings so that we can re-use them:
1685 DenseMap<StringRef, jitlink::Symbol *> ExistingStrings;
1686 for (auto *Sym : CStringSec->symbols()) {
1687
1688 // The LinkGraph builder should have created single strings blocks, and all
1689 // plugins should have maintained this invariant.
1690 auto Content = Sym->getBlock().getContent();
1691 ExistingStrings.insert(
1692 std::make_pair(StringRef(Content.data(), Content.size()), Sym));
1693 }
1694
1695 // Add all symbol names to the string section, and record the symbols for
1696 // those names.
1697 {
1698 SmallVector<jitlink::Symbol *> SymsToProcess;
1699 llvm::append_range(SymsToProcess, G.defined_symbols());
1700 llvm::append_range(SymsToProcess, G.absolute_symbols());
1701
1702 for (auto *Sym : SymsToProcess) {
1703 if (!Sym->hasName())
1704 continue;
1705
1706 auto I = ExistingStrings.find(*Sym->getName());
1707 if (I == ExistingStrings.end()) {
1708 auto &NameBlock = G.createMutableContentBlock(
1709 *CStringSec, G.allocateCString(*Sym->getName()),
1710 orc::ExecutorAddr(), 1, 0);
1711 auto &SymbolNameSym = G.addAnonymousSymbol(
1712 NameBlock, 0, NameBlock.getSize(), false, true);
1713 JITSymTabInfo.push_back({Sym, &SymbolNameSym});
1714 } else
1715 JITSymTabInfo.push_back({Sym, I->second});
1716 }
1717 }
1718
1719 return Error::success();
1720}
1721
1722Error MachOPlatform::MachOPlatformPlugin::addSymbolTableRegistration(
1723 jitlink::LinkGraph &G, MaterializationResponsibility &MR,
1724 JITSymTabVector &JITSymTabInfo, bool InBootstrapPhase) {
1725
1726 ExecutorAddr HeaderAddr;
1727 {
1728 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
1729 auto I = MP.JITDylibToHeaderAddr.find(&MR.getTargetJITDylib());
1730 assert(I != MP.JITDylibToHeaderAddr.end() && "No header registered for JD");
1731 assert(I->second && "Null header registered for JD");
1732 HeaderAddr = I->second;
1733 }
1734
1735 if (LLVM_UNLIKELY(InBootstrapPhase)) {
1736 // If we're in the bootstrap phase then just record these symbols in the
1737 // bootstrap object and then bail out -- registration will be attached to
1738 // the bootstrap graph.
1739 std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
1740 auto &SymTab = MP.Bootstrap->SymTab;
1741 for (auto &[OriginalSymbol, NameSym] : JITSymTabInfo)
1742 SymTab.push_back({NameSym->getAddress(), OriginalSymbol->getAddress(),
1743 flagsForSymbol(*OriginalSymbol)});
1744 return Error::success();
1745 }
1746
1747 SymbolTableVector SymTab;
1748 for (auto &[OriginalSymbol, NameSym] : JITSymTabInfo)
1749 SymTab.push_back({NameSym->getAddress(), OriginalSymbol->getAddress(),
1750 flagsForSymbol(*OriginalSymbol)});
1751
1752 G.allocActions().push_back(
1754 MP.RegisterObjectSymbolTable.Addr, HeaderAddr, SymTab)),
1756 MP.DeregisterObjectSymbolTable.Addr, HeaderAddr, SymTab))});
1757
1758 return Error::success();
1759}
1760
1761template <typename MachOTraits>
1763 const MachOPlatform::HeaderOptions &Opts,
1765 jitlink::Section &HeaderSection) {
1766 auto HdrInfo =
1768 MachOBuilder<MachOTraits> B(HdrInfo.PageSize);
1769
1770 B.Header.filetype = MachO::MH_DYLIB;
1771 B.Header.cputype = HdrInfo.CPUType;
1772 B.Header.cpusubtype = HdrInfo.CPUSubType;
1773
1774 if (Opts.IDDylib)
1775 B.template addLoadCommand<MachO::LC_ID_DYLIB>(
1776 Opts.IDDylib->Name, Opts.IDDylib->Timestamp,
1777 Opts.IDDylib->CurrentVersion, Opts.IDDylib->CompatibilityVersion);
1778 else
1779 B.template addLoadCommand<MachO::LC_ID_DYLIB>(JD.getName(), 0, 0, 0);
1780
1781 if (Opts.UUID)
1782 B.template addLoadCommand<MachO::LC_UUID>(*Opts.UUID);
1783
1784 for (auto &BV : Opts.BuildVersions)
1785 B.template addLoadCommand<MachO::LC_BUILD_VERSION>(
1786 BV.Platform, BV.MinOS, BV.SDK, static_cast<uint32_t>(0));
1787
1788 if (Opts.TargetTriple)
1789 B.template addLoadCommand<MachO::LC_TARGET_TRIPLE>(*Opts.TargetTriple);
1790
1792 for (auto &LD : Opts.LoadDylibs) {
1793 switch (LD.K) {
1794 case LoadKind::Default:
1795 B.template addLoadCommand<MachO::LC_LOAD_DYLIB>(
1796 LD.D.Name, LD.D.Timestamp, LD.D.CurrentVersion,
1797 LD.D.CompatibilityVersion);
1798 break;
1799 case LoadKind::Weak:
1800 B.template addLoadCommand<MachO::LC_LOAD_WEAK_DYLIB>(
1801 LD.D.Name, LD.D.Timestamp, LD.D.CurrentVersion,
1802 LD.D.CompatibilityVersion);
1803 break;
1804 }
1805 }
1806 for (auto &P : Opts.RPaths)
1807 B.template addLoadCommand<MachO::LC_RPATH>(P);
1808
1809 auto HeaderContent = G.allocateBuffer(B.layout());
1810 B.write(HeaderContent);
1811
1812 return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
1813 0);
1814}
1815
1817 SymbolStringPtr HeaderStartSymbol,
1820 createHeaderInterface(MOP, std::move(HeaderStartSymbol))),
1821 MOP(MOP), Opts(std::move(Opts)) {}
1822
1824 std::unique_ptr<MaterializationResponsibility> R) {
1825 auto G = createPlatformGraph(MOP, "<MachOHeaderMU>");
1826 addMachOHeader(R->getTargetJITDylib(), *G, R->getInitializerSymbol());
1827 MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
1828}
1829
1831 const SymbolStringPtr &Sym) {}
1832
1833void SimpleMachOHeaderMU::addMachOHeader(
1835 const SymbolStringPtr &InitializerSymbol) {
1836 auto &HeaderSection = G.createSection("__header", MemProt::Read);
1837 auto &HeaderBlock = createHeaderBlock(JD, G, HeaderSection);
1838
1839 // Init symbol is header-start symbol.
1840 G.addDefinedSymbol(HeaderBlock, 0, *InitializerSymbol, HeaderBlock.getSize(),
1842 true);
1843 for (auto &HS : AdditionalHeaderSymbols)
1844 G.addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, HeaderBlock.getSize(),
1846 true);
1847}
1848
1851 jitlink::Section &HeaderSection) {
1852 switch (MOP.getExecutionSession().getTargetTriple().getArch()) {
1853 case Triple::aarch64:
1854 case Triple::x86_64:
1855 return ::createHeaderBlock<MachO64LE>(MOP, Opts, JD, G, HeaderSection);
1856 default:
1857 llvm_unreachable("Unsupported architecture");
1858 }
1859}
1860
1861MaterializationUnit::Interface SimpleMachOHeaderMU::createHeaderInterface(
1862 MachOPlatform &MOP, const SymbolStringPtr &HeaderStartSymbol) {
1863 SymbolFlagsMap HeaderSymbolFlags;
1864
1865 HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
1866 for (auto &HS : AdditionalHeaderSymbols)
1867 HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] =
1869
1870 return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
1871 HeaderStartSymbol);
1872}
1873
1875 switch (TT.getArch()) {
1876 case Triple::aarch64:
1877 return {/* PageSize = */ 16 * 1024,
1878 /* CPUType = */ MachO::CPU_TYPE_ARM64,
1879 /* CPUSubType = */ MachO::CPU_SUBTYPE_ARM64_ALL};
1880 case Triple::x86_64:
1881 return {/* PageSize = */ 4 * 1024,
1882 /* CPUType = */ MachO::CPU_TYPE_X86_64,
1883 /* CPUSubType = */ MachO::CPU_SUBTYPE_X86_64_ALL};
1884 default:
1885 llvm_unreachable("Unrecognized architecture");
1886 }
1887}
1888
1889} // End namespace orc.
1890} // End namespace llvm.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:352
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:351
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
#define _
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
#define H(x, y, z)
Definition MD5.cpp:56
#define P(N)
static StringRef getName(Value *V)
#define LLVM_DEBUG(...)
Definition Debug.h:119
Value * RHS
Value * LHS
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
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:778
bool empty() const
Definition DenseMap.h:732
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:782
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition DenseMap.h:737
iterator end()
Definition DenseMap.h:702
unsigned size() const
Definition DenseMap.h:733
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:843
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:872
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:635
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
Manages the enabling and disabling of subtarget specific features.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
An ExecutionSession represents a running JIT program.
Definition Core.h:1112
const Triple & getTargetTriple() const
Return the triple for the executor.
Definition Core.h:1182
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition Core.h:1193
Represents an address in the executor process.
Represents a JIT'd dynamic library.
Definition Core.h:676
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:1629
Mediates between MachO initialization and ExecutionSession state.
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 ArrayRef< std::pair< const char *, const char * > > standardLazyCompilationAliases()
Returns a list of aliases required to enable lazy compilation via the ORC runtime.
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.
static Expected< std::unique_ptr< MachOPlatform > > Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &PlatformJD, std::unique_ptr< DefinitionGenerator > OrcRuntime, HeaderOptionsBuilder BuildHeaderOpts=defaultHeaderOpts, HeaderOptions PlatformJDOpts={}, MachOHeaderMUBuilder BuildMachOHeaderMU=buildSimpleMachOHeaderMU, std::optional< SymbolAliasMap > RuntimeAliases=std::nullopt)
Try to create a MachOPlatform instance, adding the ORC runtime to the given JITDylib.
static HeaderOptions defaultHeaderOpts(JITDylib &JD)
std::vector< std::pair< ExecutorAddr, MachOJITDylibDepInfo > > MachOJITDylibDepInfoMap
unique_function< std::unique_ptr< MaterializationUnit >(MachOPlatform &MOP, HeaderOptions Opts)> MachOHeaderMUBuilder
Used by setupJITDylib to create MachO header MaterializationUnits for JITDylibs.
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 SymbolAliasMap standardPlatformAliases(ExecutionSession &ES)
Returns an AliasMap containing the default aliases for the MachOPlatform.
ExecutionSession & getExecutionSession() const
Error notifyRemoving(ResourceTracker &RT) override
This method will be called under the ExecutionSession lock when a ResourceTracker is removed.
unique_function< HeaderOptions(JITDylib &JD)> HeaderOptionsBuilder
Callback for generating HeaderOptions structs for new JITDylibs.
static ArrayRef< std::pair< const char *, const char * > > requiredCXXAliases()
Returns the array of required CXX aliases.
Mangles symbol names then uniques them in the context of an ExecutionSession.
Definition Mangling.h:28
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition Core.h:350
Error defineMaterializing(SymbolFlagsMap SymbolFlags)
Attempt to claim responsibility for new definitions.
Definition Core.h:1760
const SymbolStringPtr & getInitializerSymbol() const
Returns the initialization pseudo-symbol, if any.
Definition Core.h:389
JITDylib & getTargetJITDylib() const
Returns the target JITDylib that these symbols are being materialized into.
Definition Core.h:375
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
virtual StringRef getName() const =0
Return the name of this materialization unit.
const SymbolStringPtr & getInitializerSymbol() const
Returns the initialization symbol for this MaterializationUnit (if any).
An ObjectLayer implementation built on JITLink.
static void lookupInitSymbolsAsync(unique_function< void(Error)> OnComplete, ExecutionSession &ES, const DenseMap< JITDylib *, SymbolLookupSet > &InitSyms)
Performs an async lookup for the given symbols in each of the given JITDylibs, calling the given hand...
Definition Core.cpp:1489
API to remove / transfer ownership of JIT resources.
Definition Core.h:64
JITDylib & getJITDylib() const
Return the JITDylib targeted by this tracker.
Definition Core.h:79
MachOPlatform::HeaderOptions Opts
void materialize(std::unique_ptr< MaterializationResponsibility > R) override
Implementations of this method should materialize all symbols in the materialzation unit,...
virtual jitlink::Block & createHeaderBlock(JITDylib &JD, jitlink::LinkGraph &G, jitlink::Section &HeaderSection)
SimpleMachOHeaderMU(MachOPlatform &MOP, SymbolStringPtr HeaderStartSymbol, MachOPlatform::HeaderOptions Opts)
void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override
Implementations of this method should discard the given symbol from the source (e....
static Expected< std::unique_ptr< StaticLibraryDefinitionGenerator > > Load(ObjectLayer &L, const char *FileName, VisitMembersFunction VisitMembers=VisitMembersFunction(), GetObjectFileInterface GetObjFileInterface=GetObjectFileInterface())
Try to create a StaticLibraryDefinitionGenerator from the given path.
A symbol name together with the naming level (SymbolNameKind) it is expressed in, so that a Mangler /...
static constexpr SymbolNameSpec c(StringRef Name)
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 deserialize(SPSInputBuffer &IB, MachOPlatform::MachOExecutorSymbolFlags &SF)
static bool serialize(SPSOutputBuffer &OB, const MachOPlatform::MachOExecutorSymbolFlags &SF)
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.
@ MH_DYLIB
Definition MachO.h:48
@ S_REGULAR
S_REGULAR - Regular section.
Definition MachO.h:127
void swapStruct(fat_header &mh)
Definition MachO.h:1203
@ MH_MAGIC_64
Definition MachO.h:32
@ CPU_SUBTYPE_ARM64_ALL
Definition MachO.h:1715
@ CPU_SUBTYPE_X86_64_ALL
Definition MachO.h:1682
@ CPU_TYPE_ARM64
Definition MachO.h:1639
@ CPU_TYPE_X86_64
Definition MachO.h:1635
SPSTuple< bool, SPSSequence< SPSExecutorAddr > > SPSMachOJITDylibDepInfo
std::vector< AllocActionCallPair > AllocActions
A vector of allocation actions to be run for this allocation.
SPSSequence< SPSTuple< SPSExecutorAddr, SPSMachOJITDylibDepInfo > > SPSMachOJITDylibDepInfoMap
SPSTuple< SPSExecutorAddr, SPSExecutorAddr > SPSExecutorAddrRange
LLVM_ABI StringRef MachOSwift5EntrySectionName
LLVM_ABI StringRef MachOThreadBSSSectionName
LLVM_ABI StringRef MachOThreadVarsSectionName
ExecutionSession::CallControllerHandlerBinding bindCallControllerHandlerSPS(SymbolNameSpec Name, HandlerT &&Handler, SymbolLookupFlags LF=SymbolLookupFlags::RequiredSymbol)
Bind a call-controller handler that takes concrete argument types (and a sender for a concrete return...
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:154
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:149
IntrusiveRefCntPtr< JITDylib > JITDylibSP
Definition Core.h:59
std::unique_ptr< ReExportsMaterializationUnit > symbolAliases(SymbolAliasMap Aliases)
Create a ReExportsMaterializationUnit with the given aliases.
Definition Core.h:524
LLVM_ABI StringRef MachOObjCProtoListSectionName
LLVM_ABI StringRef MachOSwift5ProtosSectionName
LLVM_ABI StringRef MachOEHFrameSectionName
LLVM_ABI StringRef MachOModInitFuncSectionName
LLVM_ABI StringRef MachOObjCConstSectionName
LLVM_ABI StringRef MachODataDataSectionName
std::unique_ptr< ReExportsMaterializationUnit > reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, JITDylibLookupFlags SourceJDLookupFlags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Create a materialization unit for re-exporting symbols from another JITDylib with alternative names/f...
Definition Core.h:533
LLVM_ABI StringRef MachOCompactUnwindSectionName
LLVM_ABI StringRef MachOSwift5ProtoSectionName
static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, ArrayRef< std::pair< const char *, const char * > > AL)
LLVM_ABI StringRef MachOObjCCatListSectionName
LLVM_ABI StringRef MachOObjCClassRefsSectionName
LLVM_ABI StringRef MachOObjCDataSectionName
LLVM_ABI StringRef MachOObjCClassNameSectionName
LLVM_ABI StringRef MachOObjCMethNameSectionName
LLVM_ABI StringRef MachOInitSectionNames[22]
LLVM_ABI StringRef MachOObjCClassListSectionName
LLVM_ABI StringRef MachOObjCSelRefsSectionName
LLVM_ABI StringRef MachOSwift5FieldMetadataSectionName
LLVM_ABI StringRef MachOCStringSectionName
LLVM_ABI StringRef MachOObjCMethTypeSectionName
LLVM_ABI StringRef MachOSwift5TypesSectionName
LLVM_ABI StringRef MachOObjCNLCatListSectionName
jitlink::Block & createHeaderBlock(MachOPlatform &MOP, const MachOPlatform::HeaderOptions &Opts, JITDylib &JD, jitlink::LinkGraph &G, jitlink::Section &HeaderSection)
LLVM_ABI StringRef MachOObjCNLClassListSectionName
LLVM_ABI StringRef MachOObjCImageInfoSectionName
LLVM_ABI MachOHeaderInfo getMachOHeaderInfoFromTriple(const Triple &TT)
LLVM_ABI RegisterDependenciesFunction NoDependenciesToRegister
This can be used as the value for a RegisterDependenciesFunction if there are no dependants to regist...
Definition Core.cpp:41
LLVM_ABI StringRef MachOThreadDataSectionName
LLVM_ABI StringRef MachOUnwindInfoSectionName
LLVM_ABI StringRef MachODataCommonSectionName
LLVM_ABI StringRef MachOObjCProtoRefsSectionName
@ Ready
Emitted to memory, but waiting on transitive dependencies.
Definition Core.h:552
DenseMap< SymbolStringPtr, SymbolAliasMapEntry > SymbolAliasMap
A map of Symbols to (Symbol, Flags) pairs.
Definition Core.h:174
LLVM_ABI StringRef MachOSwift5TypeRefSectionName
LLVM_ABI StringRef MachOObjCCatList2SectionName
DenseMap< SymbolStringPtr, JITSymbolFlags > SymbolFlagsMap
A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
LLVM_ABI iterator begin() const
value_type byte_swap(value_type value, endianness endian)
Swap the bytes of value to match the given endianness.
Definition Endian.h:45
uint32_t read32(const void *P, endianness E)
Definition Endian.h:392
void write32(void *P, uint32_t V, endianness E)
Definition Endian.h:435
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:94
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition Error.h:769
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1901
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:1933
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:1788
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
static LLVM_ABI std::optional< BuildVersionOpts > fromTriple(const Triple &TT, uint32_t MinOS, uint32_t SDK)
Configuration for the mach-o header of a JITDylib.
std::optional< std::string > TargetTriple
Optional LC_TARGET_TRIPLE.
std::optional< Dylib > IDDylib
Override for LC_IC_DYLIB.
std::optional< std::array< uint8_t, 16 > > UUID
Optional UUID. If set, this will be used to add an LC_UUID command.
std::vector< std::string > RPaths
List of LC_RPATHs.
std::vector< BuildVersionOpts > BuildVersions
List of LC_BUILD_VERSIONs.
std::vector< LoadDylibCmd > LoadDylibs
List of LC_LOAD_DYLIBs.
static constexpr SymbolNameSpec Name