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