Skip to content

Commit 6981849

Browse files
[ORC] Update ELF debugger support plugin to use AllocActions
1 parent 84fc780 commit 6981849

File tree

8 files changed

+104
-78
lines changed

8 files changed

+104
-78
lines changed

llvm/include/llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515

1616
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
1717
#include "llvm/ExecutionEngine/Orc/Core.h"
18-
#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
1918
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
19+
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
2020
#include "llvm/Support/Compiler.h"
2121
#include "llvm/Support/Error.h"
2222
#include "llvm/Support/Memory.h"
@@ -48,10 +48,6 @@ class DebugObject;
4848
///
4949
class LLVM_ABI DebugObjectManagerPlugin : public ObjectLinkingLayer::Plugin {
5050
public:
51-
// DEPRECATED - Please specify options explicitly
52-
DebugObjectManagerPlugin(ExecutionSession &ES,
53-
std::unique_ptr<DebugObjectRegistrar> Target);
54-
5551
/// Create the plugin to submit DebugObjects for JITLink artifacts. For all
5652
/// options the recommended setting is true.
5753
///
@@ -67,16 +63,14 @@ class LLVM_ABI DebugObjectManagerPlugin : public ObjectLinkingLayer::Plugin {
6763
/// sequence. When turning this off, the user has to issue the call to
6864
/// __jit_debug_register_code() on the executor side manually.
6965
///
70-
DebugObjectManagerPlugin(ExecutionSession &ES,
71-
std::unique_ptr<DebugObjectRegistrar> Target,
72-
bool RequireDebugSections, bool AutoRegisterCode);
66+
DebugObjectManagerPlugin(ExecutionSession &ES, bool RequireDebugSections,
67+
bool AutoRegisterCode, Error &Err);
7368
~DebugObjectManagerPlugin() override;
7469

7570
void notifyMaterializing(MaterializationResponsibility &MR,
7671
jitlink::LinkGraph &G, jitlink::JITLinkContext &Ctx,
7772
MemoryBufferRef InputObject) override;
7873

79-
Error notifyEmitted(MaterializationResponsibility &MR) override;
8074
Error notifyFailed(MaterializationResponsibility &MR) override;
8175
Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override;
8276

@@ -97,7 +91,7 @@ class LLVM_ABI DebugObjectManagerPlugin : public ObjectLinkingLayer::Plugin {
9791
std::mutex PendingObjsLock;
9892
std::mutex RegisteredObjsLock;
9993

100-
std::unique_ptr<DebugObjectRegistrar> Target;
94+
ExecutorAddr RegistrationAction;
10195
bool RequireDebugSections;
10296
bool AutoRegisterCode;
10397
};

llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ LLVM_ABI extern const char *MemoryReadStringsWrapperName;
5959
LLVM_ABI extern const char *RegisterEHFrameSectionAllocActionName;
6060
LLVM_ABI extern const char *DeregisterEHFrameSectionAllocActionName;
6161

62+
LLVM_ABI extern const char *RegisterJITLoaderGDBAllocActionName;
63+
6264
LLVM_ABI extern const char *RunAsMainWrapperName;
6365
LLVM_ABI extern const char *RunAsVoidFunctionWrapperName;
6466
LLVM_ABI extern const char *RunAsIntFunctionWrapperName;

llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp

Lines changed: 80 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/BinaryFormat/ELF.h"
2020
#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
2121
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
22+
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
2223
#include "llvm/Object/ELFObjectFile.h"
2324
#include "llvm/Support/Errc.h"
2425
#include "llvm/Support/MSVCErrorWorkarounds.h"
@@ -115,7 +116,9 @@ class DebugObject {
115116
public:
116117
DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
117118
ExecutionSession &ES)
118-
: MemMgr(MemMgr), JD(JD), ES(ES), Flags(DebugObjectFlags{}) {}
119+
: MemMgr(MemMgr), JD(JD), ES(ES), Flags(DebugObjectFlags{}) {
120+
FinalizeFuture = FinalizePromise.get_future();
121+
}
119122

120123
bool hasFlags(DebugObjectFlags F) const { return Flags & F; }
121124
void setFlags(DebugObjectFlags F) {
@@ -126,8 +129,17 @@ class DebugObject {
126129
}
127130

128131
using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>;
132+
void finalizeAsync(FinalizeContinuation OnAsync);
133+
134+
void failMaterialization(Error Err) {
135+
FinalizePromise.set_value(std::move(Err));
136+
}
129137

130-
void finalizeAsync(FinalizeContinuation OnFinalize);
138+
void reportTargetMem(ExecutorAddrRange TargetMem) {
139+
FinalizePromise.set_value(TargetMem);
140+
}
141+
142+
Expected<ExecutorAddrRange> awaitTargetMem() { return FinalizeFuture.get(); }
131143

132144
virtual ~DebugObject() {
133145
if (Alloc) {
@@ -151,6 +163,9 @@ class DebugObject {
151163
const JITLinkDylib *JD = nullptr;
152164
ExecutionSession &ES;
153165

166+
std::promise<MSVCPExpected<ExecutorAddrRange>> FinalizePromise;
167+
std::future<MSVCPExpected<ExecutorAddrRange>> FinalizeFuture;
168+
154169
private:
155170
DebugObjectFlags Flags;
156171
FinalizedAlloc Alloc;
@@ -160,22 +175,27 @@ class DebugObject {
160175
// copying memory over to the target and pass on the result once we're done.
161176
// Ownership of the allocation remains with us for the rest of our lifetime.
162177
void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
163-
assert(!Alloc && "Cannot finalize more than once");
164-
178+
assert(!this->Alloc && "Cannot finalize more than once");
165179
if (auto SimpleSegAlloc = finalizeWorkingMemory()) {
166180
auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);
167181
ExecutorAddrRange DebugObjRange(ROSeg.Addr, ROSeg.WorkingMem.size());
168182
SimpleSegAlloc->finalize(
169183
[this, DebugObjRange,
170184
OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) {
171185
if (FA) {
172-
Alloc = std::move(*FA);
186+
// Note: FA->getAddress() is supposed to be the address of the
187+
// memory range on the target, but InProcessMemoryManager returns
188+
// the address of a FinalizedAllocInfo helper instead.
189+
this->Alloc = std::move(*FA);
173190
OnFinalize(DebugObjRange);
174191
} else
175192
OnFinalize(FA.takeError());
176193
});
177-
} else
194+
} else {
195+
// We could report this error synchronously, but it's easier this way,
196+
// because the FinalizePromise will be triggered unconditionally.
178197
OnFinalize(SimpleSegAlloc.takeError());
198+
}
179199
}
180200

181201
/// The current implementation of ELFDebugObject replicates the approach used in
@@ -386,16 +406,17 @@ createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
386406
}
387407
}
388408

389-
DebugObjectManagerPlugin::DebugObjectManagerPlugin(
390-
ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target,
391-
bool RequireDebugSections, bool AutoRegisterCode)
392-
: ES(ES), Target(std::move(Target)),
393-
RequireDebugSections(RequireDebugSections),
394-
AutoRegisterCode(AutoRegisterCode) {}
395-
396-
DebugObjectManagerPlugin::DebugObjectManagerPlugin(
397-
ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
398-
: DebugObjectManagerPlugin(ES, std::move(Target), true, true) {}
409+
DebugObjectManagerPlugin::DebugObjectManagerPlugin(ExecutionSession &ES,
410+
bool RequireDebugSections,
411+
bool AutoRegisterCode,
412+
Error &Err)
413+
: ES(ES), RequireDebugSections(RequireDebugSections),
414+
AutoRegisterCode(AutoRegisterCode) {
415+
// Pass bootstrap symbol for registration function to enable debugging
416+
ErrorAsOutParameter _(&Err);
417+
Err = ES.getExecutorProcessControl().getBootstrapSymbols(
418+
{{RegistrationAction, rt::RegisterJITLoaderGDBAllocActionName}});
419+
}
399420

400421
DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
401422

@@ -440,48 +461,50 @@ void DebugObjectManagerPlugin::modifyPassConfig(
440461
SectionRange(GraphSection));
441462
return Error::success();
442463
});
443-
}
444-
}
445464

