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