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