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 ExecutorAddressRange &SE) {
93   if (SE.size().getValue() % sizeof(uintptr_t)) {
94     std::ostringstream ErrMsg;
95     ErrMsg << std::hex << "Size of " << SectionName << " 0x"
96            << SE.StartAddress.getValue() << " -- 0x" << SE.EndAddress.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<ExecutorAddressRange> &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.StartAddress.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<ExecutorAddressRange> &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<ExecutorAddressRange> &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.StartAddress.toPtr<const ProtocolRecord *>(),
183         Swift5Protocols.EndAddress.toPtr<const ProtocolRecord *>());
184 
185   return Error::success();
186 }
187 
188 Error registerSwift5ProtocolConformances(
189     const std::vector<ExecutorAddressRange> &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.StartAddress.toPtr<const ProtocolConformanceRecord *>(),
200         ProtoConfSec.EndAddress.toPtr<const ProtocolConformanceRecord *>());
201 
202   return Error::success();
203 }
204 
205 Error runModInits(const std::vector<ExecutorAddressRange> &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<ExecutorAddress> 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<ExecutorAddressRange> &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.StartAddress)
329     walkEHFrameSection(POSR.EHFrameSection.toSpan<const char>(),
330                        __register_frame);
331 
332   if (POSR.ThreadDataSection.StartAddress) {
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.StartAddress)
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<ExecutorAddress>
483 MachOPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle,
484                                                   string_view Sym) {
485   Expected<ExecutorAddress> Result((ExecutorAddress()));
486   if (auto Err = WrapperFunction<SPSExpected<SPSExecutorAddress>(
487           SPSExecutorAddress,
488           SPSString)>::call(&__orc_rt_macho_symbol_lookup_tag, Result,
489                             ExecutorAddress::fromPtr(DSOHandle), Sym))
490     return std::move(Err);
491   return Result;
492 }
493 
494 Expected<MachOJITDylibInitializerSequence>
495 MachOPlatformRuntimeState::getJITDylibInitializersByName(string_view Path) {
496   Expected<MachOJITDylibInitializerSequence> Result(
497       (MachOJITDylibInitializerSequence()));
498   std::string PathStr(Path.data(), Path.size());
499   if (auto Err =
500           WrapperFunction<SPSExpected<SPSMachOJITDylibInitializerSequence>(
501               SPSString)>::call(&__orc_rt_macho_get_initializers_tag, Result,
502                                 Path))
503     return std::move(Err);
504   return Result;
505 }
506 
507 Expected<void *> MachOPlatformRuntimeState::dlopenInitialize(string_view Path,
508                                                              int Mode) {
509   // Either our JITDylib wasn't loaded, or it or one of its dependencies allows
510   // reinitialization. We need to call in to the JIT to see if there's any new
511   // work pending.
512   auto InitSeq = getJITDylibInitializersByName(Path);
513   if (!InitSeq)
514     return InitSeq.takeError();
515 
516   // Init sequences should be non-empty.
517   if (InitSeq->empty())
518     return make_error<StringError>(
519         "__orc_rt_macho_get_initializers returned an "
520         "empty init sequence");
521 
522   // Otherwise register and run initializers for each JITDylib.
523   for (auto &MOJDIs : *InitSeq)
524     if (auto Err = initializeJITDylib(MOJDIs))
525       return std::move(Err);
526 
527   // Return the header for the last item in the list.
528   auto *JDS = getJITDylibStateByHeaderAddr(
529       InitSeq->back().MachOHeaderAddress.toPtr<void *>());
530   assert(JDS && "Missing state entry for JD");
531   return JDS->Header;
532 }
533 
534 Error MachOPlatformRuntimeState::initializeJITDylib(
535     MachOJITDylibInitializers &MOJDIs) {
536 
537   auto &JDS = getOrCreateJITDylibState(MOJDIs);
538   ++JDS.RefCount;
539 
540   for (auto &KV : InitSections) {
541     const auto &Name = KV.first;
542     const auto &Handler = KV.second;
543     auto I = MOJDIs.InitSections.find(Name);
544     if (I != MOJDIs.InitSections.end()) {
545       if (auto Err = Handler(I->second, MOJDIs))
546         return Err;
547     }
548   }
549 
550   return Error::success();
551 }
552 
553 class MachOPlatformRuntimeTLVManager {
554 public:
555   void *getInstance(const char *ThreadData);
556 
557 private:
558   std::unordered_map<const char *, char *> Instances;
559   std::unordered_map<const char *, std::unique_ptr<char[]>> AllocatedSections;
560 };
561 
562 void *MachOPlatformRuntimeTLVManager::getInstance(const char *ThreadData) {
563   auto I = Instances.find(ThreadData);
564   if (I != Instances.end())
565     return I->second;
566 
567   auto TDS =
568       MachOPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData);
569   if (!TDS) {
570     __orc_rt_log_error(toString(TDS.takeError()).c_str());
571     return nullptr;
572   }
573 
574   auto &Allocated = AllocatedSections[TDS->first];
575   if (!Allocated) {
576     Allocated = std::make_unique<char[]>(TDS->second);
577     memcpy(Allocated.get(), TDS->first, TDS->second);
578   }
579 
580   size_t ThreadDataDelta = ThreadData - TDS->first;
581   assert(ThreadDataDelta <= TDS->second && "ThreadData outside section bounds");
582 
583   char *Instance = Allocated.get() + ThreadDataDelta;
584   Instances[ThreadData] = Instance;
585   return Instance;
586 }
587 
588 void destroyMachOTLVMgr(void *MachOTLVMgr) {
589   delete static_cast<MachOPlatformRuntimeTLVManager *>(MachOTLVMgr);
590 }
591 
592 } // end anonymous namespace
593 
594 //------------------------------------------------------------------------------
595 //                             JIT entry points
596 //------------------------------------------------------------------------------
597 
598 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
599 __orc_rt_macho_platform_bootstrap(char *ArgData, size_t ArgSize) {
600   MachOPlatformRuntimeState::initialize();
601   return WrapperFunctionResult().release();
602 }
603 
604 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
605 __orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) {
606   MachOPlatformRuntimeState::destroy();
607   return WrapperFunctionResult().release();
608 }
609 
610 /// Wrapper function for registering metadata on a per-object basis.
611 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
612 __orc_rt_macho_register_object_sections(char *ArgData, size_t ArgSize) {
613   return WrapperFunction<SPSError(SPSMachOPerObjectSectionsToRegister)>::handle(
614              ArgData, ArgSize,
615              [](MachOPerObjectSectionsToRegister &POSR) {
616                return MachOPlatformRuntimeState::get().registerObjectSections(
617                    std::move(POSR));
618              })
619       .release();
620 }
621 
622 /// Wrapper for releasing per-object metadat.
623 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
624 __orc_rt_macho_deregister_object_sections(char *ArgData, size_t ArgSize) {
625   return WrapperFunction<SPSError(SPSMachOPerObjectSectionsToRegister)>::handle(
626              ArgData, ArgSize,
627              [](MachOPerObjectSectionsToRegister &POSR) {
628                return MachOPlatformRuntimeState::get().deregisterObjectSections(
629                    std::move(POSR));
630              })
631       .release();
632 }
633 
634 //------------------------------------------------------------------------------
635 //                            TLV support
636 //------------------------------------------------------------------------------
637 
638 ORC_RT_INTERFACE void *__orc_rt_macho_tlv_get_addr_impl(TLVDescriptor *D) {
639   auto *TLVMgr = static_cast<MachOPlatformRuntimeTLVManager *>(
640       pthread_getspecific(D->Key));
641   if (!TLVMgr) {
642     TLVMgr = new MachOPlatformRuntimeTLVManager();
643     if (pthread_setspecific(D->Key, TLVMgr)) {
644       __orc_rt_log_error("Call to pthread_setspecific failed");
645       return nullptr;
646     }
647   }
648 
649   return TLVMgr->getInstance(
650       reinterpret_cast<char *>(static_cast<uintptr_t>(D->DataAddress)));
651 }
652 
653 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
654 __orc_rt_macho_create_pthread_key(char *ArgData, size_t ArgSize) {
655   return WrapperFunction<SPSExpected<uint64_t>(void)>::handle(
656              ArgData, ArgSize,
657              []() -> Expected<uint64_t> {
658                pthread_key_t Key;
659                if (int Err = pthread_key_create(&Key, destroyMachOTLVMgr)) {
660                  __orc_rt_log_error("Call to pthread_key_create failed");
661                  return make_error<StringError>(strerror(Err));
662                }
663                return static_cast<uint64_t>(Key);
664              })
665       .release();
666 }
667 
668 //------------------------------------------------------------------------------
669 //                           cxa_atexit support
670 //------------------------------------------------------------------------------
671 
672 int __orc_rt_macho_cxa_atexit(void (*func)(void *), void *arg,
673                               void *dso_handle) {
674   return MachOPlatformRuntimeState::get().registerAtExit(func, arg, dso_handle);
675 }
676 
677 void __orc_rt_macho_cxa_finalize(void *dso_handle) {
678   MachOPlatformRuntimeState::get().runAtExits(dso_handle);
679 }
680 
681 //------------------------------------------------------------------------------
682 //                        JIT'd dlfcn alternatives.
683 //------------------------------------------------------------------------------
684 
685 const char *__orc_rt_macho_jit_dlerror() {
686   return MachOPlatformRuntimeState::get().dlerror();
687 }
688 
689 void *__orc_rt_macho_jit_dlopen(const char *path, int mode) {
690   return MachOPlatformRuntimeState::get().dlopen(path, mode);
691 }
692 
693 int __orc_rt_macho_jit_dlclose(void *dso_handle) {
694   return MachOPlatformRuntimeState::get().dlclose(dso_handle);
695 }
696 
697 void *__orc_rt_macho_jit_dlsym(void *dso_handle, const char *symbol) {
698   return MachOPlatformRuntimeState::get().dlsym(dso_handle, symbol);
699 }
700 
701 //------------------------------------------------------------------------------
702 //                             MachO Run Program
703 //------------------------------------------------------------------------------
704 
705 ORC_RT_INTERFACE int64_t __orc_rt_macho_run_program(const char *JITDylibName,
706                                                     const char *EntrySymbolName,
707                                                     int argc, char *argv[]) {
708   using MainTy = int (*)(int, char *[]);
709 
710   void *H = __orc_rt_macho_jit_dlopen(JITDylibName,
711                                       __orc_rt::macho::ORC_RT_RTLD_LAZY);
712   if (!H) {
713     __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
714     return -1;
715   }
716 
717   auto *Main =
718       reinterpret_cast<MainTy>(__orc_rt_macho_jit_dlsym(H, EntrySymbolName));
719 
720   if (!Main) {
721     __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
722     return -1;
723   }
724 
725   int Result = Main(argc, argv);
726 
727   if (__orc_rt_macho_jit_dlclose(H) == -1)
728     __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
729 
730   return Result;
731 }
732