Skip to content

Commit 217fd59

Browse files
committed
[ORC] Introduce deferred allocation-actions scheme for MachOPlatform bootstrap.
This patch modifies the MachOPlatform bootstrap process to record allocation actions for ORC runtime platform support code in a "deferred actions" vector rather than attaching it to the corresponding LinkGraphs up-front. The deferred allocation-actions are run after all the platform support code has been loaded by attaching them to a separate "bootstrap-complete" graph. This change should allow the mach-o platform support code in the ORC runtime to use advanced mach-o platform features (e.g. static inits, TLVs), provided that the support code does not use these features at runtime before the bootstrap process completes, or after the shutdown process starts. This is a nice improvement in and of itself but is motivated by specific future plans: we want to start recording unwind info in the mach-o platform state object*, and the recording functions will have their own frame info that needs registering. The deferred allocation-actions scheme allows for this. * The plan is to add a new unwind-info-lookup path to libunwind to allow it to call back to the ORC runtime to find unwind sections. This will simplify the implementation of support for JIT'd compact-unwind info.
1 parent a5ddd92 commit 217fd59

File tree

5 files changed

+408
-279
lines changed

5 files changed

+408
-279
lines changed

compiler-rt/lib/orc/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ set(ALL_ORC_SOURCES
1515
coff_platform.cpp
1616
coff_platform.per_jd.cpp
1717
elfnix_platform.cpp
18-
macho_ehframe_registration.cpp
1918
macho_platform.cpp
2019
)
2120

@@ -96,7 +95,6 @@ if (APPLE)
9695

9796
set(ORC_SOURCES
9897
${ORC_COMMON_SOURCES}
99-
macho_ehframe_registration.cpp
10098
macho_platform.cpp
10199
)
102100

compiler-rt/lib/orc/macho_ehframe_registration.cpp

Lines changed: 0 additions & 74 deletions
This file was deleted.

