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