Skip to content

Commit e8cc4d2

Browse files
committed
[ORC][MachO] Fix deferred action handling during MachOPlatform bootstrap.
DeferredAAs should only capture bootstrap actions, but after 30b73ed it was capturing all actions, including those from other plugins. This is problematic as other plugins may introduce actions that need to run before the platform actions (e.g. on arm64e we need pointer signing to run before we access any global pointers in the graph). Note that this effectively undoes 30b73ed, which was a buggy attempt to synchronize writes to the DeferredAAs vector. This patch fixes that issue the obvious way by locking the bootstrap mutex while accessing the DeferredAAs vector. No testcase yet: So far I've only seen this fail during bootstrap of arm64e JIT'd programs.
1 parent 99d2ff5 commit e8cc4d2

File tree

2 files changed

+37
-43
lines changed

2 files changed

+37
-43
lines changed

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,6 @@ class MachOPlatform : public Platform {
240240
};
241241
using JITSymTabVector = SmallVector<SymbolTablePair>;
242242

243-
Error bootstrapPipelineStart(jitlink::LinkGraph &G);
244243
Error bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G);
245244
Error bootstrapPipelineEnd(jitlink::LinkGraph &G);
246245

@@ -368,11 +367,10 @@ class MachOPlatform : public Platform {
368367
DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;
369368

370369
std::mutex PlatformMutex;
370+
BootstrapInfo *Bootstrap = nullptr;
371371
DenseMap<JITDylib *, ExecutorAddr> JITDylibToHeaderAddr;
372372
DenseMap<ExecutorAddr, JITDylib *> HeaderAddrToJITDylib;
373373
DenseMap<JITDylib *, uint64_t> JITDylibToPThreadKey;
374-
375-
std::atomic<BootstrapInfo *> Bootstrap;
376374
};
377375

378376
// Generates a MachO header.

llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -799,17 +799,21 @@ void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
799799

800800
using namespace jitlink;
801801

802-
bool InBootstrapPhase =
803-
&MR.getTargetJITDylib() == &MP.PlatformJD && MP.Bootstrap;
802+
bool InBootstrapPhase = false;
803+
804+
if (LLVM_UNLIKELY(&MR.getTargetJITDylib() == &MP.PlatformJD)) {
805+
std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
806+
if (MP.Bootstrap) {
807+
InBootstrapPhase = true;
808+
++MP.Bootstrap->ActiveGraphs;
809+
}
810+
}
804811

805812
// If we're in the bootstrap phase then increment the active graphs.
806-
if (InBootstrapPhase) {
807-
Config.PrePrunePasses.push_back(
808-
[this](LinkGraph &G) { return bootstrapPipelineStart(G); });
813+
if (LLVM_UNLIKELY(InBootstrapPhase))
809814
Config.PostAllocationPasses.push_back([this](LinkGraph &G) {
810815
return bootstrapPipelineRecordRuntimeFunctions(G);
811816
});
812-
}
813817

814818
// --- Handle Initializers ---
815819
if (auto InitSymbol = MR.getInitializerSymbol()) {
@@ -872,19 +876,11 @@ void MachOPlatform::MachOPlatformPlugin::modifyPassConfig(
872876
[this](LinkGraph &G) { return bootstrapPipelineEnd(G); });
873877
}
874878

875-
Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineStart(
876-
jitlink::LinkGraph &G) {
877-
// Increment the active graphs count in BootstrapInfo.
878-
std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
879-
++MP.Bootstrap.load()->ActiveGraphs;
880-
return Error::success();
881-
}
882-
883879
Error MachOPlatform::MachOPlatformPlugin::
884880
bootstrapPipelineRecordRuntimeFunctions(jitlink::LinkGraph &G) {
885881
// Record bootstrap function names.
886882
std::pair<StringRef, ExecutorAddr *> RuntimeSymbols[] = {
887-
{*MP.MachOHeaderStartSymbol, &MP.Bootstrap.load()->MachOHeaderAddr},
883+
{*MP.MachOHeaderStartSymbol, &MP.Bootstrap->MachOHeaderAddr},
888884
{*MP.PlatformBootstrap.Name, &MP.PlatformBootstrap.Addr},
889885
{*MP.PlatformShutdown.Name, &MP.PlatformShutdown.Addr},
890886
{*MP.RegisterJITDylib.Name, &MP.RegisterJITDylib.Addr},
@@ -924,30 +920,22 @@ Error MachOPlatform::MachOPlatformPlugin::
924920
// If this graph defines the macho header symbol then create the internal
925921
// mapping between it and PlatformJD.
926922
std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
927-
MP.JITDylibToHeaderAddr[&MP.PlatformJD] =
928-
MP.Bootstrap.load()->MachOHeaderAddr;
929-
MP.HeaderAddrToJITDylib[MP.Bootstrap.load()->MachOHeaderAddr] =
930-
&MP.PlatformJD;
923+
MP.JITDylibToHeaderAddr[&MP.PlatformJD] = MP.Bootstrap->MachOHeaderAddr;
924+
MP.HeaderAddrToJITDylib[MP.Bootstrap->MachOHeaderAddr] = &MP.PlatformJD;
931925
}
932926

933927
return Error::success();
934928
}
935929

