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