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