xref: /llvm-project/compiler-rt/lib/orc/macho_platform.cpp (revision 212cdc9a377a1b3ac96be0da20212592ebd2c818)
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