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 "bitmask_enum.h" 15 #include "common.h" 16 #include "debug.h" 17 #include "error.h" 18 #include "interval_map.h" 19 #include "jit_dispatch.h" 20 #include "record_section_tracker.h" 21 #include "wrapper_function_utils.h" 22 23 #include <algorithm> 24 #include <ios> 25 #include <map> 26 #include <mutex> 27 #include <sstream> 28 #include <string_view> 29 #include <unordered_map> 30 #include <unordered_set> 31 #include <vector> 32 33 #define DEBUG_TYPE "macho_platform" 34 35 using namespace orc_rt; 36 using namespace orc_rt::macho; 37 38 // Declare function tags for functions in the JIT process. 39 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_push_initializers_tag) 40 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_push_symbols_tag) 41 42 struct objc_image_info; 43 struct mach_header; 44 45 // Objective-C registration functions. 46 // These are weakly imported. If the Objective-C runtime has not been loaded 47 // then code containing Objective-C sections will generate an error. 48 extern "C" void 49 _objc_map_images(unsigned count, const char *const paths[], 50 const mach_header *const mhdrs[]) ORC_RT_WEAK_IMPORT; 51 52 extern "C" void _objc_load_image(const char *path, 53 const mach_header *mh) ORC_RT_WEAK_IMPORT; 54 55 // Libunwind prototypes. 56 struct unw_dynamic_unwind_sections { 57 uintptr_t dso_base; 58 uintptr_t dwarf_section; 59 size_t dwarf_section_length; 60 uintptr_t compact_unwind_section; 61 size_t compact_unwind_section_length; 62 }; 63 64 typedef int (*unw_find_dynamic_unwind_sections)( 65 uintptr_t addr, struct unw_dynamic_unwind_sections *info); 66 67 extern "C" int __unw_add_find_dynamic_unwind_sections( 68 unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) 69 ORC_RT_WEAK_IMPORT; 70 71 extern "C" int __unw_remove_find_dynamic_unwind_sections( 72 unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) 73 ORC_RT_WEAK_IMPORT; 74 75 namespace { 76 77 struct MachOJITDylibDepInfo { 78 bool Sealed = false; 79 std::vector<ExecutorAddr> DepHeaders; 80 }; 81 82 using MachOJITDylibDepInfoMap = 83 std::unordered_map<ExecutorAddr, MachOJITDylibDepInfo>; 84 85 } // anonymous namespace 86 87 namespace orc_rt { 88 89 using SPSMachOObjectPlatformSectionsMap = 90 SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>; 91 92 using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>; 93 94 using SPSMachOJITDylibDepInfoMap = 95 SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>; 96 97 template <> 98 class SPSSerializationTraits<SPSMachOJITDylibDepInfo, MachOJITDylibDepInfo> { 99 public: 100 static size_t size(const MachOJITDylibDepInfo &JDI) { 101 return SPSMachOJITDylibDepInfo::AsArgList::size(JDI.Sealed, JDI.DepHeaders); 102 } 103 104 static bool serialize(SPSOutputBuffer &OB, const MachOJITDylibDepInfo &JDI) { 105 return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, JDI.Sealed, 106 JDI.DepHeaders); 107 } 108 109 static bool deserialize(SPSInputBuffer &IB, MachOJITDylibDepInfo &JDI) { 110 return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, JDI.Sealed, 111 JDI.DepHeaders); 112 } 113 }; 114 115 struct UnwindSectionInfo { 116 std::vector<ExecutorAddrRange> CodeRanges; 117 ExecutorAddrRange DwarfSection; 118 ExecutorAddrRange CompactUnwindSection; 119 }; 120 121 using SPSUnwindSectionInfo = 122 SPSTuple<SPSSequence<SPSExecutorAddrRange>, SPSExecutorAddrRange, 123 SPSExecutorAddrRange>; 124 125 template <> 126 class SPSSerializationTraits<SPSUnwindSectionInfo, UnwindSectionInfo> { 127 public: 128 static size_t size(const UnwindSectionInfo &USI) { 129 return SPSUnwindSectionInfo::AsArgList::size( 130 USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection); 131 } 132 133 static bool serialize(SPSOutputBuffer &OB, const UnwindSectionInfo &USI) { 134 return SPSUnwindSectionInfo::AsArgList::serialize( 135 OB, USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection); 136 } 137 138 static bool deserialize(SPSInputBuffer &IB, UnwindSectionInfo &USI) { 139 return SPSUnwindSectionInfo::AsArgList::deserialize( 140 IB, USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection); 141 } 142 }; 143 144 } // namespace orc_rt 145 146 namespace { 147 struct TLVDescriptor { 148 void *(*Thunk)(TLVDescriptor *) = nullptr; 149 unsigned long Key = 0; 150 unsigned long DataAddress = 0; 151 }; 152 153 class MachOPlatformRuntimeState { 154 public: 155 // Used internally by MachOPlatformRuntimeState, but made public to enable 156 // serialization. 157 enum class MachOExecutorSymbolFlags : uint8_t { 158 None = 0, 159 Weak = 1U << 0, 160 Callable = 1U << 1, 161 ORC_RT_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Callable) 162 }; 163 164 private: 165 struct AtExitEntry { 166 void (*Func)(void *); 167 void *Arg; 168 }; 169 170 using AtExitsVector = std::vector<AtExitEntry>; 171 172 struct UnwindSections { 173 UnwindSections(const UnwindSectionInfo &USI) 174 : DwarfSection(USI.DwarfSection.toSpan<char>()), 175 CompactUnwindSection(USI.CompactUnwindSection.toSpan<char>()) {} 176 177 span<char> DwarfSection; 178 span<char> CompactUnwindSection; 179 }; 180 181 using UnwindSectionsMap = 182 IntervalMap<char *, UnwindSections, IntervalCoalescing::Disabled>; 183 184 struct JITDylibState { 185 186 using SymbolTableMap = 187 std::unordered_map<std::string_view, 188 std::pair<ExecutorAddr, MachOExecutorSymbolFlags>>; 189 190 std::string Name; 191 void *Header = nullptr; 192 bool Sealed = false; 193 size_t LinkedAgainstRefCount = 0; 194 size_t DlRefCount = 0; 195 SymbolTableMap SymbolTable; 196 std::vector<JITDylibState *> Deps; 197 AtExitsVector AtExits; 198 const objc_image_info *ObjCImageInfo = nullptr; 199 std::unordered_map<void *, std::vector<char>> DataSectionContent; 200 std::unordered_map<void *, size_t> ZeroInitRanges; 201 UnwindSectionsMap UnwindSections; 202 RecordSectionsTracker<void (*)()> ModInitsSections; 203 RecordSectionsTracker<char> ObjCRuntimeRegistrationObjects; 204 205 bool referenced() const { 206 return LinkedAgainstRefCount != 0 || DlRefCount != 0; 207 } 208 }; 209 210 public: 211 static Error create(); 212 static MachOPlatformRuntimeState &get(); 213 static Error destroy(); 214 215 MachOPlatformRuntimeState() = default; 216 217 // Delete copy and move constructors. 218 MachOPlatformRuntimeState(const MachOPlatformRuntimeState &) = delete; 219 MachOPlatformRuntimeState & 220 operator=(const MachOPlatformRuntimeState &) = delete; 221 MachOPlatformRuntimeState(MachOPlatformRuntimeState &&) = delete; 222 MachOPlatformRuntimeState &operator=(MachOPlatformRuntimeState &&) = delete; 223 224 Error initialize(); 225 Error shutdown(); 226 227 Error registerJITDylib(std::string Name, void *Header); 228 Error deregisterJITDylib(void *Header); 229 Error registerThreadDataSection(span<const char> ThreadDataSection); 230 Error deregisterThreadDataSection(span<const char> ThreadDataSection); 231 Error registerObjectSymbolTable( 232 ExecutorAddr HeaderAddr, 233 const std::vector<std::tuple<ExecutorAddr, ExecutorAddr, 234 MachOExecutorSymbolFlags>> &Entries); 235 Error deregisterObjectSymbolTable( 236 ExecutorAddr HeaderAddr, 237 const std::vector<std::tuple<ExecutorAddr, ExecutorAddr, 238 MachOExecutorSymbolFlags>> &Entries); 239 Error registerObjectPlatformSections( 240 ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindSections, 241 std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs); 242 Error deregisterObjectPlatformSections( 243 ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindSections, 244 std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs); 245 246 const char *dlerror(); 247 void *dlopen(std::string_view Name, int Mode); 248 int dlupdate(void *DSOHandle); 249 int dlclose(void *DSOHandle); 250 void *dlsym(void *DSOHandle, const char *Symbol); 251 252 int registerAtExit(void (*F)(void *), void *Arg, void *DSOHandle); 253 void runAtExits(std::unique_lock<std::mutex> &JDStatesLock, 254 JITDylibState &JDS); 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 JITDylibState *getJITDylibStateByHeader(void *DSOHandle); 263 JITDylibState *getJITDylibStateByName(std::string_view Path); 264 265 /// Requests materialization of the given symbols. For each pair, the bool 266 /// element indicates whether the symbol is required (true) or weakly 267 /// referenced (false). 268 Error requestPushSymbols(JITDylibState &JDS, 269 span<std::pair<std::string_view, bool>> Symbols); 270 271 /// Attempts to look up the given symbols locally, requesting a push from the 272 /// remote if they're not found. Results are written to the Result span, which 273 /// must have the same size as the Symbols span. 274 Error 275 lookupSymbols(JITDylibState &JDS, std::unique_lock<std::mutex> &JDStatesLock, 276 span<std::pair<ExecutorAddr, MachOExecutorSymbolFlags>> Result, 277 span<std::pair<std::string_view, bool>> Symbols); 278 279 bool lookupUnwindSections(void *Addr, unw_dynamic_unwind_sections &Info); 280 281 static int findDynamicUnwindSections(uintptr_t addr, 282 unw_dynamic_unwind_sections *info); 283 static Error registerEHFrames(span<const char> EHFrameSection); 284 static Error deregisterEHFrames(span<const char> EHFrameSection); 285 286 static Error 287 registerObjCRegistrationObjects(std::unique_lock<std::mutex> &JDStatesLock, 288 JITDylibState &JDS); 289 static Error runModInits(std::unique_lock<std::mutex> &JDStatesLock, 290 JITDylibState &JDS); 291 292 Expected<void *> dlopenImpl(std::string_view Path, int Mode); 293 Error dlopenFull(std::unique_lock<std::mutex> &JDStatesLock, 294 JITDylibState &JDS); 295 Error dlopenInitialize(std::unique_lock<std::mutex> &JDStatesLock, 296 JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo); 297 298 Error dlupdateImpl(void *DSOHandle); 299 Error dlupdateFull(std::unique_lock<std::mutex> &JDStatesLock, 300 JITDylibState &JDS); 301 Error dlupdateInitialize(std::unique_lock<std::mutex> &JDStatesLock, 302 JITDylibState &JDS); 303 304 Error dlcloseImpl(void *DSOHandle); 305 Error dlcloseDeinitialize(std::unique_lock<std::mutex> &JDStatesLock, 306 JITDylibState &JDS); 307 308 static MachOPlatformRuntimeState *MOPS; 309 310 bool UseCallbackStyleUnwindInfo = false; 311 312 // FIXME: Move to thread-state. 313 std::string DLFcnError; 314 315 // APIMutex guards against concurrent entry into key "dyld" API functions 316 // (e.g. dlopen, dlclose). 317 std::recursive_mutex DyldAPIMutex; 318 319 // JDStatesMutex guards the data structures that hold JITDylib state. 320 std::mutex JDStatesMutex; 321 std::unordered_map<void *, JITDylibState> JDStates; 322 std::unordered_map<std::string_view, void *> JDNameToHeader; 323 324 // ThreadDataSectionsMutex guards thread local data section state. 325 std::mutex ThreadDataSectionsMutex; 326 std::map<const char *, size_t> ThreadDataSections; 327 }; 328 329 } // anonymous namespace 330 331 namespace orc_rt { 332 333 class SPSMachOExecutorSymbolFlags; 334 335 template <> 336 class SPSSerializationTraits< 337 SPSMachOExecutorSymbolFlags, 338 MachOPlatformRuntimeState::MachOExecutorSymbolFlags> { 339 private: 340 using UT = std::underlying_type_t< 341 MachOPlatformRuntimeState::MachOExecutorSymbolFlags>; 342 343 public: 344 static size_t 345 size(const MachOPlatformRuntimeState::MachOExecutorSymbolFlags &SF) { 346 return sizeof(UT); 347 } 348 349 static bool 350 serialize(SPSOutputBuffer &OB, 351 const MachOPlatformRuntimeState::MachOExecutorSymbolFlags &SF) { 352 return SPSArgList<UT>::serialize(OB, static_cast<UT>(SF)); 353 } 354 355 static bool 356 deserialize(SPSInputBuffer &IB, 357 MachOPlatformRuntimeState::MachOExecutorSymbolFlags &SF) { 358 UT Tmp; 359 if (!SPSArgList<UT>::deserialize(IB, Tmp)) 360 return false; 361 SF = static_cast<MachOPlatformRuntimeState::MachOExecutorSymbolFlags>(Tmp); 362 return true; 363 } 364 }; 365 366 } // namespace orc_rt 367 368 namespace { 369 370 MachOPlatformRuntimeState *MachOPlatformRuntimeState::MOPS = nullptr; 371 372 Error MachOPlatformRuntimeState::create() { 373 assert(!MOPS && "MachOPlatformRuntimeState should be null"); 374 MOPS = new MachOPlatformRuntimeState(); 375 return MOPS->initialize(); 376 } 377 378 MachOPlatformRuntimeState &MachOPlatformRuntimeState::get() { 379 assert(MOPS && "MachOPlatformRuntimeState not initialized"); 380 return *MOPS; 381 } 382 383 Error MachOPlatformRuntimeState::destroy() { 384 assert(MOPS && "MachOPlatformRuntimeState not initialized"); 385 auto Err = MOPS->shutdown(); 386 delete MOPS; 387 return Err; 388 } 389 390 Error MachOPlatformRuntimeState::initialize() { 391 UseCallbackStyleUnwindInfo = __unw_add_find_dynamic_unwind_sections && 392 __unw_remove_find_dynamic_unwind_sections; 393 if (UseCallbackStyleUnwindInfo) { 394 ORC_RT_DEBUG({ 395 printdbg("__unw_add/remove_find_dynamic_unwind_sections available." 396 " Using callback-based frame info lookup.\n"); 397 }); 398 if (__unw_add_find_dynamic_unwind_sections(&findDynamicUnwindSections)) 399 return make_error<StringError>( 400 "Could not register findDynamicUnwindSections"); 401 } else { 402 ORC_RT_DEBUG({ 403 printdbg("__unw_add/remove_find_dynamic_unwind_sections not available." 404 " Using classic frame info registration.\n"); 405 }); 406 } 407 return Error::success(); 408 } 409 410 Error MachOPlatformRuntimeState::shutdown() { 411 if (UseCallbackStyleUnwindInfo) { 412 if (__unw_remove_find_dynamic_unwind_sections(&findDynamicUnwindSections)) { 413 ORC_RT_DEBUG( 414 { printdbg("__unw_remove_find_dynamic_unwind_sections failed.\n"); }); 415 } 416 } 417 return Error::success(); 418 } 419 420 Error MachOPlatformRuntimeState::registerJITDylib(std::string Name, 421 void *Header) { 422 ORC_RT_DEBUG({ 423 printdbg("Registering JITDylib %s: Header = %p\n", Name.c_str(), Header); 424 }); 425 std::lock_guard<std::mutex> Lock(JDStatesMutex); 426 if (JDStates.count(Header)) { 427 std::ostringstream ErrStream; 428 ErrStream << "Duplicate JITDylib registration for header " << Header 429 << " (name = " << Name << ")"; 430 return make_error<StringError>(ErrStream.str()); 431 } 432 if (JDNameToHeader.count(Name)) { 433 std::ostringstream ErrStream; 434 ErrStream << "Duplicate JITDylib registration for header " << Header 435 << " (header = " << Header << ")"; 436 return make_error<StringError>(ErrStream.str()); 437 } 438 439 auto &JDS = JDStates[Header]; 440 JDS.Name = std::move(Name); 441 JDS.Header = Header; 442 JDNameToHeader[JDS.Name] = Header; 443 return Error::success(); 444 } 445 446 Error MachOPlatformRuntimeState::deregisterJITDylib(void *Header) { 447 std::lock_guard<std::mutex> Lock(JDStatesMutex); 448 auto I = JDStates.find(Header); 449 if (I == JDStates.end()) { 450 std::ostringstream ErrStream; 451 ErrStream << "Attempted to deregister unrecognized header " << Header; 452 return make_error<StringError>(ErrStream.str()); 453 } 454 455 // Remove std::string construction once we can use C++20. 456 auto J = JDNameToHeader.find( 457 std::string(I->second.Name.data(), I->second.Name.size())); 458 assert(J != JDNameToHeader.end() && 459 "Missing JDNameToHeader entry for JITDylib"); 460 461 ORC_RT_DEBUG({ 462 printdbg("Deregistering JITDylib %s: Header = %p\n", I->second.Name.c_str(), 463 Header); 464 }); 465 466 JDNameToHeader.erase(J); 467 JDStates.erase(I); 468 return Error::success(); 469 } 470 471 Error MachOPlatformRuntimeState::registerThreadDataSection( 472 span<const char> ThreadDataSection) { 473 std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex); 474 auto I = ThreadDataSections.upper_bound(ThreadDataSection.data()); 475 if (I != ThreadDataSections.begin()) { 476 auto J = std::prev(I); 477 if (J->first + J->second > ThreadDataSection.data()) 478 return make_error<StringError>("Overlapping __thread_data sections"); 479 } 480 ThreadDataSections.insert( 481 I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size())); 482 return Error::success(); 483 } 484 485 Error MachOPlatformRuntimeState::deregisterThreadDataSection( 486 span<const char> ThreadDataSection) { 487 std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex); 488 auto I = ThreadDataSections.find(ThreadDataSection.data()); 489 if (I == ThreadDataSections.end()) 490 return make_error<StringError>("Attempt to deregister unknown thread data " 491 "section"); 492 ThreadDataSections.erase(I); 493 return Error::success(); 494 } 495 496 Error MachOPlatformRuntimeState::registerObjectSymbolTable( 497 ExecutorAddr HeaderAddr, 498 const std::vector<std::tuple<ExecutorAddr, ExecutorAddr, 499 MachOExecutorSymbolFlags>> &Entries) { 500 501 std::lock_guard<std::mutex> Lock(JDStatesMutex); 502 auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>()); 503 if (!JDS) { 504 std::ostringstream ErrStream; 505 ErrStream << "Could not register object platform sections for " 506 "unrecognized header " 507 << HeaderAddr.toPtr<void *>(); 508 return make_error<StringError>(ErrStream.str()); 509 } 510 511 for (auto &[NameAddr, SymAddr, Flags] : Entries) 512 JDS->SymbolTable[NameAddr.toPtr<const char *>()] = {SymAddr, Flags}; 513 514 return Error::success(); 515 } 516 517 Error MachOPlatformRuntimeState::deregisterObjectSymbolTable( 518 ExecutorAddr HeaderAddr, 519 const std::vector<std::tuple<ExecutorAddr, ExecutorAddr, 520 MachOExecutorSymbolFlags>> &Entries) { 521 522 std::lock_guard<std::mutex> Lock(JDStatesMutex); 523 auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>()); 524 if (!JDS) { 525 std::ostringstream ErrStream; 526 ErrStream << "Could not register object platform sections for " 527 "unrecognized header " 528 << HeaderAddr.toPtr<void *>(); 529 return make_error<StringError>(ErrStream.str()); 530 } 531 532 for (auto &[NameAddr, SymAddr, Flags] : Entries) 533 JDS->SymbolTable.erase(NameAddr.toPtr<const char *>()); 534 535 return Error::success(); 536 } 537 538 Error MachOPlatformRuntimeState::registerObjectPlatformSections( 539 ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindInfo, 540 std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs) { 541 542 // FIXME: Reject platform section registration after the JITDylib is 543 // sealed? 544 545 ORC_RT_DEBUG({ 546 printdbg("MachOPlatform: Registering object sections for %p.\n", 547 HeaderAddr.toPtr<void *>()); 548 }); 549 550 std::lock_guard<std::mutex> Lock(JDStatesMutex); 551 auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>()); 552 if (!JDS) { 553 std::ostringstream ErrStream; 554 ErrStream << "Could not register object platform sections for " 555 "unrecognized header " 556 << HeaderAddr.toPtr<void *>(); 557 return make_error<StringError>(ErrStream.str()); 558 } 559 560 if (UnwindInfo && UseCallbackStyleUnwindInfo) { 561 ORC_RT_DEBUG({ 562 printdbg(" Registering new-style unwind info for:\n" 563 " DWARF: %p -- %p\n" 564 " Compact-unwind: %p -- %p\n" 565 " for:\n", 566 UnwindInfo->DwarfSection.Start.toPtr<void *>(), 567 UnwindInfo->DwarfSection.End.toPtr<void *>(), 568 UnwindInfo->CompactUnwindSection.Start.toPtr<void *>(), 569 UnwindInfo->CompactUnwindSection.End.toPtr<void *>()); 570 }); 571 for (auto &CodeRange : UnwindInfo->CodeRanges) { 572 JDS->UnwindSections.insert(CodeRange.Start.toPtr<char *>(), 573 CodeRange.End.toPtr<char *>(), *UnwindInfo); 574 ORC_RT_DEBUG({ 575 printdbg(" [ %p -- %p ]\n", CodeRange.Start.toPtr<void *>(), 576 CodeRange.End.toPtr<void *>()); 577 }); 578 } 579 } 580 581 for (auto &KV : Secs) { 582 // FIXME: Validate section ranges? 583 if (KV.first == "__TEXT,__eh_frame") { 584 if (!UseCallbackStyleUnwindInfo) { 585 // Use classic libunwind registration. 586 if (auto Err = registerEHFrames(KV.second.toSpan<const char>())) 587 return Err; 588 } 589 } else if (KV.first == "__DATA,__data") { 590 assert(!JDS->DataSectionContent.count(KV.second.Start.toPtr<char *>()) && 591 "Address already registered."); 592 auto S = KV.second.toSpan<char>(); 593 JDS->DataSectionContent[KV.second.Start.toPtr<char *>()] = 594 std::vector<char>(S.begin(), S.end()); 595 } else if (KV.first == "__DATA,__common") { 596 JDS->ZeroInitRanges[KV.second.Start.toPtr<char *>()] = KV.second.size(); 597 } else if (KV.first == "__DATA,__thread_data") { 598 if (auto Err = registerThreadDataSection(KV.second.toSpan<const char>())) 599 return Err; 600 } else if (KV.first == "__llvm_jitlink_ObjCRuntimeRegistrationObject") 601 JDS->ObjCRuntimeRegistrationObjects.add(KV.second.toSpan<char>()); 602 else if (KV.first == "__DATA,__mod_init_func") 603 JDS->ModInitsSections.add(KV.second.toSpan<void (*)()>()); 604 else { 605 // Should this be a warning instead? 606 return make_error<StringError>( 607 "Encountered unexpected section " + 608 std::string(KV.first.data(), KV.first.size()) + 609 " while registering object platform sections"); 610 } 611 } 612 613 return Error::success(); 614 } 615 616 Error MachOPlatformRuntimeState::deregisterObjectPlatformSections( 617 ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindInfo, 618 std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs) { 619 // TODO: Make this more efficient? (maybe unnecessary if removal is rare?) 620 // TODO: Add a JITDylib prepare-for-teardown operation that clears all 621 // registered sections, causing this function to take the fast-path. 622 ORC_RT_DEBUG({ 623 printdbg("MachOPlatform: Deregistering object sections for %p.\n", 624 HeaderAddr.toPtr<void *>()); 625 }); 626 627 std::lock_guard<std::mutex> Lock(JDStatesMutex); 628 auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>()); 629 if (!JDS) { 630 std::ostringstream ErrStream; 631 ErrStream << "Could not register object platform sections for unrecognized " 632 "header " 633 << HeaderAddr.toPtr<void *>(); 634 return make_error<StringError>(ErrStream.str()); 635 } 636 637 // FIXME: Implement faster-path by returning immediately if JDS is being 638 // torn down entirely? 639 640 // TODO: Make library permanent (i.e. not able to be dlclosed) if it contains 641 // any Swift or ObjC. Once this happens we can clear (and no longer record) 642 // data section content, as the library could never be re-initialized. 643 644 if (UnwindInfo && UseCallbackStyleUnwindInfo) { 645 ORC_RT_DEBUG({ 646 printdbg(" Deregistering new-style unwind info for:\n" 647 " DWARF: %p -- %p\n" 648 " Compact-unwind: %p -- %p\n" 649 " for:\n", 650 UnwindInfo->DwarfSection.Start.toPtr<void *>(), 651 UnwindInfo->DwarfSection.End.toPtr<void *>(), 652 UnwindInfo->CompactUnwindSection.Start.toPtr<void *>(), 653 UnwindInfo->CompactUnwindSection.End.toPtr<void *>()); 654 }); 655 for (auto &CodeRange : UnwindInfo->CodeRanges) { 656 JDS->UnwindSections.erase(CodeRange.Start.toPtr<char *>(), 657 CodeRange.End.toPtr<char *>()); 658 ORC_RT_DEBUG({ 659 printdbg(" [ %p -- %p ]\n", CodeRange.Start.toPtr<void *>(), 660 CodeRange.End.toPtr<void *>()); 661 }); 662 } 663 } 664 665 for (auto &KV : Secs) { 666 // FIXME: Validate section ranges? 667 if (KV.first == "__TEXT,__eh_frame") { 668 if (!UseCallbackStyleUnwindInfo) { 669 // Use classic libunwind registration. 670 if (auto Err = deregisterEHFrames(KV.second.toSpan<const char>())) 671 return Err; 672 } 673 } else if (KV.first == "__DATA,__data") { 674 JDS->DataSectionContent.erase(KV.second.Start.toPtr<char *>()); 675 } else if (KV.first == "__DATA,__common") { 676 JDS->ZeroInitRanges.erase(KV.second.Start.toPtr<char *>()); 677 } else if (KV.first == "__DATA,__thread_data") { 678 if (auto Err = 679 deregisterThreadDataSection(KV.second.toSpan<const char>())) 680 return Err; 681 } else if (KV.first == "__llvm_jitlink_ObjCRuntimeRegistrationObject") 682 JDS->ObjCRuntimeRegistrationObjects.removeIfPresent(KV.second); 683 else if (KV.first == "__DATA,__mod_init_func") 684 JDS->ModInitsSections.removeIfPresent(KV.second); 685 else { 686 // Should this be a warning instead? 687 return make_error<StringError>( 688 "Encountered unexpected section " + 689 std::string(KV.first.data(), KV.first.size()) + 690 " while deregistering object platform sections"); 691 } 692 } 693 return Error::success(); 694 } 695 696 const char *MachOPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); } 697 698 void *MachOPlatformRuntimeState::dlopen(std::string_view Path, int Mode) { 699 ORC_RT_DEBUG({ 700 std::string S(Path.data(), Path.size()); 701 printdbg("MachOPlatform::dlopen(\"%s\")\n", S.c_str()); 702 }); 703 std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex); 704 if (auto H = dlopenImpl(Path, Mode)) 705 return *H; 706 else { 707 // FIXME: Make dlerror thread safe. 708 DLFcnError = toString(H.takeError()); 709 return nullptr; 710 } 711 } 712 713 int MachOPlatformRuntimeState::dlupdate(void *DSOHandle) { 714 ORC_RT_DEBUG({ 715 std::string S; 716 printdbg("MachOPlatform::dlupdate(%p) (%s)\n", DSOHandle, S.c_str()); 717 }); 718 std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex); 719 if (auto Err = dlupdateImpl(DSOHandle)) { 720 // FIXME: Make dlerror thread safe. 721 DLFcnError = toString(std::move(Err)); 722 return -1; 723 } 724 return 0; 725 } 726 727 int MachOPlatformRuntimeState::dlclose(void *DSOHandle) { 728 ORC_RT_DEBUG({ 729 auto *JDS = getJITDylibStateByHeader(DSOHandle); 730 std::string DylibName; 731 if (JDS) { 732 std::string S; 733 printdbg("MachOPlatform::dlclose(%p) (%s)\n", DSOHandle, S.c_str()); 734 } else 735 printdbg("MachOPlatform::dlclose(%p) (%s)\n", DSOHandle, 736 "invalid handle"); 737 }); 738 std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex); 739 if (auto Err = dlcloseImpl(DSOHandle)) { 740 // FIXME: Make dlerror thread safe. 741 DLFcnError = toString(std::move(Err)); 742 return -1; 743 } 744 return 0; 745 } 746 747 void *MachOPlatformRuntimeState::dlsym(void *DSOHandle, const char *Symbol) { 748 std::unique_lock<std::mutex> Lock(JDStatesMutex); 749 auto *JDS = getJITDylibStateByHeader(DSOHandle); 750 if (!JDS) { 751 std::ostringstream ErrStream; 752 ErrStream << "In call to dlsym, unrecognized header address " << DSOHandle; 753 DLFcnError = ErrStream.str(); 754 return nullptr; 755 } 756 757 std::string MangledName = std::string("_") + Symbol; 758 std::pair<std::string_view, bool> Lookup(MangledName, false); 759 std::pair<ExecutorAddr, MachOExecutorSymbolFlags> Result; 760 761 if (auto Err = lookupSymbols(*JDS, Lock, {&Result, 1}, {&Lookup, 1})) { 762 DLFcnError = toString(std::move(Err)); 763 return nullptr; 764 } 765 766 // Sign callable symbols as functions, to match dyld. 767 if ((Result.second & MachOExecutorSymbolFlags::Callable) == 768 MachOExecutorSymbolFlags::Callable) 769 return reinterpret_cast<void *>(Result.first.toPtr<void(void)>()); 770 return Result.first.toPtr<void *>(); 771 } 772 773 int MachOPlatformRuntimeState::registerAtExit(void (*F)(void *), void *Arg, 774 void *DSOHandle) { 775 // FIXME: Handle out-of-memory errors, returning -1 if OOM. 776 std::lock_guard<std::mutex> Lock(JDStatesMutex); 777 auto *JDS = getJITDylibStateByHeader(DSOHandle); 778 if (!JDS) { 779 ORC_RT_DEBUG({ 780 printdbg("MachOPlatformRuntimeState::registerAtExit called with " 781 "unrecognized dso handle %p\n", 782 DSOHandle); 783 }); 784 return -1; 785 } 786 JDS->AtExits.push_back({F, Arg}); 787 return 0; 788 } 789 790 void MachOPlatformRuntimeState::runAtExits( 791 std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 792 auto AtExits = std::move(JDS.AtExits); 793 794 // Unlock while running atexits, as they may trigger operations that modify 795 // JDStates. 796 JDStatesLock.unlock(); 797 while (!AtExits.empty()) { 798 auto &AE = AtExits.back(); 799 AE.Func(AE.Arg); 800 AtExits.pop_back(); 801 } 802 JDStatesLock.lock(); 803 } 804 805 void MachOPlatformRuntimeState::runAtExits(void *DSOHandle) { 806 std::unique_lock<std::mutex> Lock(JDStatesMutex); 807 auto *JDS = getJITDylibStateByHeader(DSOHandle); 808 ORC_RT_DEBUG({ 809 printdbg("MachOPlatformRuntimeState::runAtExits called on unrecognized " 810 "dso_handle %p\n", 811 DSOHandle); 812 }); 813 if (JDS) 814 runAtExits(Lock, *JDS); 815 } 816 817 Expected<std::pair<const char *, size_t>> 818 MachOPlatformRuntimeState::getThreadDataSectionFor(const char *ThreadData) { 819 std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex); 820 auto I = ThreadDataSections.upper_bound(ThreadData); 821 // Check that we have a valid entry covering this address. 822 if (I == ThreadDataSections.begin()) 823 return make_error<StringError>("No thread local data section for key"); 824 I = std::prev(I); 825 if (ThreadData >= I->first + I->second) 826 return make_error<StringError>("No thread local data section for key"); 827 return *I; 828 } 829 830 MachOPlatformRuntimeState::JITDylibState * 831 MachOPlatformRuntimeState::getJITDylibStateByHeader(void *DSOHandle) { 832 auto I = JDStates.find(DSOHandle); 833 if (I == JDStates.end()) { 834 I = JDStates.insert(std::make_pair(DSOHandle, JITDylibState())).first; 835 I->second.Header = DSOHandle; 836 } 837 return &I->second; 838 } 839 840 MachOPlatformRuntimeState::JITDylibState * 841 MachOPlatformRuntimeState::getJITDylibStateByName(std::string_view Name) { 842 // FIXME: Avoid creating string once we have C++20. 843 auto I = JDNameToHeader.find(std::string(Name.data(), Name.size())); 844 if (I != JDNameToHeader.end()) 845 return getJITDylibStateByHeader(I->second); 846 return nullptr; 847 } 848 849 Error MachOPlatformRuntimeState::requestPushSymbols( 850 JITDylibState &JDS, span<std::pair<std::string_view, bool>> Symbols) { 851 Error OpErr = Error::success(); 852 if (auto Err = WrapperFunction<SPSError( 853 SPSExecutorAddr, SPSSequence<SPSTuple<SPSString, bool>>)>:: 854 call(JITDispatch(&__orc_rt_macho_push_symbols_tag), OpErr, 855 ExecutorAddr::fromPtr(JDS.Header), Symbols)) { 856 cantFail(std::move(OpErr)); 857 return std::move(Err); 858 } 859 return OpErr; 860 } 861 862 Error MachOPlatformRuntimeState::lookupSymbols( 863 JITDylibState &JDS, std::unique_lock<std::mutex> &JDStatesLock, 864 span<std::pair<ExecutorAddr, MachOExecutorSymbolFlags>> Result, 865 span<std::pair<std::string_view, bool>> Symbols) { 866 assert(JDStatesLock.owns_lock() && 867 "JDStatesLock should be locked at call-site"); 868 assert(Result.size() == Symbols.size() && 869 "Results and Symbols span sizes should match"); 870 871 // Make an initial pass over the local symbol table. 872 std::vector<size_t> MissingSymbolIndexes; 873 for (size_t Idx = 0; Idx != Symbols.size(); ++Idx) { 874 auto I = JDS.SymbolTable.find(Symbols[Idx].first); 875 if (I != JDS.SymbolTable.end()) 876 Result[Idx] = I->second; 877 else 878 MissingSymbolIndexes.push_back(Idx); 879 } 880 881 // If everything has been resolved already then bail out early. 882 if (MissingSymbolIndexes.empty()) 883 return Error::success(); 884 885 // Otherwise call back to the controller to try to request that the symbol 886 // be materialized. 887 std::vector<std::pair<std::string_view, bool>> MissingSymbols; 888 MissingSymbols.reserve(MissingSymbolIndexes.size()); 889 ORC_RT_DEBUG({ 890 printdbg("requesting push of %i missing symbols...\n", 891 MissingSymbolIndexes.size()); 892 }); 893 for (auto MissingIdx : MissingSymbolIndexes) 894 MissingSymbols.push_back(Symbols[MissingIdx]); 895 896 JDStatesLock.unlock(); 897 if (auto Err = requestPushSymbols( 898 JDS, {MissingSymbols.data(), MissingSymbols.size()})) 899 return Err; 900 JDStatesLock.lock(); 901 902 // Try to resolve the previously missing symbols locally. 903 std::vector<size_t> MissingRequiredSymbols; 904 for (auto MissingIdx : MissingSymbolIndexes) { 905 auto I = JDS.SymbolTable.find(Symbols[MissingIdx].first); 906 if (I != JDS.SymbolTable.end()) 907 Result[MissingIdx] = I->second; 908 else { 909 if (Symbols[MissingIdx].second) 910 MissingRequiredSymbols.push_back(MissingIdx); 911 else 912 Result[MissingIdx] = {ExecutorAddr(), {}}; 913 } 914 } 915 916 // Error out if any missing symbols could not be resolved. 917 if (!MissingRequiredSymbols.empty()) { 918 std::ostringstream ErrStream; 919 ErrStream << "Lookup could not find required symbols: [ "; 920 for (auto MissingIdx : MissingRequiredSymbols) 921 ErrStream << "\"" << Symbols[MissingIdx].first << "\" "; 922 ErrStream << "]"; 923 return make_error<StringError>(ErrStream.str()); 924 } 925 926 return Error::success(); 927 } 928 929 // eh-frame registration functions. 930 // We expect these to be available for all processes. 931 extern "C" void __register_frame(const void *); 932 extern "C" void __deregister_frame(const void *); 933 934 template <typename HandleFDEFn> 935 void walkEHFrameSection(span<const char> EHFrameSection, 936 HandleFDEFn HandleFDE) { 937 const char *CurCFIRecord = EHFrameSection.data(); 938 uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); 939 940 while (CurCFIRecord != EHFrameSection.end() && Size != 0) { 941 const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4); 942 if (Size == 0xffffffff) 943 Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12; 944 else 945 Size += 4; 946 uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField); 947 948 if (Offset != 0) 949 HandleFDE(CurCFIRecord); 950 951 CurCFIRecord += Size; 952 Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); 953 } 954 } 955 956 bool MachOPlatformRuntimeState::lookupUnwindSections( 957 void *Addr, unw_dynamic_unwind_sections &Info) { 958 ORC_RT_DEBUG( 959 { printdbg("Tried to lookup unwind-info via new lookup call.\n"); }); 960 std::lock_guard<std::mutex> Lock(JDStatesMutex); 961 for (auto &KV : JDStates) { 962 auto &JD = KV.second; 963 auto I = JD.UnwindSections.find(reinterpret_cast<char *>(Addr)); 964 if (I != JD.UnwindSections.end()) { 965 Info.dso_base = reinterpret_cast<uintptr_t>(JD.Header); 966 Info.dwarf_section = 967 reinterpret_cast<uintptr_t>(I->second.DwarfSection.data()); 968 Info.dwarf_section_length = I->second.DwarfSection.size(); 969 Info.compact_unwind_section = 970 reinterpret_cast<uintptr_t>(I->second.CompactUnwindSection.data()); 971 Info.compact_unwind_section_length = 972 I->second.CompactUnwindSection.size(); 973 return true; 974 } 975 } 976 return false; 977 } 978 979 int MachOPlatformRuntimeState::findDynamicUnwindSections( 980 uintptr_t addr, unw_dynamic_unwind_sections *info) { 981 if (!info) 982 return 0; 983 return MachOPlatformRuntimeState::get().lookupUnwindSections((void *)addr, 984 *info); 985 } 986 987 Error MachOPlatformRuntimeState::registerEHFrames( 988 span<const char> EHFrameSection) { 989 walkEHFrameSection(EHFrameSection, __register_frame); 990 return Error::success(); 991 } 992 993 Error MachOPlatformRuntimeState::deregisterEHFrames( 994 span<const char> EHFrameSection) { 995 walkEHFrameSection(EHFrameSection, __deregister_frame); 996 return Error::success(); 997 } 998 999 Error MachOPlatformRuntimeState::registerObjCRegistrationObjects( 1000 std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 1001 ORC_RT_DEBUG(printdbg("Registering Objective-C / Swift metadata.\n")); 1002 1003 std::vector<char *> RegObjBases; 1004 JDS.ObjCRuntimeRegistrationObjects.processNewSections( 1005 [&](span<char> RegObj) { RegObjBases.push_back(RegObj.data()); }); 1006 1007 if (RegObjBases.empty()) 1008 return Error::success(); 1009 1010 if (!_objc_map_images || !_objc_load_image) 1011 return make_error<StringError>( 1012 "Could not register Objective-C / Swift metadata: _objc_map_images / " 1013 "_objc_load_image not found"); 1014 1015 // Release the lock while calling out to libobjc in case +load methods cause 1016 // reentering the orc runtime. 1017 JDStatesLock.unlock(); 1018 std::vector<char *> Paths; 1019 Paths.resize(RegObjBases.size()); 1020 _objc_map_images(RegObjBases.size(), Paths.data(), 1021 reinterpret_cast<mach_header **>(RegObjBases.data())); 1022 1023 for (void *RegObjBase : RegObjBases) 1024 _objc_load_image(nullptr, reinterpret_cast<mach_header *>(RegObjBase)); 1025 JDStatesLock.lock(); 1026 1027 return Error::success(); 1028 } 1029 1030 Error MachOPlatformRuntimeState::runModInits( 1031 std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 1032 std::vector<span<void (*)()>> InitSections; 1033 InitSections.reserve(JDS.ModInitsSections.numNewSections()); 1034 1035 // Copy initializer sections: If the JITDylib is unsealed then the 1036 // initializers could reach back into the JIT and cause more initializers to 1037 // be added. 1038 // FIXME: Skip unlock and run in-place on sealed JITDylibs? 1039 JDS.ModInitsSections.processNewSections( 1040 [&](span<void (*)()> Inits) { InitSections.push_back(Inits); }); 1041 1042 JDStatesLock.unlock(); 1043 for (auto InitSec : InitSections) 1044 for (auto *Init : InitSec) 1045 Init(); 1046 JDStatesLock.lock(); 1047 1048 return Error::success(); 1049 } 1050 1051 Expected<void *> MachOPlatformRuntimeState::dlopenImpl(std::string_view Path, 1052 int Mode) { 1053 std::unique_lock<std::mutex> Lock(JDStatesMutex); 1054 1055 // Try to find JITDylib state by name. 1056 auto *JDS = getJITDylibStateByName(Path); 1057 1058 if (!JDS) 1059 return make_error<StringError>("No registered JTIDylib for path " + 1060 std::string(Path.data(), Path.size())); 1061 1062 // If this JITDylib is unsealed, or this is the first dlopen then run 1063 // full dlopen path (update deps, push and run initializers, update ref 1064 // counts on all JITDylibs in the dep tree). 1065 if (!JDS->referenced() || !JDS->Sealed) { 1066 if (auto Err = dlopenFull(Lock, *JDS)) 1067 return std::move(Err); 1068 } 1069 1070 // Bump the ref-count on this dylib. 1071 ++JDS->DlRefCount; 1072 1073 // Return the header address. 1074 return JDS->Header; 1075 } 1076 1077 Error MachOPlatformRuntimeState::dlopenFull( 1078 std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 1079 // Call back to the JIT to push the initializers. 1080 Expected<MachOJITDylibDepInfoMap> DepInfo((MachOJITDylibDepInfoMap())); 1081 // Unlock so that we can accept the initializer update. 1082 JDStatesLock.unlock(); 1083 if (auto Err = WrapperFunction<SPSExpected<SPSMachOJITDylibDepInfoMap>( 1084 SPSExecutorAddr)>:: 1085 call(JITDispatch(&__orc_rt_macho_push_initializers_tag), DepInfo, 1086 ExecutorAddr::fromPtr(JDS.Header))) 1087 return Err; 1088 JDStatesLock.lock(); 1089 1090 if (!DepInfo) 1091 return DepInfo.takeError(); 1092 1093 if (auto Err = dlopenInitialize(JDStatesLock, JDS, *DepInfo)) 1094 return Err; 1095 1096 if (!DepInfo->empty()) { 1097 ORC_RT_DEBUG({ 1098 printdbg("Unrecognized dep-info key headers in dlopen of %s\n", 1099 JDS.Name.c_str()); 1100 }); 1101 std::ostringstream ErrStream; 1102 ErrStream << "Encountered unrecognized dep-info key headers " 1103 "while processing dlopen of " 1104 << JDS.Name; 1105 return make_error<StringError>(ErrStream.str()); 1106 } 1107 1108 return Error::success(); 1109 } 1110 1111 Error MachOPlatformRuntimeState::dlopenInitialize( 1112 std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS, 1113 MachOJITDylibDepInfoMap &DepInfo) { 1114 ORC_RT_DEBUG({ 1115 printdbg("MachOPlatformRuntimeState::dlopenInitialize(\"%s\")\n", 1116 JDS.Name.c_str()); 1117 }); 1118 1119 // If the header is not present in the dep map then assume that we 1120 // already processed it earlier in the dlopenInitialize traversal and 1121 // return. 1122 // TODO: Keep a visited set instead so that we can error out on missing 1123 // entries? 1124 auto I = DepInfo.find(ExecutorAddr::fromPtr(JDS.Header)); 1125 if (I == DepInfo.end()) 1126 return Error::success(); 1127 1128 auto DI = std::move(I->second); 1129 DepInfo.erase(I); 1130 1131 // We don't need to re-initialize sealed JITDylibs that have already been 1132 // initialized. Just check that their dep-map entry is empty as expected. 1133 if (JDS.Sealed) { 1134 if (!DI.DepHeaders.empty()) { 1135 std::ostringstream ErrStream; 1136 ErrStream << "Sealed JITDylib " << JDS.Header 1137 << " already has registered dependencies"; 1138 return make_error<StringError>(ErrStream.str()); 1139 } 1140 if (JDS.referenced()) 1141 return Error::success(); 1142 } else 1143 JDS.Sealed = DI.Sealed; 1144 1145 // This is an unsealed or newly sealed JITDylib. Run initializers. 1146 std::vector<JITDylibState *> OldDeps; 1147 std::swap(JDS.Deps, OldDeps); 1148 JDS.Deps.reserve(DI.DepHeaders.size()); 1149 for (auto DepHeaderAddr : DI.DepHeaders) { 1150 auto *DepJDS = getJITDylibStateByHeader(DepHeaderAddr.toPtr<void *>()); 1151 if (!DepJDS) { 1152 std::ostringstream ErrStream; 1153 ErrStream << "Encountered unrecognized dep header " 1154 << DepHeaderAddr.toPtr<void *>() << " while initializing " 1155 << JDS.Name; 1156 return make_error<StringError>(ErrStream.str()); 1157 } 1158 ++DepJDS->LinkedAgainstRefCount; 1159 if (auto Err = dlopenInitialize(JDStatesLock, *DepJDS, DepInfo)) 1160 return Err; 1161 } 1162 1163 // Initialize this JITDylib. 1164 if (auto Err = registerObjCRegistrationObjects(JDStatesLock, JDS)) 1165 return Err; 1166 if (auto Err = runModInits(JDStatesLock, JDS)) 1167 return Err; 1168 1169 // Decrement old deps. 1170 // FIXME: We should probably continue and just report deinitialize errors 1171 // here. 1172 for (auto *DepJDS : OldDeps) { 1173 --DepJDS->LinkedAgainstRefCount; 1174 if (!DepJDS->referenced()) 1175 if (auto Err = dlcloseDeinitialize(JDStatesLock, *DepJDS)) 1176 return Err; 1177 } 1178 1179 return Error::success(); 1180 } 1181 1182 Error MachOPlatformRuntimeState::dlupdateImpl(void *DSOHandle) { 1183 std::unique_lock<std::mutex> Lock(JDStatesMutex); 1184 1185 // Try to find JITDylib state by DSOHandle. 1186 auto *JDS = getJITDylibStateByHeader(DSOHandle); 1187 1188 if (!JDS) { 1189 std::ostringstream ErrStream; 1190 ErrStream << "No registered JITDylib for " << DSOHandle; 1191 return make_error<StringError>(ErrStream.str()); 1192 } 1193 1194 if (!JDS->referenced()) 1195 return make_error<StringError>("dlupdate failed, JITDylib must be open."); 1196 1197 if (!JDS->Sealed) { 1198 if (auto Err = dlupdateFull(Lock, *JDS)) 1199 return Err; 1200 } 1201 1202 return Error::success(); 1203 } 1204 1205 Error MachOPlatformRuntimeState::dlupdateFull( 1206 std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 1207 // Call back to the JIT to push the initializers. 1208 Expected<MachOJITDylibDepInfoMap> DepInfo((MachOJITDylibDepInfoMap())); 1209 // Unlock so that we can accept the initializer update. 1210 JDStatesLock.unlock(); 1211 if (auto Err = WrapperFunction<SPSExpected<SPSMachOJITDylibDepInfoMap>( 1212 SPSExecutorAddr)>:: 1213 call(JITDispatch(&__orc_rt_macho_push_initializers_tag), DepInfo, 1214 ExecutorAddr::fromPtr(JDS.Header))) 1215 return Err; 1216 JDStatesLock.lock(); 1217 1218 if (!DepInfo) 1219 return DepInfo.takeError(); 1220 1221 if (auto Err = dlupdateInitialize(JDStatesLock, JDS)) 1222 return Err; 1223 1224 return Error::success(); 1225 } 1226 1227 Error MachOPlatformRuntimeState::dlupdateInitialize( 1228 std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 1229 ORC_RT_DEBUG({ 1230 printdbg("MachOPlatformRuntimeState::dlupdateInitialize(\"%s\")\n", 1231 JDS.Name.c_str()); 1232 }); 1233 1234 // Initialize this JITDylib. 1235 if (auto Err = registerObjCRegistrationObjects(JDStatesLock, JDS)) 1236 return Err; 1237 if (auto Err = runModInits(JDStatesLock, JDS)) 1238 return Err; 1239 1240 return Error::success(); 1241 } 1242 1243 Error MachOPlatformRuntimeState::dlcloseImpl(void *DSOHandle) { 1244 std::unique_lock<std::mutex> Lock(JDStatesMutex); 1245 1246 // Try to find JITDylib state by header. 1247 auto *JDS = getJITDylibStateByHeader(DSOHandle); 1248 1249 if (!JDS) { 1250 std::ostringstream ErrStream; 1251 ErrStream << "No registered JITDylib for " << DSOHandle; 1252 return make_error<StringError>(ErrStream.str()); 1253 } 1254 1255 // Bump the ref-count. 1256 --JDS->DlRefCount; 1257 1258 if (!JDS->referenced()) 1259 return dlcloseDeinitialize(Lock, *JDS); 1260 1261 return Error::success(); 1262 } 1263 1264 Error MachOPlatformRuntimeState::dlcloseDeinitialize( 1265 std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 1266 1267 ORC_RT_DEBUG({ 1268 printdbg("MachOPlatformRuntimeState::dlcloseDeinitialize(\"%s\")\n", 1269 JDS.Name.c_str()); 1270 }); 1271 1272 runAtExits(JDStatesLock, JDS); 1273 1274 // Reset mod-inits 1275 JDS.ModInitsSections.reset(); 1276 1277 // Reset data section contents. 1278 for (auto &KV : JDS.DataSectionContent) 1279 memcpy(KV.first, KV.second.data(), KV.second.size()); 1280 for (auto &KV : JDS.ZeroInitRanges) 1281 memset(KV.first, 0, KV.second); 1282 1283 // Deinitialize any dependencies. 1284 for (auto *DepJDS : JDS.Deps) { 1285 --DepJDS->LinkedAgainstRefCount; 1286 if (!DepJDS->referenced()) 1287 if (auto Err = dlcloseDeinitialize(JDStatesLock, *DepJDS)) 1288 return Err; 1289 } 1290 1291 return Error::success(); 1292 } 1293 1294 class MachOPlatformRuntimeTLVManager { 1295 public: 1296 void *getInstance(const char *ThreadData); 1297 1298 private: 1299 std::unordered_map<const char *, char *> Instances; 1300 std::unordered_map<const char *, std::unique_ptr<char[]>> AllocatedSections; 1301 }; 1302 1303 void *MachOPlatformRuntimeTLVManager::getInstance(const char *ThreadData) { 1304 auto I = Instances.find(ThreadData); 1305 if (I != Instances.end()) 1306 return I->second; 1307 1308 auto TDS = 1309 MachOPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData); 1310 if (!TDS) { 1311 __orc_rt_log_error(toString(TDS.takeError()).c_str()); 1312 return nullptr; 1313 } 1314 1315 auto &Allocated = AllocatedSections[TDS->first]; 1316 if (!Allocated) { 1317 Allocated = std::make_unique<char[]>(TDS->second); 1318 memcpy(Allocated.get(), TDS->first, TDS->second); 1319 } 1320 1321 size_t ThreadDataDelta = ThreadData - TDS->first; 1322 assert(ThreadDataDelta <= TDS->second && "ThreadData outside section bounds"); 1323 1324 char *Instance = Allocated.get() + ThreadDataDelta; 1325 Instances[ThreadData] = Instance; 1326 return Instance; 1327 } 1328 1329 void destroyMachOTLVMgr(void *MachOTLVMgr) { 1330 delete static_cast<MachOPlatformRuntimeTLVManager *>(MachOTLVMgr); 1331 } 1332 1333 Error runWrapperFunctionCalls(std::vector<WrapperFunctionCall> WFCs) { 1334 for (auto &WFC : WFCs) 1335 if (auto Err = WFC.runWithSPSRet<void>()) 1336 return Err; 1337 return Error::success(); 1338 } 1339 1340 } // end anonymous namespace 1341 1342 //------------------------------------------------------------------------------ 1343 // JIT entry points 1344 //------------------------------------------------------------------------------ 1345 1346 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1347 __orc_rt_macho_platform_bootstrap(char *ArgData, size_t ArgSize) { 1348 return WrapperFunction<SPSError()>::handle( 1349 ArgData, ArgSize, 1350 []() { return MachOPlatformRuntimeState::create(); }) 1351 .release(); 1352 } 1353 1354 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1355 __orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) { 1356 return WrapperFunction<SPSError()>::handle( 1357 ArgData, ArgSize, 1358 []() { return MachOPlatformRuntimeState::destroy(); }) 1359 .release(); 1360 } 1361 1362 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1363 __orc_rt_macho_register_jitdylib(char *ArgData, size_t ArgSize) { 1364 return WrapperFunction<SPSError(SPSString, SPSExecutorAddr)>::handle( 1365 ArgData, ArgSize, 1366 [](std::string &Name, ExecutorAddr HeaderAddr) { 1367 return MachOPlatformRuntimeState::get().registerJITDylib( 1368 std::move(Name), HeaderAddr.toPtr<void *>()); 1369 }) 1370 .release(); 1371 } 1372 1373 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1374 __orc_rt_macho_deregister_jitdylib(char *ArgData, size_t ArgSize) { 1375 return WrapperFunction<SPSError(SPSExecutorAddr)>::handle( 1376 ArgData, ArgSize, 1377 [](ExecutorAddr HeaderAddr) { 1378 return MachOPlatformRuntimeState::get().deregisterJITDylib( 1379 HeaderAddr.toPtr<void *>()); 1380 }) 1381 .release(); 1382 } 1383 1384 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1385 __orc_rt_macho_register_object_platform_sections(char *ArgData, 1386 size_t ArgSize) { 1387 return WrapperFunction<SPSError(SPSExecutorAddr, 1388 SPSOptional<SPSUnwindSectionInfo>, 1389 SPSMachOObjectPlatformSectionsMap)>:: 1390 handle(ArgData, ArgSize, 1391 [](ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> USI, 1392 std::vector<std::pair<std::string_view, ExecutorAddrRange>> 1393 &Secs) { 1394 return MachOPlatformRuntimeState::get() 1395 .registerObjectPlatformSections(HeaderAddr, std::move(USI), 1396 std::move(Secs)); 1397 }) 1398 .release(); 1399 } 1400 1401 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1402 __orc_rt_macho_register_object_symbol_table(char *ArgData, size_t ArgSize) { 1403 using SymtabContainer = std::vector< 1404 std::tuple<ExecutorAddr, ExecutorAddr, 1405 MachOPlatformRuntimeState::MachOExecutorSymbolFlags>>; 1406 return WrapperFunction<SPSError( 1407 SPSExecutorAddr, SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr, 1408 SPSMachOExecutorSymbolFlags>>)>:: 1409 handle(ArgData, ArgSize, 1410 [](ExecutorAddr HeaderAddr, SymtabContainer &Symbols) { 1411 return MachOPlatformRuntimeState::get() 1412 .registerObjectSymbolTable(HeaderAddr, Symbols); 1413 }) 1414 .release(); 1415 } 1416 1417 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1418 __orc_rt_macho_deregister_object_symbol_table(char *ArgData, size_t ArgSize) { 1419 using SymtabContainer = std::vector< 1420 std::tuple<ExecutorAddr, ExecutorAddr, 1421 MachOPlatformRuntimeState::MachOExecutorSymbolFlags>>; 1422 return WrapperFunction<SPSError( 1423 SPSExecutorAddr, SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr, 1424 SPSMachOExecutorSymbolFlags>>)>:: 1425 handle(ArgData, ArgSize, 1426 [](ExecutorAddr HeaderAddr, SymtabContainer &Symbols) { 1427 return MachOPlatformRuntimeState::get() 1428 .deregisterObjectSymbolTable(HeaderAddr, Symbols); 1429 }) 1430 .release(); 1431 } 1432 1433 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1434 __orc_rt_macho_deregister_object_platform_sections(char *ArgData, 1435 size_t ArgSize) { 1436 return WrapperFunction<SPSError(SPSExecutorAddr, 1437 SPSOptional<SPSUnwindSectionInfo>, 1438 SPSMachOObjectPlatformSectionsMap)>:: 1439 handle(ArgData, ArgSize, 1440 [](ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> USI, 1441 std::vector<std::pair<std::string_view, ExecutorAddrRange>> 1442 &Secs) { 1443 return MachOPlatformRuntimeState::get() 1444 .deregisterObjectPlatformSections(HeaderAddr, std::move(USI), 1445 std::move(Secs)); 1446 }) 1447 .release(); 1448 } 1449 1450 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1451 __orc_rt_macho_run_wrapper_function_calls(char *ArgData, size_t ArgSize) { 1452 return WrapperFunction<SPSError(SPSSequence<SPSWrapperFunctionCall>)>::handle( 1453 ArgData, ArgSize, runWrapperFunctionCalls) 1454 .release(); 1455 } 1456 1457 //------------------------------------------------------------------------------ 1458 // TLV support 1459 //------------------------------------------------------------------------------ 1460 1461 ORC_RT_INTERFACE void *__orc_rt_macho_tlv_get_addr_impl(TLVDescriptor *D) { 1462 auto *TLVMgr = static_cast<MachOPlatformRuntimeTLVManager *>( 1463 pthread_getspecific(D->Key)); 1464 if (!TLVMgr) { 1465 TLVMgr = new MachOPlatformRuntimeTLVManager(); 1466 if (pthread_setspecific(D->Key, TLVMgr)) { 1467 __orc_rt_log_error("Call to pthread_setspecific failed"); 1468 return nullptr; 1469 } 1470 } 1471 1472 return TLVMgr->getInstance( 1473 reinterpret_cast<char *>(static_cast<uintptr_t>(D->DataAddress))); 1474 } 1475 1476 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1477 __orc_rt_macho_create_pthread_key(char *ArgData, size_t ArgSize) { 1478 return WrapperFunction<SPSExpected<uint64_t>(void)>::handle( 1479 ArgData, ArgSize, 1480 []() -> Expected<uint64_t> { 1481 pthread_key_t Key; 1482 if (int Err = pthread_key_create(&Key, destroyMachOTLVMgr)) { 1483 __orc_rt_log_error("Call to pthread_key_create failed"); 1484 return make_error<StringError>(strerror(Err)); 1485 } 1486 return static_cast<uint64_t>(Key); 1487 }) 1488 .release(); 1489 } 1490 1491 //------------------------------------------------------------------------------ 1492 // cxa_atexit support 1493 //------------------------------------------------------------------------------ 1494 1495 int __orc_rt_macho_cxa_atexit(void (*func)(void *), void *arg, 1496 void *dso_handle) { 1497 return MachOPlatformRuntimeState::get().registerAtExit(func, arg, dso_handle); 1498 } 1499 1500 void __orc_rt_macho_cxa_finalize(void *dso_handle) { 1501 MachOPlatformRuntimeState::get().runAtExits(dso_handle); 1502 } 1503 1504 //------------------------------------------------------------------------------ 1505 // JIT'd dlfcn alternatives. 1506 //------------------------------------------------------------------------------ 1507 1508 const char *__orc_rt_macho_jit_dlerror() { 1509 return MachOPlatformRuntimeState::get().dlerror(); 1510 } 1511 1512 void *__orc_rt_macho_jit_dlopen(const char *path, int mode) { 1513 return MachOPlatformRuntimeState::get().dlopen(path, mode); 1514 } 1515 1516 int __orc_rt_macho_jit_dlupdate(void *dso_handle) { 1517 return MachOPlatformRuntimeState::get().dlupdate(dso_handle); 1518 } 1519 1520 int __orc_rt_macho_jit_dlclose(void *dso_handle) { 1521 return MachOPlatformRuntimeState::get().dlclose(dso_handle); 1522 } 1523 1524 void *__orc_rt_macho_jit_dlsym(void *dso_handle, const char *symbol) { 1525 return MachOPlatformRuntimeState::get().dlsym(dso_handle, symbol); 1526 } 1527 1528 //------------------------------------------------------------------------------ 1529 // MachO Run Program 1530 //------------------------------------------------------------------------------ 1531 1532 ORC_RT_INTERFACE int64_t __orc_rt_macho_run_program(const char *JITDylibName, 1533 const char *EntrySymbolName, 1534 int argc, char *argv[]) { 1535 using MainTy = int (*)(int, char *[]); 1536 1537 void *H = 1538 __orc_rt_macho_jit_dlopen(JITDylibName, orc_rt::macho::ORC_RT_RTLD_LAZY); 1539 if (!H) { 1540 __orc_rt_log_error(__orc_rt_macho_jit_dlerror()); 1541 return -1; 1542 } 1543 1544 auto *Main = 1545 reinterpret_cast<MainTy>(__orc_rt_macho_jit_dlsym(H, EntrySymbolName)); 1546 1547 if (!Main) { 1548 __orc_rt_log_error(__orc_rt_macho_jit_dlerror()); 1549 return -1; 1550 } 1551 1552 int Result = Main(argc, argv); 1553 1554 if (__orc_rt_macho_jit_dlclose(H) == -1) 1555 __orc_rt_log_error(__orc_rt_macho_jit_dlerror()); 1556 1557 return Result; 1558 } 1559