Skip to content

Commit ff846fc

Browse files
committed
[ORC][ORC-RT] Switch MachO EH/TLV registration from EPC-calls to alloc actions.
MachOPlatform used to make an EPC-call (registerObjectSections) to register the eh-frame and thread-data sections for each linked object with the ORC runtime. Now that JITLinkMemoryManager supports allocation actions we can use these instead of an EPC call. This saves us one EPC-call per object linked, and manages registration/deregistration in the executor, rather than the controller process. In the future we may use this to allow JIT'd code in the executor to outlive the controller object while still being able to be cleanly destroyed. Since the code for allocation actions must be available when the actions are run, and since the eh-frame registration code lives in the ORC runtime itself, this change required that MachO eh-frame support be split out of macho_platform.cpp and into its own macho_ehframe_registration.cpp file that has no other dependencies. During bootstrap we start by forcing emission of macho_ehframe_registration.cpp so that eh-frame registration is guaranteed to be available for the rest of the bootstrap process. Then we load the rest of the MachO-platform runtime support, erroring out if there is any attempt to use TLVs. Once the bootstrap process is complete all subsequent code can use all features.
1 parent b77c6db commit ff846fc

File tree

5 files changed

+152
-198
lines changed

5 files changed

+152
-198
lines changed

compiler-rt/lib/orc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
set(ORC_SOURCES
55
extensible_rtti.cpp
66
log_error_to_stderr.cpp
7+
macho_ehframe_registration.cpp
78
macho_platform.cpp
89
elfnix_platform.cpp
910
run_program_wrapper.cpp

compiler-rt/lib/orc/macho_platform.cpp

Lines changed: 52 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_get_initializers_tag)
2929
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_get_deinitializers_tag)
3030
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_macho_symbol_lookup_tag)
3131

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-
3732
// Objective-C types.
3833
struct objc_class;
3934
struct objc_image_info;
@@ -66,28 +61,6 @@ extern "C" void swift_registerProtocolConformances(
6661

6762
namespace {
6863

69-
template <typename HandleFDEFn>
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-
9164
Error validatePointerSectionExtent(const char *SectionName,
9265
const ExecutorAddrRange &SE) {
9366
if (SE.size().getValue() % sizeof(uintptr_t)) {
@@ -250,8 +223,8 @@ class MachOPlatformRuntimeState {
250223
MachOPlatformRuntimeState(MachOPlatformRuntimeState &&) = delete;
251224
MachOPlatformRuntimeState &operator=(MachOPlatformRuntimeState &&) = delete;
252225

253-
Error registerObjectSections(MachOPerObjectSectionsToRegister POSR);
254-
Error deregisterObjectSections(MachOPerObjectSectionsToRegister POSR);
226+
Error registerThreadDataSection(span<const char> ThreadDataSec);
227+
Error deregisterThreadDataSection(span<const char> ThreadDataSec);
255228

256229
const char *dlerror();
257230
void *dlopen(string_view Name, int Mode);
@@ -270,8 +243,6 @@ class MachOPlatformRuntimeState {
270243
PerJITDylibState *getJITDylibStateByName(string_view Path);
271244
PerJITDylibState &getOrCreateJITDylibState(MachOJITDylibInitializers &MOJDIs);
272245

273-
Error registerThreadDataSection(span<const char> ThreadDataSec);
274-
275246
Expected<ExecutorAddr> lookupSymbolInJITDylib(void *DSOHandle,
276247
string_view Symbol);
277248

@@ -320,27 +291,28 @@ void MachOPlatformRuntimeState::destroy() {
320291
delete MOPS;
321292
}
322293

323-
Error MachOPlatformRuntimeState::registerObjectSections(
324-
MachOPerObjectSectionsToRegister POSR) {
325-
if (POSR.EHFrameSection.Start)
326-
walkEHFrameSection(POSR.EHFrameSection.toSpan<const char>(),
327-
__register_frame);
328-
329-
if (POSR.ThreadDataSection.Start) {
330-
if (auto Err = registerThreadDataSection(
331-
POSR.ThreadDataSection.toSpan<const char>()))
332-
return Err;
294+
Error MachOPlatformRuntimeState::registerThreadDataSection(
295+
span<const char> ThreadDataSection) {
296+
std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
297+
auto I = ThreadDataSections.upper_bound(ThreadDataSection.data());
298+
if (I != ThreadDataSections.begin()) {
299+
auto J = std::prev(I);
300+
if (J->first + J->second > ThreadDataSection.data())
301+
return make_error<StringError>("Overlapping __thread_data sections");
333302
}
334-
303+
ThreadDataSections.insert(
304+
I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size()));
335305
return Error::success();
336306
}
337307

338-
Error MachOPlatformRuntimeState::deregisterObjectSections(
339-
MachOPerObjectSectionsToRegister POSR) {
340-
if (POSR.EHFrameSection.Start)
341-
walkEHFrameSection(POSR.EHFrameSection.toSpan<const char>(),
342-
__deregister_frame);
343-
308+
Error MachOPlatformRuntimeState::deregisterThreadDataSection(
309+
span<const char> ThreadDataSection) {
310+
std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
311+
auto I = ThreadDataSections.find(ThreadDataSection.end());
312+
if (I == ThreadDataSections.end())
313+
return make_error<StringError>("Attempt to deregister unknown thread data "
314+
"section");
315+
ThreadDataSections.erase(I);
344316
return Error::success();
345317
}
346318

@@ -462,20 +434,6 @@ MachOPlatformRuntimeState::getOrCreateJITDylibState(
462434
return JDS;
463435
}
464436

465-
Error MachOPlatformRuntimeState::registerThreadDataSection(
466-
span<const char> ThreadDataSection) {
467-
std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
468-
auto I = ThreadDataSections.upper_bound(ThreadDataSection.data());
469-
if (I != ThreadDataSections.begin()) {
470-
auto J = std::prev(I);
471-
if (J->first + J->second > ThreadDataSection.data())
472-
return make_error<StringError>("Overlapping __thread_data sections");
473-
}
474-
ThreadDataSections.insert(
475-
I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size()));
476-
return Error::success();
477-
}
478-
479437
Expected<ExecutorAddr>
480438
MachOPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle,
481439
string_view Sym) {
@@ -587,6 +545,13 @@ void destroyMachOTLVMgr(void *MachOTLVMgr) {
587545
delete static_cast<MachOPlatformRuntimeTLVManager *>(MachOTLVMgr);
588546
}
589547

548+
Error runWrapperFunctionCalls(std::vector<WrapperFunctionCall> WFCs) {
549+
for (auto &WFC : WFCs)
550+
if (auto Err = WFC.runWithSPSRet())
551+
return Err;
552+
return Error::success();
553+
}
554+
590555
} // end anonymous namespace
591556

592557
//------------------------------------------------------------------------------
@@ -605,30 +570,41 @@ __orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) {
605570
return WrapperFunctionResult().release();
606571
}
607572

608-
/// Wrapper function for registering metadata on a per-object basis.
609573
ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
610-
__orc_rt_macho_register_object_sections(char *ArgData, size_t ArgSize) {
611-
return WrapperFunction<SPSError(SPSMachOPerObjectSectionsToRegister)>::handle(
612-
ArgData, ArgSize,
613-
[](MachOPerObjectSectionsToRegister &POSR) {
614-
return MachOPlatformRuntimeState::get().registerObjectSections(
615-
std::move(POSR));
574+
__orc_rt_macho_register_thread_data_section(char *ArgData, size_t ArgSize) {
575+
// NOTE: Does not use SPS to deserialize arg buffer, instead the arg buffer
576+
// is taken to be the range of the thread data section.
577+
return WrapperFunction<SPSError()>::handle(
578+
nullptr, 0,
579+
[&]() {
580+
return MachOPlatformRuntimeState::get()
581+
.registerThreadDataSection(
582+
span<const char>(ArgData, ArgSize));
616583
})
617584
.release();
618585
}
619586

620-
/// Wrapper for releasing per-object metadat.
621587
ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
622-
__orc_rt_macho_deregister_object_sections(char *ArgData, size_t ArgSize) {
623-
return WrapperFunction<SPSError(SPSMachOPerObjectSectionsToRegister)>::handle(
624-
ArgData, ArgSize,
625-
[](MachOPerObjectSectionsToRegister &POSR) {
626-
return MachOPlatformRuntimeState::get().deregisterObjectSections(
627-
std::move(POSR));
588+
__orc_rt_macho_deregister_thread_data_section(char *ArgData, size_t ArgSize) {
589+
// NOTE: Does not use SPS to deserialize arg buffer, instead the arg buffer
590+
// is taken to be the range of the thread data section.
591+
return WrapperFunction<SPSError()>::handle(
592+
nullptr, 0,
593+
[&]() {
594+
return MachOPlatformRuntimeState::get()
595+
.deregisterThreadDataSection(
596+
span<const char>(ArgData, ArgSize));
628597
})
629598
.release();
630599
}
631600

601+
ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
602+
__orc_rt_macho_run_wrapper_function_calls(char *ArgData, size_t ArgSize) {
603+
return WrapperFunction<SPSError(SPSSequence<SPSWrapperFunctionCall>)>::handle(
604+
ArgData, ArgSize, runWrapperFunctionCalls)
605+
.release();
606+
}
607+
632608
//------------------------------------------------------------------------------
633609
// TLV support
634610
//------------------------------------------------------------------------------

compiler-rt/lib/orc/macho_platform.h

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@ ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlsym(void *dso_handle,
3131
namespace __orc_rt {
3232
namespace macho {
3333

34-
struct MachOPerObjectSectionsToRegister {
35-
ExecutorAddrRange EHFrameSection;
36-
ExecutorAddrRange ThreadDataSection;
37-
};
38-
3934
struct MachOJITDylibInitializers {
4035
using SectionList = std::vector<ExecutorAddrRange>;
4136

@@ -67,32 +62,6 @@ enum dlopen_mode : int {
6762

6863
} // end namespace macho
6964

70-
using SPSMachOPerObjectSectionsToRegister =
71-
SPSTuple<SPSExecutorAddrRange, SPSExecutorAddrRange>;
72-
73-
template <>
74-
class SPSSerializationTraits<SPSMachOPerObjectSectionsToRegister,
75-
macho::MachOPerObjectSectionsToRegister> {
76-
77-
public:
78-
static size_t size(const macho::MachOPerObjectSectionsToRegister &MOPOSR) {
79-
return SPSMachOPerObjectSectionsToRegister::AsArgList::size(
80-
MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
81-
}
82-
83-
static bool serialize(SPSOutputBuffer &OB,
84-
const macho::MachOPerObjectSectionsToRegister &MOPOSR) {
85-
return SPSMachOPerObjectSectionsToRegister::AsArgList::serialize(
86-
OB, MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
87-
}
88-
89-
static bool deserialize(SPSInputBuffer &IB,
90-
macho::MachOPerObjectSectionsToRegister &MOPOSR) {
91-
return SPSMachOPerObjectSectionsToRegister::AsArgList::deserialize(
92-
IB, MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
93-
}
94-
};
95-
9665
using SPSNamedExecutorAddrRangeSequenceMap =
9766
SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRangeSequence>>;
9867

llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@
2626
namespace llvm {
2727
namespace orc {
2828

29-
struct MachOPerObjectSectionsToRegister {
30-
ExecutorAddrRange EHFrameSection;
31-
ExecutorAddrRange ThreadDataSection;
32-
};
33-
3429
struct MachOJITDylibInitializers {
3530
using SectionList = std::vector<ExecutorAddrRange>;
3631

@@ -171,6 +166,8 @@ class MachOPlatform : public Platform {
171166

172167
Error registerEHAndTLVSections(jitlink::LinkGraph &G);
173168

169+
Error registerEHSectionsPhase1(jitlink::LinkGraph &G);
170+
174171
std::mutex PluginMutex;
175172
MachOPlatform &MP;
176173
DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
@@ -217,19 +214,22 @@ class MachOPlatform : public Platform {
217214
Error registerInitInfo(JITDylib &JD, ExecutorAddr ObjCImageInfoAddr,
218215
ArrayRef<jitlink::Section *> InitSections);
219216

220-
Error registerPerObjectSections(const MachOPerObjectSectionsToRegister &POSR);
221-
222217
Expected<uint64_t> createPThreadKey();
223218

219+
enum PlatformState { BootstrapPhase1, BootstrapPhase2, Initialized };
220+
224221
ExecutionSession &ES;
225222
ObjectLinkingLayer &ObjLinkingLayer;
226223

227224
SymbolStringPtr MachOHeaderStartSymbol;
228-
std::atomic<bool> RuntimeBootstrapped{false};
225+
std::atomic<PlatformState> State{BootstrapPhase1};
229226

230227
ExecutorAddr orc_rt_macho_platform_bootstrap;
231228
ExecutorAddr orc_rt_macho_platform_shutdown;
232-
ExecutorAddr orc_rt_macho_register_object_sections;
229+
ExecutorAddr orc_rt_macho_register_ehframe_section;
230+
ExecutorAddr orc_rt_macho_deregister_ehframe_section;
231+
ExecutorAddr orc_rt_macho_register_thread_data_section;
232+
ExecutorAddr orc_rt_macho_deregister_thread_data_section;
233233
ExecutorAddr orc_rt_macho_create_pthread_key;
234234

235235
DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
@@ -238,40 +238,13 @@ class MachOPlatform : public Platform {
238238
// aggregating data from the jitlink.
239239
std::mutex PlatformMutex;
240240
DenseMap<JITDylib *, MachOJITDylibInitializers> InitSeqs;
241-
std::vector<MachOPerObjectSectionsToRegister> BootstrapPOSRs;
242241

243242
DenseMap<JITTargetAddress, JITDylib *> HeaderAddrToJITDylib;
244243
DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
245244
};
246245

247246
namespace shared {
248247

249-
using SPSMachOPerObjectSectionsToRegister =
250-
SPSTuple<SPSExecutorAddrRange, SPSExecutorAddrRange>;
251-
252-
template <>
253-
class SPSSerializationTraits<SPSMachOPerObjectSectionsToRegister,
254-
MachOPerObjectSectionsToRegister> {
255-
256-
public:
257-
static size_t size(const MachOPerObjectSectionsToRegister &MOPOSR) {
258-
return SPSMachOPerObjectSectionsToRegister::AsArgList::size(
259-
MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
260-
}
261-
262-
static bool serialize(SPSOutputBuffer &OB,
263-
const MachOPerObjectSectionsToRegister &MOPOSR) {
264-
return SPSMachOPerObjectSectionsToRegister::AsArgList::serialize(
265-
OB, MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
266-
}
267-
268-
static bool deserialize(SPSInputBuffer &IB,
269-
MachOPerObjectSectionsToRegister &MOPOSR) {
270-
return SPSMachOPerObjectSectionsToRegister::AsArgList::deserialize(
271-
IB, MOPOSR.EHFrameSection, MOPOSR.ThreadDataSection);
272-
}
273-
};
274-
275248
using SPSNamedExecutorAddrRangeSequenceMap =
276249
SPSSequence<SPSTuple<SPSString, SPSExecutorAddrRangeSequence>>;
277250

0 commit comments

Comments
 (0)