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