936930
Error MachOPlatform::MachOPlatformPlugin::bootstrapPipelineEnd(
937931
jitlink::LinkGraph &G) {
938-
std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
939-
assert(MP.Bootstrap && "DeferredAAs reset before bootstrap completed");
940-
941-
// Transfer any allocation actions to DeferredAAs.
942-
std::move(G.allocActions().begin(), G.allocActions().end(),
943-
std::back_inserter(MP.Bootstrap.load()->DeferredAAs));
944-
G.allocActions().clear();
932+
std::lock_guard<std::mutex> Lock(MP.Bootstrap->Mutex);
945933

946-
--MP.Bootstrap.load()->ActiveGraphs;
934+
--MP.Bootstrap->ActiveGraphs;
947935
// Notify Bootstrap->CV while holding the mutex because the mutex is
948936
// also keeping Bootstrap->CV alive.
949-
if (MP.Bootstrap.load()->ActiveGraphs == 0)
950-
MP.Bootstrap.load()->CV.notify_all();
937+
if (MP.Bootstrap->ActiveGraphs == 0)
938+
MP.Bootstrap->CV.notify_all();
951939
return Error::success();
952940
}
953941

@@ -1412,15 +1400,23 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
14121400
assert(I->second && "Null header registered for JD");
14131401
HeaderAddr = I->second;
14141402
}
1415-
G.allocActions().push_back(
1416-
{cantFail(
1417-
WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
1418-
MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo,
1419-
MachOPlatformSecs)),
1420-
cantFail(
1421-
WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
1422-
MP.DeregisterObjectPlatformSections.Addr, HeaderAddr,
1423-
UnwindInfo, MachOPlatformSecs))});
1403+
1404+
AllocActionCallPair AllocActions = {
1405+
cantFail(
1406+
WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
1407+
MP.RegisterObjectPlatformSections.Addr, HeaderAddr, UnwindInfo,
1408+
MachOPlatformSecs)),
1409+
cantFail(
1410+
WrapperFunctionCall::Create<SPSRegisterObjectPlatformSectionsArgs>(
1411+
MP.DeregisterObjectPlatformSections.Addr, HeaderAddr,
1412+
UnwindInfo, MachOPlatformSecs))};
1413+
1414+
if (LLVM_LIKELY(!InBootstrapPhase))
1415+
G.allocActions().push_back(std::move(AllocActions));
1416+
else {
1417+
std::lock_guard<std::mutex> Lock(MP.Bootstrap->Mutex);
1418+
MP.Bootstrap->DeferredAAs.push_back(std::move(AllocActions));
1419+
}
14241420
}
14251421

14261422
return Error::success();
@@ -1701,8 +1697,8 @@ Error MachOPlatform::MachOPlatformPlugin::addSymbolTableRegistration(
17011697
// If we're in the bootstrap phase then just record these symbols in the
17021698
// bootstrap object and then bail out -- registration will be attached to
17031699
// the bootstrap graph.
1704-
std::lock_guard<std::mutex> Lock(MP.Bootstrap.load()->Mutex);
1705-
auto &SymTab = MP.Bootstrap.load()->SymTab;
1700+
std::lock_guard<std::mutex> Lock(MP.Bootstrap->Mutex);
1701+
auto &SymTab = MP.Bootstrap->SymTab;
17061702
for (auto &[OriginalSymbol, NameSym] : JITSymTabInfo)
17071703
SymTab.push_back({NameSym->getAddress(), OriginalSymbol->getAddress(),
17081704
flagsForSymbol(*OriginalSymbol)});

0 commit comments

Comments
 (0)