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