compiler-rt/lib/orc/macho_platform.cpp

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ class MachOPlatformRuntimeState {
284284
Expected<ExecutorAddr> lookupSymbolInJITDylib(void *DSOHandle,
285285
std::string_view Symbol);
286286

287+
static Error registerEHFrames(span<const char> EHFrameSection);
288+
static Error deregisterEHFrames(span<const char> EHFrameSection);
289+
287290
static Error registerObjCSelectors(JITDylibState &JDS);
288291
static Error registerObjCClasses(JITDylibState &JDS);
289292
static Error registerSwift5Protocols(JITDylibState &JDS);
@@ -438,7 +441,10 @@ Error MachOPlatformRuntimeState::registerObjectPlatformSections(
438441

439442
for (auto &KV : Secs) {
440443
// FIXME: Validate section ranges?
441-
if (KV.first == "__DATA,__data") {
444+
if (KV.first == "__TEXT,__eh_frame") {
445+
if (auto Err = registerEHFrames(KV.second.toSpan<const char>()))
446+
return Err;
447+
} else if (KV.first == "__DATA,__data") {
442448
assert(!JDS->DataSectionContent.count(KV.second.Start.toPtr<char *>()) &&
443449
"Address already registered.");
444450
auto S = KV.second.toSpan<char>();
@@ -505,7 +511,10 @@ Error MachOPlatformRuntimeState::deregisterObjectPlatformSections(
505511

506512
for (auto &KV : Secs) {
507513
// FIXME: Validate section ranges?
508-
if (KV.first == "__DATA,__data") {
514+
if (KV.first == "__TEXT,__eh_frame") {
515+
if (auto Err = deregisterEHFrames(KV.second.toSpan<const char>()))
516+
return Err;
517+
} else if (KV.first == "__DATA,__data") {
509518
JDS->DataSectionContent.erase(KV.second.Start.toPtr<char *>());
510519
} else if (KV.first == "__DATA,__common") {
511520
JDS->ZeroInitRanges.erase(KV.second.Start.toPtr<char *>());
@@ -673,6 +682,45 @@ MachOPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle,
673682
return Result;
674683
}
675684

685+
// eh-frame registration functions.
686+
// We expect these to be available for all processes.
687+
extern "C" void __register_frame(const void *);
688+
extern "C" void __deregister_frame(const void *);
689+
690+
template <typename HandleFDEFn>
691+
void walkEHFrameSection(span<const char> EHFrameSection,
692+
HandleFDEFn HandleFDE) {
693+
const char *CurCFIRecord = EHFrameSection.data();
694+
uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
695+
696+
while (CurCFIRecord != EHFrameSection.end() && Size != 0) {
697+
const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
698+
if (Size == 0xffffffff)
699+
Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
700+
else
701+
Size += 4;
702+
uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
703+
704+
if (Offset != 0)
705+
HandleFDE(CurCFIRecord);
706+
707+
CurCFIRecord += Size;
708+
Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
709+
}
710+
}
711+
712+
Error MachOPlatformRuntimeState::registerEHFrames(
713+
span<const char> EHFrameSection) {
714+
walkEHFrameSection(EHFrameSection, __register_frame);
715+
return Error::success();
716+
}
717+
718+
Error MachOPlatformRuntimeState::deregisterEHFrames(
719+
span<const char> EHFrameSection) {
720+
walkEHFrameSection(EHFrameSection, __deregister_frame);
721+
return Error::success();
722+
}
723+
676724
Error MachOPlatformRuntimeState::registerObjCSelectors(JITDylibState &JDS) {
677725
if (!JDS.ObjCSelRefsSections.hasNewSections())
678726
return Error::success();
@@ -1050,14 +1098,24 @@ Error runWrapperFunctionCalls(std::vector<WrapperFunctionCall> WFCs) {
10501098

10511099
ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
10521100
__orc_rt_macho_platform_bootstrap(char *ArgData, size_t ArgSize) {
1053-
MachOPlatformRuntimeState::initialize();
1054-
return WrapperFunctionResult().release();
1101+
return WrapperFunction<SPSError()>::handle(
1102+
ArgData, ArgSize,
1103+
[]() -> Error {
1104+
MachOPlatformRuntimeState::initialize();
1105+
return Error::success();
1106+
})
1107+
.release();
10551108
}
10561109

10571110
ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
10581111
__orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) {
1059-
MachOPlatformRuntimeState::destroy();
1060-
return WrapperFunctionResult().release();
1112+
return WrapperFunction<SPSError()>::handle(
1113+
ArgData, ArgSize,
1114+
[]() -> Error {
1115+
MachOPlatformRuntimeState::destroy();
1116+
return Error::success();
1117+
})
1118+
.release();
10611119
}
10621120

10631121
ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult

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

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ class MachOPlatform : public Platform {
107107
static bool isInitializerSection(StringRef SegName, StringRef SectName);
108108

109109
private:
110+
// Data needed for bootstrap only.
111+
struct BootstrapInfo {
112+
std::mutex Mutex;
113+
std::condition_variable CV;
114+
size_t ActiveGraphs = 0;
115+
shared::AllocActions DeferredAAs;
116+
ExecutorAddr MachOHeaderAddr;
117+
};
118+
110119
// The MachOPlatformPlugin scans/modifies LinkGraphs to support MachO
111120
// platform features including initializers, exceptions, TLV, and language
112121
// runtime registration.
@@ -138,6 +147,12 @@ class MachOPlatform : public Platform {
138147
using InitSymbolDepMap =
139148
DenseMap<MaterializationResponsibility *, JITLinkSymbolSet>;
140149

150+
Error bootstrapPipelineStart(jitlink::LinkGraph &G);
151+
Error bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G);
152+
Error bootstrapPipelineEnd(jitlink::LinkGraph &G);
153+
154+
Error recordRuntimeRegistrationFunctions(jitlink::LinkGraph &G);
155+
141156
Error associateJITDylibHeaderSymbol(jitlink::LinkGraph &G,
142157
MaterializationResponsibility &MR);
143158

@@ -149,9 +164,8 @@ class MachOPlatform : public Platform {
149164

150165
Error fixTLVSectionsAndEdges(jitlink::LinkGraph &G, JITDylib &JD);
151166

152-
Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD);
153-
154-
Error registerEHSectionsPhase1(jitlink::LinkGraph &G);
167+
Error registerObjectPlatformSections(jitlink::LinkGraph &G, JITDylib &JD,
168+
bool InBootstrapPhase);
155169

156170
std::mutex PluginMutex;
157171
MachOPlatform &MP;
@@ -179,7 +193,7 @@ class MachOPlatform : public Platform {
179193
Error &Err);
180194

181195
// Associate MachOPlatform JIT-side runtime support functions with handlers.
182-
Error associateRuntimeSupportFunctions(JITDylib &PlatformJD);
196+
Error associateRuntimeSupportFunctions();
183197

184198
// Implements rt_pushInitializers by making repeat async lookups for
185199
// initializer symbols (each lookup may spawn more initializer symbols if
@@ -195,19 +209,14 @@ class MachOPlatform : public Platform {
195209
void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddr Handle,
196210
StringRef SymbolName);
197211

198-
// Records the addresses of runtime symbols used by the platform.
199-
Error bootstrapMachORuntime(JITDylib &PlatformJD);
200-
201212
// Call the ORC runtime to create a pthread key.
202213
Expected<uint64_t> createPThreadKey();
203214

204-
enum PlatformState { BootstrapPhase1, BootstrapPhase2, Initialized };
205-
206215
ExecutionSession &ES;
216+
JITDylib &PlatformJD;
207217
ObjectLinkingLayer &ObjLinkingLayer;
208218

209-
SymbolStringPtr MachOHeaderStartSymbol;
210-
std::atomic<PlatformState> State{BootstrapPhase1};
219+
SymbolStringPtr MachOHeaderStartSymbol = ES.intern("___dso_handle");
211220

212221
struct RuntimeFunction {
213222
RuntimeFunction(SymbolStringPtr Name) : Name(std::move(Name)) {}
@@ -240,6 +249,8 @@ class MachOPlatform : public Platform {
240249
DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr;
241250
DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
242251
DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
252+
253+
std::atomic<BootstrapInfo *> Bootstrap;
243254
};
244255

245256
namespace shared {

0 commit comments

Comments
 (0)