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