1bb5f97e3SLang Hames //===- macho_platform.cpp -------------------------------------------------===// 2bb5f97e3SLang Hames // 3bb5f97e3SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bb5f97e3SLang Hames // See https://llvm.org/LICENSE.txt for license information. 5bb5f97e3SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bb5f97e3SLang Hames // 7bb5f97e3SLang Hames //===----------------------------------------------------------------------===// 8bb5f97e3SLang Hames // 9bb5f97e3SLang Hames // This file contains code required to load the rest of the MachO runtime. 10bb5f97e3SLang Hames // 11bb5f97e3SLang Hames //===----------------------------------------------------------------------===// 12bb5f97e3SLang Hames 13bb5f97e3SLang Hames #include "macho_platform.h" 14bb41fc68SLang Hames #include "bitmask_enum.h" 15bb5f97e3SLang Hames #include "common.h" 16f9aef477SLang Hames #include "debug.h" 17bb5f97e3SLang Hames #include "error.h" 18bbb73fbcSLang Hames #include "interval_map.h" 1969f8923eSLang Hames #include "jit_dispatch.h" 206292f117SLang Hames #include "record_section_tracker.h" 21bb5f97e3SLang Hames #include "wrapper_function_utils.h" 22bb5f97e3SLang Hames 23fe2f5c97SLang Hames #include <algorithm> 24f9aef477SLang Hames #include <ios> 25bb5f97e3SLang Hames #include <map> 26bb5f97e3SLang Hames #include <mutex> 27bb5f97e3SLang Hames #include <sstream> 28608131b1SLang Hames #include <string_view> 29bb5f97e3SLang Hames #include <unordered_map> 30f9aef477SLang Hames #include <unordered_set> 31bb5f97e3SLang Hames #include <vector> 32bb5f97e3SLang Hames 33f9aef477SLang Hames #define DEBUG_TYPE "macho_platform" 34f9aef477SLang Hames 353e04ad42SLang Hames using namespace orc_rt; 363e04ad42SLang Hames using namespace orc_rt::macho; 37bb5f97e3SLang Hames 38bb5f97e3SLang Hames // Declare function tags for functions in the JIT process. 39f9aef477SLang Hames ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_push_initializers_tag) 40bb41fc68SLang Hames ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_push_symbols_tag) 41bb5f97e3SLang Hames 42cdcc3547SLang Hames struct objc_image_info; 43f448d446SLang Hames struct mach_header; 44cdcc3547SLang Hames 45cdcc3547SLang Hames // Objective-C registration functions. 46cdcc3547SLang Hames // These are weakly imported. If the Objective-C runtime has not been loaded 47cdcc3547SLang Hames // then code containing Objective-C sections will generate an error. 48cdcc3547SLang Hames extern "C" void 49f448d446SLang Hames _objc_map_images(unsigned count, const char *const paths[], 50f448d446SLang Hames const mach_header *const mhdrs[]) ORC_RT_WEAK_IMPORT; 51cdcc3547SLang Hames 52f448d446SLang Hames extern "C" void _objc_load_image(const char *path, 53f448d446SLang Hames const mach_header *mh) ORC_RT_WEAK_IMPORT; 542a739f27SBen Langmuir 553507df9cSLang Hames // Libunwind prototypes. 563507df9cSLang Hames struct unw_dynamic_unwind_sections { 573507df9cSLang Hames uintptr_t dso_base; 583507df9cSLang Hames uintptr_t dwarf_section; 593507df9cSLang Hames size_t dwarf_section_length; 603507df9cSLang Hames uintptr_t compact_unwind_section; 613507df9cSLang Hames size_t compact_unwind_section_length; 623507df9cSLang Hames }; 633507df9cSLang Hames 643507df9cSLang Hames typedef int (*unw_find_dynamic_unwind_sections)( 653507df9cSLang Hames uintptr_t addr, struct unw_dynamic_unwind_sections *info); 663507df9cSLang Hames 673507df9cSLang Hames extern "C" int __unw_add_find_dynamic_unwind_sections( 683507df9cSLang Hames unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) 693507df9cSLang Hames ORC_RT_WEAK_IMPORT; 703507df9cSLang Hames 713507df9cSLang Hames extern "C" int __unw_remove_find_dynamic_unwind_sections( 723507df9cSLang Hames unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) 733507df9cSLang Hames ORC_RT_WEAK_IMPORT; 743507df9cSLang Hames 75bb5f97e3SLang Hames namespace { 76bb5f97e3SLang Hames 77f9aef477SLang Hames struct MachOJITDylibDepInfo { 78f9aef477SLang Hames bool Sealed = false; 79f9aef477SLang Hames std::vector<ExecutorAddr> DepHeaders; 80cdcc3547SLang Hames }; 81cdcc3547SLang Hames 82f9aef477SLang Hames using MachOJITDylibDepInfoMap = 83f9aef477SLang Hames std::unordered_map<ExecutorAddr, MachOJITDylibDepInfo>; 84cdcc3547SLang Hames 85f9aef477SLang Hames } // anonymous namespace 86cdcc3547SLang Hames 873e04ad42SLang Hames namespace orc_rt { 88cdcc3547SLang Hames 89f9aef477SLang Hames using SPSMachOObjectPlatformSectionsMap = 90f9aef477SLang Hames SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>; 91cdcc3547SLang Hames 92f9aef477SLang Hames using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>; 93f9aef477SLang Hames 94f9aef477SLang Hames using SPSMachOJITDylibDepInfoMap = 95f9aef477SLang Hames SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>; 96f9aef477SLang Hames 97f9aef477SLang Hames template <> 98f9aef477SLang Hames class SPSSerializationTraits<SPSMachOJITDylibDepInfo, MachOJITDylibDepInfo> { 99f9aef477SLang Hames public: 100f9aef477SLang Hames static size_t size(const MachOJITDylibDepInfo &JDI) { 101f9aef477SLang Hames return SPSMachOJITDylibDepInfo::AsArgList::size(JDI.Sealed, JDI.DepHeaders); 102cdcc3547SLang Hames } 103cdcc3547SLang Hames 104f9aef477SLang Hames static bool serialize(SPSOutputBuffer &OB, const MachOJITDylibDepInfo &JDI) { 105f9aef477SLang Hames return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, JDI.Sealed, 106f9aef477SLang Hames JDI.DepHeaders); 107cdcc3547SLang Hames } 108cdcc3547SLang Hames 109f9aef477SLang Hames static bool deserialize(SPSInputBuffer &IB, MachOJITDylibDepInfo &JDI) { 110f9aef477SLang Hames return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, JDI.Sealed, 111f9aef477SLang Hames JDI.DepHeaders); 112cdcc3547SLang Hames } 113f9aef477SLang Hames }; 114cdcc3547SLang Hames 1153507df9cSLang Hames struct UnwindSectionInfo { 1163507df9cSLang Hames std::vector<ExecutorAddrRange> CodeRanges; 1173507df9cSLang Hames ExecutorAddrRange DwarfSection; 1183507df9cSLang Hames ExecutorAddrRange CompactUnwindSection; 1193507df9cSLang Hames }; 1203507df9cSLang Hames 1213507df9cSLang Hames using SPSUnwindSectionInfo = 1223507df9cSLang Hames SPSTuple<SPSSequence<SPSExecutorAddrRange>, SPSExecutorAddrRange, 1233507df9cSLang Hames SPSExecutorAddrRange>; 1243507df9cSLang Hames 1253507df9cSLang Hames template <> 1263507df9cSLang Hames class SPSSerializationTraits<SPSUnwindSectionInfo, UnwindSectionInfo> { 1273507df9cSLang Hames public: 1283507df9cSLang Hames static size_t size(const UnwindSectionInfo &USI) { 1293507df9cSLang Hames return SPSUnwindSectionInfo::AsArgList::size( 1303507df9cSLang Hames USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection); 1313507df9cSLang Hames } 1323507df9cSLang Hames 1333507df9cSLang Hames static bool serialize(SPSOutputBuffer &OB, const UnwindSectionInfo &USI) { 1343507df9cSLang Hames return SPSUnwindSectionInfo::AsArgList::serialize( 1353507df9cSLang Hames OB, USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection); 1363507df9cSLang Hames } 1373507df9cSLang Hames 1383507df9cSLang Hames static bool deserialize(SPSInputBuffer &IB, UnwindSectionInfo &USI) { 1393507df9cSLang Hames return SPSUnwindSectionInfo::AsArgList::deserialize( 1403507df9cSLang Hames IB, USI.CodeRanges, USI.DwarfSection, USI.CompactUnwindSection); 1413507df9cSLang Hames } 1423507df9cSLang Hames }; 1433507df9cSLang Hames 1443e04ad42SLang Hames } // namespace orc_rt 1452a739f27SBen Langmuir 146f9aef477SLang Hames namespace { 147eda6afdaSLang Hames struct TLVDescriptor { 148eda6afdaSLang Hames void *(*Thunk)(TLVDescriptor *) = nullptr; 149eda6afdaSLang Hames unsigned long Key = 0; 150eda6afdaSLang Hames unsigned long DataAddress = 0; 151eda6afdaSLang Hames }; 152eda6afdaSLang Hames 153bb5f97e3SLang Hames class MachOPlatformRuntimeState { 154bb41fc68SLang Hames public: 155bb41fc68SLang Hames // Used internally by MachOPlatformRuntimeState, but made public to enable 156bb41fc68SLang Hames // serialization. 157bb41fc68SLang Hames enum class MachOExecutorSymbolFlags : uint8_t { 158bb41fc68SLang Hames None = 0, 159bb41fc68SLang Hames Weak = 1U << 0, 160bb41fc68SLang Hames Callable = 1U << 1, 161bb41fc68SLang Hames ORC_RT_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Callable) 162bb41fc68SLang Hames }; 163bb41fc68SLang Hames 164bb5f97e3SLang Hames private: 165bb5f97e3SLang Hames struct AtExitEntry { 166bb5f97e3SLang Hames void (*Func)(void *); 167bb5f97e3SLang Hames void *Arg; 168bb5f97e3SLang Hames }; 169bb5f97e3SLang Hames 170bb5f97e3SLang Hames using AtExitsVector = std::vector<AtExitEntry>; 171bb5f97e3SLang Hames 1723507df9cSLang Hames struct UnwindSections { 1733507df9cSLang Hames UnwindSections(const UnwindSectionInfo &USI) 1743507df9cSLang Hames : DwarfSection(USI.DwarfSection.toSpan<char>()), 1753507df9cSLang Hames CompactUnwindSection(USI.CompactUnwindSection.toSpan<char>()) {} 1763507df9cSLang Hames 1773507df9cSLang Hames span<char> DwarfSection; 1783507df9cSLang Hames span<char> CompactUnwindSection; 1793507df9cSLang Hames }; 1803507df9cSLang Hames 1813507df9cSLang Hames using UnwindSectionsMap = 1823507df9cSLang Hames IntervalMap<char *, UnwindSections, IntervalCoalescing::Disabled>; 1833507df9cSLang Hames 184f9aef477SLang Hames struct JITDylibState { 185bb41fc68SLang Hames 186bb41fc68SLang Hames using SymbolTableMap = 187bb41fc68SLang Hames std::unordered_map<std::string_view, 188bb41fc68SLang Hames std::pair<ExecutorAddr, MachOExecutorSymbolFlags>>; 189bb41fc68SLang Hames 190f9aef477SLang Hames std::string Name; 191bb5f97e3SLang Hames void *Header = nullptr; 192f9aef477SLang Hames bool Sealed = false; 193f9aef477SLang Hames size_t LinkedAgainstRefCount = 0; 194f9aef477SLang Hames size_t DlRefCount = 0; 195bb41fc68SLang Hames SymbolTableMap SymbolTable; 196f9aef477SLang Hames std::vector<JITDylibState *> Deps; 197bb5f97e3SLang Hames AtExitsVector AtExits; 198f9aef477SLang Hames const objc_image_info *ObjCImageInfo = nullptr; 19947e9e588SLang Hames std::unordered_map<void *, std::vector<char>> DataSectionContent; 20047e9e588SLang Hames std::unordered_map<void *, size_t> ZeroInitRanges; 2013507df9cSLang Hames UnwindSectionsMap UnwindSections; 202873584b6SLang Hames RecordSectionsTracker<void (*)()> ModInitsSections; 203f448d446SLang Hames RecordSectionsTracker<char> ObjCRuntimeRegistrationObjects; 204f9aef477SLang Hames 205f9aef477SLang Hames bool referenced() const { 206f9aef477SLang Hames return LinkedAgainstRefCount != 0 || DlRefCount != 0; 207f9aef477SLang Hames } 208bb5f97e3SLang Hames }; 209bb5f97e3SLang Hames 210bb5f97e3SLang Hames public: 2113507df9cSLang Hames static Error create(); 212bb5f97e3SLang Hames static MachOPlatformRuntimeState &get(); 2133507df9cSLang Hames static Error destroy(); 214bb5f97e3SLang Hames 215bb5f97e3SLang Hames MachOPlatformRuntimeState() = default; 216bb5f97e3SLang Hames 217bb5f97e3SLang Hames // Delete copy and move constructors. 218bb5f97e3SLang Hames MachOPlatformRuntimeState(const MachOPlatformRuntimeState &) = delete; 219bb5f97e3SLang Hames MachOPlatformRuntimeState & 220bb5f97e3SLang Hames operator=(const MachOPlatformRuntimeState &) = delete; 221bb5f97e3SLang Hames MachOPlatformRuntimeState(MachOPlatformRuntimeState &&) = delete; 222bb5f97e3SLang Hames MachOPlatformRuntimeState &operator=(MachOPlatformRuntimeState &&) = delete; 223bb5f97e3SLang Hames 2243507df9cSLang Hames Error initialize(); 2253507df9cSLang Hames Error shutdown(); 2263507df9cSLang Hames 227f9aef477SLang Hames Error registerJITDylib(std::string Name, void *Header); 228f9aef477SLang Hames Error deregisterJITDylib(void *Header); 229f9aef477SLang Hames Error registerThreadDataSection(span<const char> ThreadDataSection); 230f9aef477SLang Hames Error deregisterThreadDataSection(span<const char> ThreadDataSection); 231bb41fc68SLang Hames Error registerObjectSymbolTable( 232bb41fc68SLang Hames ExecutorAddr HeaderAddr, 233bb41fc68SLang Hames const std::vector<std::tuple<ExecutorAddr, ExecutorAddr, 234bb41fc68SLang Hames MachOExecutorSymbolFlags>> &Entries); 235bb41fc68SLang Hames Error deregisterObjectSymbolTable( 236bb41fc68SLang Hames ExecutorAddr HeaderAddr, 237bb41fc68SLang Hames const std::vector<std::tuple<ExecutorAddr, ExecutorAddr, 238bb41fc68SLang Hames MachOExecutorSymbolFlags>> &Entries); 239f9aef477SLang Hames Error registerObjectPlatformSections( 2403507df9cSLang Hames ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindSections, 2411dcff823SLang Hames std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs); 242f9aef477SLang Hames Error deregisterObjectPlatformSections( 2433507df9cSLang Hames ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindSections, 2441dcff823SLang Hames std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs); 245bb5f97e3SLang Hames 246bb5f97e3SLang Hames const char *dlerror(); 2471dcff823SLang Hames void *dlopen(std::string_view Name, int Mode); 248*5f9e6c81SSahilPatidar int dlupdate(void *DSOHandle); 249bb5f97e3SLang Hames int dlclose(void *DSOHandle); 250bb41fc68SLang Hames void *dlsym(void *DSOHandle, const char *Symbol); 251bb5f97e3SLang Hames 252bb5f97e3SLang Hames int registerAtExit(void (*F)(void *), void *Arg, void *DSOHandle); 253e7707464SLang Hames void runAtExits(std::unique_lock<std::mutex> &JDStatesLock, 254e7707464SLang Hames JITDylibState &JDS); 255bb5f97e3SLang Hames void runAtExits(void *DSOHandle); 256bb5f97e3SLang Hames 257eda6afdaSLang Hames /// Returns the base address of the section containing ThreadData. 258eda6afdaSLang Hames Expected<std::pair<const char *, size_t>> 259eda6afdaSLang Hames getThreadDataSectionFor(const char *ThreadData); 260eda6afdaSLang Hames 261bb5f97e3SLang Hames private: 262f9aef477SLang Hames JITDylibState *getJITDylibStateByHeader(void *DSOHandle); 2631dcff823SLang Hames JITDylibState *getJITDylibStateByName(std::string_view Path); 264bb5f97e3SLang Hames 265bb41fc68SLang Hames /// Requests materialization of the given symbols. For each pair, the bool 266bb41fc68SLang Hames /// element indicates whether the symbol is required (true) or weakly 267bb41fc68SLang Hames /// referenced (false). 268bb41fc68SLang Hames Error requestPushSymbols(JITDylibState &JDS, 269bb41fc68SLang Hames span<std::pair<std::string_view, bool>> Symbols); 270bb41fc68SLang Hames 271437b4f1cSLang Hames /// Attempts to look up the given symbols locally, requesting a push from the 272437b4f1cSLang Hames /// remote if they're not found. Results are written to the Result span, which 273437b4f1cSLang Hames /// must have the same size as the Symbols span. 274437b4f1cSLang Hames Error 275437b4f1cSLang Hames lookupSymbols(JITDylibState &JDS, std::unique_lock<std::mutex> &JDStatesLock, 276437b4f1cSLang Hames span<std::pair<ExecutorAddr, MachOExecutorSymbolFlags>> Result, 277437b4f1cSLang Hames span<std::pair<std::string_view, bool>> Symbols); 278bb5f97e3SLang Hames 2793507df9cSLang Hames bool lookupUnwindSections(void *Addr, unw_dynamic_unwind_sections &Info); 2803507df9cSLang Hames 2813507df9cSLang Hames static int findDynamicUnwindSections(uintptr_t addr, 2823507df9cSLang Hames unw_dynamic_unwind_sections *info); 283217fd59cSLang Hames static Error registerEHFrames(span<const char> EHFrameSection); 284217fd59cSLang Hames static Error deregisterEHFrames(span<const char> EHFrameSection); 285217fd59cSLang Hames 286fa089efaSBen Langmuir static Error 287fa089efaSBen Langmuir registerObjCRegistrationObjects(std::unique_lock<std::mutex> &JDStatesLock, 288fa089efaSBen Langmuir JITDylibState &JDS); 289e7707464SLang Hames static Error runModInits(std::unique_lock<std::mutex> &JDStatesLock, 290e7707464SLang Hames JITDylibState &JDS); 291f9aef477SLang Hames 2921dcff823SLang Hames Expected<void *> dlopenImpl(std::string_view Path, int Mode); 293e7707464SLang Hames Error dlopenFull(std::unique_lock<std::mutex> &JDStatesLock, 294e7707464SLang Hames JITDylibState &JDS); 295e7707464SLang Hames Error dlopenInitialize(std::unique_lock<std::mutex> &JDStatesLock, 296e7707464SLang Hames JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo); 297f9aef477SLang Hames 298*5f9e6c81SSahilPatidar Error dlupdateImpl(void *DSOHandle); 29968f31aaaSSahilPatidar Error dlupdateFull(std::unique_lock<std::mutex> &JDStatesLock, 30068f31aaaSSahilPatidar JITDylibState &JDS); 30168f31aaaSSahilPatidar Error dlupdateInitialize(std::unique_lock<std::mutex> &JDStatesLock, 30268f31aaaSSahilPatidar JITDylibState &JDS); 30368f31aaaSSahilPatidar 304f9aef477SLang Hames Error dlcloseImpl(void *DSOHandle); 305e7707464SLang Hames Error dlcloseDeinitialize(std::unique_lock<std::mutex> &JDStatesLock, 306e7707464SLang Hames JITDylibState &JDS); 307bb5f97e3SLang Hames 308bb5f97e3SLang Hames static MachOPlatformRuntimeState *MOPS; 309bb5f97e3SLang Hames 3103507df9cSLang Hames bool UseCallbackStyleUnwindInfo = false; 3113507df9cSLang Hames 312bb5f97e3SLang Hames // FIXME: Move to thread-state. 313bb5f97e3SLang Hames std::string DLFcnError; 314bb5f97e3SLang Hames 315e7707464SLang Hames // APIMutex guards against concurrent entry into key "dyld" API functions 316e7707464SLang Hames // (e.g. dlopen, dlclose). 317e7707464SLang Hames std::recursive_mutex DyldAPIMutex; 318e7707464SLang Hames 319e7707464SLang Hames // JDStatesMutex guards the data structures that hold JITDylib state. 320e7707464SLang Hames std::mutex JDStatesMutex; 321f9aef477SLang Hames std::unordered_map<void *, JITDylibState> JDStates; 3221dcff823SLang Hames std::unordered_map<std::string_view, void *> JDNameToHeader; 323eda6afdaSLang Hames 324e7707464SLang Hames // ThreadDataSectionsMutex guards thread local data section state. 325eda6afdaSLang Hames std::mutex ThreadDataSectionsMutex; 326eda6afdaSLang Hames std::map<const char *, size_t> ThreadDataSections; 327bb5f97e3SLang Hames }; 328bb5f97e3SLang Hames 329bb41fc68SLang Hames } // anonymous namespace 330bb41fc68SLang Hames 3313e04ad42SLang Hames namespace orc_rt { 332bb41fc68SLang Hames 333bb41fc68SLang Hames class SPSMachOExecutorSymbolFlags; 334bb41fc68SLang Hames 335bb41fc68SLang Hames template <> 336bb41fc68SLang Hames class SPSSerializationTraits< 337bb41fc68SLang Hames SPSMachOExecutorSymbolFlags, 338bb41fc68SLang Hames MachOPlatformRuntimeState::MachOExecutorSymbolFlags> { 339bb41fc68SLang Hames private: 340bb41fc68SLang Hames using UT = std::underlying_type_t< 341bb41fc68SLang Hames MachOPlatformRuntimeState::MachOExecutorSymbolFlags>; 342bb41fc68SLang Hames 343bb41fc68SLang Hames public: 344bb41fc68SLang Hames static size_t 345bb41fc68SLang Hames size(const MachOPlatformRuntimeState::MachOExecutorSymbolFlags &SF) { 346bb41fc68SLang Hames return sizeof(UT); 347bb41fc68SLang Hames } 348bb41fc68SLang Hames 349bb41fc68SLang Hames static bool 350bb41fc68SLang Hames serialize(SPSOutputBuffer &OB, 351bb41fc68SLang Hames const MachOPlatformRuntimeState::MachOExecutorSymbolFlags &SF) { 352bb41fc68SLang Hames return SPSArgList<UT>::serialize(OB, static_cast<UT>(SF)); 353bb41fc68SLang Hames } 354bb41fc68SLang Hames 355bb41fc68SLang Hames static bool 356bb41fc68SLang Hames deserialize(SPSInputBuffer &IB, 357bb41fc68SLang Hames MachOPlatformRuntimeState::MachOExecutorSymbolFlags &SF) { 358bb41fc68SLang Hames UT Tmp; 359bb41fc68SLang Hames if (!SPSArgList<UT>::deserialize(IB, Tmp)) 360bb41fc68SLang Hames return false; 361bb41fc68SLang Hames SF = static_cast<MachOPlatformRuntimeState::MachOExecutorSymbolFlags>(Tmp); 362bb41fc68SLang Hames return true; 363bb41fc68SLang Hames } 364bb41fc68SLang Hames }; 365bb41fc68SLang Hames 3663e04ad42SLang Hames } // namespace orc_rt 367bb41fc68SLang Hames 368bb41fc68SLang Hames namespace { 369bb41fc68SLang Hames 370bb5f97e3SLang Hames MachOPlatformRuntimeState *MachOPlatformRuntimeState::MOPS = nullptr; 371bb5f97e3SLang Hames 3723507df9cSLang Hames Error MachOPlatformRuntimeState::create() { 373bb5f97e3SLang Hames assert(!MOPS && "MachOPlatformRuntimeState should be null"); 374bb5f97e3SLang Hames MOPS = new MachOPlatformRuntimeState(); 3753507df9cSLang Hames return MOPS->initialize(); 376bb5f97e3SLang Hames } 377bb5f97e3SLang Hames 378bb5f97e3SLang Hames MachOPlatformRuntimeState &MachOPlatformRuntimeState::get() { 379bb5f97e3SLang Hames assert(MOPS && "MachOPlatformRuntimeState not initialized"); 380bb5f97e3SLang Hames return *MOPS; 381bb5f97e3SLang Hames } 382bb5f97e3SLang Hames 3833507df9cSLang Hames Error MachOPlatformRuntimeState::destroy() { 384bb5f97e3SLang Hames assert(MOPS && "MachOPlatformRuntimeState not initialized"); 3853507df9cSLang Hames auto Err = MOPS->shutdown(); 386bb5f97e3SLang Hames delete MOPS; 3873507df9cSLang Hames return Err; 3883507df9cSLang Hames } 3893507df9cSLang Hames 3903507df9cSLang Hames Error MachOPlatformRuntimeState::initialize() { 3913507df9cSLang Hames UseCallbackStyleUnwindInfo = __unw_add_find_dynamic_unwind_sections && 3923507df9cSLang Hames __unw_remove_find_dynamic_unwind_sections; 3933507df9cSLang Hames if (UseCallbackStyleUnwindInfo) { 3943507df9cSLang Hames ORC_RT_DEBUG({ 3953507df9cSLang Hames printdbg("__unw_add/remove_find_dynamic_unwind_sections available." 3963507df9cSLang Hames " Using callback-based frame info lookup.\n"); 3973507df9cSLang Hames }); 3983507df9cSLang Hames if (__unw_add_find_dynamic_unwind_sections(&findDynamicUnwindSections)) 3993507df9cSLang Hames return make_error<StringError>( 4003507df9cSLang Hames "Could not register findDynamicUnwindSections"); 4013507df9cSLang Hames } else { 4023507df9cSLang Hames ORC_RT_DEBUG({ 4033507df9cSLang Hames printdbg("__unw_add/remove_find_dynamic_unwind_sections not available." 4043507df9cSLang Hames " Using classic frame info registration.\n"); 4053507df9cSLang Hames }); 4063507df9cSLang Hames } 4073507df9cSLang Hames return Error::success(); 4083507df9cSLang Hames } 4093507df9cSLang Hames 4103507df9cSLang Hames Error MachOPlatformRuntimeState::shutdown() { 411332a934cSLang Hames if (UseCallbackStyleUnwindInfo) { 4123507df9cSLang Hames if (__unw_remove_find_dynamic_unwind_sections(&findDynamicUnwindSections)) { 4133507df9cSLang Hames ORC_RT_DEBUG( 4143507df9cSLang Hames { printdbg("__unw_remove_find_dynamic_unwind_sections failed.\n"); }); 4153507df9cSLang Hames } 4163507df9cSLang Hames } 4173507df9cSLang Hames return Error::success(); 418bb5f97e3SLang Hames } 419bb5f97e3SLang Hames 420f9aef477SLang Hames Error MachOPlatformRuntimeState::registerJITDylib(std::string Name, 421f9aef477SLang Hames void *Header) { 422f9aef477SLang Hames ORC_RT_DEBUG({ 423f9aef477SLang Hames printdbg("Registering JITDylib %s: Header = %p\n", Name.c_str(), Header); 424f9aef477SLang Hames }); 425e7707464SLang Hames std::lock_guard<std::mutex> Lock(JDStatesMutex); 426f9aef477SLang Hames if (JDStates.count(Header)) { 427f9aef477SLang Hames std::ostringstream ErrStream; 428f9aef477SLang Hames ErrStream << "Duplicate JITDylib registration for header " << Header 429f9aef477SLang Hames << " (name = " << Name << ")"; 430f9aef477SLang Hames return make_error<StringError>(ErrStream.str()); 431f9aef477SLang Hames } 432f9aef477SLang Hames if (JDNameToHeader.count(Name)) { 433f9aef477SLang Hames std::ostringstream ErrStream; 434f9aef477SLang Hames ErrStream << "Duplicate JITDylib registration for header " << Header 435f9aef477SLang Hames << " (header = " << Header << ")"; 436f9aef477SLang Hames return make_error<StringError>(ErrStream.str()); 437f9aef477SLang Hames } 438f9aef477SLang Hames 439f9aef477SLang Hames auto &JDS = JDStates[Header]; 440f9aef477SLang Hames JDS.Name = std::move(Name); 441f9aef477SLang Hames JDS.Header = Header; 442f9aef477SLang Hames JDNameToHeader[JDS.Name] = Header; 443f9aef477SLang Hames return Error::success(); 444f9aef477SLang Hames } 445f9aef477SLang Hames 446f9aef477SLang Hames Error MachOPlatformRuntimeState::deregisterJITDylib(void *Header) { 447e7707464SLang Hames std::lock_guard<std::mutex> Lock(JDStatesMutex); 448f9aef477SLang Hames auto I = JDStates.find(Header); 449f9aef477SLang Hames if (I == JDStates.end()) { 450f9aef477SLang Hames std::ostringstream ErrStream; 451f9aef477SLang Hames ErrStream << "Attempted to deregister unrecognized header " << Header; 452f9aef477SLang Hames return make_error<StringError>(ErrStream.str()); 453f9aef477SLang Hames } 454f9aef477SLang Hames 455f9aef477SLang Hames // Remove std::string construction once we can use C++20. 456f9aef477SLang Hames auto J = JDNameToHeader.find( 457f9aef477SLang Hames std::string(I->second.Name.data(), I->second.Name.size())); 458f9aef477SLang Hames assert(J != JDNameToHeader.end() && 459f9aef477SLang Hames "Missing JDNameToHeader entry for JITDylib"); 460f9aef477SLang Hames 461f9aef477SLang Hames ORC_RT_DEBUG({ 462f9aef477SLang Hames printdbg("Deregistering JITDylib %s: Header = %p\n", I->second.Name.c_str(), 463f9aef477SLang Hames Header); 464f9aef477SLang Hames }); 465f9aef477SLang Hames 466f9aef477SLang Hames JDNameToHeader.erase(J); 467f9aef477SLang Hames JDStates.erase(I); 468f9aef477SLang Hames return Error::success(); 469f9aef477SLang Hames } 470f9aef477SLang Hames 471ff846fcbSLang Hames Error MachOPlatformRuntimeState::registerThreadDataSection( 472ff846fcbSLang Hames span<const char> ThreadDataSection) { 473ff846fcbSLang Hames std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex); 474ff846fcbSLang Hames auto I = ThreadDataSections.upper_bound(ThreadDataSection.data()); 475ff846fcbSLang Hames if (I != ThreadDataSections.begin()) { 476ff846fcbSLang Hames auto J = std::prev(I); 477ff846fcbSLang Hames if (J->first + J->second > ThreadDataSection.data()) 478ff846fcbSLang Hames return make_error<StringError>("Overlapping __thread_data sections"); 479eda6afdaSLang Hames } 480ff846fcbSLang Hames ThreadDataSections.insert( 481ff846fcbSLang Hames I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size())); 482bb5f97e3SLang Hames return Error::success(); 483bb5f97e3SLang Hames } 484bb5f97e3SLang Hames 485ff846fcbSLang Hames Error MachOPlatformRuntimeState::deregisterThreadDataSection( 486ff846fcbSLang Hames span<const char> ThreadDataSection) { 487ff846fcbSLang Hames std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex); 4883fb64161SLang Hames auto I = ThreadDataSections.find(ThreadDataSection.data()); 489ff846fcbSLang Hames if (I == ThreadDataSections.end()) 490ff846fcbSLang Hames return make_error<StringError>("Attempt to deregister unknown thread data " 491ff846fcbSLang Hames "section"); 492ff846fcbSLang Hames ThreadDataSections.erase(I); 493bb5f97e3SLang Hames return Error::success(); 494bb5f97e3SLang Hames } 495bb5f97e3SLang Hames 496bb41fc68SLang Hames Error MachOPlatformRuntimeState::registerObjectSymbolTable( 497bb41fc68SLang Hames ExecutorAddr HeaderAddr, 498bb41fc68SLang Hames const std::vector<std::tuple<ExecutorAddr, ExecutorAddr, 499bb41fc68SLang Hames MachOExecutorSymbolFlags>> &Entries) { 500bb41fc68SLang Hames 501bb41fc68SLang Hames std::lock_guard<std::mutex> Lock(JDStatesMutex); 502bb41fc68SLang Hames auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>()); 503bb41fc68SLang Hames if (!JDS) { 504bb41fc68SLang Hames std::ostringstream ErrStream; 505bb41fc68SLang Hames ErrStream << "Could not register object platform sections for " 506bb41fc68SLang Hames "unrecognized header " 507bb41fc68SLang Hames << HeaderAddr.toPtr<void *>(); 508bb41fc68SLang Hames return make_error<StringError>(ErrStream.str()); 509bb41fc68SLang Hames } 510bb41fc68SLang Hames 511bb41fc68SLang Hames for (auto &[NameAddr, SymAddr, Flags] : Entries) 512bb41fc68SLang Hames JDS->SymbolTable[NameAddr.toPtr<const char *>()] = {SymAddr, Flags}; 513bb41fc68SLang Hames 514bb41fc68SLang Hames return Error::success(); 515bb41fc68SLang Hames } 516bb41fc68SLang Hames 517bb41fc68SLang Hames Error MachOPlatformRuntimeState::deregisterObjectSymbolTable( 518bb41fc68SLang Hames ExecutorAddr HeaderAddr, 519bb41fc68SLang Hames const std::vector<std::tuple<ExecutorAddr, ExecutorAddr, 520bb41fc68SLang Hames MachOExecutorSymbolFlags>> &Entries) { 521bb41fc68SLang Hames 522bb41fc68SLang Hames std::lock_guard<std::mutex> Lock(JDStatesMutex); 523bb41fc68SLang Hames auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>()); 524bb41fc68SLang Hames if (!JDS) { 525bb41fc68SLang Hames std::ostringstream ErrStream; 526bb41fc68SLang Hames ErrStream << "Could not register object platform sections for " 527bb41fc68SLang Hames "unrecognized header " 528bb41fc68SLang Hames << HeaderAddr.toPtr<void *>(); 529bb41fc68SLang Hames return make_error<StringError>(ErrStream.str()); 530bb41fc68SLang Hames } 531bb41fc68SLang Hames 532bb41fc68SLang Hames for (auto &[NameAddr, SymAddr, Flags] : Entries) 533bb41fc68SLang Hames JDS->SymbolTable.erase(NameAddr.toPtr<const char *>()); 534bb41fc68SLang Hames 535bb41fc68SLang Hames return Error::success(); 536bb41fc68SLang Hames } 537bb41fc68SLang Hames 538f9aef477SLang Hames Error MachOPlatformRuntimeState::registerObjectPlatformSections( 5393507df9cSLang Hames ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindInfo, 5401dcff823SLang Hames std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs) { 541e7707464SLang Hames 542e7707464SLang Hames // FIXME: Reject platform section registration after the JITDylib is 543e7707464SLang Hames // sealed? 544e7707464SLang Hames 545f9aef477SLang Hames ORC_RT_DEBUG({ 546f9aef477SLang Hames printdbg("MachOPlatform: Registering object sections for %p.\n", 547f9aef477SLang Hames HeaderAddr.toPtr<void *>()); 548f9aef477SLang Hames }); 549f9aef477SLang Hames 550e7707464SLang Hames std::lock_guard<std::mutex> Lock(JDStatesMutex); 551f9aef477SLang Hames auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>()); 552f9aef477SLang Hames if (!JDS) { 553f9aef477SLang Hames std::ostringstream ErrStream; 554f9aef477SLang Hames ErrStream << "Could not register object platform sections for " 555f9aef477SLang Hames "unrecognized header " 556f9aef477SLang Hames << HeaderAddr.toPtr<void *>(); 557f9aef477SLang Hames return make_error<StringError>(ErrStream.str()); 558f9aef477SLang Hames } 559f9aef477SLang Hames 5603507df9cSLang Hames if (UnwindInfo && UseCallbackStyleUnwindInfo) { 5613507df9cSLang Hames ORC_RT_DEBUG({ 5623507df9cSLang Hames printdbg(" Registering new-style unwind info for:\n" 5633507df9cSLang Hames " DWARF: %p -- %p\n" 5643507df9cSLang Hames " Compact-unwind: %p -- %p\n" 5653507df9cSLang Hames " for:\n", 5663507df9cSLang Hames UnwindInfo->DwarfSection.Start.toPtr<void *>(), 5673507df9cSLang Hames UnwindInfo->DwarfSection.End.toPtr<void *>(), 5683507df9cSLang Hames UnwindInfo->CompactUnwindSection.Start.toPtr<void *>(), 5693507df9cSLang Hames UnwindInfo->CompactUnwindSection.End.toPtr<void *>()); 5703507df9cSLang Hames }); 5713507df9cSLang Hames for (auto &CodeRange : UnwindInfo->CodeRanges) { 5723507df9cSLang Hames JDS->UnwindSections.insert(CodeRange.Start.toPtr<char *>(), 5733507df9cSLang Hames CodeRange.End.toPtr<char *>(), *UnwindInfo); 5743507df9cSLang Hames ORC_RT_DEBUG({ 5753507df9cSLang Hames printdbg(" [ %p -- %p ]\n", CodeRange.Start.toPtr<void *>(), 5763507df9cSLang Hames CodeRange.End.toPtr<void *>()); 5773507df9cSLang Hames }); 5783507df9cSLang Hames } 5793507df9cSLang Hames } 5803507df9cSLang Hames 581f9aef477SLang Hames for (auto &KV : Secs) { 582f9aef477SLang Hames // FIXME: Validate section ranges? 583217fd59cSLang Hames if (KV.first == "__TEXT,__eh_frame") { 5843507df9cSLang Hames if (!UseCallbackStyleUnwindInfo) { 5853507df9cSLang Hames // Use classic libunwind registration. 586217fd59cSLang Hames if (auto Err = registerEHFrames(KV.second.toSpan<const char>())) 587217fd59cSLang Hames return Err; 5883507df9cSLang Hames } 589217fd59cSLang Hames } else if (KV.first == "__DATA,__data") { 59047e9e588SLang Hames assert(!JDS->DataSectionContent.count(KV.second.Start.toPtr<char *>()) && 59147e9e588SLang Hames "Address already registered."); 59247e9e588SLang Hames auto S = KV.second.toSpan<char>(); 59347e9e588SLang Hames JDS->DataSectionContent[KV.second.Start.toPtr<char *>()] = 59447e9e588SLang Hames std::vector<char>(S.begin(), S.end()); 59547e9e588SLang Hames } else if (KV.first == "__DATA,__common") { 59647e9e588SLang Hames JDS->ZeroInitRanges[KV.second.Start.toPtr<char *>()] = KV.second.size(); 59747e9e588SLang Hames } else if (KV.first == "__DATA,__thread_data") { 598f9aef477SLang Hames if (auto Err = registerThreadDataSection(KV.second.toSpan<const char>())) 599f9aef477SLang Hames return Err; 600f448d446SLang Hames } else if (KV.first == "__llvm_jitlink_ObjCRuntimeRegistrationObject") 601f448d446SLang Hames JDS->ObjCRuntimeRegistrationObjects.add(KV.second.toSpan<char>()); 602f9aef477SLang Hames else if (KV.first == "__DATA,__mod_init_func") 603873584b6SLang Hames JDS->ModInitsSections.add(KV.second.toSpan<void (*)()>()); 604f9aef477SLang Hames else { 605f9aef477SLang Hames // Should this be a warning instead? 606f9aef477SLang Hames return make_error<StringError>( 607f9aef477SLang Hames "Encountered unexpected section " + 608f9aef477SLang Hames std::string(KV.first.data(), KV.first.size()) + 609f9aef477SLang Hames " while registering object platform sections"); 610f9aef477SLang Hames } 611f9aef477SLang Hames } 612f9aef477SLang Hames 613f9aef477SLang Hames return Error::success(); 614f9aef477SLang Hames } 615f9aef477SLang Hames 616f9aef477SLang Hames Error MachOPlatformRuntimeState::deregisterObjectPlatformSections( 6173507df9cSLang Hames ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> UnwindInfo, 6181dcff823SLang Hames std::vector<std::pair<std::string_view, ExecutorAddrRange>> Secs) { 619f9aef477SLang Hames // TODO: Make this more efficient? (maybe unnecessary if removal is rare?) 620f9aef477SLang Hames // TODO: Add a JITDylib prepare-for-teardown operation that clears all 621f9aef477SLang Hames // registered sections, causing this function to take the fast-path. 622f9aef477SLang Hames ORC_RT_DEBUG({ 6236098e2e5SLang Hames printdbg("MachOPlatform: Deregistering object sections for %p.\n", 624f9aef477SLang Hames HeaderAddr.toPtr<void *>()); 625f9aef477SLang Hames }); 626f9aef477SLang Hames 627e7707464SLang Hames std::lock_guard<std::mutex> Lock(JDStatesMutex); 628f9aef477SLang Hames auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>()); 629f9aef477SLang Hames if (!JDS) { 630f9aef477SLang Hames std::ostringstream ErrStream; 631f9aef477SLang Hames ErrStream << "Could not register object platform sections for unrecognized " 632f9aef477SLang Hames "header " 633f9aef477SLang Hames << HeaderAddr.toPtr<void *>(); 634f9aef477SLang Hames return make_error<StringError>(ErrStream.str()); 635f9aef477SLang Hames } 636f9aef477SLang Hames 637f9aef477SLang Hames // FIXME: Implement faster-path by returning immediately if JDS is being 638f9aef477SLang Hames // torn down entirely? 639f9aef477SLang Hames 64047e9e588SLang Hames // TODO: Make library permanent (i.e. not able to be dlclosed) if it contains 64147e9e588SLang Hames // any Swift or ObjC. Once this happens we can clear (and no longer record) 64247e9e588SLang Hames // data section content, as the library could never be re-initialized. 64347e9e588SLang Hames 6443507df9cSLang Hames if (UnwindInfo && UseCallbackStyleUnwindInfo) { 6453507df9cSLang Hames ORC_RT_DEBUG({ 6463507df9cSLang Hames printdbg(" Deregistering new-style unwind info for:\n" 6473507df9cSLang Hames " DWARF: %p -- %p\n" 6483507df9cSLang Hames " Compact-unwind: %p -- %p\n" 6493507df9cSLang Hames " for:\n", 6503507df9cSLang Hames UnwindInfo->DwarfSection.Start.toPtr<void *>(), 6513507df9cSLang Hames UnwindInfo->DwarfSection.End.toPtr<void *>(), 6523507df9cSLang Hames UnwindInfo->CompactUnwindSection.Start.toPtr<void *>(), 6533507df9cSLang Hames UnwindInfo->CompactUnwindSection.End.toPtr<void *>()); 6543507df9cSLang Hames }); 6553507df9cSLang Hames for (auto &CodeRange : UnwindInfo->CodeRanges) { 6563507df9cSLang Hames JDS->UnwindSections.erase(CodeRange.Start.toPtr<char *>(), 6573507df9cSLang Hames CodeRange.End.toPtr<char *>()); 6583507df9cSLang Hames ORC_RT_DEBUG({ 6593507df9cSLang Hames printdbg(" [ %p -- %p ]\n", CodeRange.Start.toPtr<void *>(), 6603507df9cSLang Hames CodeRange.End.toPtr<void *>()); 6613507df9cSLang Hames }); 6623507df9cSLang Hames } 6633507df9cSLang Hames } 6643507df9cSLang Hames 665f9aef477SLang Hames for (auto &KV : Secs) { 666f9aef477SLang Hames // FIXME: Validate section ranges? 667217fd59cSLang Hames if (KV.first == "__TEXT,__eh_frame") { 6683507df9cSLang Hames if (!UseCallbackStyleUnwindInfo) { 6693507df9cSLang Hames // Use classic libunwind registration. 670217fd59cSLang Hames if (auto Err = deregisterEHFrames(KV.second.toSpan<const char>())) 671217fd59cSLang Hames return Err; 6723507df9cSLang Hames } 673217fd59cSLang Hames } else if (KV.first == "__DATA,__data") { 67447e9e588SLang Hames JDS->DataSectionContent.erase(KV.second.Start.toPtr<char *>()); 67547e9e588SLang Hames } else if (KV.first == "__DATA,__common") { 67647e9e588SLang Hames JDS->ZeroInitRanges.erase(KV.second.Start.toPtr<char *>()); 67747e9e588SLang Hames } else if (KV.first == "__DATA,__thread_data") { 678f9aef477SLang Hames if (auto Err = 679f9aef477SLang Hames deregisterThreadDataSection(KV.second.toSpan<const char>())) 680f9aef477SLang Hames return Err; 681f448d446SLang Hames } else if (KV.first == "__llvm_jitlink_ObjCRuntimeRegistrationObject") 682f448d446SLang Hames JDS->ObjCRuntimeRegistrationObjects.removeIfPresent(KV.second); 683873584b6SLang Hames else if (KV.first == "__DATA,__mod_init_func") 684873584b6SLang Hames JDS->ModInitsSections.removeIfPresent(KV.second); 685873584b6SLang Hames else { 686f9aef477SLang Hames // Should this be a warning instead? 687f9aef477SLang Hames return make_error<StringError>( 688f9aef477SLang Hames "Encountered unexpected section " + 689f9aef477SLang Hames std::string(KV.first.data(), KV.first.size()) + 690f9aef477SLang Hames " while deregistering object platform sections"); 691f9aef477SLang Hames } 692f9aef477SLang Hames } 693f9aef477SLang Hames return Error::success(); 694f9aef477SLang Hames } 695f9aef477SLang Hames 696bb5f97e3SLang Hames const char *MachOPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); } 697bb5f97e3SLang Hames 6981dcff823SLang Hames void *MachOPlatformRuntimeState::dlopen(std::string_view Path, int Mode) { 699f9aef477SLang Hames ORC_RT_DEBUG({ 700f9aef477SLang Hames std::string S(Path.data(), Path.size()); 701f9aef477SLang Hames printdbg("MachOPlatform::dlopen(\"%s\")\n", S.c_str()); 702f9aef477SLang Hames }); 703e7707464SLang Hames std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex); 704f9aef477SLang Hames if (auto H = dlopenImpl(Path, Mode)) 705f9aef477SLang Hames return *H; 706f9aef477SLang Hames else { 707f9aef477SLang Hames // FIXME: Make dlerror thread safe. 708bb5f97e3SLang Hames DLFcnError = toString(H.takeError()); 709bb5f97e3SLang Hames return nullptr; 710bb5f97e3SLang Hames } 711bb5f97e3SLang Hames } 712bb5f97e3SLang Hames 713*5f9e6c81SSahilPatidar int MachOPlatformRuntimeState::dlupdate(void *DSOHandle) { 71468f31aaaSSahilPatidar ORC_RT_DEBUG({ 71568f31aaaSSahilPatidar std::string S; 71668f31aaaSSahilPatidar printdbg("MachOPlatform::dlupdate(%p) (%s)\n", DSOHandle, S.c_str()); 71768f31aaaSSahilPatidar }); 71868f31aaaSSahilPatidar std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex); 719*5f9e6c81SSahilPatidar if (auto Err = dlupdateImpl(DSOHandle)) { 72068f31aaaSSahilPatidar // FIXME: Make dlerror thread safe. 72168f31aaaSSahilPatidar DLFcnError = toString(std::move(Err)); 72268f31aaaSSahilPatidar return -1; 72368f31aaaSSahilPatidar } 72468f31aaaSSahilPatidar return 0; 72568f31aaaSSahilPatidar } 72668f31aaaSSahilPatidar 727bb5f97e3SLang Hames int MachOPlatformRuntimeState::dlclose(void *DSOHandle) { 728f9aef477SLang Hames ORC_RT_DEBUG({ 729f9aef477SLang Hames auto *JDS = getJITDylibStateByHeader(DSOHandle); 730f9aef477SLang Hames std::string DylibName; 731f9aef477SLang Hames if (JDS) { 732f9aef477SLang Hames std::string S; 733f9aef477SLang Hames printdbg("MachOPlatform::dlclose(%p) (%s)\n", DSOHandle, S.c_str()); 734f9aef477SLang Hames } else 735f9aef477SLang Hames printdbg("MachOPlatform::dlclose(%p) (%s)\n", DSOHandle, 736f9aef477SLang Hames "invalid handle"); 737f9aef477SLang Hames }); 738e7707464SLang Hames std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex); 739f9aef477SLang Hames if (auto Err = dlcloseImpl(DSOHandle)) { 740f9aef477SLang Hames // FIXME: Make dlerror thread safe. 741f9aef477SLang Hames DLFcnError = toString(std::move(Err)); 742f9aef477SLang Hames return -1; 743f9aef477SLang Hames } 744bb5f97e3SLang Hames return 0; 745bb5f97e3SLang Hames } 746bb5f97e3SLang Hames 747bb41fc68SLang Hames void *MachOPlatformRuntimeState::dlsym(void *DSOHandle, const char *Symbol) { 74893509b44SLang Hames std::unique_lock<std::mutex> Lock(JDStatesMutex); 749bb41fc68SLang Hames auto *JDS = getJITDylibStateByHeader(DSOHandle); 750bb41fc68SLang Hames if (!JDS) { 751bb41fc68SLang Hames std::ostringstream ErrStream; 752bb41fc68SLang Hames ErrStream << "In call to dlsym, unrecognized header address " << DSOHandle; 753bb41fc68SLang Hames DLFcnError = ErrStream.str(); 754bb41fc68SLang Hames return nullptr; 755bb5f97e3SLang Hames } 756bb5f97e3SLang Hames 757437b4f1cSLang Hames std::string MangledName = std::string("_") + Symbol; 758437b4f1cSLang Hames std::pair<std::string_view, bool> Lookup(MangledName, false); 759437b4f1cSLang Hames std::pair<ExecutorAddr, MachOExecutorSymbolFlags> Result; 760bb41fc68SLang Hames 761437b4f1cSLang Hames if (auto Err = lookupSymbols(*JDS, Lock, {&Result, 1}, {&Lookup, 1})) { 762bb41fc68SLang Hames DLFcnError = toString(std::move(Err)); 763bb41fc68SLang Hames return nullptr; 764bb41fc68SLang Hames } 765bb41fc68SLang Hames 766dc58f781SBen Langmuir // Sign callable symbols as functions, to match dyld. 767dc58f781SBen Langmuir if ((Result.second & MachOExecutorSymbolFlags::Callable) == 768dc58f781SBen Langmuir MachOExecutorSymbolFlags::Callable) 769dc58f781SBen Langmuir return reinterpret_cast<void *>(Result.first.toPtr<void(void)>()); 770437b4f1cSLang Hames return Result.first.toPtr<void *>(); 771bb5f97e3SLang Hames } 772bb5f97e3SLang Hames 773bb5f97e3SLang Hames int MachOPlatformRuntimeState::registerAtExit(void (*F)(void *), void *Arg, 774bb5f97e3SLang Hames void *DSOHandle) { 775bb5f97e3SLang Hames // FIXME: Handle out-of-memory errors, returning -1 if OOM. 776e7707464SLang Hames std::lock_guard<std::mutex> Lock(JDStatesMutex); 777f9aef477SLang Hames auto *JDS = getJITDylibStateByHeader(DSOHandle); 778f9aef477SLang Hames if (!JDS) { 779f9aef477SLang Hames ORC_RT_DEBUG({ 780f9aef477SLang Hames printdbg("MachOPlatformRuntimeState::registerAtExit called with " 781f9aef477SLang Hames "unrecognized dso handle %p\n", 782f9aef477SLang Hames DSOHandle); 783f9aef477SLang Hames }); 784f9aef477SLang Hames return -1; 785f9aef477SLang Hames } 786bb5f97e3SLang Hames JDS->AtExits.push_back({F, Arg}); 787bb5f97e3SLang Hames return 0; 788bb5f97e3SLang Hames } 789bb5f97e3SLang Hames 790e7707464SLang Hames void MachOPlatformRuntimeState::runAtExits( 791e7707464SLang Hames std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 792e7707464SLang Hames auto AtExits = std::move(JDS.AtExits); 793e7707464SLang Hames 794e7707464SLang Hames // Unlock while running atexits, as they may trigger operations that modify 795e7707464SLang Hames // JDStates. 796e7707464SLang Hames JDStatesLock.unlock(); 797e7707464SLang Hames while (!AtExits.empty()) { 798e7707464SLang Hames auto &AE = AtExits.back(); 799f9aef477SLang Hames AE.Func(AE.Arg); 800e7707464SLang Hames AtExits.pop_back(); 801f9aef477SLang Hames } 802e7707464SLang Hames JDStatesLock.lock(); 803bb5f97e3SLang Hames } 804bb5f97e3SLang Hames 805f9aef477SLang Hames void MachOPlatformRuntimeState::runAtExits(void *DSOHandle) { 806e7707464SLang Hames std::unique_lock<std::mutex> Lock(JDStatesMutex); 807f9aef477SLang Hames auto *JDS = getJITDylibStateByHeader(DSOHandle); 808f9aef477SLang Hames ORC_RT_DEBUG({ 809f9aef477SLang Hames printdbg("MachOPlatformRuntimeState::runAtExits called on unrecognized " 810f9aef477SLang Hames "dso_handle %p\n", 811f9aef477SLang Hames DSOHandle); 812f9aef477SLang Hames }); 813f9aef477SLang Hames if (JDS) 814e7707464SLang Hames runAtExits(Lock, *JDS); 815bb5f97e3SLang Hames } 816bb5f97e3SLang Hames 817eda6afdaSLang Hames Expected<std::pair<const char *, size_t>> 818eda6afdaSLang Hames MachOPlatformRuntimeState::getThreadDataSectionFor(const char *ThreadData) { 819eda6afdaSLang Hames std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex); 820eda6afdaSLang Hames auto I = ThreadDataSections.upper_bound(ThreadData); 821eda6afdaSLang Hames // Check that we have a valid entry covering this address. 822eda6afdaSLang Hames if (I == ThreadDataSections.begin()) 823eda6afdaSLang Hames return make_error<StringError>("No thread local data section for key"); 824eda6afdaSLang Hames I = std::prev(I); 825eda6afdaSLang Hames if (ThreadData >= I->first + I->second) 826eda6afdaSLang Hames return make_error<StringError>("No thread local data section for key"); 827eda6afdaSLang Hames return *I; 828eda6afdaSLang Hames } 829eda6afdaSLang Hames 830f9aef477SLang Hames MachOPlatformRuntimeState::JITDylibState * 831f9aef477SLang Hames MachOPlatformRuntimeState::getJITDylibStateByHeader(void *DSOHandle) { 832bb5f97e3SLang Hames auto I = JDStates.find(DSOHandle); 833f9aef477SLang Hames if (I == JDStates.end()) { 834f9aef477SLang Hames I = JDStates.insert(std::make_pair(DSOHandle, JITDylibState())).first; 835f9aef477SLang Hames I->second.Header = DSOHandle; 836f9aef477SLang Hames } 837bb5f97e3SLang Hames return &I->second; 838bb5f97e3SLang Hames } 839bb5f97e3SLang Hames 840f9aef477SLang Hames MachOPlatformRuntimeState::JITDylibState * 8411dcff823SLang Hames MachOPlatformRuntimeState::getJITDylibStateByName(std::string_view Name) { 842f9aef477SLang Hames // FIXME: Avoid creating string once we have C++20. 843bb5f97e3SLang Hames auto I = JDNameToHeader.find(std::string(Name.data(), Name.size())); 844f9aef477SLang Hames if (I != JDNameToHeader.end()) 845f9aef477SLang Hames return getJITDylibStateByHeader(I->second); 846bb5f97e3SLang Hames return nullptr; 847bb5f97e3SLang Hames } 848bb5f97e3SLang Hames 849bb41fc68SLang Hames Error MachOPlatformRuntimeState::requestPushSymbols( 850bb41fc68SLang Hames JITDylibState &JDS, span<std::pair<std::string_view, bool>> Symbols) { 851bb41fc68SLang Hames Error OpErr = Error::success(); 852bb41fc68SLang Hames if (auto Err = WrapperFunction<SPSError( 853bb41fc68SLang Hames SPSExecutorAddr, SPSSequence<SPSTuple<SPSString, bool>>)>:: 85469f8923eSLang Hames call(JITDispatch(&__orc_rt_macho_push_symbols_tag), OpErr, 855bb41fc68SLang Hames ExecutorAddr::fromPtr(JDS.Header), Symbols)) { 856bb41fc68SLang Hames cantFail(std::move(OpErr)); 857bb5f97e3SLang Hames return std::move(Err); 858bb41fc68SLang Hames } 859bb41fc68SLang Hames return OpErr; 860bb41fc68SLang Hames } 861bb41fc68SLang Hames 862437b4f1cSLang Hames Error MachOPlatformRuntimeState::lookupSymbols( 863437b4f1cSLang Hames JITDylibState &JDS, std::unique_lock<std::mutex> &JDStatesLock, 864437b4f1cSLang Hames span<std::pair<ExecutorAddr, MachOExecutorSymbolFlags>> Result, 865437b4f1cSLang Hames span<std::pair<std::string_view, bool>> Symbols) { 866437b4f1cSLang Hames assert(JDStatesLock.owns_lock() && 867437b4f1cSLang Hames "JDStatesLock should be locked at call-site"); 868437b4f1cSLang Hames assert(Result.size() == Symbols.size() && 869437b4f1cSLang Hames "Results and Symbols span sizes should match"); 870bb41fc68SLang Hames 871437b4f1cSLang Hames // Make an initial pass over the local symbol table. 872437b4f1cSLang Hames std::vector<size_t> MissingSymbolIndexes; 873bb41fc68SLang Hames for (size_t Idx = 0; Idx != Symbols.size(); ++Idx) { 874bb41fc68SLang Hames auto I = JDS.SymbolTable.find(Symbols[Idx].first); 875bb41fc68SLang Hames if (I != JDS.SymbolTable.end()) 876437b4f1cSLang Hames Result[Idx] = I->second; 877bb41fc68SLang Hames else 878437b4f1cSLang Hames MissingSymbolIndexes.push_back(Idx); 879bb41fc68SLang Hames } 880bb41fc68SLang Hames 881437b4f1cSLang Hames // If everything has been resolved already then bail out early. 882437b4f1cSLang Hames if (MissingSymbolIndexes.empty()) 883437b4f1cSLang Hames return Error::success(); 884437b4f1cSLang Hames 885437b4f1cSLang Hames // Otherwise call back to the controller to try to request that the symbol 886437b4f1cSLang Hames // be materialized. 887437b4f1cSLang Hames std::vector<std::pair<std::string_view, bool>> MissingSymbols; 888437b4f1cSLang Hames MissingSymbols.reserve(MissingSymbolIndexes.size()); 889f1e3e8a1SJan Svoboda ORC_RT_DEBUG({ 890437b4f1cSLang Hames printdbg("requesting push of %i missing symbols...\n", 891437b4f1cSLang Hames MissingSymbolIndexes.size()); 892f1e3e8a1SJan Svoboda }); 893437b4f1cSLang Hames for (auto MissingIdx : MissingSymbolIndexes) 894437b4f1cSLang Hames MissingSymbols.push_back(Symbols[MissingIdx]); 895437b4f1cSLang Hames 896437b4f1cSLang Hames JDStatesLock.unlock(); 897437b4f1cSLang Hames if (auto Err = requestPushSymbols( 898437b4f1cSLang Hames JDS, {MissingSymbols.data(), MissingSymbols.size()})) 899437b4f1cSLang Hames return Err; 900437b4f1cSLang Hames JDStatesLock.lock(); 901437b4f1cSLang Hames 902437b4f1cSLang Hames // Try to resolve the previously missing symbols locally. 903437b4f1cSLang Hames std::vector<size_t> MissingRequiredSymbols; 904437b4f1cSLang Hames for (auto MissingIdx : MissingSymbolIndexes) { 905437b4f1cSLang Hames auto I = JDS.SymbolTable.find(Symbols[MissingIdx].first); 906437b4f1cSLang Hames if (I != JDS.SymbolTable.end()) 907437b4f1cSLang Hames Result[MissingIdx] = I->second; 908437b4f1cSLang Hames else { 909437b4f1cSLang Hames if (Symbols[MissingIdx].second) 910437b4f1cSLang Hames MissingRequiredSymbols.push_back(MissingIdx); 911437b4f1cSLang Hames else 912437b4f1cSLang Hames Result[MissingIdx] = {ExecutorAddr(), {}}; 913437b4f1cSLang Hames } 914437b4f1cSLang Hames } 915437b4f1cSLang Hames 916437b4f1cSLang Hames // Error out if any missing symbols could not be resolved. 917437b4f1cSLang Hames if (!MissingRequiredSymbols.empty()) { 918437b4f1cSLang Hames std::ostringstream ErrStream; 919437b4f1cSLang Hames ErrStream << "Lookup could not find required symbols: [ "; 920437b4f1cSLang Hames for (auto MissingIdx : MissingRequiredSymbols) 921437b4f1cSLang Hames ErrStream << "\"" << Symbols[MissingIdx].first << "\" "; 922437b4f1cSLang Hames ErrStream << "]"; 923437b4f1cSLang Hames return make_error<StringError>(ErrStream.str()); 924437b4f1cSLang Hames } 925437b4f1cSLang Hames 926437b4f1cSLang Hames return Error::success(); 927bb5f97e3SLang Hames } 928bb5f97e3SLang Hames 929217fd59cSLang Hames // eh-frame registration functions. 930217fd59cSLang Hames // We expect these to be available for all processes. 931217fd59cSLang Hames extern "C" void __register_frame(const void *); 932217fd59cSLang Hames extern "C" void __deregister_frame(const void *); 933217fd59cSLang Hames 934217fd59cSLang Hames template <typename HandleFDEFn> 935217fd59cSLang Hames void walkEHFrameSection(span<const char> EHFrameSection, 936217fd59cSLang Hames HandleFDEFn HandleFDE) { 937217fd59cSLang Hames const char *CurCFIRecord = EHFrameSection.data(); 938217fd59cSLang Hames uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); 939217fd59cSLang Hames 940217fd59cSLang Hames while (CurCFIRecord != EHFrameSection.end() && Size != 0) { 941217fd59cSLang Hames const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4); 942217fd59cSLang Hames if (Size == 0xffffffff) 943217fd59cSLang Hames Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12; 944217fd59cSLang Hames else 945217fd59cSLang Hames Size += 4; 946217fd59cSLang Hames uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField); 947217fd59cSLang Hames 948217fd59cSLang Hames if (Offset != 0) 949217fd59cSLang Hames HandleFDE(CurCFIRecord); 950217fd59cSLang Hames 951217fd59cSLang Hames CurCFIRecord += Size; 952217fd59cSLang Hames Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord); 953217fd59cSLang Hames } 954217fd59cSLang Hames } 955217fd59cSLang Hames 9563507df9cSLang Hames bool MachOPlatformRuntimeState::lookupUnwindSections( 9573507df9cSLang Hames void *Addr, unw_dynamic_unwind_sections &Info) { 9583507df9cSLang Hames ORC_RT_DEBUG( 9593507df9cSLang Hames { printdbg("Tried to lookup unwind-info via new lookup call.\n"); }); 9603507df9cSLang Hames std::lock_guard<std::mutex> Lock(JDStatesMutex); 9613507df9cSLang Hames for (auto &KV : JDStates) { 9623507df9cSLang Hames auto &JD = KV.second; 9633507df9cSLang Hames auto I = JD.UnwindSections.find(reinterpret_cast<char *>(Addr)); 9643507df9cSLang Hames if (I != JD.UnwindSections.end()) { 9653507df9cSLang Hames Info.dso_base = reinterpret_cast<uintptr_t>(JD.Header); 9663507df9cSLang Hames Info.dwarf_section = 9673507df9cSLang Hames reinterpret_cast<uintptr_t>(I->second.DwarfSection.data()); 9683507df9cSLang Hames Info.dwarf_section_length = I->second.DwarfSection.size(); 9693507df9cSLang Hames Info.compact_unwind_section = 9703507df9cSLang Hames reinterpret_cast<uintptr_t>(I->second.CompactUnwindSection.data()); 9713507df9cSLang Hames Info.compact_unwind_section_length = 9723507df9cSLang Hames I->second.CompactUnwindSection.size(); 9733507df9cSLang Hames return true; 9743507df9cSLang Hames } 9753507df9cSLang Hames } 9763507df9cSLang Hames return false; 9773507df9cSLang Hames } 9783507df9cSLang Hames 9793507df9cSLang Hames int MachOPlatformRuntimeState::findDynamicUnwindSections( 9803507df9cSLang Hames uintptr_t addr, unw_dynamic_unwind_sections *info) { 9813507df9cSLang Hames if (!info) 9823507df9cSLang Hames return 0; 9833507df9cSLang Hames return MachOPlatformRuntimeState::get().lookupUnwindSections((void *)addr, 9843507df9cSLang Hames *info); 9853507df9cSLang Hames } 9863507df9cSLang Hames 987217fd59cSLang Hames Error MachOPlatformRuntimeState::registerEHFrames( 988217fd59cSLang Hames span<const char> EHFrameSection) { 989217fd59cSLang Hames walkEHFrameSection(EHFrameSection, __register_frame); 990217fd59cSLang Hames return Error::success(); 991217fd59cSLang Hames } 992217fd59cSLang Hames 993217fd59cSLang Hames Error MachOPlatformRuntimeState::deregisterEHFrames( 994217fd59cSLang Hames span<const char> EHFrameSection) { 995217fd59cSLang Hames walkEHFrameSection(EHFrameSection, __deregister_frame); 996217fd59cSLang Hames return Error::success(); 997217fd59cSLang Hames } 998217fd59cSLang Hames 999f448d446SLang Hames Error MachOPlatformRuntimeState::registerObjCRegistrationObjects( 1000fa089efaSBen Langmuir std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 10019d701c8aSLang Hames ORC_RT_DEBUG(printdbg("Registering Objective-C / Swift metadata.\n")); 10029d701c8aSLang Hames 100361d535acSLang Hames std::vector<char *> RegObjBases; 100461d535acSLang Hames JDS.ObjCRuntimeRegistrationObjects.processNewSections( 100561d535acSLang Hames [&](span<char> RegObj) { RegObjBases.push_back(RegObj.data()); }); 100661d535acSLang Hames 100761d535acSLang Hames if (RegObjBases.empty()) 100861d535acSLang Hames return Error::success(); 100961d535acSLang Hames 1010f448d446SLang Hames if (!_objc_map_images || !_objc_load_image) 1011bb5f97e3SLang Hames return make_error<StringError>( 1012f448d446SLang Hames "Could not register Objective-C / Swift metadata: _objc_map_images / " 1013f448d446SLang Hames "_objc_load_image not found"); 1014bb5f97e3SLang Hames 1015fa089efaSBen Langmuir // Release the lock while calling out to libobjc in case +load methods cause 1016fa089efaSBen Langmuir // reentering the orc runtime. 1017fa089efaSBen Langmuir JDStatesLock.unlock(); 1018f448d446SLang Hames std::vector<char *> Paths; 1019f448d446SLang Hames Paths.resize(RegObjBases.size()); 1020f448d446SLang Hames _objc_map_images(RegObjBases.size(), Paths.data(), 1021f448d446SLang Hames reinterpret_cast<mach_header **>(RegObjBases.data())); 1022f9aef477SLang Hames 1023f448d446SLang Hames for (void *RegObjBase : RegObjBases) 1024f448d446SLang Hames _objc_load_image(nullptr, reinterpret_cast<mach_header *>(RegObjBase)); 1025fa089efaSBen Langmuir JDStatesLock.lock(); 1026f9aef477SLang Hames 1027f9aef477SLang Hames return Error::success(); 1028f9aef477SLang Hames } 1029f9aef477SLang Hames 1030e7707464SLang Hames Error MachOPlatformRuntimeState::runModInits( 1031e7707464SLang Hames std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 1032e7707464SLang Hames std::vector<span<void (*)()>> InitSections; 1033e7707464SLang Hames InitSections.reserve(JDS.ModInitsSections.numNewSections()); 1034e7707464SLang Hames 1035e7707464SLang Hames // Copy initializer sections: If the JITDylib is unsealed then the 1036e7707464SLang Hames // initializers could reach back into the JIT and cause more initializers to 1037e7707464SLang Hames // be added. 1038e7707464SLang Hames // FIXME: Skip unlock and run in-place on sealed JITDylibs? 1039e7707464SLang Hames JDS.ModInitsSections.processNewSections( 1040e7707464SLang Hames [&](span<void (*)()> Inits) { InitSections.push_back(Inits); }); 1041e7707464SLang Hames 1042e7707464SLang Hames JDStatesLock.unlock(); 1043e7707464SLang Hames for (auto InitSec : InitSections) 1044e7707464SLang Hames for (auto *Init : InitSec) 1045873584b6SLang Hames Init(); 1046e7707464SLang Hames JDStatesLock.lock(); 1047e7707464SLang Hames 1048f9aef477SLang Hames return Error::success(); 1049f9aef477SLang Hames } 1050f9aef477SLang Hames 10511dcff823SLang Hames Expected<void *> MachOPlatformRuntimeState::dlopenImpl(std::string_view Path, 1052f9aef477SLang Hames int Mode) { 1053e7707464SLang Hames std::unique_lock<std::mutex> Lock(JDStatesMutex); 1054e7707464SLang Hames 1055f9aef477SLang Hames // Try to find JITDylib state by name. 1056f9aef477SLang Hames auto *JDS = getJITDylibStateByName(Path); 1057f9aef477SLang Hames 1058f9aef477SLang Hames if (!JDS) 1059f9aef477SLang Hames return make_error<StringError>("No registered JTIDylib for path " + 1060f9aef477SLang Hames std::string(Path.data(), Path.size())); 1061f9aef477SLang Hames 1062f9aef477SLang Hames // If this JITDylib is unsealed, or this is the first dlopen then run 1063f9aef477SLang Hames // full dlopen path (update deps, push and run initializers, update ref 1064f9aef477SLang Hames // counts on all JITDylibs in the dep tree). 1065f9aef477SLang Hames if (!JDS->referenced() || !JDS->Sealed) { 1066e7707464SLang Hames if (auto Err = dlopenFull(Lock, *JDS)) 1067bb5f97e3SLang Hames return std::move(Err); 1068f9aef477SLang Hames } 1069bb5f97e3SLang Hames 1070f9aef477SLang Hames // Bump the ref-count on this dylib. 1071f9aef477SLang Hames ++JDS->DlRefCount; 1072f9aef477SLang Hames 1073f9aef477SLang Hames // Return the header address. 1074bb5f97e3SLang Hames return JDS->Header; 1075bb5f97e3SLang Hames } 1076bb5f97e3SLang Hames 1077e7707464SLang Hames Error MachOPlatformRuntimeState::dlopenFull( 1078e7707464SLang Hames std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 1079f9aef477SLang Hames // Call back to the JIT to push the initializers. 1080f9aef477SLang Hames Expected<MachOJITDylibDepInfoMap> DepInfo((MachOJITDylibDepInfoMap())); 1081e7707464SLang Hames // Unlock so that we can accept the initializer update. 1082e7707464SLang Hames JDStatesLock.unlock(); 1083f9aef477SLang Hames if (auto Err = WrapperFunction<SPSExpected<SPSMachOJITDylibDepInfoMap>( 108469f8923eSLang Hames SPSExecutorAddr)>:: 108569f8923eSLang Hames call(JITDispatch(&__orc_rt_macho_push_initializers_tag), DepInfo, 108669f8923eSLang Hames ExecutorAddr::fromPtr(JDS.Header))) 1087f9aef477SLang Hames return Err; 1088e7707464SLang Hames JDStatesLock.lock(); 1089e7707464SLang Hames 1090f9aef477SLang Hames if (!DepInfo) 1091f9aef477SLang Hames return DepInfo.takeError(); 1092bb5f97e3SLang Hames 1093e7707464SLang Hames if (auto Err = dlopenInitialize(JDStatesLock, JDS, *DepInfo)) 1094f9aef477SLang Hames return Err; 1095bb5f97e3SLang Hames 1096f9aef477SLang Hames if (!DepInfo->empty()) { 1097f9aef477SLang Hames ORC_RT_DEBUG({ 1098f9aef477SLang Hames printdbg("Unrecognized dep-info key headers in dlopen of %s\n", 1099f9aef477SLang Hames JDS.Name.c_str()); 1100f9aef477SLang Hames }); 1101f9aef477SLang Hames std::ostringstream ErrStream; 1102f9aef477SLang Hames ErrStream << "Encountered unrecognized dep-info key headers " 1103f9aef477SLang Hames "while processing dlopen of " 1104f9aef477SLang Hames << JDS.Name; 1105f9aef477SLang Hames return make_error<StringError>(ErrStream.str()); 1106f9aef477SLang Hames } 1107f9aef477SLang Hames 1108f9aef477SLang Hames return Error::success(); 1109f9aef477SLang Hames } 1110f9aef477SLang Hames 1111f9aef477SLang Hames Error MachOPlatformRuntimeState::dlopenInitialize( 1112e7707464SLang Hames std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS, 1113e7707464SLang Hames MachOJITDylibDepInfoMap &DepInfo) { 1114f9aef477SLang Hames ORC_RT_DEBUG({ 1115f9aef477SLang Hames printdbg("MachOPlatformRuntimeState::dlopenInitialize(\"%s\")\n", 1116f9aef477SLang Hames JDS.Name.c_str()); 1117f9aef477SLang Hames }); 1118f9aef477SLang Hames 1119f9aef477SLang Hames // If the header is not present in the dep map then assume that we 1120f9aef477SLang Hames // already processed it earlier in the dlopenInitialize traversal and 1121f9aef477SLang Hames // return. 1122f9aef477SLang Hames // TODO: Keep a visited set instead so that we can error out on missing 1123f9aef477SLang Hames // entries? 1124f9aef477SLang Hames auto I = DepInfo.find(ExecutorAddr::fromPtr(JDS.Header)); 1125f9aef477SLang Hames if (I == DepInfo.end()) 1126f9aef477SLang Hames return Error::success(); 1127f9aef477SLang Hames 1128f9aef477SLang Hames auto DI = std::move(I->second); 1129f9aef477SLang Hames DepInfo.erase(I); 1130f9aef477SLang Hames 1131f9aef477SLang Hames // We don't need to re-initialize sealed JITDylibs that have already been 1132f9aef477SLang Hames // initialized. Just check that their dep-map entry is empty as expected. 1133f9aef477SLang Hames if (JDS.Sealed) { 1134f9aef477SLang Hames if (!DI.DepHeaders.empty()) { 1135f9aef477SLang Hames std::ostringstream ErrStream; 1136f9aef477SLang Hames ErrStream << "Sealed JITDylib " << JDS.Header 1137f9aef477SLang Hames << " already has registered dependencies"; 1138f9aef477SLang Hames return make_error<StringError>(ErrStream.str()); 1139f9aef477SLang Hames } 1140f9aef477SLang Hames if (JDS.referenced()) 1141f9aef477SLang Hames return Error::success(); 1142f9aef477SLang Hames } else 1143f9aef477SLang Hames JDS.Sealed = DI.Sealed; 1144f9aef477SLang Hames 1145f9aef477SLang Hames // This is an unsealed or newly sealed JITDylib. Run initializers. 1146f9aef477SLang Hames std::vector<JITDylibState *> OldDeps; 1147f9aef477SLang Hames std::swap(JDS.Deps, OldDeps); 1148f9aef477SLang Hames JDS.Deps.reserve(DI.DepHeaders.size()); 1149f9aef477SLang Hames for (auto DepHeaderAddr : DI.DepHeaders) { 1150f9aef477SLang Hames auto *DepJDS = getJITDylibStateByHeader(DepHeaderAddr.toPtr<void *>()); 1151f9aef477SLang Hames if (!DepJDS) { 1152f9aef477SLang Hames std::ostringstream ErrStream; 1153f9aef477SLang Hames ErrStream << "Encountered unrecognized dep header " 1154f9aef477SLang Hames << DepHeaderAddr.toPtr<void *>() << " while initializing " 1155f9aef477SLang Hames << JDS.Name; 1156f9aef477SLang Hames return make_error<StringError>(ErrStream.str()); 1157f9aef477SLang Hames } 1158f9aef477SLang Hames ++DepJDS->LinkedAgainstRefCount; 1159e7707464SLang Hames if (auto Err = dlopenInitialize(JDStatesLock, *DepJDS, DepInfo)) 1160bb5f97e3SLang Hames return Err; 1161bb5f97e3SLang Hames } 1162f9aef477SLang Hames 1163f9aef477SLang Hames // Initialize this JITDylib. 1164fa089efaSBen Langmuir if (auto Err = registerObjCRegistrationObjects(JDStatesLock, JDS)) 1165f9aef477SLang Hames return Err; 1166e7707464SLang Hames if (auto Err = runModInits(JDStatesLock, JDS)) 1167f9aef477SLang Hames return Err; 1168f9aef477SLang Hames 1169f9aef477SLang Hames // Decrement old deps. 1170f9aef477SLang Hames // FIXME: We should probably continue and just report deinitialize errors 1171f9aef477SLang Hames // here. 1172f9aef477SLang Hames for (auto *DepJDS : OldDeps) { 1173f9aef477SLang Hames --DepJDS->LinkedAgainstRefCount; 1174f9aef477SLang Hames if (!DepJDS->referenced()) 1175e7707464SLang Hames if (auto Err = dlcloseDeinitialize(JDStatesLock, *DepJDS)) 1176f9aef477SLang Hames return Err; 1177f9aef477SLang Hames } 1178f9aef477SLang Hames 1179f9aef477SLang Hames return Error::success(); 1180f9aef477SLang Hames } 1181f9aef477SLang Hames 1182*5f9e6c81SSahilPatidar Error MachOPlatformRuntimeState::dlupdateImpl(void *DSOHandle) { 118368f31aaaSSahilPatidar std::unique_lock<std::mutex> Lock(JDStatesMutex); 118468f31aaaSSahilPatidar 118568f31aaaSSahilPatidar // Try to find JITDylib state by DSOHandle. 118668f31aaaSSahilPatidar auto *JDS = getJITDylibStateByHeader(DSOHandle); 118768f31aaaSSahilPatidar 118868f31aaaSSahilPatidar if (!JDS) { 118968f31aaaSSahilPatidar std::ostringstream ErrStream; 119068f31aaaSSahilPatidar ErrStream << "No registered JITDylib for " << DSOHandle; 119168f31aaaSSahilPatidar return make_error<StringError>(ErrStream.str()); 119268f31aaaSSahilPatidar } 119368f31aaaSSahilPatidar 119468f31aaaSSahilPatidar if (!JDS->referenced()) 119568f31aaaSSahilPatidar return make_error<StringError>("dlupdate failed, JITDylib must be open."); 119668f31aaaSSahilPatidar 119768f31aaaSSahilPatidar if (!JDS->Sealed) { 119868f31aaaSSahilPatidar if (auto Err = dlupdateFull(Lock, *JDS)) 119968f31aaaSSahilPatidar return Err; 120068f31aaaSSahilPatidar } 120168f31aaaSSahilPatidar 120268f31aaaSSahilPatidar return Error::success(); 120368f31aaaSSahilPatidar } 120468f31aaaSSahilPatidar 120568f31aaaSSahilPatidar Error MachOPlatformRuntimeState::dlupdateFull( 120668f31aaaSSahilPatidar std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 120768f31aaaSSahilPatidar // Call back to the JIT to push the initializers. 120868f31aaaSSahilPatidar Expected<MachOJITDylibDepInfoMap> DepInfo((MachOJITDylibDepInfoMap())); 120968f31aaaSSahilPatidar // Unlock so that we can accept the initializer update. 121068f31aaaSSahilPatidar JDStatesLock.unlock(); 121168f31aaaSSahilPatidar if (auto Err = WrapperFunction<SPSExpected<SPSMachOJITDylibDepInfoMap>( 121268f31aaaSSahilPatidar SPSExecutorAddr)>:: 121368f31aaaSSahilPatidar call(JITDispatch(&__orc_rt_macho_push_initializers_tag), DepInfo, 121468f31aaaSSahilPatidar ExecutorAddr::fromPtr(JDS.Header))) 121568f31aaaSSahilPatidar return Err; 121668f31aaaSSahilPatidar JDStatesLock.lock(); 121768f31aaaSSahilPatidar 121868f31aaaSSahilPatidar if (!DepInfo) 121968f31aaaSSahilPatidar return DepInfo.takeError(); 122068f31aaaSSahilPatidar 122168f31aaaSSahilPatidar if (auto Err = dlupdateInitialize(JDStatesLock, JDS)) 122268f31aaaSSahilPatidar return Err; 122368f31aaaSSahilPatidar 122468f31aaaSSahilPatidar return Error::success(); 122568f31aaaSSahilPatidar } 122668f31aaaSSahilPatidar 122768f31aaaSSahilPatidar Error MachOPlatformRuntimeState::dlupdateInitialize( 122868f31aaaSSahilPatidar std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 122968f31aaaSSahilPatidar ORC_RT_DEBUG({ 123068f31aaaSSahilPatidar printdbg("MachOPlatformRuntimeState::dlupdateInitialize(\"%s\")\n", 123168f31aaaSSahilPatidar JDS.Name.c_str()); 123268f31aaaSSahilPatidar }); 123368f31aaaSSahilPatidar 123468f31aaaSSahilPatidar // Initialize this JITDylib. 123568f31aaaSSahilPatidar if (auto Err = registerObjCRegistrationObjects(JDStatesLock, JDS)) 123668f31aaaSSahilPatidar return Err; 123768f31aaaSSahilPatidar if (auto Err = runModInits(JDStatesLock, JDS)) 123868f31aaaSSahilPatidar return Err; 123968f31aaaSSahilPatidar 124068f31aaaSSahilPatidar return Error::success(); 124168f31aaaSSahilPatidar } 124268f31aaaSSahilPatidar 1243f9aef477SLang Hames Error MachOPlatformRuntimeState::dlcloseImpl(void *DSOHandle) { 1244e7707464SLang Hames std::unique_lock<std::mutex> Lock(JDStatesMutex); 1245e7707464SLang Hames 1246f9aef477SLang Hames // Try to find JITDylib state by header. 1247f9aef477SLang Hames auto *JDS = getJITDylibStateByHeader(DSOHandle); 1248f9aef477SLang Hames 1249f9aef477SLang Hames if (!JDS) { 1250f9aef477SLang Hames std::ostringstream ErrStream; 1251f9aef477SLang Hames ErrStream << "No registered JITDylib for " << DSOHandle; 1252f9aef477SLang Hames return make_error<StringError>(ErrStream.str()); 1253f9aef477SLang Hames } 1254f9aef477SLang Hames 1255f9aef477SLang Hames // Bump the ref-count. 1256f9aef477SLang Hames --JDS->DlRefCount; 1257f9aef477SLang Hames 1258f9aef477SLang Hames if (!JDS->referenced()) 1259e7707464SLang Hames return dlcloseDeinitialize(Lock, *JDS); 1260f9aef477SLang Hames 1261f9aef477SLang Hames return Error::success(); 1262f9aef477SLang Hames } 1263f9aef477SLang Hames 1264e7707464SLang Hames Error MachOPlatformRuntimeState::dlcloseDeinitialize( 1265e7707464SLang Hames std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) { 1266f9aef477SLang Hames 1267f9aef477SLang Hames ORC_RT_DEBUG({ 1268f9aef477SLang Hames printdbg("MachOPlatformRuntimeState::dlcloseDeinitialize(\"%s\")\n", 1269f9aef477SLang Hames JDS.Name.c_str()); 1270f9aef477SLang Hames }); 1271f9aef477SLang Hames 1272e7707464SLang Hames runAtExits(JDStatesLock, JDS); 1273f9aef477SLang Hames 1274f9aef477SLang Hames // Reset mod-inits 1275873584b6SLang Hames JDS.ModInitsSections.reset(); 1276f9aef477SLang Hames 127747e9e588SLang Hames // Reset data section contents. 127847e9e588SLang Hames for (auto &KV : JDS.DataSectionContent) 127947e9e588SLang Hames memcpy(KV.first, KV.second.data(), KV.second.size()); 128047e9e588SLang Hames for (auto &KV : JDS.ZeroInitRanges) 128147e9e588SLang Hames memset(KV.first, 0, KV.second); 128247e9e588SLang Hames 1283f9aef477SLang Hames // Deinitialize any dependencies. 1284f9aef477SLang Hames for (auto *DepJDS : JDS.Deps) { 1285f9aef477SLang Hames --DepJDS->LinkedAgainstRefCount; 1286f9aef477SLang Hames if (!DepJDS->referenced()) 1287e7707464SLang Hames if (auto Err = dlcloseDeinitialize(JDStatesLock, *DepJDS)) 1288f9aef477SLang Hames return Err; 1289bb5f97e3SLang Hames } 1290bb5f97e3SLang Hames 1291bb5f97e3SLang Hames return Error::success(); 1292bb5f97e3SLang Hames } 1293bb5f97e3SLang Hames 1294eda6afdaSLang Hames class MachOPlatformRuntimeTLVManager { 1295eda6afdaSLang Hames public: 1296eda6afdaSLang Hames void *getInstance(const char *ThreadData); 1297eda6afdaSLang Hames 1298eda6afdaSLang Hames private: 1299eda6afdaSLang Hames std::unordered_map<const char *, char *> Instances; 1300eda6afdaSLang Hames std::unordered_map<const char *, std::unique_ptr<char[]>> AllocatedSections; 1301eda6afdaSLang Hames }; 1302eda6afdaSLang Hames 1303eda6afdaSLang Hames void *MachOPlatformRuntimeTLVManager::getInstance(const char *ThreadData) { 1304eda6afdaSLang Hames auto I = Instances.find(ThreadData); 1305eda6afdaSLang Hames if (I != Instances.end()) 1306eda6afdaSLang Hames return I->second; 1307eda6afdaSLang Hames 1308eda6afdaSLang Hames auto TDS = 1309eda6afdaSLang Hames MachOPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData); 1310eda6afdaSLang Hames if (!TDS) { 1311eda6afdaSLang Hames __orc_rt_log_error(toString(TDS.takeError()).c_str()); 1312eda6afdaSLang Hames return nullptr; 1313eda6afdaSLang Hames } 1314eda6afdaSLang Hames 1315eda6afdaSLang Hames auto &Allocated = AllocatedSections[TDS->first]; 1316eda6afdaSLang Hames if (!Allocated) { 1317eda6afdaSLang Hames Allocated = std::make_unique<char[]>(TDS->second); 1318eda6afdaSLang Hames memcpy(Allocated.get(), TDS->first, TDS->second); 1319eda6afdaSLang Hames } 1320eda6afdaSLang Hames 1321eda6afdaSLang Hames size_t ThreadDataDelta = ThreadData - TDS->first; 1322eda6afdaSLang Hames assert(ThreadDataDelta <= TDS->second && "ThreadData outside section bounds"); 1323eda6afdaSLang Hames 1324eda6afdaSLang Hames char *Instance = Allocated.get() + ThreadDataDelta; 1325eda6afdaSLang Hames Instances[ThreadData] = Instance; 1326eda6afdaSLang Hames return Instance; 1327eda6afdaSLang Hames } 1328eda6afdaSLang Hames 1329eda6afdaSLang Hames void destroyMachOTLVMgr(void *MachOTLVMgr) { 1330eda6afdaSLang Hames delete static_cast<MachOPlatformRuntimeTLVManager *>(MachOTLVMgr); 1331eda6afdaSLang Hames } 1332eda6afdaSLang Hames 1333ff846fcbSLang Hames Error runWrapperFunctionCalls(std::vector<WrapperFunctionCall> WFCs) { 1334ff846fcbSLang Hames for (auto &WFC : WFCs) 13350ede1b90SLang Hames if (auto Err = WFC.runWithSPSRet<void>()) 1336ff846fcbSLang Hames return Err; 1337ff846fcbSLang Hames return Error::success(); 1338ff846fcbSLang Hames } 1339ff846fcbSLang Hames 1340bb5f97e3SLang Hames } // end anonymous namespace 1341bb5f97e3SLang Hames 1342bb5f97e3SLang Hames //------------------------------------------------------------------------------ 1343bb5f97e3SLang Hames // JIT entry points 1344bb5f97e3SLang Hames //------------------------------------------------------------------------------ 1345bb5f97e3SLang Hames 134634fccfb2SLang Hames ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1347bb5f97e3SLang Hames __orc_rt_macho_platform_bootstrap(char *ArgData, size_t ArgSize) { 1348217fd59cSLang Hames return WrapperFunction<SPSError()>::handle( 1349217fd59cSLang Hames ArgData, ArgSize, 13503507df9cSLang Hames []() { return MachOPlatformRuntimeState::create(); }) 1351217fd59cSLang Hames .release(); 1352bb5f97e3SLang Hames } 1353bb5f97e3SLang Hames 135434fccfb2SLang Hames ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1355bb5f97e3SLang Hames __orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) { 1356217fd59cSLang Hames return WrapperFunction<SPSError()>::handle( 1357217fd59cSLang Hames ArgData, ArgSize, 13583507df9cSLang Hames []() { return MachOPlatformRuntimeState::destroy(); }) 1359217fd59cSLang Hames .release(); 1360bb5f97e3SLang Hames } 1361bb5f97e3SLang Hames 136234fccfb2SLang Hames ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1363f9aef477SLang Hames __orc_rt_macho_register_jitdylib(char *ArgData, size_t ArgSize) { 1364f9aef477SLang Hames return WrapperFunction<SPSError(SPSString, SPSExecutorAddr)>::handle( 1365089acf25SLang Hames ArgData, ArgSize, 1366f9aef477SLang Hames [](std::string &Name, ExecutorAddr HeaderAddr) { 1367f9aef477SLang Hames return MachOPlatformRuntimeState::get().registerJITDylib( 1368f9aef477SLang Hames std::move(Name), HeaderAddr.toPtr<void *>()); 1369bb5f97e3SLang Hames }) 1370bb5f97e3SLang Hames .release(); 1371bb5f97e3SLang Hames } 1372bb5f97e3SLang Hames 137334fccfb2SLang Hames ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1374f9aef477SLang Hames __orc_rt_macho_deregister_jitdylib(char *ArgData, size_t ArgSize) { 1375f9aef477SLang Hames return WrapperFunction<SPSError(SPSExecutorAddr)>::handle( 1376089acf25SLang Hames ArgData, ArgSize, 1377f9aef477SLang Hames [](ExecutorAddr HeaderAddr) { 1378f9aef477SLang Hames return MachOPlatformRuntimeState::get().deregisterJITDylib( 1379f9aef477SLang Hames HeaderAddr.toPtr<void *>()); 1380f9aef477SLang Hames }) 1381f9aef477SLang Hames .release(); 1382f9aef477SLang Hames } 1383f9aef477SLang Hames 138434fccfb2SLang Hames ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1385f9aef477SLang Hames __orc_rt_macho_register_object_platform_sections(char *ArgData, 1386f9aef477SLang Hames size_t ArgSize) { 1387f9aef477SLang Hames return WrapperFunction<SPSError(SPSExecutorAddr, 13883507df9cSLang Hames SPSOptional<SPSUnwindSectionInfo>, 1389f9aef477SLang Hames SPSMachOObjectPlatformSectionsMap)>:: 1390f9aef477SLang Hames handle(ArgData, ArgSize, 13913507df9cSLang Hames [](ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> USI, 13921dcff823SLang Hames std::vector<std::pair<std::string_view, ExecutorAddrRange>> 13931dcff823SLang Hames &Secs) { 1394ff846fcbSLang Hames return MachOPlatformRuntimeState::get() 13953507df9cSLang Hames .registerObjectPlatformSections(HeaderAddr, std::move(USI), 13963507df9cSLang Hames std::move(Secs)); 1397f9aef477SLang Hames }) 1398f9aef477SLang Hames .release(); 1399f9aef477SLang Hames } 1400f9aef477SLang Hames 140134fccfb2SLang Hames ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1402bb41fc68SLang Hames __orc_rt_macho_register_object_symbol_table(char *ArgData, size_t ArgSize) { 1403bb41fc68SLang Hames using SymtabContainer = std::vector< 1404bb41fc68SLang Hames std::tuple<ExecutorAddr, ExecutorAddr, 1405bb41fc68SLang Hames MachOPlatformRuntimeState::MachOExecutorSymbolFlags>>; 1406bb41fc68SLang Hames return WrapperFunction<SPSError( 1407bb41fc68SLang Hames SPSExecutorAddr, SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr, 1408bb41fc68SLang Hames SPSMachOExecutorSymbolFlags>>)>:: 1409bb41fc68SLang Hames handle(ArgData, ArgSize, 1410bb41fc68SLang Hames [](ExecutorAddr HeaderAddr, SymtabContainer &Symbols) { 1411bb41fc68SLang Hames return MachOPlatformRuntimeState::get() 1412bb41fc68SLang Hames .registerObjectSymbolTable(HeaderAddr, Symbols); 1413bb41fc68SLang Hames }) 1414bb41fc68SLang Hames .release(); 1415bb41fc68SLang Hames } 1416bb41fc68SLang Hames 1417bb41fc68SLang Hames ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1418bb41fc68SLang Hames __orc_rt_macho_deregister_object_symbol_table(char *ArgData, size_t ArgSize) { 1419bb41fc68SLang Hames using SymtabContainer = std::vector< 1420bb41fc68SLang Hames std::tuple<ExecutorAddr, ExecutorAddr, 1421bb41fc68SLang Hames MachOPlatformRuntimeState::MachOExecutorSymbolFlags>>; 1422bb41fc68SLang Hames return WrapperFunction<SPSError( 1423bb41fc68SLang Hames SPSExecutorAddr, SPSSequence<SPSTuple<SPSExecutorAddr, SPSExecutorAddr, 1424bb41fc68SLang Hames SPSMachOExecutorSymbolFlags>>)>:: 1425bb41fc68SLang Hames handle(ArgData, ArgSize, 1426bb41fc68SLang Hames [](ExecutorAddr HeaderAddr, SymtabContainer &Symbols) { 1427bb41fc68SLang Hames return MachOPlatformRuntimeState::get() 1428bb41fc68SLang Hames .deregisterObjectSymbolTable(HeaderAddr, Symbols); 1429bb41fc68SLang Hames }) 1430bb41fc68SLang Hames .release(); 1431bb41fc68SLang Hames } 1432bb41fc68SLang Hames 1433bb41fc68SLang Hames ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1434f9aef477SLang Hames __orc_rt_macho_deregister_object_platform_sections(char *ArgData, 1435f9aef477SLang Hames size_t ArgSize) { 1436f9aef477SLang Hames return WrapperFunction<SPSError(SPSExecutorAddr, 14373507df9cSLang Hames SPSOptional<SPSUnwindSectionInfo>, 1438f9aef477SLang Hames SPSMachOObjectPlatformSectionsMap)>:: 1439f9aef477SLang Hames handle(ArgData, ArgSize, 14403507df9cSLang Hames [](ExecutorAddr HeaderAddr, std::optional<UnwindSectionInfo> USI, 14411dcff823SLang Hames std::vector<std::pair<std::string_view, ExecutorAddrRange>> 14421dcff823SLang Hames &Secs) { 1443f9aef477SLang Hames return MachOPlatformRuntimeState::get() 14443507df9cSLang Hames .deregisterObjectPlatformSections(HeaderAddr, std::move(USI), 1445f9aef477SLang Hames std::move(Secs)); 1446bb5f97e3SLang Hames }) 1447bb5f97e3SLang Hames .release(); 1448bb5f97e3SLang Hames } 1449bb5f97e3SLang Hames 145034fccfb2SLang Hames ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1451ff846fcbSLang Hames __orc_rt_macho_run_wrapper_function_calls(char *ArgData, size_t ArgSize) { 1452ff846fcbSLang Hames return WrapperFunction<SPSError(SPSSequence<SPSWrapperFunctionCall>)>::handle( 1453ff846fcbSLang Hames ArgData, ArgSize, runWrapperFunctionCalls) 1454ff846fcbSLang Hames .release(); 1455ff846fcbSLang Hames } 1456ff846fcbSLang Hames 1457bb5f97e3SLang Hames //------------------------------------------------------------------------------ 1458eda6afdaSLang Hames // TLV support 1459eda6afdaSLang Hames //------------------------------------------------------------------------------ 1460eda6afdaSLang Hames 1461eda6afdaSLang Hames ORC_RT_INTERFACE void *__orc_rt_macho_tlv_get_addr_impl(TLVDescriptor *D) { 1462eda6afdaSLang Hames auto *TLVMgr = static_cast<MachOPlatformRuntimeTLVManager *>( 1463eda6afdaSLang Hames pthread_getspecific(D->Key)); 1464eda6afdaSLang Hames if (!TLVMgr) { 1465eda6afdaSLang Hames TLVMgr = new MachOPlatformRuntimeTLVManager(); 1466eda6afdaSLang Hames if (pthread_setspecific(D->Key, TLVMgr)) { 1467eda6afdaSLang Hames __orc_rt_log_error("Call to pthread_setspecific failed"); 1468eda6afdaSLang Hames return nullptr; 1469eda6afdaSLang Hames } 1470eda6afdaSLang Hames } 1471eda6afdaSLang Hames 1472eda6afdaSLang Hames return TLVMgr->getInstance( 1473eda6afdaSLang Hames reinterpret_cast<char *>(static_cast<uintptr_t>(D->DataAddress))); 1474eda6afdaSLang Hames } 1475eda6afdaSLang Hames 147634fccfb2SLang Hames ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult 1477eda6afdaSLang Hames __orc_rt_macho_create_pthread_key(char *ArgData, size_t ArgSize) { 1478eda6afdaSLang Hames return WrapperFunction<SPSExpected<uint64_t>(void)>::handle( 1479eda6afdaSLang Hames ArgData, ArgSize, 1480eda6afdaSLang Hames []() -> Expected<uint64_t> { 1481eda6afdaSLang Hames pthread_key_t Key; 1482eda6afdaSLang Hames if (int Err = pthread_key_create(&Key, destroyMachOTLVMgr)) { 1483eda6afdaSLang Hames __orc_rt_log_error("Call to pthread_key_create failed"); 1484eda6afdaSLang Hames return make_error<StringError>(strerror(Err)); 1485eda6afdaSLang Hames } 1486eda6afdaSLang Hames return static_cast<uint64_t>(Key); 1487eda6afdaSLang Hames }) 1488eda6afdaSLang Hames .release(); 1489eda6afdaSLang Hames } 1490eda6afdaSLang Hames 1491eda6afdaSLang Hames //------------------------------------------------------------------------------ 1492bb5f97e3SLang Hames // cxa_atexit support 1493bb5f97e3SLang Hames //------------------------------------------------------------------------------ 1494bb5f97e3SLang Hames 1495bb5f97e3SLang Hames int __orc_rt_macho_cxa_atexit(void (*func)(void *), void *arg, 1496bb5f97e3SLang Hames void *dso_handle) { 1497bb5f97e3SLang Hames return MachOPlatformRuntimeState::get().registerAtExit(func, arg, dso_handle); 1498bb5f97e3SLang Hames } 1499bb5f97e3SLang Hames 1500bb5f97e3SLang Hames void __orc_rt_macho_cxa_finalize(void *dso_handle) { 1501bb5f97e3SLang Hames MachOPlatformRuntimeState::get().runAtExits(dso_handle); 1502bb5f97e3SLang Hames } 1503bb5f97e3SLang Hames 1504bb5f97e3SLang Hames //------------------------------------------------------------------------------ 1505bb5f97e3SLang Hames // JIT'd dlfcn alternatives. 1506bb5f97e3SLang Hames //------------------------------------------------------------------------------ 1507bb5f97e3SLang Hames 1508bb5f97e3SLang Hames const char *__orc_rt_macho_jit_dlerror() { 1509bb5f97e3SLang Hames return MachOPlatformRuntimeState::get().dlerror(); 1510bb5f97e3SLang Hames } 1511bb5f97e3SLang Hames 1512bb5f97e3SLang Hames void *__orc_rt_macho_jit_dlopen(const char *path, int mode) { 1513bb5f97e3SLang Hames return MachOPlatformRuntimeState::get().dlopen(path, mode); 1514bb5f97e3SLang Hames } 1515bb5f97e3SLang Hames 1516*5f9e6c81SSahilPatidar int __orc_rt_macho_jit_dlupdate(void *dso_handle) { 1517*5f9e6c81SSahilPatidar return MachOPlatformRuntimeState::get().dlupdate(dso_handle); 151868f31aaaSSahilPatidar } 151968f31aaaSSahilPatidar 1520bb5f97e3SLang Hames int __orc_rt_macho_jit_dlclose(void *dso_handle) { 1521bb5f97e3SLang Hames return MachOPlatformRuntimeState::get().dlclose(dso_handle); 1522bb5f97e3SLang Hames } 1523bb5f97e3SLang Hames 1524bb5f97e3SLang Hames void *__orc_rt_macho_jit_dlsym(void *dso_handle, const char *symbol) { 1525bb5f97e3SLang Hames return MachOPlatformRuntimeState::get().dlsym(dso_handle, symbol); 1526bb5f97e3SLang Hames } 1527bb5f97e3SLang Hames 1528bb5f97e3SLang Hames //------------------------------------------------------------------------------ 1529bb5f97e3SLang Hames // MachO Run Program 1530bb5f97e3SLang Hames //------------------------------------------------------------------------------ 1531bb5f97e3SLang Hames 1532bb5f97e3SLang Hames ORC_RT_INTERFACE int64_t __orc_rt_macho_run_program(const char *JITDylibName, 1533bb5f97e3SLang Hames const char *EntrySymbolName, 1534bb5f97e3SLang Hames int argc, char *argv[]) { 1535bb5f97e3SLang Hames using MainTy = int (*)(int, char *[]); 1536bb5f97e3SLang Hames 15373e04ad42SLang Hames void *H = 15383e04ad42SLang Hames __orc_rt_macho_jit_dlopen(JITDylibName, orc_rt::macho::ORC_RT_RTLD_LAZY); 1539bb5f97e3SLang Hames if (!H) { 1540bb5f97e3SLang Hames __orc_rt_log_error(__orc_rt_macho_jit_dlerror()); 1541bb5f97e3SLang Hames return -1; 1542bb5f97e3SLang Hames } 1543bb5f97e3SLang Hames 1544bb5f97e3SLang Hames auto *Main = 1545bb5f97e3SLang Hames reinterpret_cast<MainTy>(__orc_rt_macho_jit_dlsym(H, EntrySymbolName)); 1546bb5f97e3SLang Hames 1547bb5f97e3SLang Hames if (!Main) { 1548bb5f97e3SLang Hames __orc_rt_log_error(__orc_rt_macho_jit_dlerror()); 1549bb5f97e3SLang Hames return -1; 1550bb5f97e3SLang Hames } 1551bb5f97e3SLang Hames 1552bb5f97e3SLang Hames int Result = Main(argc, argv); 1553bb5f97e3SLang Hames 1554bb5f97e3SLang Hames if (__orc_rt_macho_jit_dlclose(H) == -1) 1555bb5f97e3SLang Hames __orc_rt_log_error(__orc_rt_macho_jit_dlerror()); 1556bb5f97e3SLang Hames 1557bb5f97e3SLang Hames return Result; 1558bb5f97e3SLang Hames } 1559