Configure the plugin to automatically call the debugger rendezvous breakpoint `__jit_debug_register_code()` for every translation unit (enabled) or never at all (disabled). Default API and behavior remain unchanged.
If AutoRegisterCode is turned off, it's the client's own responsibility to call the rendezvous breakpoint function at an appropriate time.
Depending on the complexity of the debugger's rendezvous breakpoint implementation, this can provide significant performance improvements in cases where many debug objects are added in sequence.
Reviewed By: lhames
Differential Revision: https://reviews.llvm.org/D147310
return createStringError(inconvertibleErrorCode(),
"No debug support for given object layer type");
- ObjLinkingLayer->addPlugin(
- std::make_unique<DebugObjectManagerPlugin>(ES, std::move(*Registrar)));
+ ObjLinkingLayer->addPlugin(std::make_unique<DebugObjectManagerPlugin>(
+ ES, std::move(*Registrar), true, true));
return Error::success();
}
/// names. Note that this may cause significant memory and transport
/// overhead for objects built with a release configuration.
///
+ /// AutoRegisterCode:
+ /// Notify the debugger for each new debug object. This is a good default
+ /// mode, but it may cause significant overhead when adding many modules in
+ /// sequence. When turning this off, the user has to issue the call to
+ /// __jit_debug_register_code() on the executor side manually.
+ ///
DebugObjectManagerPlugin(ExecutionSession &ES,
std::unique_ptr<DebugObjectRegistrar> Target,
- bool RequireDebugSections);
+ bool RequireDebugSections, bool AutoRegisterCode);
~DebugObjectManagerPlugin();
void notifyMaterializing(MaterializationResponsibility &MR,
std::unique_ptr<DebugObjectRegistrar> Target;
bool RequireDebugSections;
+ bool AutoRegisterCode;
};
} // namespace orc
/// Abstract interface for registering debug objects in the executor process.
class DebugObjectRegistrar {
public:
- virtual Error registerDebugObject(ExecutorAddrRange TargetMem) = 0;
+ virtual Error registerDebugObject(ExecutorAddrRange TargetMem,
+ bool AutoRegisterCode) = 0;
virtual ~DebugObjectRegistrar() = default;
};
EPCDebugObjectRegistrar(ExecutionSession &ES, ExecutorAddr RegisterFn)
: ES(ES), RegisterFn(RegisterFn) {}
- Error registerDebugObject(ExecutorAddrRange TargetMem) override;
+ Error registerDebugObject(ExecutorAddrRange TargetMem,
+ bool AutoRegisterCode) override;
private:
ExecutionSession &ES;
DebugObjectManagerPlugin::DebugObjectManagerPlugin(
ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target,
- bool RequireDebugSections)
+ bool RequireDebugSections, bool AutoRegisterCode)
: ES(ES), Target(std::move(Target)),
- RequireDebugSections(RequireDebugSections) {}
+ RequireDebugSections(RequireDebugSections),
+ AutoRegisterCode(AutoRegisterCode) {}
DebugObjectManagerPlugin::DebugObjectManagerPlugin(
ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
- : DebugObjectManagerPlugin(ES, std::move(Target), true) {}
+ : DebugObjectManagerPlugin(ES, std::move(Target), true, true) {}
DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
FinalizePromise.set_value(TargetMem.takeError());
return;
}
- if (Error Err = Target->registerDebugObject(*TargetMem)) {
+ if (Error Err =
+ Target->registerDebugObject(*TargetMem, AutoRegisterCode)) {
FinalizePromise.set_value(std::move(Err));
return;
}
Writer.write(SecCmd);
}
+ static constexpr bool AutoRegisterCode = true;
SectionRange R(MachOContainerBlock->getSection());
G.allocActions().push_back(
{cantFail(shared::WrapperFunctionCall::Create<
- shared::SPSArgList<shared::SPSExecutorAddrRange>>(
- RegisterActionAddr, R.getRange())),
+ shared::SPSArgList<shared::SPSExecutorAddrRange, bool>>(
+ RegisterActionAddr, R.getRange(), AutoRegisterCode)),
{}});
return Error::success();
}
return std::make_unique<EPCDebugObjectRegistrar>(ES, (*Result)[0][0]);
}
-Error EPCDebugObjectRegistrar::registerDebugObject(
- ExecutorAddrRange TargetMem) {
- return ES.callSPSWrapper<void(shared::SPSExecutorAddrRange)>(RegisterFn,
- TargetMem);
+Error EPCDebugObjectRegistrar::registerDebugObject(ExecutorAddrRange TargetMem,
+ bool AutoRegisterCode) {
+ return ES.callSPSWrapper<void(shared::SPSExecutorAddrRange, bool)>(
+ RegisterFn, TargetMem, AutoRegisterCode);
}
} // namespace orc
using namespace llvm::orc;
// Register debug object, return error message or null for success.
-static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
+static void appendJITDebugDescriptor(const char *ObjAddr, size_t Size) {
LLVM_DEBUG({
- dbgs() << "Registering debug object with GDB JIT interface "
+ dbgs() << "Adding debug object to GDB JIT interface "
<< formatv("([{0:x16} -- {1:x16}])",
reinterpret_cast<uintptr_t>(ObjAddr),
reinterpret_cast<uintptr_t>(ObjAddr + Size))
__jit_debug_descriptor.first_entry = E;
__jit_debug_descriptor.relevant_entry = E;
-
- // Run into the rendezvous breakpoint.
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
- __jit_debug_register_code();
}
extern "C" orc::shared::CWrapperFunctionResult
llvm_orc_registerJITLoaderGDBAllocAction(const char *Data, size_t Size) {
using namespace orc::shared;
- return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
+ return WrapperFunction<SPSError(SPSExecutorAddrRange, bool)>::handle(
Data, Size,
- [](ExecutorAddrRange R) {
- registerJITLoaderGDBImpl(R.Start.toPtr<const char *>(),
+ [](ExecutorAddrRange R, bool AutoRegisterCode) {
+ appendJITDebugDescriptor(R.Start.toPtr<const char *>(),
R.size());
+ // Run into the rendezvous breakpoint.
+ if (AutoRegisterCode)
+ __jit_debug_register_code();
return Error::success();
})
.release();
extern "C" orc::shared::CWrapperFunctionResult
llvm_orc_registerJITLoaderGDBWrapper(const char *Data, uint64_t Size) {
using namespace orc::shared;
- return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
+ return WrapperFunction<SPSError(SPSExecutorAddrRange, bool)>::handle(
Data, Size,
- [](ExecutorAddrRange R) {
- registerJITLoaderGDBImpl(R.Start.toPtr<const char *>(),
+ [](ExecutorAddrRange R, bool AutoRegisterCode) {
+ appendJITDebugDescriptor(R.Start.toPtr<const char *>(),
R.size());
+ // Run into the rendezvous breakpoint.
+ if (AutoRegisterCode)
+ __jit_debug_register_code();
return Error::success();
})
.release();
L->addPlugin(std::make_unique<orc::EHFrameRegistrationPlugin>(
ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(ES))));
L->addPlugin(std::make_unique<orc::DebugObjectManagerPlugin>(
- ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(ES))));
+ ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(ES)), true, true));
}
return L;
});
ES, ExitOnErr(EPCEHFrameRegistrar::Create(this->ES))));
if (DebuggerSupport)
ObjLayer.addPlugin(std::make_unique<DebugObjectManagerPlugin>(
- ES, ExitOnErr(createJITLoaderGDBRegistrar(this->ES))));
+ ES, ExitOnErr(createJITLoaderGDBRegistrar(this->ES)), true, true));
}
ObjLayer.addPlugin(std::make_unique<JITLinkSessionPlugin>(*this));