1 //===- macho_platform.cpp -------------------------------------------------===//
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 // This file contains code required to load the rest of the MachO runtime.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "macho_platform.h"
14 #include "common.h"
15 #include "error.h"
16 #include "wrapper_function_utils.h"
17 
18 #include <map>
19 #include <mutex>
20 #include <sstream>
21 #include <unordered_map>
22 #include <vector>
23 
24 using namespace __orc_rt;
25 using namespace __orc_rt::macho;
26 
27 // Declare function tags for functions in the JIT process.
28 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_get_initializers_tag)
29 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_get_deinitializers_tag)
30 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_symbol_lookup_tag)
31 
32 // eh-frame registration functions.
33 // We expect these to be available for all processes.
34 extern "C" void __register_frame(const void *);
35 extern "C" void __deregister_frame(const void *);
36 
37 // Objective-C types.
38 struct objc_class;
39 struct objc_image_info;
40 struct objc_object;
41 struct objc_selector;
42 
43 using Class = objc_class *;
44 using id = objc_object *;
45 using SEL = objc_selector *;
46 
47 // Objective-C registration functions.
48 // These are weakly imported. If the Objective-C runtime has not been loaded
49 // then code containing Objective-C sections will generate an error.
50 extern "C" id objc_msgSend(id, SEL, ...) ORC_RT_WEAK_IMPORT;
51 extern "C" Class objc_readClassPair(Class,
52                                     const objc_image_info *) ORC_RT_WEAK_IMPORT;
53 extern "C" SEL sel_registerName(const char *) ORC_RT_WEAK_IMPORT;
54 
55 // Swift types.
56 class ProtocolRecord;
57 class ProtocolConformanceRecord;
58 
59 extern "C" void
60 swift_registerProtocols(const ProtocolRecord *begin,
61                         const ProtocolRecord *end) ORC_RT_WEAK_IMPORT;
62 
63 extern "C" void swift_registerProtocolConformances(
64     const ProtocolConformanceRecord *begin,
65     const ProtocolConformanceRecord *end) ORC_RT_WEAK_IMPORT;
66 
67 namespace {
68 
69 template <typename HandleFDEFn>
70 void walkEHFrameSection(span<const char> EHFrameSection,
71                         HandleFDEFn HandleFDE) {
72   const char *CurCFIRecord = EHFrameSection.data();
73   uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
74 
75   while (CurCFIRecord != EHFrameSection.end() && Size != 0) {
76     const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
77     if (Size == 0xffffffff)
78       Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
79     else
80       Size += 4;
81     uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
82 
83     if (Offset != 0)
84       HandleFDE(CurCFIRecord);
85 
86     CurCFIRecord += Size;
87     Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
88   }
89 }
90 
91 Error validatePointerSectionExtent(const char *SectionName,
92                                    const ExecutorAddrRange &SE) {
93   if (SE.size().getValue() % sizeof(uintptr_t)) {
94     std::ostringstream ErrMsg;
95     ErrMsg << std::hex << "Size of " << SectionName << " 0x"
96            << SE.Start.getValue() << " -- 0x" << SE.End.getValue()
97            << " is not a pointer multiple";
98     return make_error<StringError>(ErrMsg.str());
99   }
100   return Error::success();
101 }
102 
103 Error registerObjCSelectors(
104     const std::vector<ExecutorAddrRange> &ObjCSelRefsSections,
105     const MachOJITDylibInitializers &MOJDIs) {
106 
107   if (ORC_RT_UNLIKELY(!sel_registerName))
108     return make_error<StringError>("sel_registerName is not available");
109 
110   for (const auto &ObjCSelRefs : ObjCSelRefsSections) {
111 
112     if (auto Err = validatePointerSectionExtent("__objc_selrefs", ObjCSelRefs))
113       return Err;
114 
115     fprintf(stderr, "Processing selrefs section at 0x%llx\n",
116             ObjCSelRefs.Start.getValue());
117     for (uintptr_t SelEntry : ObjCSelRefs.toSpan<uintptr_t>()) {
118       const char *SelName = reinterpret_cast<const char *>(SelEntry);
119       fprintf(stderr, "Registering selector \"%s\"\n", SelName);
120       auto Sel = sel_registerName(SelName);
121       *reinterpret_cast<SEL *>(SelEntry) = Sel;
122     }
123   }
124 
125   return Error::success();
126 }
127 
128 Error registerObjCClasses(
129     const std::vector<ExecutorAddrRange> &ObjCClassListSections,
130     const MachOJITDylibInitializers &MOJDIs) {
131 
132   if (ObjCClassListSections.empty())
133     return Error::success();
134 
135   if (ORC_RT_UNLIKELY(!objc_msgSend))
136     return make_error<StringError>("objc_msgSend is not available");
137   if (ORC_RT_UNLIKELY(!objc_readClassPair))
138     return make_error<StringError>("objc_readClassPair is not available");
139 
140   struct ObjCClassCompiled {
141     void *Metaclass;
142     void *Parent;
143     void *Cache1;
144     void *Cache2;
145     void *Data;
146   };
147 
148   auto *ImageInfo =
149       MOJDIs.ObjCImageInfoAddress.toPtr<const objc_image_info *>();
150   auto ClassSelector = sel_registerName("class");
151 
152   for (const auto &ObjCClassList : ObjCClassListSections) {
153 
154     if (auto Err =
155             validatePointerSectionExtent("__objc_classlist", ObjCClassList))
156       return Err;
157 
158     for (uintptr_t ClassPtr : ObjCClassList.toSpan<uintptr_t>()) {
159       auto *Cls = reinterpret_cast<Class>(ClassPtr);
160       auto *ClassCompiled = reinterpret_cast<ObjCClassCompiled *>(ClassPtr);
161       objc_msgSend(reinterpret_cast<id>(ClassCompiled->Parent), ClassSelector);
162       auto Registered = objc_readClassPair(Cls, ImageInfo);
163 
164       // FIXME: Improve diagnostic by reporting the failed class's name.
165       if (Registered != Cls)
166         return make_error<StringError>("Unable to register Objective-C class");
167     }
168   }
169   return Error::success();
170 }
171 
172 Error registerSwift5Protocols(
173     const std::vector<ExecutorAddrRange> &Swift5ProtocolSections,
174     const MachOJITDylibInitializers &MOJDIs) {
175 
176   if (ORC_RT_UNLIKELY(!Swift5ProtocolSections.empty() &&
177                       !swift_registerProtocols))
178     return make_error<StringError>("swift_registerProtocols is not available");
179 
180   for (const auto &Swift5Protocols : Swift5ProtocolSections)
181     swift_registerProtocols(
182         Swift5Protocols.Start.toPtr<const ProtocolRecord *>(),
183         Swift5Protocols.End.toPtr<const ProtocolRecord *>());
184 
185   return Error::success();
186 }
187 
188 Error registerSwift5ProtocolConformances(
189     const std::vector<ExecutorAddrRange> &Swift5ProtocolConformanceSections,
190     const MachOJITDylibInitializers &MOJDIs) {
191 
192   if (ORC_RT_UNLIKELY(!Swift5ProtocolConformanceSections.empty() &&
193                       !swift_registerProtocolConformances))
194     return make_error<StringError>(
195         "swift_registerProtocolConformances is not available");
196 
197   for (const auto &ProtoConfSec : Swift5ProtocolConformanceSections)
198     swift_registerProtocolConformances(
199         ProtoConfSec.Start.toPtr<const ProtocolConformanceRecord *>(),
200         ProtoConfSec.End.toPtr<const ProtocolConformanceRecord *>());
201 
202   return Error::success();
203 }
204 
205 Error runModInits(const std::vector<ExecutorAddrRange> &ModInitsSections,
206                   const MachOJITDylibInitializers &MOJDIs) {
207 
208   for (const auto &ModInits : ModInitsSections) {
209     if (auto Err = validatePointerSectionExtent("__mod_inits", ModInits))
210       return Err;
211 
212     using InitFunc = void (*)();
213     for (auto *Init : ModInits.toSpan<InitFunc>())
214       (*Init)();
215   }
216 
217   return Error::success();
218 }
219 
220 struct TLVDescriptor {
221   void *(*Thunk)(TLVDescriptor *) = nullptr;
222   unsigned long Key = 0;
223   unsigned long DataAddress = 0;
224 };
225 
226 class MachOPlatformRuntimeState {
227 private:
228   struct AtExitEntry {
229     void (*Func)(void *);
230     void *Arg;
231   };
232 
233   using AtExitsVector = std::vector<AtExitEntry>;
234 
235   struct PerJITDylibState {
236     void *Header = nullptr;
237     size_t RefCount = 0;
238     bool AllowReinitialization = false;
239     AtExitsVector AtExits;
240   };
241 
242 public:
243   static void initialize();
244   static MachOPlatformRuntimeState &get();
245   static void destroy();
246 
247   MachOPlatformRuntimeState() = default;
248 
249   // Delete copy and move constructors.
250   MachOPlatformRuntimeState(const MachOPlatformRuntimeState &) = delete;
251   MachOPlatformRuntimeState &
252   operator=(const MachOPlatformRuntimeState &) = delete;
253   MachOPlatformRuntimeState(MachOPlatformRuntimeState &&) = delete;
254   MachOPlatformRuntimeState &operator=(MachOPlatformRuntimeState &&) = delete;
255 
256   Error registerObjectSections(MachOPerObjectSectionsToRegister POSR);
257   Error deregisterObjectSections(MachOPerObjectSectionsToRegister POSR);
258 
259   const char *dlerror();
260   void *dlopen(string_view Name, int Mode);
261   int dlclose(void *DSOHandle);
262   void *dlsym(void *DSOHandle, string_view Symbol);
263 
264   int registerAtExit(void (*F)(void *), void *Arg, void *DSOHandle);
265   void runAtExits(void *DSOHandle);
266 
267   /// Returns the base address of the section containing ThreadData.
268   Expected<std::pair<const char *, size_t>>
269   getThreadDataSectionFor(const char *ThreadData);
270 
271 private:
272   PerJITDylibState *getJITDylibStateByHeaderAddr(void *DSOHandle);
273   PerJITDylibState *getJITDylibStateByName(string_view Path);
274   PerJITDylibState &getOrCreateJITDylibState(MachOJITDylibInitializers &MOJDIs);
275 
276   Error registerThreadDataSection(span<const char> ThreadDataSec);
277 
278   Expected<ExecutorAddr> lookupSymbolInJITDylib(void *DSOHandle,
279                                                 string_view Symbol);
280 
281   Expected<MachOJITDylibInitializerSequence>
282   getJITDylibInitializersByName(string_view Path);
283   Expected<void *> dlopenInitialize(string_view Path, int Mode);
284   Error initializeJITDylib(MachOJITDylibInitializers &MOJDIs);
285 
286   static MachOPlatformRuntimeState *MOPS;
287 
288   using InitSectionHandler =
289       Error (*)(const std::vector<ExecutorAddrRange> &Sections,
290                 const MachOJITDylibInitializers &MOJDIs);
291   const std::vector<std::pair<const char *, InitSectionHandler>> InitSections =
292       {{"__DATA,__objc_selrefs", registerObjCSelectors},
293        {"__DATA,__objc_classlist", registerObjCClasses},
294        {"__TEXT,__swift5_protos", registerSwift5Protocols},
295        {"__TEXT,__swift5_proto", registerSwift5ProtocolConformances},
296        {"__DATA,__mod_init_func", runModInits}};
297 
298   // FIXME: Move to thread-state.
299   std::string DLFcnError;
300 
301   std::recursive_mutex JDStatesMutex;
302   std::unordered_map<void *, PerJITDylibState> JDStates;
303   std::unordered_map<std::string, void *> JDNameToHeader;
304 
305   std::mutex ThreadDataSectionsMutex;
306   std::map<const char *, size_t> ThreadDataSections;
307 };
308 
309 MachOPlatformRuntimeState *MachOPlatformRuntimeState::MOPS = nullptr;
310 
311 void MachOPlatformRuntimeState::initialize() {
312   assert(!MOPS && "MachOPlatformRuntimeState should be null");
313   MOPS = new MachOPlatformRuntimeState();
314 }
315 
316 MachOPlatformRuntimeState &MachOPlatformRuntimeState::get() {
317   assert(MOPS && "MachOPlatformRuntimeState not initialized");
318   return *MOPS;
319 }
320 
321 void MachOPlatformRuntimeState::destroy() {
322   assert(MOPS && "MachOPlatformRuntimeState not initialized");
323   delete MOPS;
324 }
325 
326 Error MachOPlatformRuntimeState::registerObjectSections(
327     MachOPerObjectSectionsToRegister POSR) {
328   if (POSR.EHFrameSection.Start)
329     walkEHFrameSection(POSR.EHFrameSection.toSpan<const char>(),
330                        __register_frame);
331 
332   if (POSR.ThreadDataSection.Start) {
333     if (auto Err = registerThreadDataSection(
334             POSR.ThreadDataSection.toSpan<const char>()))
335       return Err;
336   }
337 
338   return Error::success();
339 }
340 
341 Error MachOPlatformRuntimeState::deregisterObjectSections(
342     MachOPerObjectSectionsToRegister POSR) {
343   if (POSR.EHFrameSection.Start)
344     walkEHFrameSection(POSR.EHFrameSection.toSpan<const char>(),
345                        __deregister_frame);
346 
347   return Error::success();
348 }
349 
350 const char *MachOPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); }
351 
352 void *MachOPlatformRuntimeState::dlopen(string_view Path, int Mode) {
353   std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
354 
355   // Use fast path if all JITDylibs are already loaded and don't require
356   // re-running initializers.
357   if (auto *JDS = getJITDylibStateByName(Path)) {
358     if (!JDS->AllowReinitialization) {
359       ++JDS->RefCount;
360       return JDS->Header;
361     }
362   }
363 
364   auto H = dlopenInitialize(Path, Mode);
365   if (!H) {
366     DLFcnError = toString(H.takeError());
367     return nullptr;
368   }
369 
370   return *H;
371 }
372 
373 int MachOPlatformRuntimeState::dlclose(void *DSOHandle) {
374   runAtExits(DSOHandle);
375   return 0;
376 }
377 
378 void *MachOPlatformRuntimeState::dlsym(void *DSOHandle, string_view Symbol) {
379   auto Addr = lookupSymbolInJITDylib(DSOHandle, Symbol);
380   if (!Addr) {
381     DLFcnError = toString(Addr.takeError());
382     return 0;
383   }
384 
385   return Addr->toPtr<void *>();
386 }
387 
388 int MachOPlatformRuntimeState::registerAtExit(void (*F)(void *), void *Arg,
389                                               void *DSOHandle) {
390   // FIXME: Handle out-of-memory errors, returning -1 if OOM.
391   std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
392   auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);
393   assert(JDS && "JITDylib state not initialized");
394   JDS->AtExits.push_back({F, Arg});
395   return 0;
396 }
397 
398 void MachOPlatformRuntimeState::runAtExits(void *DSOHandle) {
399   // FIXME: Should atexits be allowed to run concurrently with access to
400   // JDState?
401   AtExitsVector V;
402   {
403     std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
404     auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);
405     assert(JDS && "JITDlybi state not initialized");
406     std::swap(V, JDS->AtExits);
407   }
408 
409   while (!V.empty()) {
410     auto &AE = V.back();
411     AE.Func(AE.Arg);
412     V.pop_back();
413   }
414 }
415 
416 Expected<std::pair<const char *, size_t>>
417 MachOPlatformRuntimeState::getThreadDataSectionFor(const char *ThreadData) {
418   std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
419   auto I = ThreadDataSections.upper_bound(ThreadData);
420   // Check that we have a valid entry covering this address.
421   if (I == ThreadDataSections.begin())
422     return make_error<StringError>("No thread local data section for key");
423   I = std::prev(I);
424   if (ThreadData >= I->first + I->second)
425     return make_error<StringError>("No thread local data section for key");
426   return *I;
427 }
428 
429 MachOPlatformRuntimeState::PerJITDylibState *
430 MachOPlatformRuntimeState::getJITDylibStateByHeaderAddr(void *DSOHandle) {
431   auto I = JDStates.find(DSOHandle);
432   if (I == JDStates.end())
433     return nullptr;
434   return &I->second;
435 }
436 
437 MachOPlatformRuntimeState::PerJITDylibState *
438 MachOPlatformRuntimeState::getJITDylibStateByName(string_view Name) {
439   // FIXME: Avoid creating string copy here.
440   auto I = JDNameToHeader.find(std::string(Name.data(), Name.size()));
441   if (I == JDNameToHeader.end())
442     return nullptr;
443   void *H = I->second;
444   auto J = JDStates.find(H);
445   assert(J != JDStates.end() &&
446          "JITDylib has name map entry but no header map entry");
447   return &J->second;
448 }
449 
450 MachOPlatformRuntimeState::PerJITDylibState &
451 MachOPlatformRuntimeState::getOrCreateJITDylibState(
452     MachOJITDylibInitializers &MOJDIs) {
453   void *Header = MOJDIs.MachOHeaderAddress.toPtr<void *>();
454 
455   auto &JDS = JDStates[Header];
456 
457   // If this entry hasn't been created yet.
458   if (!JDS.Header) {
459     assert(!JDNameToHeader.count(MOJDIs.Name) &&
460            "JITDylib has header map entry but no name map entry");
461     JDNameToHeader[MOJDIs.Name] = Header;
462     JDS.Header = Header;
463   }
464 
465   return JDS;
466 }
467 
468 Error MachOPlatformRuntimeState::registerThreadDataSection(
469     span<const char> ThreadDataSection) {
470   std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
471   auto I = ThreadDataSections.upper_bound(ThreadDataSection.data());
472   if (I != ThreadDataSections.begin()) {
473     auto J = std::prev(I);
474     if (J->first + J->second > ThreadDataSection.data())
475       return make_error<StringError>("Overlapping __thread_data sections");
476   }
477   ThreadDataSections.insert(
478       I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size()));
479   return Error::success();
480 }
481 
482 Expected<ExecutorAddr>
483 MachOPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle,
484                                                   string_view Sym) {
485   Expected<ExecutorAddr> Result((ExecutorAddr()));
486   if (auto Err = WrapperFunction<SPSExpected<SPSExecutorAddr>(
487           SPSExecutorAddr, SPSString)>::call(&__orc_rt_macho_symbol_lookup_tag,
488                                              Result,
489                                              ExecutorAddr::fromPtr(DSOHandle),
490                                              Sym))
491     return std::move(Err);
492   return Result;
493 }
494 
495 Expected<MachOJITDylibInitializerSequence>
496 MachOPlatformRuntimeState::getJITDylibInitializersByName(string_view Path) {
497   Expected<MachOJITDylibInitializerSequence> Result(
498       (MachOJITDylibInitializerSequence()));
499   std::string PathStr(Path.data(), Path.size());
500   if (auto Err =
501           WrapperFunction<SPSExpected<SPSMachOJITDylibInitializerSequence>(
502               SPSString)>::call(&__orc_rt_macho_get_initializers_tag, Result,
503                                 Path))
504     return std::move(Err);
505   return Result;
506 }
507 
508 Expected<void *> MachOPlatformRuntimeState::dlopenInitialize(string_view Path,
509                                                              int Mode) {
510   // Either our JITDylib wasn't loaded, or it or one of its dependencies allows
511   // reinitialization. We need to call in to the JIT to see if there's any new
512   // work pending.
513   auto InitSeq = getJITDylibInitializersByName(Path);
514   if (!InitSeq)
515     return InitSeq.takeError();
516 
517   // Init sequences should be non-empty.
518   if (InitSeq->empty())
519     return make_error<StringError>(
520         "__orc_rt_macho_get_initializers returned an "
521         "empty init sequence");
522 
523   // Otherwise register and run initializers for each JITDylib.
524   for (auto &MOJDIs : *InitSeq)
525     if (auto Err = initializeJITDylib(MOJDIs))
526       return std::move(Err);
527 
528   // Return the header for the last item in the list.
529   auto *JDS = getJITDylibStateByHeaderAddr(
530       InitSeq->back().MachOHeaderAddress.toPtr<void *>());
531   assert(JDS && "Missing state entry for JD");
532   return JDS->Header;
533 }
534 
535 Error MachOPlatformRuntimeState::initializeJITDylib(
536     MachOJITDylibInitializers &MOJDIs) {
537 
538   auto &JDS = getOrCreateJITDylibState(MOJDIs);
539   ++JDS.RefCount;
540 
541   for (auto &KV : InitSections) {
542     const auto &Name = KV.first;
543     const auto &Handler = KV.second;
544     auto I = MOJDIs.InitSections.find(Name);
545     if (I != MOJDIs.InitSections.end()) {
546       if (auto Err = Handler(I->second, MOJDIs))
547         return Err;
548     }
549   }
550 
551   return Error::success();
552 }
553 
554 class MachOPlatformRuntimeTLVManager {
555 public:
556   void *getInstance(const char *ThreadData);
557 
558 private:
559   std::unordered_map<const char *, char *> Instances;
560   std::unordered_map<const char *, std::unique_ptr<char[]>> AllocatedSections;
561 };
562 
563 void *MachOPlatformRuntimeTLVManager::getInstance(const char *ThreadData) {
564   auto I = Instances.find(ThreadData);
565   if (I != Instances.end())
566     return I->second;
567 
568   auto TDS =
569       MachOPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData);
570   if (!TDS) {
571     __orc_rt_log_error(toString(TDS.takeError()).c_str());
572     return nullptr;
573   }
574 
575   auto &Allocated = AllocatedSections[TDS->first];
576   if (!Allocated) {
577     Allocated = std::make_unique<char[]>(TDS->second);
578     memcpy(Allocated.get(), TDS->first, TDS->second);
579   }
580 
581   size_t ThreadDataDelta = ThreadData - TDS->first;
582   assert(ThreadDataDelta <= TDS->second && "ThreadData outside section bounds");
583 
584   char *Instance = Allocated.get() + ThreadDataDelta;
585   Instances[ThreadData] = Instance;
586   return Instance;
587 }
588 
589 void destroyMachOTLVMgr(void *MachOTLVMgr) {
590   delete static_cast<MachOPlatformRuntimeTLVManager *>(MachOTLVMgr);
591 }
592 
593 } // end anonymous namespace
594 
595 //------------------------------------------------------------------------------
596 //                             JIT entry points
597 //------------------------------------------------------------------------------
598 
599 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
600 __orc_rt_macho_platform_bootstrap(char *ArgData, size_t ArgSize) {
601   MachOPlatformRuntimeState::initialize();
602   return WrapperFunctionResult().release();
603 }
604 
605 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
606 __orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) {
607   MachOPlatformRuntimeState::destroy();
608   return WrapperFunctionResult().release();
609 }
610 
611 /// Wrapper function for registering metadata on a per-object basis.
612 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
613 __orc_rt_macho_register_object_sections(char *ArgData, size_t ArgSize) {
614   return WrapperFunction<SPSError(SPSMachOPerObjectSectionsToRegister)>::handle(
615              ArgData, ArgSize,
616              [](MachOPerObjectSectionsToRegister &POSR) {
617                return MachOPlatformRuntimeState::get().registerObjectSections(
618                    std::move(POSR));
619              })
620       .release();
621 }
622 
623 /// Wrapper for releasing per-object metadat.
624 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
625 __orc_rt_macho_deregister_object_sections(char *ArgData, size_t ArgSize) {
626   return WrapperFunction<SPSError(SPSMachOPerObjectSectionsToRegister)>::handle(
627              ArgData, ArgSize,
628              [](MachOPerObjectSectionsToRegister &POSR) {
629                return MachOPlatformRuntimeState::get().deregisterObjectSections(
630                    std::move(POSR));
631              })
632       .release();
633 }
634 
635 //------------------------------------------------------------------------------
636 //                            TLV support
637 //------------------------------------------------------------------------------
638 
639 ORC_RT_INTERFACE void *__orc_rt_macho_tlv_get_addr_impl(TLVDescriptor *D) {
640   auto *TLVMgr = static_cast<MachOPlatformRuntimeTLVManager *>(
641       pthread_getspecific(D->Key));
642   if (!TLVMgr) {
643     TLVMgr = new MachOPlatformRuntimeTLVManager();
644     if (pthread_setspecific(D->Key, TLVMgr)) {
645       __orc_rt_log_error("Call to pthread_setspecific failed");
646       return nullptr;
647     }
648   }
649 
650   return TLVMgr->getInstance(
651       reinterpret_cast<char *>(static_cast<uintptr_t>(D->DataAddress)));
652 }
653 
654 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
655 __orc_rt_macho_create_pthread_key(char *ArgData, size_t ArgSize) {
656   return WrapperFunction<SPSExpected<uint64_t>(void)>::handle(
657              ArgData, ArgSize,
658              []() -> Expected<uint64_t> {
659                pthread_key_t Key;
660                if (int Err = pthread_key_create(&Key, destroyMachOTLVMgr)) {
661                  __orc_rt_log_error("Call to pthread_key_create failed");
662                  return make_error<StringError>(strerror(Err));
663                }
664                return static_cast<uint64_t>(Key);
665              })
666       .release();
667 }
668 
669 //------------------------------------------------------------------------------
670 //                           cxa_atexit support
671 //------------------------------------------------------------------------------
672 
673 int __orc_rt_macho_cxa_atexit(void (*func)(void *), void *arg,
674                               void *dso_handle) {
675   return MachOPlatformRuntimeState::get().registerAtExit(func, arg, dso_handle);
676 }
677 
678 void __orc_rt_macho_cxa_finalize(void *dso_handle) {
679   MachOPlatformRuntimeState::get().runAtExits(dso_handle);
680 }
681 
682 //------------------------------------------------------------------------------
683 //                        JIT'd dlfcn alternatives.
684 //------------------------------------------------------------------------------
685 
686 const char *__orc_rt_macho_jit_dlerror() {
687   return MachOPlatformRuntimeState::get().dlerror();
688 }
689 
690 void *__orc_rt_macho_jit_dlopen(const char *path, int mode) {
691   return MachOPlatformRuntimeState::get().dlopen(path, mode);
692 }
693 
694 int __orc_rt_macho_jit_dlclose(void *dso_handle) {
695   return MachOPlatformRuntimeState::get().dlclose(dso_handle);
696 }
697 
698 void *__orc_rt_macho_jit_dlsym(void *dso_handle, const char *symbol) {
699   return MachOPlatformRuntimeState::get().dlsym(dso_handle, symbol);
700 }
701 
702 //------------------------------------------------------------------------------
703 //                             MachO Run Program
704 //------------------------------------------------------------------------------
705 
706 ORC_RT_INTERFACE int64_t __orc_rt_macho_run_program(const char *JITDylibName,
707                                                     const char *EntrySymbolName,
708                                                     int argc, char *argv[]) {
709   using MainTy = int (*)(int, char *[]);
710 
711   void *H = __orc_rt_macho_jit_dlopen(JITDylibName,
712                                       __orc_rt::macho::ORC_RT_RTLD_LAZY);
713   if (!H) {
714     __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
715     return -1;
716   }
717 
718   auto *Main =
719       reinterpret_cast<MainTy>(__orc_rt_macho_jit_dlsym(H, EntrySymbolName));
720 
721   if (!Main) {
722     __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
723     return -1;
724   }
725 
726   int Result = Main(argc, argv);
727 
728   if (__orc_rt_macho_jit_dlclose(H) == -1)
729     __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
730 
731   return Result;
732 }
733