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