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/x86_64.h"
13 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
14 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
15 #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
16 #include "llvm/Support/BinaryByteStream.h"
17 #include "llvm/Support/Debug.h"
18 
19 #define DEBUG_TYPE "orc"
20 
21 using namespace llvm;
22 using namespace llvm::orc;
23 using namespace llvm::orc::shared;
24 
25 namespace llvm {
26 namespace orc {
27 namespace shared {
28 
29 using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>;
30 using SPSMachOJITDylibDepInfoMap =
31     SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>;
32 
33 template <>
34 class SPSSerializationTraits<SPSMachOJITDylibDepInfo,
35                              MachOPlatform::MachOJITDylibDepInfo> {
36 public:
37   static size_t size(const MachOPlatform::MachOJITDylibDepInfo &DDI) {
38     return SPSMachOJITDylibDepInfo::AsArgList::size(DDI.Sealed, DDI.DepHeaders);
39   }
40 
41   static bool serialize(SPSOutputBuffer &OB,
42                         const MachOPlatform::MachOJITDylibDepInfo &DDI) {
43     return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, DDI.Sealed,
44                                                          DDI.DepHeaders);
45   }
46 
47   static bool deserialize(SPSInputBuffer &IB,
48                           MachOPlatform::MachOJITDylibDepInfo &DDI) {
49     return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, DDI.Sealed,
50                                                            DDI.DepHeaders);
51   }
52 };
53 
54 } // namespace shared
55 } // namespace orc
56 } // namespace llvm
57 
58 namespace {
59 
60 class MachOHeaderMaterializationUnit : public MaterializationUnit {
61 public:
62   MachOHeaderMaterializationUnit(MachOPlatform &MOP,
63                                  const SymbolStringPtr &HeaderStartSymbol)
64       : MaterializationUnit(createHeaderInterface(MOP, HeaderStartSymbol)),
65         MOP(MOP) {}
66 
67   StringRef getName() const override { return "MachOHeaderMU"; }
68 
69   void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
70     unsigned PointerSize;
71     support::endianness Endianness;
72     const auto &TT =
73         MOP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
74 
75     switch (TT.getArch()) {
76     case Triple::aarch64:
77     case Triple::x86_64:
78       PointerSize = 8;
79       Endianness = support::endianness::little;
80       break;
81     default:
82       llvm_unreachable("Unrecognized architecture");
83     }
84 
85     auto G = std::make_unique<jitlink::LinkGraph>(
86         "<MachOHeaderMU>", TT, PointerSize, Endianness,
87         jitlink::getGenericEdgeKindName);
88     auto &HeaderSection = G->createSection("__header", jitlink::MemProt::Read);
89     auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
90 
91     // Init symbol is header-start symbol.
92     G->addDefinedSymbol(HeaderBlock, 0, *R->getInitializerSymbol(),
93                         HeaderBlock.getSize(), jitlink::Linkage::Strong,
94                         jitlink::Scope::Default, false, true);
95     for (auto &HS : AdditionalHeaderSymbols)
96       G->addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name,
97                           HeaderBlock.getSize(), jitlink::Linkage::Strong,
98                           jitlink::Scope::Default, false, true);
99 
100     MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G));
101   }
102 
103   void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {}
104 
105 private:
106   struct HeaderSymbol {
107     const char *Name;
108     uint64_t Offset;
109   };
110 
111   static constexpr HeaderSymbol AdditionalHeaderSymbols[] = {
112       {"___mh_executable_header", 0}};
113 
114   static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G,
115                                            jitlink::Section &HeaderSection) {
116     MachO::mach_header_64 Hdr;
117     Hdr.magic = MachO::MH_MAGIC_64;
118     switch (G.getTargetTriple().getArch()) {
119     case Triple::aarch64:
120       Hdr.cputype = MachO::CPU_TYPE_ARM64;
121       Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
122       break;
123     case Triple::x86_64:
124       Hdr.cputype = MachO::CPU_TYPE_X86_64;
125       Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
126       break;
127     default:
128       llvm_unreachable("Unrecognized architecture");
129     }
130     Hdr.filetype = MachO::MH_DYLIB; // Custom file type?
131     Hdr.ncmds = 0;
132     Hdr.sizeofcmds = 0;
133     Hdr.flags = 0;
134     Hdr.reserved = 0;
135 
136     if (G.getEndianness() != support::endian::system_endianness())
137       MachO::swapStruct(Hdr);
138 
139     auto HeaderContent = G.allocateString(
140         StringRef(reinterpret_cast<const char *>(&Hdr), sizeof(Hdr)));
141 
142     return G.createContentBlock(HeaderSection, HeaderContent, ExecutorAddr(), 8,
143                                 0);
144   }
145 
146   static MaterializationUnit::Interface
147   createHeaderInterface(MachOPlatform &MOP,
148                         const SymbolStringPtr &HeaderStartSymbol) {
149     SymbolFlagsMap HeaderSymbolFlags;
150 
151     HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported;
152     for (auto &HS : AdditionalHeaderSymbols)
153       HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] =
154           JITSymbolFlags::Exported;
155 
156     return MaterializationUnit::Interface(std::move(HeaderSymbolFlags),
157                                           HeaderStartSymbol);
158   }
159 
160   MachOPlatform &MOP;
161 };
162 
163 constexpr MachOHeaderMaterializationUnit::HeaderSymbol
164     MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[];
165 
166 StringRef EHFrameSectionName = "__TEXT,__eh_frame";
167 StringRef ModInitFuncSectionName = "__DATA,__mod_init_func";
168 StringRef ObjCClassListSectionName = "__DATA,__objc_classlist";
169 StringRef ObjCImageInfoSectionName = "__DATA,__objc_image_info";
170 StringRef ObjCSelRefsSectionName = "__DATA,__objc_selrefs";
171 StringRef Swift5ProtoSectionName = "__TEXT,__swift5_proto";
172 StringRef Swift5ProtosSectionName = "__TEXT,__swift5_protos";
173 StringRef Swift5TypesSectionName = "__TEXT,__swift5_types";
174 StringRef ThreadBSSSectionName = "__DATA,__thread_bss";
175 StringRef ThreadDataSectionName = "__DATA,__thread_data";
176 StringRef ThreadVarsSectionName = "__DATA,__thread_vars";
177 
178 StringRef InitSectionNames[] = {
179     ModInitFuncSectionName, ObjCSelRefsSectionName, ObjCClassListSectionName,
180     Swift5ProtosSectionName, Swift5ProtoSectionName, Swift5TypesSectionName};
181 
182 } // end anonymous namespace
183 
184 namespace llvm {
185 namespace orc {
186 
187 Expected<std::unique_ptr<MachOPlatform>>
188 MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
189                       JITDylib &PlatformJD, const char *OrcRuntimePath,
190                       Optional<SymbolAliasMap> RuntimeAliases) {
191 
192   auto &EPC = ES.getExecutorProcessControl();
193 
194   // If the target is not supported then bail out immediately.
195   if (!supportedTarget(EPC.getTargetTriple()))
196     return make_error<StringError>("Unsupported MachOPlatform triple: " +
197                                        EPC.getTargetTriple().str(),
198                                    inconvertibleErrorCode());
199 
200   // Create default aliases if the caller didn't supply any.
201   if (!RuntimeAliases)
202     RuntimeAliases = standardPlatformAliases(ES);
203 
204   // Define the aliases.
205   if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases))))
206     return std::move(Err);
207 
208   // Add JIT-dispatch function support symbols.
209   if (auto Err = PlatformJD.define(absoluteSymbols(
210           {{ES.intern("___orc_rt_jit_dispatch"),
211             {EPC.getJITDispatchInfo().JITDispatchFunction.getValue(),
212              JITSymbolFlags::Exported}},
213            {ES.intern("___orc_rt_jit_dispatch_ctx"),
214             {EPC.getJITDispatchInfo().JITDispatchContext.getValue(),
215              JITSymbolFlags::Exported}}})))
216     return std::move(Err);
217 
218   // Create a generator for the ORC runtime archive.
219   auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load(
220       ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple());
221   if (!OrcRuntimeArchiveGenerator)
222     return OrcRuntimeArchiveGenerator.takeError();
223 
224   // Create the instance.
225   Error Err = Error::success();
226   auto P = std::unique_ptr<MachOPlatform>(
227       new MachOPlatform(ES, ObjLinkingLayer, PlatformJD,
228                         std::move(*OrcRuntimeArchiveGenerator), Err));
229   if (Err)
230     return std::move(Err);
231   return std::move(P);
232 }
233 
234 Error MachOPlatform::setupJITDylib(JITDylib &JD) {
235   if (auto Err = JD.define(std::make_unique<MachOHeaderMaterializationUnit>(
236           *this, MachOHeaderStartSymbol)))
237     return Err;
238 
239   return ES.lookup({&JD}, MachOHeaderStartSymbol).takeError();
240 }
241 
242 Error MachOPlatform::teardownJITDylib(JITDylib &JD) {
243   std::lock_guard<std::mutex> Lock(PlatformMutex);
244   auto I = JITDylibToHeaderAddr.find(&JD);
245   if (I != JITDylibToHeaderAddr.end()) {
246     assert(HeaderAddrToJITDylib.count(I->second) &&
247            "HeaderAddrToJITDylib missing entry");
248     HeaderAddrToJITDylib.erase(I->second);
249     JITDylibToHeaderAddr.erase(I);
250   }
251   JITDylibToPThreadKey.erase(&JD);
252   return Error::success();
253 }
254 
255 Error MachOPlatform::notifyAdding(ResourceTracker &RT,
256                                   const MaterializationUnit &MU) {
257   auto &JD = RT.getJITDylib();
258   const auto &InitSym = MU.getInitializerSymbol();
259   if (!InitSym)
260     return Error::success();
261 
262   RegisteredInitSymbols[&JD].add(InitSym,
263                                  SymbolLookupFlags::WeaklyReferencedSymbol);
264   LLVM_DEBUG({
265     dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU "
266            << MU.getName() << "\n";
267   });
268   return Error::success();
269 }
270 
271 Error MachOPlatform::notifyRemoving(ResourceTracker &RT) {
272   llvm_unreachable("Not supported yet");
273 }
274 
275 static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases,
276                        ArrayRef<std::pair<const char *, const char *>> AL) {
277   for (auto &KV : AL) {
278     auto AliasName = ES.intern(KV.first);
279     assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map");
280     Aliases[std::move(AliasName)] = {ES.intern(KV.second),
281                                      JITSymbolFlags::Exported};
282   }
283 }
284 
285 SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) {
286   SymbolAliasMap Aliases;
287   addAliases(ES, Aliases, requiredCXXAliases());
288   addAliases(ES, Aliases, standardRuntimeUtilityAliases());
289   return Aliases;
290 }
291 
292 ArrayRef<std::pair<const char *, const char *>>
293 MachOPlatform::requiredCXXAliases() {
294   static const std::pair<const char *, const char *> RequiredCXXAliases[] = {
295       {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}};
296 
297   return ArrayRef<std::pair<const char *, const char *>>(RequiredCXXAliases);
298 }
299 
300 ArrayRef<std::pair<const char *, const char *>>
301 MachOPlatform::standardRuntimeUtilityAliases() {
302   static const std::pair<const char *, const char *>
303       StandardRuntimeUtilityAliases[] = {
304           {"___orc_rt_run_program", "___orc_rt_macho_run_program"},
305           {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"},
306           {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"},
307           {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"},
308           {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"},
309           {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};
310 
311   return ArrayRef<std::pair<const char *, const char *>>(
312       StandardRuntimeUtilityAliases);
313 }
314 
315 bool MachOPlatform::isInitializerSection(StringRef SegName,
316                                          StringRef SectName) {
317   for (auto &Name : InitSectionNames) {
318     if (Name.startswith(SegName) && Name.substr(7) == SectName)
319       return true;
320   }
321   return false;
322 }
323 
324 bool MachOPlatform::supportedTarget(const Triple &TT) {
325   switch (TT.getArch()) {
326   case Triple::aarch64:
327   case Triple::x86_64:
328     return true;
329   default:
330     return false;
331   }
332 }
333 
334 MachOPlatform::MachOPlatform(
335     ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
336     JITDylib &PlatformJD,
337     std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
338     : ES(ES), ObjLinkingLayer(ObjLinkingLayer),
339       MachOHeaderStartSymbol(ES.intern("___dso_handle")) {
340   ErrorAsOutParameter _(&Err);
341 
342   ObjLinkingLayer.addPlugin(std::make_unique<MachOPlatformPlugin>(*this));
343 
344   PlatformJD.addGenerator(std::move(OrcRuntimeGenerator));
345 
346   // Force linking of eh-frame registration functions.
347   if (auto Err2 = lookupAndRecordAddrs(
348           ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
349           {{ES.intern("___orc_rt_macho_register_ehframe_section"),
350             &orc_rt_macho_register_ehframe_section},
351            {ES.intern("___orc_rt_macho_deregister_ehframe_section"),
352             &orc_rt_macho_deregister_ehframe_section}})) {
353     Err = std::move(Err2);
354     return;
355   }
356 
357   State = BootstrapPhase2;
358 
359   // Associate wrapper function tags with JIT-side function implementations.
360   if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) {
361     Err = std::move(E2);
362     return;
363   }
364 
365   // Lookup addresses of runtime functions callable by the platform,
366   // call the platform bootstrap function to initialize the platform-state
367   // object in the executor.
368   if (auto E2 = bootstrapMachORuntime(PlatformJD)) {
369     Err = std::move(E2);
370     return;
371   }
372 
373   // PlatformJD hasn't been set up by the platform yet (since we're creating
374   // the platform now), so set it up.
375   if (auto E2 = setupJITDylib(PlatformJD)) {
376     Err = std::move(E2);
377     return;
378   }
379 
380   State = Initialized;
381 }
382 
383 Error MachOPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
384   ExecutionSession::JITDispatchHandlerAssociationMap WFs;
385 
386   using PushInitializersSPSSig =
387       SPSExpected<SPSMachOJITDylibDepInfoMap>(SPSExecutorAddr);
388   WFs[ES.intern("___orc_rt_macho_push_initializers_tag")] =
389       ES.wrapAsyncWithSPS<PushInitializersSPSSig>(
390           this, &MachOPlatform::rt_pushInitializers);
391 
392   using LookupSymbolSPSSig =
393       SPSExpected<SPSExecutorAddr>(SPSExecutorAddr, SPSString);
394   WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] =
395       ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
396                                               &MachOPlatform::rt_lookupSymbol);
397 
398   return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
399 }
400 
401 void MachOPlatform::pushInitializersLoop(
402     PushInitializersSendResultFn SendResult, JITDylibSP JD) {
403   DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
404   DenseMap<JITDylib *, SmallVector<JITDylib *>> JDDepMap;
405   SmallVector<JITDylib *, 16> Worklist({JD.get()});
406 
407   ES.runSessionLocked([&]() {
408     while (!Worklist.empty()) {
409       // FIXME: Check for defunct dylibs.
410 
411       auto DepJD = Worklist.back();
412       Worklist.pop_back();
413 
414       // If we've already visited this JITDylib on this iteration then continue.
415       if (JDDepMap.count(DepJD))
416         continue;
417 
418       // Add dep info.
419       auto &DM = JDDepMap[DepJD];
420       DepJD->withLinkOrderDo([&](const JITDylibSearchOrder &O) {
421         for (auto &KV : O) {
422           if (KV.first == DepJD)
423             continue;
424           DM.push_back(KV.first);
425           Worklist.push_back(KV.first);
426         }
427       });
428 
429       // Add any registered init symbols.
430       auto RISItr = RegisteredInitSymbols.find(DepJD);
431       if (RISItr != RegisteredInitSymbols.end()) {
432         NewInitSymbols[DepJD] = std::move(RISItr->second);
433         RegisteredInitSymbols.erase(RISItr);
434       }
435     }
436   });
437 
438   // If there are no further init symbols to look up then send the link order
439   // (as a list of header addresses) to the caller.
440   if (NewInitSymbols.empty()) {
441 
442     // To make the list intelligible to the runtime we need to convert all
443     // JITDylib pointers to their header addresses.
444     DenseMap<JITDylib *, ExecutorAddr> HeaderAddrs;
445     HeaderAddrs.reserve(JDDepMap.size());
446     {
447       std::lock_guard<std::mutex> Lock(PlatformMutex);
448       for (auto &KV : JDDepMap) {
449         auto I = JITDylibToHeaderAddr.find(KV.first);
450         if (I == JITDylibToHeaderAddr.end()) {
451           // The header address should have been materialized by the previous
452           // round, but we need to handle the pathalogical case where someone
453           // removes the symbol on another thread while we're running.
454           SendResult(
455               make_error<StringError>("JITDylib " + KV.first->getName() +
456                                           " has no registered header address",
457                                       inconvertibleErrorCode()));
458           return;
459         }
460         HeaderAddrs[KV.first] = I->second;
461       }
462     }
463 
464     // Build the dep info map to return.
465     MachOJITDylibDepInfoMap DIM;
466     DIM.reserve(JDDepMap.size());
467     for (auto &KV : JDDepMap) {
468       assert(HeaderAddrs.count(KV.first) && "Missing header addr");
469       auto H = HeaderAddrs[KV.first];
470       MachOJITDylibDepInfo DepInfo;
471       for (auto &Dep : KV.second) {
472         assert(HeaderAddrs.count(Dep) && "Missing header addr");
473         DepInfo.DepHeaders.push_back(HeaderAddrs[Dep]);
474       }
475       DIM.push_back(std::make_pair(H, std::move(DepInfo)));
476     }
477     SendResult(DIM);
478     return;
479   }
480 
481   // Otherwise issue a lookup and re-run this phase when it completes.
482   lookupInitSymbolsAsync(
483       [this, SendResult = std::move(SendResult), &JD](Error Err) mutable {
484         if (Err)
485           SendResult(std::move(Err));
486         else
487           pushInitializersLoop(std::move(SendResult), JD);
488       },
489       ES, std::move(NewInitSymbols));
490 }
491 
492 void MachOPlatform::rt_pushInitializers(PushInitializersSendResultFn SendResult,
493                                         ExecutorAddr JDHeaderAddr) {
494   JITDylibSP JD;
495   {
496     std::lock_guard<std::mutex> Lock(PlatformMutex);
497     auto I = HeaderAddrToJITDylib.find(JDHeaderAddr);
498     if (I != HeaderAddrToJITDylib.end())
499       JD = I->second;
500   }
501 
502   LLVM_DEBUG({
503     dbgs() << "MachOPlatform::rt_pushInitializers(" << JDHeaderAddr << ") ";
504     if (JD)
505       dbgs() << "pushing initializers for " << JD->getName() << "\n";
506     else
507       dbgs() << "No JITDylib for header address.\n";
508   });
509 
510   if (!JD) {
511     SendResult(
512         make_error<StringError>("No JITDylib with header addr " +
513                                     formatv("{0:x}", JDHeaderAddr.getValue()),
514                                 inconvertibleErrorCode()));
515     return;
516   }
517 
518   pushInitializersLoop(std::move(SendResult), JD);
519 }
520 
521 void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
522                                     ExecutorAddr Handle, StringRef SymbolName) {
523   LLVM_DEBUG({
524     dbgs() << "MachOPlatform::rt_lookupSymbol(\""
525            << formatv("{0:x}", Handle.getValue()) << "\")\n";
526   });
527 
528   JITDylib *JD = nullptr;
529 
530   {
531     std::lock_guard<std::mutex> Lock(PlatformMutex);
532     auto I = HeaderAddrToJITDylib.find(Handle);
533     if (I != HeaderAddrToJITDylib.end())
534       JD = I->second;
535   }
536 
537   if (!JD) {
538     LLVM_DEBUG({
539       dbgs() << "  No JITDylib for handle "
540              << formatv("{0:x}", Handle.getValue()) << "\n";
541     });
542     SendResult(make_error<StringError>("No JITDylib associated with handle " +
543                                            formatv("{0:x}", Handle.getValue()),
544                                        inconvertibleErrorCode()));
545     return;
546   }
547 
548   // Use functor class to work around XL build compiler issue on AIX.
549   class RtLookupNotifyComplete {
550   public:
551     RtLookupNotifyComplete(SendSymbolAddressFn &&SendResult)
552         : SendResult(std::move(SendResult)) {}
553     void operator()(Expected<SymbolMap> Result) {
554       if (Result) {
555         assert(Result->size() == 1 && "Unexpected result map count");
556         SendResult(ExecutorAddr(Result->begin()->second.getAddress()));
557       } else {
558         SendResult(Result.takeError());
559       }
560     }
561 
562   private:
563     SendSymbolAddressFn SendResult;
564   };
565 
566   // FIXME: Proper mangling.
567   auto MangledName = ("_" + SymbolName).str();
568   ES.lookup(
569       LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}},
570       SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready,
571       RtLookupNotifyComplete(std::move(SendResult)), NoDependenciesToRegister);
572 }
573 
574 Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) {
575   if (auto Err = lookupAndRecordAddrs(
576           ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
577           {{ES.intern("___orc_rt_macho_platform_bootstrap"),
578             &orc_rt_macho_platform_bootstrap},
579            {ES.intern("___orc_rt_macho_platform_shutdown"),
580             &orc_rt_macho_platform_shutdown},
581            {ES.intern("___orc_rt_macho_register_jitdylib"),
582             &orc_rt_macho_register_jitdylib},
583            {ES.intern("___orc_rt_macho_deregister_jitdylib"),
584             &orc_rt_macho_deregister_jitdylib},
585            {ES.intern("___orc_rt_macho_register_object_platform_sections"),
586             &orc_rt_macho_register_object_platform_sections},
587            {ES.intern("___orc_rt_macho_deregister_object_platform_sections"),
588             &orc_rt_macho_deregister_object_platform_sections},
589            {ES.intern("___orc_rt_macho_create_pthread_key"),
590             &orc_rt_macho_create_pthread_key}}))
591     return Err;
592 
593   return ES.callSPSWrapper<void()>(orc_rt_macho_platform_bootstrap);
594 }
595 
596 Expected<uint64_t> MachOPlatform::createPThreadKey() {
597   if (!orc_rt_macho_create_pthread_key)
598     return make_error<StringError>(
599         "Attempting to create pthread key in target, but runtime support has "
600         "not been loaded yet",
601         inconvertibleErrorCode());
602 
603   Expected<uint64_t> Result(0);
604   if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
605           orc_rt_macho_create_pthread_key, Result))
606     return std::move(Err);
607   return Result;
608 }
609 
610 void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
611     MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
612     jitlink::PassConfiguration &Config) {
613 
614   auto PS = MP.State.load();
615 
616   // --- Handle Initializers ---
617   if (auto InitSymbol = MR.getInitializerSymbol()) {
618 
619     // If the initializer symbol is the MachOHeader start symbol then just
620     // register it and then bail out -- the header materialization unit
621     // definitely doesn't need any other passes.
622     if (InitSymbol == MP.MachOHeaderStartSymbol) {
623       Config.PostAllocationPasses.push_back([this, &MR](jitlink::LinkGraph &G) {
624         return associateJITDylibHeaderSymbol(G, MR);
625       });
626       return;
627     }
628 
629     // If the object contains an init symbol other than the header start symbol
630     // then add passes to preserve, process and register the init
631     // sections/symbols.
632     Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) {
633       if (auto Err = preserveInitSections(G, MR))
634         return Err;
635       return processObjCImageInfo(G, MR);
636     });
637   }
638 
639   // --- Add passes for eh-frame and TLV support ---
640   if (PS == MachOPlatform::BootstrapPhase1) {
641     Config.PostFixupPasses.push_back(
642         [this](jitlink::LinkGraph &G) { return registerEHSectionsPhase1(G); });
643     return;
644   }
645 
646   // Insert TLV lowering at the start of the PostPrunePasses, since we want
647   // it to run before GOT/PLT lowering.
648   Config.PostPrunePasses.insert(
649       Config.PostPrunePasses.begin(),
650       [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
651         return fixTLVSectionsAndEdges(G, JD);
652       });
653 
654   // Add a pass to register the final addresses of any special sections in the
655   // object with the runtime.
656   Config.PostAllocationPasses.push_back(
657       [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) {
658         return registerObjectPlatformSections(G, JD);
659       });
660 }
661 
662 ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap
663 MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies(
664     MaterializationResponsibility &MR) {
665   std::lock_guard<std::mutex> Lock(PluginMutex);
666   auto I = InitSymbolDeps.find(&MR);
667   if (I != InitSymbolDeps.end()) {
668     SyntheticSymbolDependenciesMap Result;
669     Result[MR.getInitializerSymbol()] = std::move(I->second);
670     InitSymbolDeps.erase(&MR);
671     return Result;
672   }
673   return SyntheticSymbolDependenciesMap();
674 }
675 
676 Error MachOPlatform::MachOPlatformPlugin::associateJITDylibHeaderSymbol(
677     jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
678   auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) {
679     return Sym->getName() == *MP.MachOHeaderStartSymbol;
680   });
681   assert(I != G.defined_symbols().end() && "Missing MachO header start symbol");
682 
683   auto &JD = MR.getTargetJITDylib();
684   std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
685   auto HeaderAddr = (*I)->getAddress();
686   MP.JITDylibToHeaderAddr[&JD] = HeaderAddr;
687   MP.HeaderAddrToJITDylib[HeaderAddr] = &JD;
688   G.allocActions().push_back(
689       {cantFail(
690            WrapperFunctionCall::Create<SPSArgList<SPSString, SPSExecutorAddr>>(
691                MP.orc_rt_macho_register_jitdylib, JD.getName(), HeaderAddr)),
692        cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(
693            MP.orc_rt_macho_deregister_jitdylib, HeaderAddr))});
694   return Error::success();
695 }
696 
697 Error MachOPlatform::MachOPlatformPlugin::preserveInitSections(
698     jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
699 
700   JITLinkSymbolSet InitSectionSymbols;
701   for (auto &InitSectionName : InitSectionNames) {
702     // Skip non-init sections.
703     auto *InitSection = G.findSectionByName(InitSectionName);
704     if (!InitSection)
705       continue;
706 
707     // Make a pass over live symbols in the section: those blocks are already
708     // preserved.
709     DenseSet<jitlink::Block *> AlreadyLiveBlocks;
710     for (auto &Sym : InitSection->symbols()) {
711       auto &B = Sym->getBlock();
712       if (Sym->isLive() && Sym->getOffset() == 0 &&
713           Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) {
714         InitSectionSymbols.insert(Sym);
715         AlreadyLiveBlocks.insert(&B);
716       }
717     }
718 
719     // Add anonymous symbols to preserve any not-already-preserved blocks.
720     for (auto *B : InitSection->blocks())
721       if (!AlreadyLiveBlocks.count(B))
722         InitSectionSymbols.insert(
723             &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true));
724   }
725 
726   if (!InitSectionSymbols.empty()) {
727     std::lock_guard<std::mutex> Lock(PluginMutex);
728     InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
729   }
730 
731   return Error::success();
732 }
733 
734 Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
735     jitlink::LinkGraph &G, MaterializationResponsibility &MR) {
736 
737   // If there's an ObjC imagine info then either
738   //   (1) It's the first __objc_imageinfo we've seen in this JITDylib. In
739   //       this case we name and record it.
740   // OR
741   //   (2) We already have a recorded __objc_imageinfo for this JITDylib,
742   //       in which case we just verify it.
743   auto *ObjCImageInfo = G.findSectionByName(ObjCImageInfoSectionName);
744   if (!ObjCImageInfo)
745     return Error::success();
746 
747   auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();
748 
749   // Check that the section is not empty if present.
750   if (llvm::empty(ObjCImageInfoBlocks))
751     return make_error<StringError>("Empty " + ObjCImageInfoSectionName +
752                                        " section in " + G.getName(),
753                                    inconvertibleErrorCode());
754 
755   // Check that there's only one block in the section.
756   if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
757     return make_error<StringError>("Multiple blocks in " +
758                                        ObjCImageInfoSectionName +
759                                        " section in " + G.getName(),
760                                    inconvertibleErrorCode());
761 
762   // Check that the __objc_imageinfo section is unreferenced.
763   // FIXME: We could optimize this check if Symbols had a ref-count.
764   for (auto &Sec : G.sections()) {
765     if (&Sec != ObjCImageInfo)
766       for (auto *B : Sec.blocks())
767         for (auto &E : B->edges())
768           if (E.getTarget().isDefined() &&
769               &E.getTarget().getBlock().getSection() == ObjCImageInfo)
770             return make_error<StringError>(ObjCImageInfoSectionName +
771                                                " is referenced within file " +
772                                                G.getName(),
773                                            inconvertibleErrorCode());
774   }
775 
776   auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin();
777   auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data();
778   auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness());
779   auto Flags =
780       support::endian::read32(ObjCImageInfoData + 4, G.getEndianness());
781 
782   // Lock the mutex while we verify / update the ObjCImageInfos map.
783   std::lock_guard<std::mutex> Lock(PluginMutex);
784 
785   auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib());
786   if (ObjCImageInfoItr != ObjCImageInfos.end()) {
787     // We've already registered an __objc_imageinfo section. Verify the
788     // content of this new section matches, then delete it.
789     if (ObjCImageInfoItr->second.first != Version)
790       return make_error<StringError>(
791           "ObjC version in " + G.getName() +
792               " does not match first registered version",
793           inconvertibleErrorCode());
794     if (ObjCImageInfoItr->second.second != Flags)
795       return make_error<StringError>("ObjC flags in " + G.getName() +
796                                          " do not match first registered flags",
797                                      inconvertibleErrorCode());
798 
799     // __objc_imageinfo is valid. Delete the block.
800     for (auto *S : ObjCImageInfo->symbols())
801       G.removeDefinedSymbol(*S);
802     G.removeBlock(ObjCImageInfoBlock);
803   } else {
804     // We haven't registered an __objc_imageinfo section yet. Register and
805     // move on. The section should already be marked no-dead-strip.
806     ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags);
807   }
808 
809   return Error::success();
810 }
811 
812 Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
813     jitlink::LinkGraph &G, JITDylib &JD) {
814 
815   // Rename external references to __tlv_bootstrap to ___orc_rt_tlv_get_addr.
816   for (auto *Sym : G.external_symbols())
817     if (Sym->getName() == "__tlv_bootstrap") {
818       Sym->setName("___orc_rt_macho_tlv_get_addr");
819       break;
820     }
821 
822   // Store key in __thread_vars struct fields.
823   if (auto *ThreadDataSec = G.findSectionByName(ThreadVarsSectionName)) {
824     Optional<uint64_t> Key;
825     {
826       std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
827       auto I = MP.JITDylibToPThreadKey.find(&JD);
828       if (I != MP.JITDylibToPThreadKey.end())
829         Key = I->second;
830     }
831 
832     if (!Key) {
833       if (auto KeyOrErr = MP.createPThreadKey())
834         Key = *KeyOrErr;
835       else
836         return KeyOrErr.takeError();
837     }
838 
839     uint64_t PlatformKeyBits =
840         support::endian::byte_swap(*Key, G.getEndianness());
841 
842     for (auto *B : ThreadDataSec->blocks()) {
843       if (B->getSize() != 3 * G.getPointerSize())
844         return make_error<StringError>("__thread_vars block at " +
845                                            formatv("{0:x}", B->getAddress()) +
846                                            " has unexpected size",
847                                        inconvertibleErrorCode());
848 
849       auto NewBlockContent = G.allocateBuffer(B->getSize());
850       llvm::copy(B->getContent(), NewBlockContent.data());
851       memcpy(NewBlockContent.data() + G.getPointerSize(), &PlatformKeyBits,
852              G.getPointerSize());
853       B->setContent(NewBlockContent);
854     }
855   }
856 
857   // Transform any TLV edges into GOT edges.
858   for (auto *B : G.blocks())
859     for (auto &E : B->edges())
860       if (E.getKind() ==
861           jitlink::x86_64::RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable)
862         E.setKind(jitlink::x86_64::
863                       RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable);
864 
865   return Error::success();
866 }
867 
868 Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
869     jitlink::LinkGraph &G, JITDylib &JD) {
870 
871   // Add an action to register the eh-frame.
872   if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) {
873     jitlink::SectionRange R(*EHFrameSection);
874     if (!R.empty())
875       G.allocActions().push_back(
876           {cantFail(
877                WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
878                    MP.orc_rt_macho_register_ehframe_section, R.getRange())),
879            cantFail(
880                WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
881                    MP.orc_rt_macho_deregister_ehframe_section, R.getRange()))});
882   }
883 
884   // Get a pointer to the thread data section if there is one. It will be used
885   // below.
886   jitlink::Section *ThreadDataSection =
887       G.findSectionByName(ThreadDataSectionName);
888 
889   // Handle thread BSS section if there is one.
890   if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
891     // If there's already a thread data section in this graph then merge the
892     // thread BSS section content into it, otherwise just treat the thread
893     // BSS section as the thread data section.
894     if (ThreadDataSection)
895       G.mergeSections(*ThreadDataSection, *ThreadBSSSection);
896     else
897       ThreadDataSection = ThreadBSSSection;
898   }
899 
900   SmallVector<std::pair<StringRef, ExecutorAddrRange>, 8> MachOPlatformSecs;
901 
902   // Having merged thread BSS (if present) and thread data (if present),
903   // record the resulting section range.
904   if (ThreadDataSection) {
905     jitlink::SectionRange R(*ThreadDataSection);
906     if (!R.empty()) {
907       if (MP.State != MachOPlatform::Initialized)
908         return make_error<StringError>("__thread_data section encountered, but "
909                                        "MachOPlatform has not finished booting",
910                                        inconvertibleErrorCode());
911 
912       MachOPlatformSecs.push_back({ThreadDataSectionName, R.getRange()});
913     }
914   }
915 
916   // If any platform sections were found then add an allocation action to call
917   // the registration function.
918   StringRef PlatformSections[] = {
919       ModInitFuncSectionName,   ObjCClassListSectionName,
920       ObjCImageInfoSectionName, ObjCSelRefsSectionName,
921       Swift5ProtoSectionName,   Swift5ProtosSectionName,
922       Swift5TypesSectionName,
923   };
924 
925   for (auto &SecName : PlatformSections) {
926     auto *Sec = G.findSectionByName(SecName);
927     if (!Sec)
928       continue;
929     jitlink::SectionRange R(*Sec);
930     if (R.empty())
931       continue;
932 
933     MachOPlatformSecs.push_back({SecName, R.getRange()});
934   }
935 
936   if (!MachOPlatformSecs.empty()) {
937     Optional<ExecutorAddr> HeaderAddr;
938     {
939       std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
940       auto I = MP.JITDylibToHeaderAddr.find(&JD);
941       if (I != MP.JITDylibToHeaderAddr.end())
942         HeaderAddr = I->second;
943     }
944 
945     if (!HeaderAddr)
946       return make_error<StringError>("Missing header for " + JD.getName(),
947                                      inconvertibleErrorCode());
948 
949     // Dump the scraped inits.
950     LLVM_DEBUG({
951       dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n";
952       for (auto &KV : MachOPlatformSecs)
953         dbgs() << "  " << KV.first << ": " << KV.second << "\n";
954     });
955 
956     using SPSRegisterObjectPlatformSectionsArgs =
957         SPSArgList<SPSExecutorAddr,
958                    SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>>;
959     G.allocActions().push_back(
960         {cantFail(
961              WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
962                  MP.orc_rt_macho_register_object_platform_sections, *HeaderAddr,
963                  MachOPlatformSecs)),
964          cantFail(
965              WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
966                  MP.orc_rt_macho_deregister_object_platform_sections,
967                  *HeaderAddr, MachOPlatformSecs))});
968   }
969 
970   return Error::success();
971 }
972 
973 Error MachOPlatform::MachOPlatformPlugin::registerEHSectionsPhase1(
974     jitlink::LinkGraph &G) {
975 
976   // If there's no eh-frame there's nothing to do.
977   auto *EHFrameSection = G.findSectionByName(EHFrameSectionName);
978   if (!EHFrameSection)
979     return Error::success();
980 
981   // If the eh-frame section is empty there's nothing to do.
982   jitlink::SectionRange R(*EHFrameSection);
983   if (R.empty())
984     return Error::success();
985 
986   // Since we're linking the object containing the registration code now the
987   // addresses won't be ready in the platform. We'll have to find them in this
988   // graph instead.
989   ExecutorAddr orc_rt_macho_register_ehframe_section;
990   ExecutorAddr orc_rt_macho_deregister_ehframe_section;
991   for (auto *Sym : G.defined_symbols()) {
992     if (!Sym->hasName())
993       continue;
994     if (Sym->getName() == "___orc_rt_macho_register_ehframe_section")
995       orc_rt_macho_register_ehframe_section = ExecutorAddr(Sym->getAddress());
996     else if (Sym->getName() == "___orc_rt_macho_deregister_ehframe_section")
997       orc_rt_macho_deregister_ehframe_section = ExecutorAddr(Sym->getAddress());
998 
999     if (orc_rt_macho_register_ehframe_section &&
1000         orc_rt_macho_deregister_ehframe_section)
1001       break;
1002   }
1003 
1004   // If we failed to find the required functions then bail out.
1005   if (!orc_rt_macho_register_ehframe_section ||
1006       !orc_rt_macho_deregister_ehframe_section)
1007     return make_error<StringError>("Could not find eh-frame registration "
1008                                    "functions during platform bootstrap",
1009                                    inconvertibleErrorCode());
1010 
1011   // Otherwise, add allocation actions to the graph to register eh-frames for
1012   // this object.
1013   G.allocActions().push_back(
1014       {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
1015            orc_rt_macho_register_ehframe_section, R.getRange())),
1016        cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
1017            orc_rt_macho_deregister_ehframe_section, R.getRange()))});
1018 
1019   return Error::success();
1020 }
1021 
1022 } // End namespace orc.
1023 } // End namespace llvm.
1024