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