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