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"
14bb5f97e3SLang Hames #include "common.h"
15f9aef477SLang Hames #include "debug.h"
16bb5f97e3SLang Hames #include "error.h"
17bb5f97e3SLang Hames #include "wrapper_function_utils.h"
18bb5f97e3SLang Hames 
19*fe2f5c97SLang Hames #include <algorithm>
20f9aef477SLang Hames #include <ios>
21bb5f97e3SLang Hames #include <map>
22bb5f97e3SLang Hames #include <mutex>
23bb5f97e3SLang Hames #include <sstream>
24bb5f97e3SLang Hames #include <unordered_map>
25f9aef477SLang Hames #include <unordered_set>
26bb5f97e3SLang Hames #include <vector>
27bb5f97e3SLang Hames 
28f9aef477SLang Hames #define DEBUG_TYPE "macho_platform"
29f9aef477SLang Hames 
30bb5f97e3SLang Hames using namespace __orc_rt;
31bb5f97e3SLang Hames using namespace __orc_rt::macho;
32bb5f97e3SLang Hames 
33bb5f97e3SLang Hames // Declare function tags for functions in the JIT process.
34f9aef477SLang Hames ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_push_initializers_tag)
358afa4c40SLang Hames ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_symbol_lookup_tag)
36bb5f97e3SLang Hames 
37cdcc3547SLang Hames // Objective-C types.
38cdcc3547SLang Hames struct objc_class;
39cdcc3547SLang Hames struct objc_image_info;
40cdcc3547SLang Hames struct objc_object;
41cdcc3547SLang Hames struct objc_selector;
42cdcc3547SLang Hames 
43cdcc3547SLang Hames using Class = objc_class *;
44cdcc3547SLang Hames using id = objc_object *;
45cdcc3547SLang Hames using SEL = objc_selector *;
46cdcc3547SLang Hames 
47cdcc3547SLang Hames // Objective-C registration functions.
48cdcc3547SLang Hames // These are weakly imported. If the Objective-C runtime has not been loaded
49cdcc3547SLang Hames // then code containing Objective-C sections will generate an error.
50cdcc3547SLang Hames extern "C" id objc_msgSend(id, SEL, ...) ORC_RT_WEAK_IMPORT;
51cdcc3547SLang Hames extern "C" Class objc_readClassPair(Class,
52cdcc3547SLang Hames                                     const objc_image_info *) ORC_RT_WEAK_IMPORT;
53cdcc3547SLang Hames extern "C" SEL sel_registerName(const char *) ORC_RT_WEAK_IMPORT;
54cdcc3547SLang Hames 
55cdcc3547SLang Hames // Swift types.
56cdcc3547SLang Hames class ProtocolRecord;
57cdcc3547SLang Hames class ProtocolConformanceRecord;
582a739f27SBen Langmuir class TypeMetadataRecord;
59cdcc3547SLang Hames 
60cdcc3547SLang Hames extern "C" void
61cdcc3547SLang Hames swift_registerProtocols(const ProtocolRecord *begin,
62cdcc3547SLang Hames                         const ProtocolRecord *end) ORC_RT_WEAK_IMPORT;
63cdcc3547SLang Hames 
64cdcc3547SLang Hames extern "C" void swift_registerProtocolConformances(
65cdcc3547SLang Hames     const ProtocolConformanceRecord *begin,
66cdcc3547SLang Hames     const ProtocolConformanceRecord *end) ORC_RT_WEAK_IMPORT;
67cdcc3547SLang Hames 
682a739f27SBen Langmuir extern "C" void swift_registerTypeMetadataRecords(
692a739f27SBen Langmuir     const TypeMetadataRecord *begin,
702a739f27SBen Langmuir     const TypeMetadataRecord *end) ORC_RT_WEAK_IMPORT;
712a739f27SBen Langmuir 
72bb5f97e3SLang Hames namespace {
73bb5f97e3SLang Hames 
74f9aef477SLang Hames struct MachOJITDylibDepInfo {
75f9aef477SLang Hames   bool Sealed = false;
76f9aef477SLang Hames   std::vector<ExecutorAddr> DepHeaders;
77cdcc3547SLang Hames };
78cdcc3547SLang Hames 
79f9aef477SLang Hames using MachOJITDylibDepInfoMap =
80f9aef477SLang Hames     std::unordered_map<ExecutorAddr, MachOJITDylibDepInfo>;
81cdcc3547SLang Hames 
82f9aef477SLang Hames } // anonymous namespace
83cdcc3547SLang Hames 
84f9aef477SLang Hames namespace __orc_rt {
85cdcc3547SLang Hames 
86f9aef477SLang Hames using SPSMachOObjectPlatformSectionsMap =
87f9aef477SLang Hames     SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRange>>;
88cdcc3547SLang Hames 
89f9aef477SLang Hames using SPSMachOJITDylibDepInfo = SPSTuple<bool, SPSSequence<SPSExecutorAddr>>;
90f9aef477SLang Hames 
91f9aef477SLang Hames using SPSMachOJITDylibDepInfoMap =
92f9aef477SLang Hames     SPSSequence<SPSTuple<SPSExecutorAddr, SPSMachOJITDylibDepInfo>>;
93f9aef477SLang Hames 
94f9aef477SLang Hames template <>
95f9aef477SLang Hames class SPSSerializationTraits<SPSMachOJITDylibDepInfo, MachOJITDylibDepInfo> {
96f9aef477SLang Hames public:
size(const MachOJITDylibDepInfo & JDI)97f9aef477SLang Hames   static size_t size(const MachOJITDylibDepInfo &JDI) {
98f9aef477SLang Hames     return SPSMachOJITDylibDepInfo::AsArgList::size(JDI.Sealed, JDI.DepHeaders);
99cdcc3547SLang Hames   }
100cdcc3547SLang Hames 
serialize(SPSOutputBuffer & OB,const MachOJITDylibDepInfo & JDI)101f9aef477SLang Hames   static bool serialize(SPSOutputBuffer &OB, const MachOJITDylibDepInfo &JDI) {
102f9aef477SLang Hames     return SPSMachOJITDylibDepInfo::AsArgList::serialize(OB, JDI.Sealed,
103f9aef477SLang Hames                                                          JDI.DepHeaders);
104cdcc3547SLang Hames   }
105cdcc3547SLang Hames 
deserialize(SPSInputBuffer & IB,MachOJITDylibDepInfo & JDI)106f9aef477SLang Hames   static bool deserialize(SPSInputBuffer &IB, MachOJITDylibDepInfo &JDI) {
107f9aef477SLang Hames     return SPSMachOJITDylibDepInfo::AsArgList::deserialize(IB, JDI.Sealed,
108f9aef477SLang Hames                                                            JDI.DepHeaders);
109cdcc3547SLang Hames   }
110f9aef477SLang Hames };
111cdcc3547SLang Hames 
112f9aef477SLang Hames } // namespace __orc_rt
1132a739f27SBen Langmuir 
114f9aef477SLang Hames namespace {
115eda6afdaSLang Hames struct TLVDescriptor {
116eda6afdaSLang Hames   void *(*Thunk)(TLVDescriptor *) = nullptr;
117eda6afdaSLang Hames   unsigned long Key = 0;
118eda6afdaSLang Hames   unsigned long DataAddress = 0;
119eda6afdaSLang Hames };
120eda6afdaSLang Hames 
121bb5f97e3SLang Hames class MachOPlatformRuntimeState {
122bb5f97e3SLang Hames private:
123bb5f97e3SLang Hames   struct AtExitEntry {
124bb5f97e3SLang Hames     void (*Func)(void *);
125bb5f97e3SLang Hames     void *Arg;
126bb5f97e3SLang Hames   };
127bb5f97e3SLang Hames 
128bb5f97e3SLang Hames   using AtExitsVector = std::vector<AtExitEntry>;
129bb5f97e3SLang Hames 
130f9aef477SLang Hames   struct JITDylibState {
131f9aef477SLang Hames     std::string Name;
132bb5f97e3SLang Hames     void *Header = nullptr;
133f9aef477SLang Hames     bool Sealed = false;
134f9aef477SLang Hames     size_t LinkedAgainstRefCount = 0;
135f9aef477SLang Hames     size_t DlRefCount = 0;
136f9aef477SLang Hames     std::vector<JITDylibState *> Deps;
137bb5f97e3SLang Hames     AtExitsVector AtExits;
138f9aef477SLang Hames     const objc_image_info *ObjCImageInfo = nullptr;
139f9aef477SLang Hames     std::vector<span<void (*)()>> ModInitsSections;
140f9aef477SLang Hames     std::vector<span<void (*)()>> ModInitsSectionsNew;
141f9aef477SLang Hames     std::vector<span<uintptr_t>> ObjCClassListSections;
142f9aef477SLang Hames     std::vector<span<uintptr_t>> ObjCClassListSectionsNew;
143f9aef477SLang Hames     std::vector<span<uintptr_t>> ObjCSelRefsSections;
144f9aef477SLang Hames     std::vector<span<uintptr_t>> ObjCSelRefsSectionsNew;
145f9aef477SLang Hames     std::vector<span<char>> Swift5ProtoSections;
146f9aef477SLang Hames     std::vector<span<char>> Swift5ProtoSectionsNew;
147f9aef477SLang Hames     std::vector<span<char>> Swift5ProtosSections;
148f9aef477SLang Hames     std::vector<span<char>> Swift5ProtosSectionsNew;
149f9aef477SLang Hames     std::vector<span<char>> Swift5TypesSections;
150f9aef477SLang Hames     std::vector<span<char>> Swift5TypesSectionsNew;
151f9aef477SLang Hames 
referenced__anon104e62320211::MachOPlatformRuntimeState::JITDylibState152f9aef477SLang Hames     bool referenced() const {
153f9aef477SLang Hames       return LinkedAgainstRefCount != 0 || DlRefCount != 0;
154f9aef477SLang Hames     }
155bb5f97e3SLang Hames   };
156bb5f97e3SLang Hames 
157bb5f97e3SLang Hames public:
158bb5f97e3SLang Hames   static void initialize();
159bb5f97e3SLang Hames   static MachOPlatformRuntimeState &get();
160bb5f97e3SLang Hames   static void destroy();
161bb5f97e3SLang Hames 
162bb5f97e3SLang Hames   MachOPlatformRuntimeState() = default;
163bb5f97e3SLang Hames 
164bb5f97e3SLang Hames   // Delete copy and move constructors.
165bb5f97e3SLang Hames   MachOPlatformRuntimeState(const MachOPlatformRuntimeState &) = delete;
166bb5f97e3SLang Hames   MachOPlatformRuntimeState &
167bb5f97e3SLang Hames   operator=(const MachOPlatformRuntimeState &) = delete;
168bb5f97e3SLang Hames   MachOPlatformRuntimeState(MachOPlatformRuntimeState &&) = delete;
169bb5f97e3SLang Hames   MachOPlatformRuntimeState &operator=(MachOPlatformRuntimeState &&) = delete;
170bb5f97e3SLang Hames 
171f9aef477SLang Hames   Error registerJITDylib(std::string Name, void *Header);
172f9aef477SLang Hames   Error deregisterJITDylib(void *Header);
173f9aef477SLang Hames   Error registerThreadDataSection(span<const char> ThreadDataSection);
174f9aef477SLang Hames   Error deregisterThreadDataSection(span<const char> ThreadDataSection);
175f9aef477SLang Hames   Error registerObjectPlatformSections(
176f9aef477SLang Hames       ExecutorAddr HeaderAddr,
177f9aef477SLang Hames       std::vector<std::pair<string_view, ExecutorAddrRange>> Secs);
178f9aef477SLang Hames   Error deregisterObjectPlatformSections(
179f9aef477SLang Hames       ExecutorAddr HeaderAddr,
180f9aef477SLang Hames       std::vector<std::pair<string_view, ExecutorAddrRange>> Secs);
181bb5f97e3SLang Hames 
182bb5f97e3SLang Hames   const char *dlerror();
183bb5f97e3SLang Hames   void *dlopen(string_view Name, int Mode);
184bb5f97e3SLang Hames   int dlclose(void *DSOHandle);
185bb5f97e3SLang Hames   void *dlsym(void *DSOHandle, string_view Symbol);
186bb5f97e3SLang Hames 
187bb5f97e3SLang Hames   int registerAtExit(void (*F)(void *), void *Arg, void *DSOHandle);
188f9aef477SLang Hames   void runAtExits(JITDylibState &JDS);
189bb5f97e3SLang Hames   void runAtExits(void *DSOHandle);
190bb5f97e3SLang Hames 
191eda6afdaSLang Hames   /// Returns the base address of the section containing ThreadData.
192eda6afdaSLang Hames   Expected<std::pair<const char *, size_t>>
193eda6afdaSLang Hames   getThreadDataSectionFor(const char *ThreadData);
194eda6afdaSLang Hames 
195bb5f97e3SLang Hames private:
196f9aef477SLang Hames   JITDylibState *getJITDylibStateByHeader(void *DSOHandle);
197f9aef477SLang Hames   JITDylibState *getJITDylibStateByName(string_view Path);
198bb5f97e3SLang Hames 
1990820fbabSLang Hames   Expected<ExecutorAddr> lookupSymbolInJITDylib(void *DSOHandle,
200bb5f97e3SLang Hames                                                 string_view Symbol);
201bb5f97e3SLang Hames 
202f9aef477SLang Hames   static Error registerObjCSelectors(JITDylibState &JDS);
203f9aef477SLang Hames   static Error registerObjCClasses(JITDylibState &JDS);
204f9aef477SLang Hames   static Error registerSwift5Protocols(JITDylibState &JDS);
205f9aef477SLang Hames   static Error registerSwift5ProtocolConformances(JITDylibState &JDS);
206f9aef477SLang Hames   static Error registerSwift5Types(JITDylibState &JDS);
207f9aef477SLang Hames   static Error runModInits(JITDylibState &JDS);
208f9aef477SLang Hames 
209f9aef477SLang Hames   Expected<void *> dlopenImpl(string_view Path, int Mode);
210f9aef477SLang Hames   Error dlopenFull(JITDylibState &JDS);
211f9aef477SLang Hames   Error dlopenInitialize(JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo);
212f9aef477SLang Hames 
213f9aef477SLang Hames   Error dlcloseImpl(void *DSOHandle);
214f9aef477SLang Hames   Error dlcloseDeinitialize(JITDylibState &JDS);
215bb5f97e3SLang Hames 
216bb5f97e3SLang Hames   static MachOPlatformRuntimeState *MOPS;
217bb5f97e3SLang Hames 
218bb5f97e3SLang Hames   // FIXME: Move to thread-state.
219bb5f97e3SLang Hames   std::string DLFcnError;
220bb5f97e3SLang Hames 
221bb5f97e3SLang Hames   std::recursive_mutex JDStatesMutex;
222f9aef477SLang Hames   std::unordered_map<void *, JITDylibState> JDStates;
223f9aef477SLang Hames   std::unordered_map<string_view, void *> JDNameToHeader;
224eda6afdaSLang Hames 
225eda6afdaSLang Hames   std::mutex ThreadDataSectionsMutex;
226eda6afdaSLang Hames   std::map<const char *, size_t> ThreadDataSections;
227bb5f97e3SLang Hames };
228bb5f97e3SLang Hames 
229bb5f97e3SLang Hames MachOPlatformRuntimeState *MachOPlatformRuntimeState::MOPS = nullptr;
230bb5f97e3SLang Hames 
initialize()231bb5f97e3SLang Hames void MachOPlatformRuntimeState::initialize() {
232bb5f97e3SLang Hames   assert(!MOPS && "MachOPlatformRuntimeState should be null");
233bb5f97e3SLang Hames   MOPS = new MachOPlatformRuntimeState();
234bb5f97e3SLang Hames }
235bb5f97e3SLang Hames 
get()236bb5f97e3SLang Hames MachOPlatformRuntimeState &MachOPlatformRuntimeState::get() {
237bb5f97e3SLang Hames   assert(MOPS && "MachOPlatformRuntimeState not initialized");
238bb5f97e3SLang Hames   return *MOPS;
239bb5f97e3SLang Hames }
240bb5f97e3SLang Hames 
destroy()241bb5f97e3SLang Hames void MachOPlatformRuntimeState::destroy() {
242bb5f97e3SLang Hames   assert(MOPS && "MachOPlatformRuntimeState not initialized");
243bb5f97e3SLang Hames   delete MOPS;
244bb5f97e3SLang Hames }
245bb5f97e3SLang Hames 
registerJITDylib(std::string Name,void * Header)246f9aef477SLang Hames Error MachOPlatformRuntimeState::registerJITDylib(std::string Name,
247f9aef477SLang Hames                                                   void *Header) {
248f9aef477SLang Hames   ORC_RT_DEBUG({
249f9aef477SLang Hames     printdbg("Registering JITDylib %s: Header = %p\n", Name.c_str(), Header);
250f9aef477SLang Hames   });
251f9aef477SLang Hames   std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
252f9aef477SLang Hames   if (JDStates.count(Header)) {
253f9aef477SLang Hames     std::ostringstream ErrStream;
254f9aef477SLang Hames     ErrStream << "Duplicate JITDylib registration for header " << Header
255f9aef477SLang Hames               << " (name = " << Name << ")";
256f9aef477SLang Hames     return make_error<StringError>(ErrStream.str());
257f9aef477SLang Hames   }
258f9aef477SLang Hames   if (JDNameToHeader.count(Name)) {
259f9aef477SLang Hames     std::ostringstream ErrStream;
260f9aef477SLang Hames     ErrStream << "Duplicate JITDylib registration for header " << Header
261f9aef477SLang Hames               << " (header = " << Header << ")";
262f9aef477SLang Hames     return make_error<StringError>(ErrStream.str());
263f9aef477SLang Hames   }
264f9aef477SLang Hames 
265f9aef477SLang Hames   auto &JDS = JDStates[Header];
266f9aef477SLang Hames   JDS.Name = std::move(Name);
267f9aef477SLang Hames   JDS.Header = Header;
268f9aef477SLang Hames   JDNameToHeader[JDS.Name] = Header;
269f9aef477SLang Hames   return Error::success();
270f9aef477SLang Hames }
271f9aef477SLang Hames 
deregisterJITDylib(void * Header)272f9aef477SLang Hames Error MachOPlatformRuntimeState::deregisterJITDylib(void *Header) {
273f9aef477SLang Hames   std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
274f9aef477SLang Hames   auto I = JDStates.find(Header);
275f9aef477SLang Hames   if (I == JDStates.end()) {
276f9aef477SLang Hames     std::ostringstream ErrStream;
277f9aef477SLang Hames     ErrStream << "Attempted to deregister unrecognized header " << Header;
278f9aef477SLang Hames     return make_error<StringError>(ErrStream.str());
279f9aef477SLang Hames   }
280f9aef477SLang Hames 
281f9aef477SLang Hames   // Remove std::string construction once we can use C++20.
282f9aef477SLang Hames   auto J = JDNameToHeader.find(
283f9aef477SLang Hames       std::string(I->second.Name.data(), I->second.Name.size()));
284f9aef477SLang Hames   assert(J != JDNameToHeader.end() &&
285f9aef477SLang Hames          "Missing JDNameToHeader entry for JITDylib");
286f9aef477SLang Hames 
287f9aef477SLang Hames   ORC_RT_DEBUG({
288f9aef477SLang Hames     printdbg("Deregistering JITDylib %s: Header = %p\n", I->second.Name.c_str(),
289f9aef477SLang Hames              Header);
290f9aef477SLang Hames   });
291f9aef477SLang Hames 
292f9aef477SLang Hames   JDNameToHeader.erase(J);
293f9aef477SLang Hames   JDStates.erase(I);
294f9aef477SLang Hames   return Error::success();
295f9aef477SLang Hames }
296f9aef477SLang Hames 
registerThreadDataSection(span<const char> ThreadDataSection)297ff846fcbSLang Hames Error MachOPlatformRuntimeState::registerThreadDataSection(
298ff846fcbSLang Hames     span<const char> ThreadDataSection) {
299ff846fcbSLang Hames   std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
300ff846fcbSLang Hames   auto I = ThreadDataSections.upper_bound(ThreadDataSection.data());
301ff846fcbSLang Hames   if (I != ThreadDataSections.begin()) {
302ff846fcbSLang Hames     auto J = std::prev(I);
303ff846fcbSLang Hames     if (J->first + J->second > ThreadDataSection.data())
304ff846fcbSLang Hames       return make_error<StringError>("Overlapping __thread_data sections");
305eda6afdaSLang Hames   }
306ff846fcbSLang Hames   ThreadDataSections.insert(
307ff846fcbSLang Hames       I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size()));
308bb5f97e3SLang Hames   return Error::success();
309bb5f97e3SLang Hames }
310bb5f97e3SLang Hames 
deregisterThreadDataSection(span<const char> ThreadDataSection)311ff846fcbSLang Hames Error MachOPlatformRuntimeState::deregisterThreadDataSection(
312ff846fcbSLang Hames     span<const char> ThreadDataSection) {
313ff846fcbSLang Hames   std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
3143fb64161SLang Hames   auto I = ThreadDataSections.find(ThreadDataSection.data());
315ff846fcbSLang Hames   if (I == ThreadDataSections.end())
316ff846fcbSLang Hames     return make_error<StringError>("Attempt to deregister unknown thread data "
317ff846fcbSLang Hames                                    "section");
318ff846fcbSLang Hames   ThreadDataSections.erase(I);
319bb5f97e3SLang Hames   return Error::success();
320bb5f97e3SLang Hames }
321bb5f97e3SLang Hames 
registerObjectPlatformSections(ExecutorAddr HeaderAddr,std::vector<std::pair<string_view,ExecutorAddrRange>> Secs)322f9aef477SLang Hames Error MachOPlatformRuntimeState::registerObjectPlatformSections(
323f9aef477SLang Hames     ExecutorAddr HeaderAddr,
324f9aef477SLang Hames     std::vector<std::pair<string_view, ExecutorAddrRange>> Secs) {
325f9aef477SLang Hames   ORC_RT_DEBUG({
326f9aef477SLang Hames     printdbg("MachOPlatform: Registering object sections for %p.\n",
327f9aef477SLang Hames              HeaderAddr.toPtr<void *>());
328f9aef477SLang Hames   });
329f9aef477SLang Hames 
330f9aef477SLang Hames   std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
331f9aef477SLang Hames   auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>());
332f9aef477SLang Hames   if (!JDS) {
333f9aef477SLang Hames     std::ostringstream ErrStream;
334f9aef477SLang Hames     ErrStream << "Could not register object platform sections for "
335f9aef477SLang Hames                  "unrecognized header "
336f9aef477SLang Hames               << HeaderAddr.toPtr<void *>();
337f9aef477SLang Hames     return make_error<StringError>(ErrStream.str());
338f9aef477SLang Hames   }
339f9aef477SLang Hames 
340f9aef477SLang Hames   for (auto &KV : Secs) {
341f9aef477SLang Hames     // FIXME: Validate section ranges?
342f9aef477SLang Hames     if (KV.first == "__DATA,__thread_data") {
343f9aef477SLang Hames       if (auto Err = registerThreadDataSection(KV.second.toSpan<const char>()))
344f9aef477SLang Hames         return Err;
345f9aef477SLang Hames     } else if (KV.first == "__DATA,__objc_selrefs")
346f9aef477SLang Hames       JDS->ObjCSelRefsSectionsNew.push_back(KV.second.toSpan<uintptr_t>());
347f9aef477SLang Hames     else if (KV.first == "__DATA,__objc_classlist")
348f9aef477SLang Hames       JDS->ObjCClassListSectionsNew.push_back(KV.second.toSpan<uintptr_t>());
349f9aef477SLang Hames     else if (KV.first == "__TEXT,__swift5_protos")
350f9aef477SLang Hames       JDS->Swift5ProtosSectionsNew.push_back(KV.second.toSpan<char>());
351f9aef477SLang Hames     else if (KV.first == "__TEXT,__swift5_proto")
352f9aef477SLang Hames       JDS->Swift5ProtoSectionsNew.push_back(KV.second.toSpan<char>());
353f9aef477SLang Hames     else if (KV.first == "__TEXT,__swift5_types")
354f9aef477SLang Hames       JDS->Swift5TypesSectionsNew.push_back(KV.second.toSpan<char>());
355f9aef477SLang Hames     else if (KV.first == "__DATA,__mod_init_func")
356f9aef477SLang Hames       JDS->ModInitsSectionsNew.push_back(KV.second.toSpan<void (*)()>());
357f9aef477SLang Hames     else {
358f9aef477SLang Hames       // Should this be a warning instead?
359f9aef477SLang Hames       return make_error<StringError>(
360f9aef477SLang Hames           "Encountered unexpected section " +
361f9aef477SLang Hames           std::string(KV.first.data(), KV.first.size()) +
362f9aef477SLang Hames           " while registering object platform sections");
363f9aef477SLang Hames     }
364f9aef477SLang Hames   }
365f9aef477SLang Hames 
366f9aef477SLang Hames   return Error::success();
367f9aef477SLang Hames }
368f9aef477SLang Hames 
369f9aef477SLang Hames // Remove the given range from the given vector if present.
370f9aef477SLang Hames // Returns true if the range was removed, false otherwise.
371f9aef477SLang Hames template <typename T>
removeIfPresent(std::vector<span<T>> & V,ExecutorAddrRange R)372f9aef477SLang Hames bool removeIfPresent(std::vector<span<T>> &V, ExecutorAddrRange R) {
373f9aef477SLang Hames   auto RI = std::find_if(
374f9aef477SLang Hames       V.rbegin(), V.rend(),
375f9aef477SLang Hames       [RS = R.toSpan<T>()](const span<T> &E) { return E.data() == RS.data(); });
376f9aef477SLang Hames   if (RI != V.rend()) {
377f9aef477SLang Hames     V.erase(std::next(RI).base());
378f9aef477SLang Hames     return true;
379f9aef477SLang Hames   }
380f9aef477SLang Hames   return false;
381f9aef477SLang Hames }
382f9aef477SLang Hames 
deregisterObjectPlatformSections(ExecutorAddr HeaderAddr,std::vector<std::pair<string_view,ExecutorAddrRange>> Secs)383f9aef477SLang Hames Error MachOPlatformRuntimeState::deregisterObjectPlatformSections(
384f9aef477SLang Hames     ExecutorAddr HeaderAddr,
385f9aef477SLang Hames     std::vector<std::pair<string_view, ExecutorAddrRange>> Secs) {
386f9aef477SLang Hames   // TODO: Make this more efficient? (maybe unnecessary if removal is rare?)
387f9aef477SLang Hames   // TODO: Add a JITDylib prepare-for-teardown operation that clears all
388f9aef477SLang Hames   //       registered sections, causing this function to take the fast-path.
389f9aef477SLang Hames   ORC_RT_DEBUG({
390f9aef477SLang Hames     printdbg("MachOPlatform: Registering object sections for %p.\n",
391f9aef477SLang Hames              HeaderAddr.toPtr<void *>());
392f9aef477SLang Hames   });
393f9aef477SLang Hames 
394f9aef477SLang Hames   std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
395f9aef477SLang Hames   auto *JDS = getJITDylibStateByHeader(HeaderAddr.toPtr<void *>());
396f9aef477SLang Hames   if (!JDS) {
397f9aef477SLang Hames     std::ostringstream ErrStream;
398f9aef477SLang Hames     ErrStream << "Could not register object platform sections for unrecognized "
399f9aef477SLang Hames                  "header "
400f9aef477SLang Hames               << HeaderAddr.toPtr<void *>();
401f9aef477SLang Hames     return make_error<StringError>(ErrStream.str());
402f9aef477SLang Hames   }
403f9aef477SLang Hames 
404f9aef477SLang Hames   // FIXME: Implement faster-path by returning immediately if JDS is being
405f9aef477SLang Hames   // torn down entirely?
406f9aef477SLang Hames 
407f9aef477SLang Hames   for (auto &KV : Secs) {
408f9aef477SLang Hames     // FIXME: Validate section ranges?
409f9aef477SLang Hames     if (KV.first == "__DATA,__thread_data") {
410f9aef477SLang Hames       if (auto Err =
411f9aef477SLang Hames               deregisterThreadDataSection(KV.second.toSpan<const char>()))
412f9aef477SLang Hames         return Err;
413f9aef477SLang Hames     } else if (KV.first == "__DATA,__objc_selrefs") {
414f9aef477SLang Hames       if (!removeIfPresent(JDS->ObjCSelRefsSections, KV.second))
415f9aef477SLang Hames         removeIfPresent(JDS->ObjCSelRefsSectionsNew, KV.second);
416f9aef477SLang Hames     } else if (KV.first == "__DATA,__objc_classlist") {
417f9aef477SLang Hames       if (!removeIfPresent(JDS->ObjCClassListSections, KV.second))
418f9aef477SLang Hames         removeIfPresent(JDS->ObjCClassListSectionsNew, KV.second);
419f9aef477SLang Hames     } else if (KV.first == "__TEXT,__swift5_protos") {
420f9aef477SLang Hames       if (!removeIfPresent(JDS->Swift5ProtosSections, KV.second))
421f9aef477SLang Hames         removeIfPresent(JDS->Swift5ProtosSectionsNew, KV.second);
422f9aef477SLang Hames     } else if (KV.first == "__TEXT,__swift5_proto") {
423f9aef477SLang Hames       if (!removeIfPresent(JDS->Swift5ProtoSections, KV.second))
424f9aef477SLang Hames         removeIfPresent(JDS->Swift5ProtoSectionsNew, KV.second);
425f9aef477SLang Hames     } else if (KV.first == "__TEXT,__swift5_types") {
426f9aef477SLang Hames       if (!removeIfPresent(JDS->Swift5TypesSections, KV.second))
427f9aef477SLang Hames         removeIfPresent(JDS->Swift5TypesSectionsNew, KV.second);
428f9aef477SLang Hames     } else if (KV.first == "__DATA,__mod_init_func") {
429f9aef477SLang Hames       if (!removeIfPresent(JDS->ModInitsSections, KV.second))
430f9aef477SLang Hames         removeIfPresent(JDS->ModInitsSectionsNew, KV.second);
431f9aef477SLang Hames     } else {
432f9aef477SLang Hames       // Should this be a warning instead?
433f9aef477SLang Hames       return make_error<StringError>(
434f9aef477SLang Hames           "Encountered unexpected section " +
435f9aef477SLang Hames           std::string(KV.first.data(), KV.first.size()) +
436f9aef477SLang Hames           " while deregistering object platform sections");
437f9aef477SLang Hames     }
438f9aef477SLang Hames   }
439f9aef477SLang Hames   return Error::success();
440f9aef477SLang Hames }
441f9aef477SLang Hames 
dlerror()442bb5f97e3SLang Hames const char *MachOPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); }
443bb5f97e3SLang Hames 
dlopen(string_view Path,int Mode)444bb5f97e3SLang Hames void *MachOPlatformRuntimeState::dlopen(string_view Path, int Mode) {
445f9aef477SLang Hames   ORC_RT_DEBUG({
446f9aef477SLang Hames     std::string S(Path.data(), Path.size());
447f9aef477SLang Hames     printdbg("MachOPlatform::dlopen(\"%s\")\n", S.c_str());
448f9aef477SLang Hames   });
449bb5f97e3SLang Hames   std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
450f9aef477SLang Hames   if (auto H = dlopenImpl(Path, Mode))
451f9aef477SLang Hames     return *H;
452f9aef477SLang Hames   else {
453f9aef477SLang Hames     // FIXME: Make dlerror thread safe.
454bb5f97e3SLang Hames     DLFcnError = toString(H.takeError());
455bb5f97e3SLang Hames     return nullptr;
456bb5f97e3SLang Hames   }
457bb5f97e3SLang Hames }
458bb5f97e3SLang Hames 
dlclose(void * DSOHandle)459bb5f97e3SLang Hames int MachOPlatformRuntimeState::dlclose(void *DSOHandle) {
460f9aef477SLang Hames   ORC_RT_DEBUG({
461f9aef477SLang Hames     auto *JDS = getJITDylibStateByHeader(DSOHandle);
462f9aef477SLang Hames     std::string DylibName;
463f9aef477SLang Hames     if (JDS) {
464f9aef477SLang Hames       std::string S;
465f9aef477SLang Hames       printdbg("MachOPlatform::dlclose(%p) (%s)\n", DSOHandle, S.c_str());
466f9aef477SLang Hames     } else
467f9aef477SLang Hames       printdbg("MachOPlatform::dlclose(%p) (%s)\n", DSOHandle,
468f9aef477SLang Hames                "invalid handle");
469f9aef477SLang Hames   });
470f9aef477SLang Hames   std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
471f9aef477SLang Hames   if (auto Err = dlcloseImpl(DSOHandle)) {
472f9aef477SLang Hames     // FIXME: Make dlerror thread safe.
473f9aef477SLang Hames     DLFcnError = toString(std::move(Err));
474f9aef477SLang Hames     return -1;
475f9aef477SLang Hames   }
476bb5f97e3SLang Hames   return 0;
477bb5f97e3SLang Hames }
478bb5f97e3SLang Hames 
dlsym(void * DSOHandle,string_view Symbol)479bb5f97e3SLang Hames void *MachOPlatformRuntimeState::dlsym(void *DSOHandle, string_view Symbol) {
480bb5f97e3SLang Hames   auto Addr = lookupSymbolInJITDylib(DSOHandle, Symbol);
481bb5f97e3SLang Hames   if (!Addr) {
482bb5f97e3SLang Hames     DLFcnError = toString(Addr.takeError());
483bb5f97e3SLang Hames     return 0;
484bb5f97e3SLang Hames   }
485bb5f97e3SLang Hames 
486bb5f97e3SLang Hames   return Addr->toPtr<void *>();
487bb5f97e3SLang Hames }
488bb5f97e3SLang Hames 
registerAtExit(void (* F)(void *),void * Arg,void * DSOHandle)489bb5f97e3SLang Hames int MachOPlatformRuntimeState::registerAtExit(void (*F)(void *), void *Arg,
490bb5f97e3SLang Hames                                               void *DSOHandle) {
491bb5f97e3SLang Hames   // FIXME: Handle out-of-memory errors, returning -1 if OOM.
492bb5f97e3SLang Hames   std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
493f9aef477SLang Hames   auto *JDS = getJITDylibStateByHeader(DSOHandle);
494f9aef477SLang Hames   if (!JDS) {
495f9aef477SLang Hames     ORC_RT_DEBUG({
496f9aef477SLang Hames       printdbg("MachOPlatformRuntimeState::registerAtExit called with "
497f9aef477SLang Hames                "unrecognized dso handle %p\n",
498f9aef477SLang Hames                DSOHandle);
499f9aef477SLang Hames     });
500f9aef477SLang Hames     return -1;
501f9aef477SLang Hames   }
502bb5f97e3SLang Hames   JDS->AtExits.push_back({F, Arg});
503bb5f97e3SLang Hames   return 0;
504bb5f97e3SLang Hames }
505bb5f97e3SLang Hames 
runAtExits(JITDylibState & JDS)506f9aef477SLang Hames void MachOPlatformRuntimeState::runAtExits(JITDylibState &JDS) {
507f9aef477SLang Hames   while (!JDS.AtExits.empty()) {
508f9aef477SLang Hames     auto &AE = JDS.AtExits.back();
509f9aef477SLang Hames     AE.Func(AE.Arg);
510f9aef477SLang Hames     JDS.AtExits.pop_back();
511f9aef477SLang Hames   }
512bb5f97e3SLang Hames }
513bb5f97e3SLang Hames 
runAtExits(void * DSOHandle)514f9aef477SLang Hames void MachOPlatformRuntimeState::runAtExits(void *DSOHandle) {
515f9aef477SLang Hames   std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
516f9aef477SLang Hames   auto *JDS = getJITDylibStateByHeader(DSOHandle);
517f9aef477SLang Hames   ORC_RT_DEBUG({
518f9aef477SLang Hames     printdbg("MachOPlatformRuntimeState::runAtExits called on unrecognized "
519f9aef477SLang Hames              "dso_handle %p\n",
520f9aef477SLang Hames              DSOHandle);
521f9aef477SLang Hames   });
522f9aef477SLang Hames   if (JDS)
523f9aef477SLang Hames     runAtExits(*JDS);
524bb5f97e3SLang Hames }
525bb5f97e3SLang Hames 
526eda6afdaSLang Hames Expected<std::pair<const char *, size_t>>
getThreadDataSectionFor(const char * ThreadData)527eda6afdaSLang Hames MachOPlatformRuntimeState::getThreadDataSectionFor(const char *ThreadData) {
528eda6afdaSLang Hames   std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
529eda6afdaSLang Hames   auto I = ThreadDataSections.upper_bound(ThreadData);
530eda6afdaSLang Hames   // Check that we have a valid entry covering this address.
531eda6afdaSLang Hames   if (I == ThreadDataSections.begin())
532eda6afdaSLang Hames     return make_error<StringError>("No thread local data section for key");
533eda6afdaSLang Hames   I = std::prev(I);
534eda6afdaSLang Hames   if (ThreadData >= I->first + I->second)
535eda6afdaSLang Hames     return make_error<StringError>("No thread local data section for key");
536eda6afdaSLang Hames   return *I;
537eda6afdaSLang Hames }
538eda6afdaSLang Hames 
539f9aef477SLang Hames MachOPlatformRuntimeState::JITDylibState *
getJITDylibStateByHeader(void * DSOHandle)540f9aef477SLang Hames MachOPlatformRuntimeState::getJITDylibStateByHeader(void *DSOHandle) {
541bb5f97e3SLang Hames   auto I = JDStates.find(DSOHandle);
542f9aef477SLang Hames   if (I == JDStates.end()) {
543f9aef477SLang Hames     I = JDStates.insert(std::make_pair(DSOHandle, JITDylibState())).first;
544f9aef477SLang Hames     I->second.Header = DSOHandle;
545f9aef477SLang Hames   }
546bb5f97e3SLang Hames   return &I->second;
547bb5f97e3SLang Hames }
548bb5f97e3SLang Hames 
549f9aef477SLang Hames MachOPlatformRuntimeState::JITDylibState *
getJITDylibStateByName(string_view Name)550bb5f97e3SLang Hames MachOPlatformRuntimeState::getJITDylibStateByName(string_view Name) {
551f9aef477SLang Hames   // FIXME: Avoid creating string once we have C++20.
552bb5f97e3SLang Hames   auto I = JDNameToHeader.find(std::string(Name.data(), Name.size()));
553f9aef477SLang Hames   if (I != JDNameToHeader.end())
554f9aef477SLang Hames     return getJITDylibStateByHeader(I->second);
555bb5f97e3SLang Hames   return nullptr;
556bb5f97e3SLang Hames }
557bb5f97e3SLang Hames 
5580820fbabSLang Hames Expected<ExecutorAddr>
lookupSymbolInJITDylib(void * DSOHandle,string_view Sym)559bb5f97e3SLang Hames MachOPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle,
560bb5f97e3SLang Hames                                                   string_view Sym) {
5610820fbabSLang Hames   Expected<ExecutorAddr> Result((ExecutorAddr()));
5620820fbabSLang Hames   if (auto Err = WrapperFunction<SPSExpected<SPSExecutorAddr>(
5630820fbabSLang Hames           SPSExecutorAddr, SPSString)>::call(&__orc_rt_macho_symbol_lookup_tag,
5640820fbabSLang Hames                                              Result,
5650820fbabSLang Hames                                              ExecutorAddr::fromPtr(DSOHandle),
5660820fbabSLang Hames                                              Sym))
567bb5f97e3SLang Hames     return std::move(Err);
568bb5f97e3SLang Hames   return Result;
569bb5f97e3SLang Hames }
570bb5f97e3SLang Hames 
571f9aef477SLang Hames template <typename T>
moveAppendSections(std::vector<span<T>> & Dst,std::vector<span<T>> & Src)572f9aef477SLang Hames static void moveAppendSections(std::vector<span<T>> &Dst,
573f9aef477SLang Hames                                std::vector<span<T>> &Src) {
574f9aef477SLang Hames   if (Dst.empty()) {
575f9aef477SLang Hames     Dst = std::move(Src);
576f9aef477SLang Hames     return;
577bb5f97e3SLang Hames   }
578bb5f97e3SLang Hames 
579f9aef477SLang Hames   Dst.reserve(Dst.size() + Src.size());
580f9aef477SLang Hames   std::copy(Src.begin(), Src.end(), std::back_inserter(Dst));
581f9aef477SLang Hames   Src.clear();
582f9aef477SLang Hames }
583bb5f97e3SLang Hames 
registerObjCSelectors(JITDylibState & JDS)584f9aef477SLang Hames Error MachOPlatformRuntimeState::registerObjCSelectors(JITDylibState &JDS) {
585f9aef477SLang Hames 
586f9aef477SLang Hames   if (JDS.ObjCSelRefsSectionsNew.empty())
587f9aef477SLang Hames     return Error::success();
588f9aef477SLang Hames 
589f9aef477SLang Hames   if (ORC_RT_UNLIKELY(!sel_registerName))
590f9aef477SLang Hames     return make_error<StringError>("sel_registerName is not available");
591f9aef477SLang Hames 
592f9aef477SLang Hames   for (const auto &ObjCSelRefs : JDS.ObjCSelRefsSectionsNew) {
593f9aef477SLang Hames     for (uintptr_t &SelEntry : ObjCSelRefs) {
594f9aef477SLang Hames       const char *SelName = reinterpret_cast<const char *>(SelEntry);
595f9aef477SLang Hames       auto Sel = sel_registerName(SelName);
596f9aef477SLang Hames       *reinterpret_cast<SEL *>(&SelEntry) = Sel;
597f9aef477SLang Hames     }
598f9aef477SLang Hames   }
599f9aef477SLang Hames 
600f9aef477SLang Hames   moveAppendSections(JDS.ObjCSelRefsSections, JDS.ObjCSelRefsSectionsNew);
601f9aef477SLang Hames   return Error::success();
602f9aef477SLang Hames }
603f9aef477SLang Hames 
registerObjCClasses(JITDylibState & JDS)604f9aef477SLang Hames Error MachOPlatformRuntimeState::registerObjCClasses(JITDylibState &JDS) {
605f9aef477SLang Hames 
606f9aef477SLang Hames   if (JDS.ObjCClassListSectionsNew.empty())
607f9aef477SLang Hames     return Error::success();
608f9aef477SLang Hames 
609f9aef477SLang Hames   if (ORC_RT_UNLIKELY(!objc_msgSend))
610f9aef477SLang Hames     return make_error<StringError>("objc_msgSend is not available");
611f9aef477SLang Hames   if (ORC_RT_UNLIKELY(!objc_readClassPair))
612f9aef477SLang Hames     return make_error<StringError>("objc_readClassPair is not available");
613f9aef477SLang Hames 
614f9aef477SLang Hames   struct ObjCClassCompiled {
615f9aef477SLang Hames     void *Metaclass;
616f9aef477SLang Hames     void *Parent;
617f9aef477SLang Hames     void *Cache1;
618f9aef477SLang Hames     void *Cache2;
619f9aef477SLang Hames     void *Data;
620f9aef477SLang Hames   };
621f9aef477SLang Hames 
622f9aef477SLang Hames   auto ClassSelector = sel_registerName("class");
623f9aef477SLang Hames 
624f9aef477SLang Hames   for (const auto &ObjCClassList : JDS.ObjCClassListSectionsNew) {
625f9aef477SLang Hames     for (uintptr_t ClassPtr : ObjCClassList) {
626f9aef477SLang Hames       auto *Cls = reinterpret_cast<Class>(ClassPtr);
627f9aef477SLang Hames       auto *ClassCompiled = reinterpret_cast<ObjCClassCompiled *>(ClassPtr);
628f9aef477SLang Hames       objc_msgSend(reinterpret_cast<id>(ClassCompiled->Parent), ClassSelector);
629f9aef477SLang Hames       auto Registered = objc_readClassPair(Cls, JDS.ObjCImageInfo);
630f9aef477SLang Hames 
631f9aef477SLang Hames       // FIXME: Improve diagnostic by reporting the failed class's name.
632f9aef477SLang Hames       if (Registered != Cls)
633f9aef477SLang Hames         return make_error<StringError>("Unable to register Objective-C class");
634f9aef477SLang Hames     }
635f9aef477SLang Hames   }
636f9aef477SLang Hames 
637f9aef477SLang Hames   moveAppendSections(JDS.ObjCClassListSections, JDS.ObjCClassListSectionsNew);
638f9aef477SLang Hames   return Error::success();
639f9aef477SLang Hames }
640f9aef477SLang Hames 
registerSwift5Protocols(JITDylibState & JDS)641f9aef477SLang Hames Error MachOPlatformRuntimeState::registerSwift5Protocols(JITDylibState &JDS) {
642f9aef477SLang Hames 
643f9aef477SLang Hames   if (JDS.Swift5ProtosSectionsNew.empty())
644f9aef477SLang Hames     return Error::success();
645f9aef477SLang Hames 
646f9aef477SLang Hames   if (ORC_RT_UNLIKELY(!swift_registerProtocols))
647f9aef477SLang Hames     return make_error<StringError>("swift_registerProtocols is not available");
648f9aef477SLang Hames 
649f9aef477SLang Hames   for (const auto &Swift5Protocols : JDS.Swift5ProtoSectionsNew)
650f9aef477SLang Hames     swift_registerProtocols(
651f9aef477SLang Hames         reinterpret_cast<const ProtocolRecord *>(Swift5Protocols.data()),
652f9aef477SLang Hames         reinterpret_cast<const ProtocolRecord *>(Swift5Protocols.data() +
653f9aef477SLang Hames                                                  Swift5Protocols.size()));
654f9aef477SLang Hames 
655f9aef477SLang Hames   moveAppendSections(JDS.Swift5ProtoSections, JDS.Swift5ProtoSectionsNew);
656f9aef477SLang Hames   return Error::success();
657f9aef477SLang Hames }
658f9aef477SLang Hames 
registerSwift5ProtocolConformances(JITDylibState & JDS)659f9aef477SLang Hames Error MachOPlatformRuntimeState::registerSwift5ProtocolConformances(
660f9aef477SLang Hames     JITDylibState &JDS) {
661f9aef477SLang Hames 
662f9aef477SLang Hames   if (JDS.Swift5ProtosSectionsNew.empty())
663f9aef477SLang Hames     return Error::success();
664f9aef477SLang Hames 
665f9aef477SLang Hames   if (ORC_RT_UNLIKELY(!swift_registerProtocolConformances))
666bb5f97e3SLang Hames     return make_error<StringError>(
667f9aef477SLang Hames         "swift_registerProtocolConformances is not available");
668bb5f97e3SLang Hames 
669f9aef477SLang Hames   for (const auto &ProtoConfSec : JDS.Swift5ProtosSectionsNew)
670f9aef477SLang Hames     swift_registerProtocolConformances(
671f9aef477SLang Hames         reinterpret_cast<const ProtocolConformanceRecord *>(
672f9aef477SLang Hames             ProtoConfSec.data()),
673f9aef477SLang Hames         reinterpret_cast<const ProtocolConformanceRecord *>(
674f9aef477SLang Hames             ProtoConfSec.data() + ProtoConfSec.size()));
675f9aef477SLang Hames 
676f9aef477SLang Hames   moveAppendSections(JDS.Swift5ProtosSections, JDS.Swift5ProtosSectionsNew);
677f9aef477SLang Hames   return Error::success();
678f9aef477SLang Hames }
679f9aef477SLang Hames 
registerSwift5Types(JITDylibState & JDS)680f9aef477SLang Hames Error MachOPlatformRuntimeState::registerSwift5Types(JITDylibState &JDS) {
681f9aef477SLang Hames 
682f9aef477SLang Hames   if (JDS.Swift5TypesSectionsNew.empty())
683f9aef477SLang Hames     return Error::success();
684f9aef477SLang Hames 
685f9aef477SLang Hames   if (ORC_RT_UNLIKELY(!swift_registerTypeMetadataRecords))
686f9aef477SLang Hames     return make_error<StringError>(
687f9aef477SLang Hames         "swift_registerTypeMetadataRecords is not available");
688f9aef477SLang Hames 
689f9aef477SLang Hames   for (const auto &TypeSec : JDS.Swift5TypesSectionsNew)
690f9aef477SLang Hames     swift_registerTypeMetadataRecords(
691f9aef477SLang Hames         reinterpret_cast<const TypeMetadataRecord *>(TypeSec.data()),
692f9aef477SLang Hames         reinterpret_cast<const TypeMetadataRecord *>(TypeSec.data() +
693f9aef477SLang Hames                                                      TypeSec.size()));
694f9aef477SLang Hames 
695f9aef477SLang Hames   moveAppendSections(JDS.Swift5TypesSections, JDS.Swift5TypesSectionsNew);
696f9aef477SLang Hames   return Error::success();
697f9aef477SLang Hames }
698f9aef477SLang Hames 
runModInits(JITDylibState & JDS)699f9aef477SLang Hames Error MachOPlatformRuntimeState::runModInits(JITDylibState &JDS) {
700f9aef477SLang Hames 
701f9aef477SLang Hames   for (const auto &ModInits : JDS.ModInitsSectionsNew) {
702f9aef477SLang Hames     for (void (*Init)() : ModInits)
703f9aef477SLang Hames       (*Init)();
704f9aef477SLang Hames   }
705f9aef477SLang Hames 
706f9aef477SLang Hames   moveAppendSections(JDS.ModInitsSections, JDS.ModInitsSectionsNew);
707f9aef477SLang Hames   return Error::success();
708f9aef477SLang Hames }
709f9aef477SLang Hames 
dlopenImpl(string_view Path,int Mode)710f9aef477SLang Hames Expected<void *> MachOPlatformRuntimeState::dlopenImpl(string_view Path,
711f9aef477SLang Hames                                                        int Mode) {
712f9aef477SLang Hames   // Try to find JITDylib state by name.
713f9aef477SLang Hames   auto *JDS = getJITDylibStateByName(Path);
714f9aef477SLang Hames 
715f9aef477SLang Hames   if (!JDS)
716f9aef477SLang Hames     return make_error<StringError>("No registered JTIDylib for path " +
717f9aef477SLang Hames                                    std::string(Path.data(), Path.size()));
718f9aef477SLang Hames 
719f9aef477SLang Hames   // If this JITDylib is unsealed, or this is the first dlopen then run
720f9aef477SLang Hames   // full dlopen path (update deps, push and run initializers, update ref
721f9aef477SLang Hames   // counts on all JITDylibs in the dep tree).
722f9aef477SLang Hames   if (!JDS->referenced() || !JDS->Sealed) {
723f9aef477SLang Hames     if (auto Err = dlopenFull(*JDS))
724bb5f97e3SLang Hames       return std::move(Err);
725f9aef477SLang Hames   }
726bb5f97e3SLang Hames 
727f9aef477SLang Hames   // Bump the ref-count on this dylib.
728f9aef477SLang Hames   ++JDS->DlRefCount;
729f9aef477SLang Hames 
730f9aef477SLang Hames   // Return the header address.
731bb5f97e3SLang Hames   return JDS->Header;
732bb5f97e3SLang Hames }
733bb5f97e3SLang Hames 
dlopenFull(JITDylibState & JDS)734f9aef477SLang Hames Error MachOPlatformRuntimeState::dlopenFull(JITDylibState &JDS) {
735f9aef477SLang Hames   // Call back to the JIT to push the initializers.
736f9aef477SLang Hames   Expected<MachOJITDylibDepInfoMap> DepInfo((MachOJITDylibDepInfoMap()));
737f9aef477SLang Hames   if (auto Err = WrapperFunction<SPSExpected<SPSMachOJITDylibDepInfoMap>(
738f9aef477SLang Hames           SPSExecutorAddr)>::call(&__orc_rt_macho_push_initializers_tag,
739f9aef477SLang Hames                                   DepInfo, ExecutorAddr::fromPtr(JDS.Header)))
740f9aef477SLang Hames     return Err;
741f9aef477SLang Hames   if (!DepInfo)
742f9aef477SLang Hames     return DepInfo.takeError();
743bb5f97e3SLang Hames 
744f9aef477SLang Hames   if (auto Err = dlopenInitialize(JDS, *DepInfo))
745f9aef477SLang Hames     return Err;
746bb5f97e3SLang Hames 
747f9aef477SLang Hames   if (!DepInfo->empty()) {
748f9aef477SLang Hames     ORC_RT_DEBUG({
749f9aef477SLang Hames       printdbg("Unrecognized dep-info key headers in dlopen of %s\n",
750f9aef477SLang Hames                JDS.Name.c_str());
751f9aef477SLang Hames     });
752f9aef477SLang Hames     std::ostringstream ErrStream;
753f9aef477SLang Hames     ErrStream << "Encountered unrecognized dep-info key headers "
754f9aef477SLang Hames                  "while processing dlopen of "
755f9aef477SLang Hames               << JDS.Name;
756f9aef477SLang Hames     return make_error<StringError>(ErrStream.str());
757f9aef477SLang Hames   }
758f9aef477SLang Hames 
759f9aef477SLang Hames   return Error::success();
760f9aef477SLang Hames }
761f9aef477SLang Hames 
dlopenInitialize(JITDylibState & JDS,MachOJITDylibDepInfoMap & DepInfo)762f9aef477SLang Hames Error MachOPlatformRuntimeState::dlopenInitialize(
763f9aef477SLang Hames     JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo) {
764f9aef477SLang Hames   ORC_RT_DEBUG({
765f9aef477SLang Hames     printdbg("MachOPlatformRuntimeState::dlopenInitialize(\"%s\")\n",
766f9aef477SLang Hames              JDS.Name.c_str());
767f9aef477SLang Hames   });
768f9aef477SLang Hames 
769f9aef477SLang Hames   // If the header is not present in the dep map then assume that we
770f9aef477SLang Hames   // already processed it earlier in the dlopenInitialize traversal and
771f9aef477SLang Hames   // return.
772f9aef477SLang Hames   // TODO: Keep a visited set instead so that we can error out on missing
773f9aef477SLang Hames   //       entries?
774f9aef477SLang Hames   auto I = DepInfo.find(ExecutorAddr::fromPtr(JDS.Header));
775f9aef477SLang Hames   if (I == DepInfo.end())
776f9aef477SLang Hames     return Error::success();
777f9aef477SLang Hames 
778f9aef477SLang Hames   auto DI = std::move(I->second);
779f9aef477SLang Hames   DepInfo.erase(I);
780f9aef477SLang Hames 
781f9aef477SLang Hames   // We don't need to re-initialize sealed JITDylibs that have already been
782f9aef477SLang Hames   // initialized. Just check that their dep-map entry is empty as expected.
783f9aef477SLang Hames   if (JDS.Sealed) {
784f9aef477SLang Hames     if (!DI.DepHeaders.empty()) {
785f9aef477SLang Hames       std::ostringstream ErrStream;
786f9aef477SLang Hames       ErrStream << "Sealed JITDylib " << JDS.Header
787f9aef477SLang Hames                 << " already has registered dependencies";
788f9aef477SLang Hames       return make_error<StringError>(ErrStream.str());
789f9aef477SLang Hames     }
790f9aef477SLang Hames     if (JDS.referenced())
791f9aef477SLang Hames       return Error::success();
792f9aef477SLang Hames   } else
793f9aef477SLang Hames     JDS.Sealed = DI.Sealed;
794f9aef477SLang Hames 
795f9aef477SLang Hames   // This is an unsealed or newly sealed JITDylib. Run initializers.
796f9aef477SLang Hames   std::vector<JITDylibState *> OldDeps;
797f9aef477SLang Hames   std::swap(JDS.Deps, OldDeps);
798f9aef477SLang Hames   JDS.Deps.reserve(DI.DepHeaders.size());
799f9aef477SLang Hames   for (auto DepHeaderAddr : DI.DepHeaders) {
800f9aef477SLang Hames     auto *DepJDS = getJITDylibStateByHeader(DepHeaderAddr.toPtr<void *>());
801f9aef477SLang Hames     if (!DepJDS) {
802f9aef477SLang Hames       std::ostringstream ErrStream;
803f9aef477SLang Hames       ErrStream << "Encountered unrecognized dep header "
804f9aef477SLang Hames                 << DepHeaderAddr.toPtr<void *>() << " while initializing "
805f9aef477SLang Hames                 << JDS.Name;
806f9aef477SLang Hames       return make_error<StringError>(ErrStream.str());
807f9aef477SLang Hames     }
808f9aef477SLang Hames     ++DepJDS->LinkedAgainstRefCount;
809f9aef477SLang Hames     if (auto Err = dlopenInitialize(*DepJDS, DepInfo))
810bb5f97e3SLang Hames       return Err;
811bb5f97e3SLang Hames   }
812f9aef477SLang Hames 
813f9aef477SLang Hames   // Initialize this JITDylib.
814f9aef477SLang Hames   if (auto Err = registerObjCSelectors(JDS))
815f9aef477SLang Hames     return Err;
816f9aef477SLang Hames   if (auto Err = registerObjCClasses(JDS))
817f9aef477SLang Hames     return Err;
818f9aef477SLang Hames   if (auto Err = registerSwift5Protocols(JDS))
819f9aef477SLang Hames     return Err;
820f9aef477SLang Hames   if (auto Err = registerSwift5ProtocolConformances(JDS))
821f9aef477SLang Hames     return Err;
822f9aef477SLang Hames   if (auto Err = registerSwift5Types(JDS))
823f9aef477SLang Hames     return Err;
824f9aef477SLang Hames   if (auto Err = runModInits(JDS))
825f9aef477SLang Hames     return Err;
826f9aef477SLang Hames 
827f9aef477SLang Hames   // Decrement old deps.
828f9aef477SLang Hames   // FIXME: We should probably continue and just report deinitialize errors
829f9aef477SLang Hames   // here.
830f9aef477SLang Hames   for (auto *DepJDS : OldDeps) {
831f9aef477SLang Hames     --DepJDS->LinkedAgainstRefCount;
832f9aef477SLang Hames     if (!DepJDS->referenced())
833f9aef477SLang Hames       if (auto Err = dlcloseDeinitialize(*DepJDS))
834f9aef477SLang Hames         return Err;
835f9aef477SLang Hames   }
836f9aef477SLang Hames 
837f9aef477SLang Hames   return Error::success();
838f9aef477SLang Hames }
839f9aef477SLang Hames 
dlcloseImpl(void * DSOHandle)840f9aef477SLang Hames Error MachOPlatformRuntimeState::dlcloseImpl(void *DSOHandle) {
841f9aef477SLang Hames   // Try to find JITDylib state by header.
842f9aef477SLang Hames   auto *JDS = getJITDylibStateByHeader(DSOHandle);
843f9aef477SLang Hames 
844f9aef477SLang Hames   if (!JDS) {
845f9aef477SLang Hames     std::ostringstream ErrStream;
846f9aef477SLang Hames     ErrStream << "No registered JITDylib for " << DSOHandle;
847f9aef477SLang Hames     return make_error<StringError>(ErrStream.str());
848f9aef477SLang Hames   }
849f9aef477SLang Hames 
850f9aef477SLang Hames   // Bump the ref-count.
851f9aef477SLang Hames   --JDS->DlRefCount;
852f9aef477SLang Hames 
853f9aef477SLang Hames   if (!JDS->referenced())
854f9aef477SLang Hames     return dlcloseDeinitialize(*JDS);
855f9aef477SLang Hames 
856f9aef477SLang Hames   return Error::success();
857f9aef477SLang Hames }
858f9aef477SLang Hames 
dlcloseDeinitialize(JITDylibState & JDS)859f9aef477SLang Hames Error MachOPlatformRuntimeState::dlcloseDeinitialize(JITDylibState &JDS) {
860f9aef477SLang Hames 
861f9aef477SLang Hames   ORC_RT_DEBUG({
862f9aef477SLang Hames     printdbg("MachOPlatformRuntimeState::dlcloseDeinitialize(\"%s\")\n",
863f9aef477SLang Hames              JDS.Name.c_str());
864f9aef477SLang Hames   });
865f9aef477SLang Hames 
866f9aef477SLang Hames   runAtExits(JDS);
867f9aef477SLang Hames 
868f9aef477SLang Hames   // Reset mod-inits
869f9aef477SLang Hames   moveAppendSections(JDS.ModInitsSections, JDS.ModInitsSectionsNew);
870f9aef477SLang Hames   JDS.ModInitsSectionsNew = std::move(JDS.ModInitsSections);
871f9aef477SLang Hames 
872f9aef477SLang Hames   // Deinitialize any dependencies.
873f9aef477SLang Hames   for (auto *DepJDS : JDS.Deps) {
874f9aef477SLang Hames     --DepJDS->LinkedAgainstRefCount;
875f9aef477SLang Hames     if (!DepJDS->referenced())
876f9aef477SLang Hames       if (auto Err = dlcloseDeinitialize(*DepJDS))
877f9aef477SLang Hames         return Err;
878bb5f97e3SLang Hames   }
879bb5f97e3SLang Hames 
880bb5f97e3SLang Hames   return Error::success();
881bb5f97e3SLang Hames }
882bb5f97e3SLang Hames 
883eda6afdaSLang Hames class MachOPlatformRuntimeTLVManager {
884eda6afdaSLang Hames public:
885eda6afdaSLang Hames   void *getInstance(const char *ThreadData);
886eda6afdaSLang Hames 
887eda6afdaSLang Hames private:
888eda6afdaSLang Hames   std::unordered_map<const char *, char *> Instances;
889eda6afdaSLang Hames   std::unordered_map<const char *, std::unique_ptr<char[]>> AllocatedSections;
890eda6afdaSLang Hames };
891eda6afdaSLang Hames 
getInstance(const char * ThreadData)892eda6afdaSLang Hames void *MachOPlatformRuntimeTLVManager::getInstance(const char *ThreadData) {
893eda6afdaSLang Hames   auto I = Instances.find(ThreadData);
894eda6afdaSLang Hames   if (I != Instances.end())
895eda6afdaSLang Hames     return I->second;
896eda6afdaSLang Hames 
897eda6afdaSLang Hames   auto TDS =
898eda6afdaSLang Hames       MachOPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData);
899eda6afdaSLang Hames   if (!TDS) {
900eda6afdaSLang Hames     __orc_rt_log_error(toString(TDS.takeError()).c_str());
901eda6afdaSLang Hames     return nullptr;
902eda6afdaSLang Hames   }
903eda6afdaSLang Hames 
904eda6afdaSLang Hames   auto &Allocated = AllocatedSections[TDS->first];
905eda6afdaSLang Hames   if (!Allocated) {
906eda6afdaSLang Hames     Allocated = std::make_unique<char[]>(TDS->second);
907eda6afdaSLang Hames     memcpy(Allocated.get(), TDS->first, TDS->second);
908eda6afdaSLang Hames   }
909eda6afdaSLang Hames 
910eda6afdaSLang Hames   size_t ThreadDataDelta = ThreadData - TDS->first;
911eda6afdaSLang Hames   assert(ThreadDataDelta <= TDS->second && "ThreadData outside section bounds");
912eda6afdaSLang Hames 
913eda6afdaSLang Hames   char *Instance = Allocated.get() + ThreadDataDelta;
914eda6afdaSLang Hames   Instances[ThreadData] = Instance;
915eda6afdaSLang Hames   return Instance;
916eda6afdaSLang Hames }
917eda6afdaSLang Hames 
destroyMachOTLVMgr(void * MachOTLVMgr)918eda6afdaSLang Hames void destroyMachOTLVMgr(void *MachOTLVMgr) {
919eda6afdaSLang Hames   delete static_cast<MachOPlatformRuntimeTLVManager *>(MachOTLVMgr);
920eda6afdaSLang Hames }
921eda6afdaSLang Hames 
runWrapperFunctionCalls(std::vector<WrapperFunctionCall> WFCs)922ff846fcbSLang Hames Error runWrapperFunctionCalls(std::vector<WrapperFunctionCall> WFCs) {
923ff846fcbSLang Hames   for (auto &WFC : WFCs)
9240ede1b90SLang Hames     if (auto Err = WFC.runWithSPSRet<void>())
925ff846fcbSLang Hames       return Err;
926ff846fcbSLang Hames   return Error::success();
927ff846fcbSLang Hames }
928ff846fcbSLang Hames 
929bb5f97e3SLang Hames } // end anonymous namespace
930bb5f97e3SLang Hames 
931bb5f97e3SLang Hames //------------------------------------------------------------------------------
932bb5f97e3SLang Hames //                             JIT entry points
933bb5f97e3SLang Hames //------------------------------------------------------------------------------
934bb5f97e3SLang Hames 
935bb5f97e3SLang Hames ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_platform_bootstrap(char * ArgData,size_t ArgSize)936bb5f97e3SLang Hames __orc_rt_macho_platform_bootstrap(char *ArgData, size_t ArgSize) {
937bb5f97e3SLang Hames   MachOPlatformRuntimeState::initialize();
938bb5f97e3SLang Hames   return WrapperFunctionResult().release();
939bb5f97e3SLang Hames }
940bb5f97e3SLang Hames 
941bb5f97e3SLang Hames ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_platform_shutdown(char * ArgData,size_t ArgSize)942bb5f97e3SLang Hames __orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) {
943bb5f97e3SLang Hames   MachOPlatformRuntimeState::destroy();
944bb5f97e3SLang Hames   return WrapperFunctionResult().release();
945bb5f97e3SLang Hames }
946bb5f97e3SLang Hames 
947bb5f97e3SLang Hames ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_register_jitdylib(char * ArgData,size_t ArgSize)948f9aef477SLang Hames __orc_rt_macho_register_jitdylib(char *ArgData, size_t ArgSize) {
949f9aef477SLang Hames   return WrapperFunction<SPSError(SPSString, SPSExecutorAddr)>::handle(
950089acf25SLang Hames              ArgData, ArgSize,
951f9aef477SLang Hames              [](std::string &Name, ExecutorAddr HeaderAddr) {
952f9aef477SLang Hames                return MachOPlatformRuntimeState::get().registerJITDylib(
953f9aef477SLang Hames                    std::move(Name), HeaderAddr.toPtr<void *>());
954bb5f97e3SLang Hames              })
955bb5f97e3SLang Hames       .release();
956bb5f97e3SLang Hames }
957bb5f97e3SLang Hames 
958bb5f97e3SLang Hames ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_deregister_jitdylib(char * ArgData,size_t ArgSize)959f9aef477SLang Hames __orc_rt_macho_deregister_jitdylib(char *ArgData, size_t ArgSize) {
960f9aef477SLang Hames   return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(
961089acf25SLang Hames              ArgData, ArgSize,
962f9aef477SLang Hames              [](ExecutorAddr HeaderAddr) {
963f9aef477SLang Hames                return MachOPlatformRuntimeState::get().deregisterJITDylib(
964f9aef477SLang Hames                    HeaderAddr.toPtr<void *>());
965f9aef477SLang Hames              })
966f9aef477SLang Hames       .release();
967f9aef477SLang Hames }
968f9aef477SLang Hames 
969f9aef477SLang Hames ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_register_object_platform_sections(char * ArgData,size_t ArgSize)970f9aef477SLang Hames __orc_rt_macho_register_object_platform_sections(char *ArgData,
971f9aef477SLang Hames                                                  size_t ArgSize) {
972f9aef477SLang Hames   return WrapperFunction<SPSError(SPSExecutorAddr,
973f9aef477SLang Hames                                   SPSMachOObjectPlatformSectionsMap)>::
974f9aef477SLang Hames       handle(ArgData, ArgSize,
975f9aef477SLang Hames              [](ExecutorAddr HeaderAddr,
976f9aef477SLang Hames                 std::vector<std::pair<string_view, ExecutorAddrRange>> &Secs) {
977ff846fcbSLang Hames                return MachOPlatformRuntimeState::get()
978f9aef477SLang Hames                    .registerObjectPlatformSections(HeaderAddr, std::move(Secs));
979f9aef477SLang Hames              })
980f9aef477SLang Hames           .release();
981f9aef477SLang Hames }
982f9aef477SLang Hames 
983f9aef477SLang Hames ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_deregister_object_platform_sections(char * ArgData,size_t ArgSize)984f9aef477SLang Hames __orc_rt_macho_deregister_object_platform_sections(char *ArgData,
985f9aef477SLang Hames                                                    size_t ArgSize) {
986f9aef477SLang Hames   return WrapperFunction<SPSError(SPSExecutorAddr,
987f9aef477SLang Hames                                   SPSMachOObjectPlatformSectionsMap)>::
988f9aef477SLang Hames       handle(ArgData, ArgSize,
989f9aef477SLang Hames              [](ExecutorAddr HeaderAddr,
990f9aef477SLang Hames                 std::vector<std::pair<string_view, ExecutorAddrRange>> &Secs) {
991f9aef477SLang Hames                return MachOPlatformRuntimeState::get()
992f9aef477SLang Hames                    .deregisterObjectPlatformSections(HeaderAddr,
993f9aef477SLang Hames                                                      std::move(Secs));
994bb5f97e3SLang Hames              })
995bb5f97e3SLang Hames           .release();
996bb5f97e3SLang Hames }
997bb5f97e3SLang Hames 
998ff846fcbSLang Hames ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_run_wrapper_function_calls(char * ArgData,size_t ArgSize)999ff846fcbSLang Hames __orc_rt_macho_run_wrapper_function_calls(char *ArgData, size_t ArgSize) {
1000ff846fcbSLang Hames   return WrapperFunction<SPSError(SPSSequence<SPSWrapperFunctionCall>)>::handle(
1001ff846fcbSLang Hames              ArgData, ArgSize, runWrapperFunctionCalls)
1002ff846fcbSLang Hames       .release();
1003ff846fcbSLang Hames }
1004ff846fcbSLang Hames 
1005bb5f97e3SLang Hames //------------------------------------------------------------------------------
1006eda6afdaSLang Hames //                            TLV support
1007eda6afdaSLang Hames //------------------------------------------------------------------------------
1008eda6afdaSLang Hames 
__orc_rt_macho_tlv_get_addr_impl(TLVDescriptor * D)1009eda6afdaSLang Hames ORC_RT_INTERFACE void *__orc_rt_macho_tlv_get_addr_impl(TLVDescriptor *D) {
1010eda6afdaSLang Hames   auto *TLVMgr = static_cast<MachOPlatformRuntimeTLVManager *>(
1011eda6afdaSLang Hames       pthread_getspecific(D->Key));
1012eda6afdaSLang Hames   if (!TLVMgr) {
1013eda6afdaSLang Hames     TLVMgr = new MachOPlatformRuntimeTLVManager();
1014eda6afdaSLang Hames     if (pthread_setspecific(D->Key, TLVMgr)) {
1015eda6afdaSLang Hames       __orc_rt_log_error("Call to pthread_setspecific failed");
1016eda6afdaSLang Hames       return nullptr;
1017eda6afdaSLang Hames     }
1018eda6afdaSLang Hames   }
1019eda6afdaSLang Hames 
1020eda6afdaSLang Hames   return TLVMgr->getInstance(
1021eda6afdaSLang Hames       reinterpret_cast<char *>(static_cast<uintptr_t>(D->DataAddress)));
1022eda6afdaSLang Hames }
1023eda6afdaSLang Hames 
1024eda6afdaSLang Hames ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_create_pthread_key(char * ArgData,size_t ArgSize)1025eda6afdaSLang Hames __orc_rt_macho_create_pthread_key(char *ArgData, size_t ArgSize) {
1026eda6afdaSLang Hames   return WrapperFunction<SPSExpected<uint64_t>(void)>::handle(
1027eda6afdaSLang Hames              ArgData, ArgSize,
1028eda6afdaSLang Hames              []() -> Expected<uint64_t> {
1029eda6afdaSLang Hames                pthread_key_t Key;
1030eda6afdaSLang Hames                if (int Err = pthread_key_create(&Key, destroyMachOTLVMgr)) {
1031eda6afdaSLang Hames                  __orc_rt_log_error("Call to pthread_key_create failed");
1032eda6afdaSLang Hames                  return make_error<StringError>(strerror(Err));
1033eda6afdaSLang Hames                }
1034eda6afdaSLang Hames                return static_cast<uint64_t>(Key);
1035eda6afdaSLang Hames              })
1036eda6afdaSLang Hames       .release();
1037eda6afdaSLang Hames }
1038eda6afdaSLang Hames 
1039eda6afdaSLang Hames //------------------------------------------------------------------------------
1040bb5f97e3SLang Hames //                           cxa_atexit support
1041bb5f97e3SLang Hames //------------------------------------------------------------------------------
1042bb5f97e3SLang Hames 
__orc_rt_macho_cxa_atexit(void (* func)(void *),void * arg,void * dso_handle)1043bb5f97e3SLang Hames int __orc_rt_macho_cxa_atexit(void (*func)(void *), void *arg,
1044bb5f97e3SLang Hames                               void *dso_handle) {
1045bb5f97e3SLang Hames   return MachOPlatformRuntimeState::get().registerAtExit(func, arg, dso_handle);
1046bb5f97e3SLang Hames }
1047bb5f97e3SLang Hames 
__orc_rt_macho_cxa_finalize(void * dso_handle)1048bb5f97e3SLang Hames void __orc_rt_macho_cxa_finalize(void *dso_handle) {
1049bb5f97e3SLang Hames   MachOPlatformRuntimeState::get().runAtExits(dso_handle);
1050bb5f97e3SLang Hames }
1051bb5f97e3SLang Hames 
1052bb5f97e3SLang Hames //------------------------------------------------------------------------------
1053bb5f97e3SLang Hames //                        JIT'd dlfcn alternatives.
1054bb5f97e3SLang Hames //------------------------------------------------------------------------------
1055bb5f97e3SLang Hames 
__orc_rt_macho_jit_dlerror()1056bb5f97e3SLang Hames const char *__orc_rt_macho_jit_dlerror() {
1057bb5f97e3SLang Hames   return MachOPlatformRuntimeState::get().dlerror();
1058bb5f97e3SLang Hames }
1059bb5f97e3SLang Hames 
__orc_rt_macho_jit_dlopen(const char * path,int mode)1060bb5f97e3SLang Hames void *__orc_rt_macho_jit_dlopen(const char *path, int mode) {
1061bb5f97e3SLang Hames   return MachOPlatformRuntimeState::get().dlopen(path, mode);
1062bb5f97e3SLang Hames }
1063bb5f97e3SLang Hames 
__orc_rt_macho_jit_dlclose(void * dso_handle)1064bb5f97e3SLang Hames int __orc_rt_macho_jit_dlclose(void *dso_handle) {
1065bb5f97e3SLang Hames   return MachOPlatformRuntimeState::get().dlclose(dso_handle);
1066bb5f97e3SLang Hames }
1067bb5f97e3SLang Hames 
__orc_rt_macho_jit_dlsym(void * dso_handle,const char * symbol)1068bb5f97e3SLang Hames void *__orc_rt_macho_jit_dlsym(void *dso_handle, const char *symbol) {
1069bb5f97e3SLang Hames   return MachOPlatformRuntimeState::get().dlsym(dso_handle, symbol);
1070bb5f97e3SLang Hames }
1071bb5f97e3SLang Hames 
1072bb5f97e3SLang Hames //------------------------------------------------------------------------------
1073bb5f97e3SLang Hames //                             MachO Run Program
1074bb5f97e3SLang Hames //------------------------------------------------------------------------------
1075bb5f97e3SLang Hames 
__orc_rt_macho_run_program(const char * JITDylibName,const char * EntrySymbolName,int argc,char * argv[])1076bb5f97e3SLang Hames ORC_RT_INTERFACE int64_t __orc_rt_macho_run_program(const char *JITDylibName,
1077bb5f97e3SLang Hames                                                     const char *EntrySymbolName,
1078bb5f97e3SLang Hames                                                     int argc, char *argv[]) {
1079bb5f97e3SLang Hames   using MainTy = int (*)(int, char *[]);
1080bb5f97e3SLang Hames 
1081bb5f97e3SLang Hames   void *H = __orc_rt_macho_jit_dlopen(JITDylibName,
1082bb5f97e3SLang Hames                                       __orc_rt::macho::ORC_RT_RTLD_LAZY);
1083bb5f97e3SLang Hames   if (!H) {
1084bb5f97e3SLang Hames     __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
1085bb5f97e3SLang Hames     return -1;
1086bb5f97e3SLang Hames   }
1087bb5f97e3SLang Hames 
1088bb5f97e3SLang Hames   auto *Main =
1089bb5f97e3SLang Hames       reinterpret_cast<MainTy>(__orc_rt_macho_jit_dlsym(H, EntrySymbolName));
1090bb5f97e3SLang Hames 
1091bb5f97e3SLang Hames   if (!Main) {
1092bb5f97e3SLang Hames     __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
1093bb5f97e3SLang Hames     return -1;
1094bb5f97e3SLang Hames   }
1095bb5f97e3SLang Hames 
1096bb5f97e3SLang Hames   int Result = Main(argc, argv);
1097bb5f97e3SLang Hames 
1098bb5f97e3SLang Hames   if (__orc_rt_macho_jit_dlclose(H) == -1)
1099bb5f97e3SLang Hames     __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
1100bb5f97e3SLang Hames 
1101bb5f97e3SLang Hames   return Result;
1102bb5f97e3SLang Hames }
1103