1 //===- macho_platform.cpp -------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains code required to load the rest of the MachO runtime.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "macho_platform.h"
14 #include "common.h"
15 #include "error.h"
16 #include "wrapper_function_utils.h"
17
18 #include <map>
19 #include <mutex>
20 #include <sstream>
21 #include <unordered_map>
22 #include <vector>
23
24 using namespace __orc_rt;
25 using namespace __orc_rt::macho;
26
27 // Declare function tags for functions in the JIT process.
28 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_get_initializers_tag)
29 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_get_deinitializers_tag)
30 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_symbol_lookup_tag)
31
32 // eh-frame registration functions.
33 // We expect these to be available for all processes.
34 extern "C" void __register_frame(const void *);
35 extern "C" void __deregister_frame(const void *);
36
37 // Objective-C types.
38 struct objc_class;
39 struct objc_image_info;
40 struct objc_object;
41 struct objc_selector;
42
43 using Class = objc_class *;
44 using id = objc_object *;
45 using SEL = objc_selector *;
46
47 // Objective-C registration functions.
48 // These are weakly imported. If the Objective-C runtime has not been loaded
49 // then code containing Objective-C sections will generate an error.
50 extern "C" id objc_msgSend(id, SEL, ...) ORC_RT_WEAK_IMPORT;
51 extern "C" Class objc_readClassPair(Class,
52 const objc_image_info *) ORC_RT_WEAK_IMPORT;
53 extern "C" SEL sel_registerName(const char *) ORC_RT_WEAK_IMPORT;
54
55 // Swift types.
56 class ProtocolRecord;
57 class ProtocolConformanceRecord;
58
59 extern "C" void
60 swift_registerProtocols(const ProtocolRecord *begin,
61 const ProtocolRecord *end) ORC_RT_WEAK_IMPORT;
62
63 extern "C" void swift_registerProtocolConformances(
64 const ProtocolConformanceRecord *begin,
65 const ProtocolConformanceRecord *end) ORC_RT_WEAK_IMPORT;
66
67 namespace {
68
69 template <typename HandleFDEFn>
walkEHFrameSection(span<const char> EHFrameSection,HandleFDEFn HandleFDE)70 void walkEHFrameSection(span<const char> EHFrameSection,
71 HandleFDEFn HandleFDE) {
72 const char *CurCFIRecord = EHFrameSection.data();
73 uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
74
75 while (CurCFIRecord != EHFrameSection.end() && Size != 0) {
76 const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
77 if (Size == 0xffffffff)
78 Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
79 else
80 Size += 4;
81 uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
82
83 if (Offset != 0)
84 HandleFDE(CurCFIRecord);
85
86 CurCFIRecord += Size;
87 Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
88 }
89 }
90
validatePointerSectionExtent(const char * SectionName,const ExecutorAddressRange & SE)91 Error validatePointerSectionExtent(const char *SectionName,
92 const ExecutorAddressRange &SE) {
93 if (SE.size().getValue() % sizeof(uintptr_t)) {
94 std::ostringstream ErrMsg;
95 ErrMsg << std::hex << "Size of " << SectionName << " 0x"
96 << SE.StartAddress.getValue() << " -- 0x" << SE.EndAddress.getValue()
97 << " is not a pointer multiple";
98 return make_error<StringError>(ErrMsg.str());
99 }
100 return Error::success();
101 }
102
registerObjCSelectors(const std::vector<ExecutorAddressRange> & ObjCSelRefsSections,const MachOJITDylibInitializers & MOJDIs)103 Error registerObjCSelectors(
104 const std::vector<ExecutorAddressRange> &ObjCSelRefsSections,
105 const MachOJITDylibInitializers &MOJDIs) {
106
107 if (ORC_RT_UNLIKELY(!sel_registerName))
108 return make_error<StringError>("sel_registerName is not available");
109
110 for (const auto &ObjCSelRefs : ObjCSelRefsSections) {
111
112 if (auto Err = validatePointerSectionExtent("__objc_selrefs", ObjCSelRefs))
113 return Err;
114
115 fprintf(stderr, "Processing selrefs section at 0x%llx\n",
116 ObjCSelRefs.StartAddress.getValue());
117 for (uintptr_t SelEntry : ObjCSelRefs.toSpan<uintptr_t>()) {
118 const char *SelName = reinterpret_cast<const char *>(SelEntry);
119 fprintf(stderr, "Registering selector \"%s\"\n", SelName);
120 auto Sel = sel_registerName(SelName);
121 *reinterpret_cast<SEL *>(SelEntry) = Sel;
122 }
123 }
124
125 return Error::success();
126 }
127
registerObjCClasses(const std::vector<ExecutorAddressRange> & ObjCClassListSections,const MachOJITDylibInitializers & MOJDIs)128 Error registerObjCClasses(
129 const std::vector<ExecutorAddressRange> &ObjCClassListSections,
130 const MachOJITDylibInitializers &MOJDIs) {
131
132 if (ObjCClassListSections.empty())
133 return Error::success();
134
135 if (ORC_RT_UNLIKELY(!objc_msgSend))
136 return make_error<StringError>("objc_msgSend is not available");
137 if (ORC_RT_UNLIKELY(!objc_readClassPair))
138 return make_error<StringError>("objc_readClassPair is not available");
139
140 struct ObjCClassCompiled {
141 void *Metaclass;
142 void *Parent;
143 void *Cache1;
144 void *Cache2;
145 void *Data;
146 };
147
148 auto *ImageInfo =
149 MOJDIs.ObjCImageInfoAddress.toPtr<const objc_image_info *>();
150 auto ClassSelector = sel_registerName("class");
151
152 for (const auto &ObjCClassList : ObjCClassListSections) {
153
154 if (auto Err =
155 validatePointerSectionExtent("__objc_classlist", ObjCClassList))
156 return Err;
157
158 for (uintptr_t ClassPtr : ObjCClassList.toSpan<uintptr_t>()) {
159 auto *Cls = reinterpret_cast<Class>(ClassPtr);
160 auto *ClassCompiled = reinterpret_cast<ObjCClassCompiled *>(ClassPtr);
161 objc_msgSend(reinterpret_cast<id>(ClassCompiled->Parent), ClassSelector);
162 auto Registered = objc_readClassPair(Cls, ImageInfo);
163
164 // FIXME: Improve diagnostic by reporting the failed class's name.
165 if (Registered != Cls)
166 return make_error<StringError>("Unable to register Objective-C class");
167 }
168 }
169 return Error::success();
170 }
171
registerSwift5Protocols(const std::vector<ExecutorAddressRange> & Swift5ProtocolSections,const MachOJITDylibInitializers & MOJDIs)172 Error registerSwift5Protocols(
173 const std::vector<ExecutorAddressRange> &Swift5ProtocolSections,
174 const MachOJITDylibInitializers &MOJDIs) {
175
176 if (ORC_RT_UNLIKELY(!Swift5ProtocolSections.empty() &&
177 !swift_registerProtocols))
178 return make_error<StringError>("swift_registerProtocols is not available");
179
180 for (const auto &Swift5Protocols : Swift5ProtocolSections)
181 swift_registerProtocols(
182 Swift5Protocols.StartAddress.toPtr<const ProtocolRecord *>(),
183 Swift5Protocols.EndAddress.toPtr<const ProtocolRecord *>());
184
185 return Error::success();
186 }
187
registerSwift5ProtocolConformances(const std::vector<ExecutorAddressRange> & Swift5ProtocolConformanceSections,const MachOJITDylibInitializers & MOJDIs)188 Error registerSwift5ProtocolConformances(
189 const std::vector<ExecutorAddressRange> &Swift5ProtocolConformanceSections,
190 const MachOJITDylibInitializers &MOJDIs) {
191
192 if (ORC_RT_UNLIKELY(!Swift5ProtocolConformanceSections.empty() &&
193 !swift_registerProtocolConformances))
194 return make_error<StringError>(
195 "swift_registerProtocolConformances is not available");
196
197 for (const auto &ProtoConfSec : Swift5ProtocolConformanceSections)
198 swift_registerProtocolConformances(
199 ProtoConfSec.StartAddress.toPtr<const ProtocolConformanceRecord *>(),
200 ProtoConfSec.EndAddress.toPtr<const ProtocolConformanceRecord *>());
201
202 return Error::success();
203 }
204
runModInits(const std::vector<ExecutorAddressRange> & ModInitsSections,const MachOJITDylibInitializers & MOJDIs)205 Error runModInits(const std::vector<ExecutorAddressRange> &ModInitsSections,
206 const MachOJITDylibInitializers &MOJDIs) {
207
208 for (const auto &ModInits : ModInitsSections) {
209 if (auto Err = validatePointerSectionExtent("__mod_inits", ModInits))
210 return Err;
211
212 using InitFunc = void (*)();
213 for (auto *Init : ModInits.toSpan<InitFunc>())
214 (*Init)();
215 }
216
217 return Error::success();
218 }
219
220 struct TLVDescriptor {
221 void *(*Thunk)(TLVDescriptor *) = nullptr;
222 unsigned long Key = 0;
223 unsigned long DataAddress = 0;
224 };
225
226 class MachOPlatformRuntimeState {
227 private:
228 struct AtExitEntry {
229 void (*Func)(void *);
230 void *Arg;
231 };
232
233 using AtExitsVector = std::vector<AtExitEntry>;
234
235 struct PerJITDylibState {
236 void *Header = nullptr;
237 size_t RefCount = 0;
238 bool AllowReinitialization = false;
239 AtExitsVector AtExits;
240 };
241
242 public:
243 static void initialize();
244 static MachOPlatformRuntimeState &get();
245 static void destroy();
246
247 MachOPlatformRuntimeState() = default;
248
249 // Delete copy and move constructors.
250 MachOPlatformRuntimeState(const MachOPlatformRuntimeState &) = delete;
251 MachOPlatformRuntimeState &
252 operator=(const MachOPlatformRuntimeState &) = delete;
253 MachOPlatformRuntimeState(MachOPlatformRuntimeState &&) = delete;
254 MachOPlatformRuntimeState &operator=(MachOPlatformRuntimeState &&) = delete;
255
256 Error registerObjectSections(MachOPerObjectSectionsToRegister POSR);
257 Error deregisterObjectSections(MachOPerObjectSectionsToRegister POSR);
258
259 const char *dlerror();
260 void *dlopen(string_view Name, int Mode);
261 int dlclose(void *DSOHandle);
262 void *dlsym(void *DSOHandle, string_view Symbol);
263
264 int registerAtExit(void (*F)(void *), void *Arg, void *DSOHandle);
265 void runAtExits(void *DSOHandle);
266
267 /// Returns the base address of the section containing ThreadData.
268 Expected<std::pair<const char *, size_t>>
269 getThreadDataSectionFor(const char *ThreadData);
270
271 private:
272 PerJITDylibState *getJITDylibStateByHeaderAddr(void *DSOHandle);
273 PerJITDylibState *getJITDylibStateByName(string_view Path);
274 PerJITDylibState &getOrCreateJITDylibState(MachOJITDylibInitializers &MOJDIs);
275
276 Error registerThreadDataSection(span<const char> ThreadDataSec);
277
278 Expected<ExecutorAddress> lookupSymbolInJITDylib(void *DSOHandle,
279 string_view Symbol);
280
281 Expected<MachOJITDylibInitializerSequence>
282 getJITDylibInitializersByName(string_view Path);
283 Expected<void *> dlopenInitialize(string_view Path, int Mode);
284 Error initializeJITDylib(MachOJITDylibInitializers &MOJDIs);
285
286 static MachOPlatformRuntimeState *MOPS;
287
288 using InitSectionHandler =
289 Error (*)(const std::vector<ExecutorAddressRange> &Sections,
290 const MachOJITDylibInitializers &MOJDIs);
291 const std::vector<std::pair<const char *, InitSectionHandler>> InitSections =
292 {{"__DATA,__objc_selrefs", registerObjCSelectors},
293 {"__DATA,__objc_classlist", registerObjCClasses},
294 {"__TEXT,__swift5_protos", registerSwift5Protocols},
295 {"__TEXT,__swift5_proto", registerSwift5ProtocolConformances},
296 {"__DATA,__mod_init_func", runModInits}};
297
298 // FIXME: Move to thread-state.
299 std::string DLFcnError;
300
301 std::recursive_mutex JDStatesMutex;
302 std::unordered_map<void *, PerJITDylibState> JDStates;
303 std::unordered_map<std::string, void *> JDNameToHeader;
304
305 std::mutex ThreadDataSectionsMutex;
306 std::map<const char *, size_t> ThreadDataSections;
307 };
308
309 MachOPlatformRuntimeState *MachOPlatformRuntimeState::MOPS = nullptr;
310
initialize()311 void MachOPlatformRuntimeState::initialize() {
312 assert(!MOPS && "MachOPlatformRuntimeState should be null");
313 MOPS = new MachOPlatformRuntimeState();
314 }
315
get()316 MachOPlatformRuntimeState &MachOPlatformRuntimeState::get() {
317 assert(MOPS && "MachOPlatformRuntimeState not initialized");
318 return *MOPS;
319 }
320
destroy()321 void MachOPlatformRuntimeState::destroy() {
322 assert(MOPS && "MachOPlatformRuntimeState not initialized");
323 delete MOPS;
324 }
325
registerObjectSections(MachOPerObjectSectionsToRegister POSR)326 Error MachOPlatformRuntimeState::registerObjectSections(
327 MachOPerObjectSectionsToRegister POSR) {
328 if (POSR.EHFrameSection.StartAddress)
329 walkEHFrameSection(POSR.EHFrameSection.toSpan<const char>(),
330 __register_frame);
331
332 if (POSR.ThreadDataSection.StartAddress) {
333 if (auto Err = registerThreadDataSection(
334 POSR.ThreadDataSection.toSpan<const char>()))
335 return Err;
336 }
337
338 return Error::success();
339 }
340
deregisterObjectSections(MachOPerObjectSectionsToRegister POSR)341 Error MachOPlatformRuntimeState::deregisterObjectSections(
342 MachOPerObjectSectionsToRegister POSR) {
343 if (POSR.EHFrameSection.StartAddress)
344 walkEHFrameSection(POSR.EHFrameSection.toSpan<const char>(),
345 __deregister_frame);
346
347 return Error::success();
348 }
349
dlerror()350 const char *MachOPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); }
351
dlopen(string_view Path,int Mode)352 void *MachOPlatformRuntimeState::dlopen(string_view Path, int Mode) {
353 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
354
355 // Use fast path if all JITDylibs are already loaded and don't require
356 // re-running initializers.
357 if (auto *JDS = getJITDylibStateByName(Path)) {
358 if (!JDS->AllowReinitialization) {
359 ++JDS->RefCount;
360 return JDS->Header;
361 }
362 }
363
364 auto H = dlopenInitialize(Path, Mode);
365 if (!H) {
366 DLFcnError = toString(H.takeError());
367 return nullptr;
368 }
369
370 return *H;
371 }
372
dlclose(void * DSOHandle)373 int MachOPlatformRuntimeState::dlclose(void *DSOHandle) {
374 runAtExits(DSOHandle);
375 return 0;
376 }
377
dlsym(void * DSOHandle,string_view Symbol)378 void *MachOPlatformRuntimeState::dlsym(void *DSOHandle, string_view Symbol) {
379 auto Addr = lookupSymbolInJITDylib(DSOHandle, Symbol);
380 if (!Addr) {
381 DLFcnError = toString(Addr.takeError());
382 return 0;
383 }
384
385 return Addr->toPtr<void *>();
386 }
387
registerAtExit(void (* F)(void *),void * Arg,void * DSOHandle)388 int MachOPlatformRuntimeState::registerAtExit(void (*F)(void *), void *Arg,
389 void *DSOHandle) {
390 // FIXME: Handle out-of-memory errors, returning -1 if OOM.
391 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
392 auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);
393 assert(JDS && "JITDylib state not initialized");
394 JDS->AtExits.push_back({F, Arg});
395 return 0;
396 }
397
runAtExits(void * DSOHandle)398 void MachOPlatformRuntimeState::runAtExits(void *DSOHandle) {
399 // FIXME: Should atexits be allowed to run concurrently with access to
400 // JDState?
401 AtExitsVector V;
402 {
403 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
404 auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);
405 assert(JDS && "JITDlybi state not initialized");
406 std::swap(V, JDS->AtExits);
407 }
408
409 while (!V.empty()) {
410 auto &AE = V.back();
411 AE.Func(AE.Arg);
412 V.pop_back();
413 }
414 }
415
416 Expected<std::pair<const char *, size_t>>
getThreadDataSectionFor(const char * ThreadData)417 MachOPlatformRuntimeState::getThreadDataSectionFor(const char *ThreadData) {
418 std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
419 auto I = ThreadDataSections.upper_bound(ThreadData);
420 // Check that we have a valid entry covering this address.
421 if (I == ThreadDataSections.begin())
422 return make_error<StringError>("No thread local data section for key");
423 I = std::prev(I);
424 if (ThreadData >= I->first + I->second)
425 return make_error<StringError>("No thread local data section for key");
426 return *I;
427 }
428
429 MachOPlatformRuntimeState::PerJITDylibState *
getJITDylibStateByHeaderAddr(void * DSOHandle)430 MachOPlatformRuntimeState::getJITDylibStateByHeaderAddr(void *DSOHandle) {
431 auto I = JDStates.find(DSOHandle);
432 if (I == JDStates.end())
433 return nullptr;
434 return &I->second;
435 }
436
437 MachOPlatformRuntimeState::PerJITDylibState *
getJITDylibStateByName(string_view Name)438 MachOPlatformRuntimeState::getJITDylibStateByName(string_view Name) {
439 // FIXME: Avoid creating string copy here.
440 auto I = JDNameToHeader.find(std::string(Name.data(), Name.size()));
441 if (I == JDNameToHeader.end())
442 return nullptr;
443 void *H = I->second;
444 auto J = JDStates.find(H);
445 assert(J != JDStates.end() &&
446 "JITDylib has name map entry but no header map entry");
447 return &J->second;
448 }
449
450 MachOPlatformRuntimeState::PerJITDylibState &
getOrCreateJITDylibState(MachOJITDylibInitializers & MOJDIs)451 MachOPlatformRuntimeState::getOrCreateJITDylibState(
452 MachOJITDylibInitializers &MOJDIs) {
453 void *Header = MOJDIs.MachOHeaderAddress.toPtr<void *>();
454
455 auto &JDS = JDStates[Header];
456
457 // If this entry hasn't been created yet.
458 if (!JDS.Header) {
459 assert(!JDNameToHeader.count(MOJDIs.Name) &&
460 "JITDylib has header map entry but no name map entry");
461 JDNameToHeader[MOJDIs.Name] = Header;
462 JDS.Header = Header;
463 }
464
465 return JDS;
466 }
467
registerThreadDataSection(span<const char> ThreadDataSection)468 Error MachOPlatformRuntimeState::registerThreadDataSection(
469 span<const char> ThreadDataSection) {
470 std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
471 auto I = ThreadDataSections.upper_bound(ThreadDataSection.data());
472 if (I != ThreadDataSections.begin()) {
473 auto J = std::prev(I);
474 if (J->first + J->second > ThreadDataSection.data())
475 return make_error<StringError>("Overlapping __thread_data sections");
476 }
477 ThreadDataSections.insert(
478 I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size()));
479 return Error::success();
480 }
481
482 Expected<ExecutorAddress>
lookupSymbolInJITDylib(void * DSOHandle,string_view Sym)483 MachOPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle,
484 string_view Sym) {
485 Expected<ExecutorAddress> Result((ExecutorAddress()));
486 if (auto Err = WrapperFunction<SPSExpected<SPSExecutorAddress>(
487 SPSExecutorAddress,
488 SPSString)>::call(&__orc_rt_macho_symbol_lookup_tag, Result,
489 ExecutorAddress::fromPtr(DSOHandle), Sym))
490 return std::move(Err);
491 return Result;
492 }
493
494 Expected<MachOJITDylibInitializerSequence>
getJITDylibInitializersByName(string_view Path)495 MachOPlatformRuntimeState::getJITDylibInitializersByName(string_view Path) {
496 Expected<MachOJITDylibInitializerSequence> Result(
497 (MachOJITDylibInitializerSequence()));
498 std::string PathStr(Path.data(), Path.size());
499 if (auto Err =
500 WrapperFunction<SPSExpected<SPSMachOJITDylibInitializerSequence>(
501 SPSString)>::call(&__orc_rt_macho_get_initializers_tag, Result,
502 Path))
503 return std::move(Err);
504 return Result;
505 }
506
dlopenInitialize(string_view Path,int Mode)507 Expected<void *> MachOPlatformRuntimeState::dlopenInitialize(string_view Path,
508 int Mode) {
509 // Either our JITDylib wasn't loaded, or it or one of its dependencies allows
510 // reinitialization. We need to call in to the JIT to see if there's any new
511 // work pending.
512 auto InitSeq = getJITDylibInitializersByName(Path);
513 if (!InitSeq)
514 return InitSeq.takeError();
515
516 // Init sequences should be non-empty.
517 if (InitSeq->empty())
518 return make_error<StringError>(
519 "__orc_rt_macho_get_initializers returned an "
520 "empty init sequence");
521
522 // Otherwise register and run initializers for each JITDylib.
523 for (auto &MOJDIs : *InitSeq)
524 if (auto Err = initializeJITDylib(MOJDIs))
525 return std::move(Err);
526
527 // Return the header for the last item in the list.
528 auto *JDS = getJITDylibStateByHeaderAddr(
529 InitSeq->back().MachOHeaderAddress.toPtr<void *>());
530 assert(JDS && "Missing state entry for JD");
531 return JDS->Header;
532 }
533
initializeJITDylib(MachOJITDylibInitializers & MOJDIs)534 Error MachOPlatformRuntimeState::initializeJITDylib(
535 MachOJITDylibInitializers &MOJDIs) {
536
537 auto &JDS = getOrCreateJITDylibState(MOJDIs);
538 ++JDS.RefCount;
539
540 for (auto &KV : InitSections) {
541 const auto &Name = KV.first;
542 const auto &Handler = KV.second;
543 auto I = MOJDIs.InitSections.find(Name);
544 if (I != MOJDIs.InitSections.end()) {
545 if (auto Err = Handler(I->second, MOJDIs))
546 return Err;
547 }
548 }
549
550 return Error::success();
551 }
552
553 class MachOPlatformRuntimeTLVManager {
554 public:
555 void *getInstance(const char *ThreadData);
556
557 private:
558 std::unordered_map<const char *, char *> Instances;
559 std::unordered_map<const char *, std::unique_ptr<char[]>> AllocatedSections;
560 };
561
getInstance(const char * ThreadData)562 void *MachOPlatformRuntimeTLVManager::getInstance(const char *ThreadData) {
563 auto I = Instances.find(ThreadData);
564 if (I != Instances.end())
565 return I->second;
566
567 auto TDS =
568 MachOPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData);
569 if (!TDS) {
570 __orc_rt_log_error(toString(TDS.takeError()).c_str());
571 return nullptr;
572 }
573
574 auto &Allocated = AllocatedSections[TDS->first];
575 if (!Allocated) {
576 Allocated = std::make_unique<char[]>(TDS->second);
577 memcpy(Allocated.get(), TDS->first, TDS->second);
578 }
579
580 size_t ThreadDataDelta = ThreadData - TDS->first;
581 assert(ThreadDataDelta <= TDS->second && "ThreadData outside section bounds");
582
583 char *Instance = Allocated.get() + ThreadDataDelta;
584 Instances[ThreadData] = Instance;
585 return Instance;
586 }
587
destroyMachOTLVMgr(void * MachOTLVMgr)588 void destroyMachOTLVMgr(void *MachOTLVMgr) {
589 delete static_cast<MachOPlatformRuntimeTLVManager *>(MachOTLVMgr);
590 }
591
592 } // end anonymous namespace
593
594 //------------------------------------------------------------------------------
595 // JIT entry points
596 //------------------------------------------------------------------------------
597
598 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_platform_bootstrap(char * ArgData,size_t ArgSize)599 __orc_rt_macho_platform_bootstrap(char *ArgData, size_t ArgSize) {
600 MachOPlatformRuntimeState::initialize();
601 return WrapperFunctionResult().release();
602 }
603
604 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_platform_shutdown(char * ArgData,size_t ArgSize)605 __orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) {
606 MachOPlatformRuntimeState::destroy();
607 return WrapperFunctionResult().release();
608 }
609
610 /// Wrapper function for registering metadata on a per-object basis.
611 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_register_object_sections(char * ArgData,size_t ArgSize)612 __orc_rt_macho_register_object_sections(char *ArgData, size_t ArgSize) {
613 return WrapperFunction<SPSError(SPSMachOPerObjectSectionsToRegister)>::handle(
614 ArgData, ArgSize,
615 [](MachOPerObjectSectionsToRegister &POSR) {
616 return MachOPlatformRuntimeState::get().registerObjectSections(
617 std::move(POSR));
618 })
619 .release();
620 }
621
622 /// Wrapper for releasing per-object metadat.
623 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_deregister_object_sections(char * ArgData,size_t ArgSize)624 __orc_rt_macho_deregister_object_sections(char *ArgData, size_t ArgSize) {
625 return WrapperFunction<SPSError(SPSMachOPerObjectSectionsToRegister)>::handle(
626 ArgData, ArgSize,
627 [](MachOPerObjectSectionsToRegister &POSR) {
628 return MachOPlatformRuntimeState::get().deregisterObjectSections(
629 std::move(POSR));
630 })
631 .release();
632 }
633
634 //------------------------------------------------------------------------------
635 // TLV support
636 //------------------------------------------------------------------------------
637
__orc_rt_macho_tlv_get_addr_impl(TLVDescriptor * D)638 ORC_RT_INTERFACE void *__orc_rt_macho_tlv_get_addr_impl(TLVDescriptor *D) {
639 auto *TLVMgr = static_cast<MachOPlatformRuntimeTLVManager *>(
640 pthread_getspecific(D->Key));
641 if (!TLVMgr) {
642 TLVMgr = new MachOPlatformRuntimeTLVManager();
643 if (pthread_setspecific(D->Key, TLVMgr)) {
644 __orc_rt_log_error("Call to pthread_setspecific failed");
645 return nullptr;
646 }
647 }
648
649 return TLVMgr->getInstance(
650 reinterpret_cast<char *>(static_cast<uintptr_t>(D->DataAddress)));
651 }
652
653 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_create_pthread_key(char * ArgData,size_t ArgSize)654 __orc_rt_macho_create_pthread_key(char *ArgData, size_t ArgSize) {
655 return WrapperFunction<SPSExpected<uint64_t>(void)>::handle(
656 ArgData, ArgSize,
657 []() -> Expected<uint64_t> {
658 pthread_key_t Key;
659 if (int Err = pthread_key_create(&Key, destroyMachOTLVMgr)) {
660 __orc_rt_log_error("Call to pthread_key_create failed");
661 return make_error<StringError>(strerror(Err));
662 }
663 return static_cast<uint64_t>(Key);
664 })
665 .release();
666 }
667
668 //------------------------------------------------------------------------------
669 // cxa_atexit support
670 //------------------------------------------------------------------------------
671
__orc_rt_macho_cxa_atexit(void (* func)(void *),void * arg,void * dso_handle)672 int __orc_rt_macho_cxa_atexit(void (*func)(void *), void *arg,
673 void *dso_handle) {
674 return MachOPlatformRuntimeState::get().registerAtExit(func, arg, dso_handle);
675 }
676
__orc_rt_macho_cxa_finalize(void * dso_handle)677 void __orc_rt_macho_cxa_finalize(void *dso_handle) {
678 MachOPlatformRuntimeState::get().runAtExits(dso_handle);
679 }
680
681 //------------------------------------------------------------------------------
682 // JIT'd dlfcn alternatives.
683 //------------------------------------------------------------------------------
684
__orc_rt_macho_jit_dlerror()685 const char *__orc_rt_macho_jit_dlerror() {
686 return MachOPlatformRuntimeState::get().dlerror();
687 }
688
__orc_rt_macho_jit_dlopen(const char * path,int mode)689 void *__orc_rt_macho_jit_dlopen(const char *path, int mode) {
690 return MachOPlatformRuntimeState::get().dlopen(path, mode);
691 }
692
__orc_rt_macho_jit_dlclose(void * dso_handle)693 int __orc_rt_macho_jit_dlclose(void *dso_handle) {
694 return MachOPlatformRuntimeState::get().dlclose(dso_handle);
695 }
696
__orc_rt_macho_jit_dlsym(void * dso_handle,const char * symbol)697 void *__orc_rt_macho_jit_dlsym(void *dso_handle, const char *symbol) {
698 return MachOPlatformRuntimeState::get().dlsym(dso_handle, symbol);
699 }
700
701 //------------------------------------------------------------------------------
702 // MachO Run Program
703 //------------------------------------------------------------------------------
704
__orc_rt_macho_run_program(const char * JITDylibName,const char * EntrySymbolName,int argc,char * argv[])705 ORC_RT_INTERFACE int64_t __orc_rt_macho_run_program(const char *JITDylibName,
706 const char *EntrySymbolName,
707 int argc, char *argv[]) {
708 using MainTy = int (*)(int, char *[]);
709
710 void *H = __orc_rt_macho_jit_dlopen(JITDylibName,
711 __orc_rt::macho::ORC_RT_RTLD_LAZY);
712 if (!H) {
713 __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
714 return -1;
715 }
716
717 auto *Main =
718 reinterpret_cast<MainTy>(__orc_rt_macho_jit_dlsym(H, EntrySymbolName));
719
720 if (!Main) {
721 __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
722 return -1;
723 }
724
725 int Result = Main(argc, argv);
726
727 if (__orc_rt_macho_jit_dlclose(H) == -1)
728 __orc_rt_log_error(__orc_rt_macho_jit_dlerror());
729
730 return Result;
731 }
732