446-
Error DebugObjectManagerPlugin::notifyEmitted(
447-
MaterializationResponsibility &MR) {
448-
std::lock_guard<std::mutex> Lock(PendingObjsLock);
449-
auto It = PendingObjs.find(&MR);
450-
if (It == PendingObjs.end())
451-
return Error::success();
452-
453-
// During finalization the debug object is registered with the target.
454-
// Materialization must wait for this process to finish. Otherwise we might
455-
// start running code before the debugger processed the corresponding debug
456-
// info.
457-
std::promise<MSVCPError> FinalizePromise;
458-
std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
459-
460-
It->second->finalizeAsync(
461-
[this, &FinalizePromise, &MR](Expected<ExecutorAddrRange> TargetMem) {
462-
// Any failure here will fail materialization.
463-
if (!TargetMem) {
464-
FinalizePromise.set_value(TargetMem.takeError());
465-
return;
466-
}
467-
if (Error Err =
468-
Target->registerDebugObject(*TargetMem, AutoRegisterCode)) {
469-
FinalizePromise.set_value(std::move(Err));
470-
return;
471-
}
472-
473-
// Once our tracking info is updated, notifyEmitted() can return and
474-
// finish materialization.
475-
FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
476-
assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock");
477-
std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
478-
auto It = PendingObjs.find(&MR);
479-
RegisteredObjs[K].push_back(std::move(It->second));
480-
PendingObjs.erase(It);
481-
}));
482-
});
483-
484-
return FinalizeErr.get();
465+
PassConfig.PreFixupPasses.push_back(
466+
[this, &DebugObj, &MR](LinkGraph &G) -> Error {
467+
DebugObj.finalizeAsync([this, &DebugObj,
468+
&MR](Expected<ExecutorAddrRange> TargetMem) {
469+
if (!TargetMem) {
470+
DebugObj.failMaterialization(TargetMem.takeError());
471+
return;
472+
}
473+
// Update tracking info
474+
Error Err = MR.withResourceKeyDo([&](ResourceKey K) {
475+
std::lock_guard<std::mutex> LockPending(PendingObjsLock);
476+
std::lock_guard<std::mutex> LockRegistered(RegisteredObjsLock);
477+
auto It = PendingObjs.find(&MR);
478+
RegisteredObjs[K].push_back(std::move(It->second));
479+
PendingObjs.erase(It);
480+
});
481+
482+
if (Err)
483+
DebugObj.failMaterialization(std::move(Err));
484+
485+
// Unblock post-fixup pass
486+
DebugObj.reportTargetMem(*TargetMem);
487+
});
488+
return Error::success();
489+
});
490+
491+
PassConfig.PostFixupPasses.push_back(
492+
[this, &DebugObj](LinkGraph &G) -> Error {
493+
Expected<ExecutorAddrRange> R = DebugObj.awaitTargetMem();
494+
if (!R)
495+
return R.takeError();
496+
if (R->empty())
497+
return Error::success();
498+
499+
using namespace shared;
500+
G.allocActions().push_back(
501+
{cantFail(WrapperFunctionCall::Create<
502+
SPSArgList<SPSExecutorAddrRange, bool>>(
503+
RegistrationAction, *R, AutoRegisterCode)),
504+
{/* no deregistration */}});
505+
return Error::success();
506+
});
507+
}
485508
}
486509

487510
Error DebugObjectManagerPlugin::notifyFailed(

llvm/lib/ExecutionEngine/Orc/Debugging/DebuggerSupport.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,10 @@ Error enableDebuggerSupport(LLJIT &J) {
3535

3636
switch (TT.getObjectFormat()) {
3737
case Triple::ELF: {
38-
auto Registrar = createJITLoaderGDBRegistrar(ES);
39-
if (!Registrar)
40-
return Registrar.takeError();
38+
Error TargetSymErr = Error::success();
4139
ObjLinkingLayer->addPlugin(std::make_unique<DebugObjectManagerPlugin>(
42-
ES, std::move(*Registrar), false, true));
43-
return Error::success();
40+
ES, false, true, TargetSymErr));
41+
return TargetSymErr;
4442
}
4543
case Triple::MachO: {
4644
auto DS = GDBJITDebugInfoRegistrationPlugin::Create(ES, *ProcessSymsJD, TT);

llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ const char *RegisterEHFrameSectionAllocActionName =
7474
const char *DeregisterEHFrameSectionAllocActionName =
7575
"llvm_orc_deregisterEHFrameAllocAction";
7676

77+
const char *RegisterJITLoaderGDBAllocActionName =
78+
"llvm_orc_registerJITLoaderGDBAllocAction";
79+
7780
const char *RunAsMainWrapperName = "__llvm_orc_bootstrap_run_as_main_wrapper";
7881
const char *RunAsVoidFunctionWrapperName =
7982
"__llvm_orc_bootstrap_run_as_void_function_wrapper";

llvm/lib/ExecutionEngine/Orc/TargetProcess/DefaultHostBootstrapValues.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "llvm/ExecutionEngine/Orc/TargetProcess/DefaultHostBootstrapValues.h"
1010

1111
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12+
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
1213
#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
1314

1415
#ifdef __APPLE__
@@ -27,6 +28,9 @@ void addDefaultBootstrapValuesForHostProcess(
2728
BootstrapSymbols[rt::DeregisterEHFrameSectionAllocActionName] =
2829
ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionAllocAction);
2930

31+
BootstrapSymbols[rt::RegisterJITLoaderGDBAllocActionName] =
32+
ExecutorAddr::fromPtr(&llvm_orc_registerJITLoaderGDBAllocAction);
33+
3034
#ifdef __APPLE__
3135
if (!dlsym(RTLD_DEFAULT, "__unw_add_find_dynamic_unwind_sections"))
3236
BootstrapMap["darwin-use-ehframes-only"].push_back(1);

llvm/lib/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleRemoteEPCServer.h"
1010

1111
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12+
#include "llvm/ExecutionEngine/Orc/TargetProcess/DefaultHostBootstrapValues.h"
1213
#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
1314
#include "llvm/Support/FormatVariadic.h"
1415
#include "llvm/Support/Process.h"
@@ -206,10 +207,7 @@ Error SimpleRemoteEPCServer::sendSetupMessage(
206207
"Dispatch function name should not be set");
207208
EI.BootstrapSymbols[ExecutorSessionObjectName] = ExecutorAddr::fromPtr(this);
208209
EI.BootstrapSymbols[DispatchFnName] = ExecutorAddr::fromPtr(jitDispatchEntry);
209-
EI.BootstrapSymbols[rt::RegisterEHFrameSectionAllocActionName] =
210-
ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionAllocAction);
211-
EI.BootstrapSymbols[rt::DeregisterEHFrameSectionAllocActionName] =
212-
ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionAllocAction);
210+
addDefaultBootstrapValuesForHostProcess(EI.BootstrapMap, EI.BootstrapSymbols);
213211

214212
using SPSSerialize =
215213
shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;

llvm/tools/llvm-jitlink/llvm-jitlink.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,9 +1295,13 @@ Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
12951295
} else if (TT.isOSBinFormatELF()) {
12961296
if (!NoExec)
12971297
ObjLayer.addPlugin(ExitOnErr(EHFrameRegistrationPlugin::Create(ES)));
1298-
if (DebuggerSupport)
1298+
if (DebuggerSupport) {
1299+
Error TargetSymErr = Error::success();
12991300
ObjLayer.addPlugin(std::make_unique<DebugObjectManagerPlugin>(
1300-
ES, ExitOnErr(createJITLoaderGDBRegistrar(this->ES)), true, true));
1301+
ES, true, true, TargetSymErr));
1302+
logAllUnhandledErrors(std::move(TargetSymErr), errs(),
1303+
"Debugger support not available: ");
1304+
}
13011305
}
13021306

13031307
if (auto MainJDOrErr = ES.createJITDylib("main"))

0 commit comments

Comments
 (0)