[JITLink][ORC] Add EHFrameRegistrar interface, use in EHFrameRegistrationPlugin.

Replaces direct calls to eh-frame registration with calls to methods on an
EHFrameRegistrar instance. This allows clients to substitute a registrar that
registers frames in a remote process via IPC/RPC.

llvm-svn: 365098
This commit is contained in:
Lang Hames 2019-07-04 00:05:12 +00:00
parent f7e52fbdb5
commit f5a885fddd
5 changed files with 73 additions and 17 deletions

View File

@ -27,6 +27,41 @@ Error registerEHFrameSection(const void *EHFrameSectionAddr);
/// Deregisters all FDEs in the given eh-frame section with the current process. /// Deregisters all FDEs in the given eh-frame section with the current process.
Error deregisterEHFrameSection(const void *EHFrameSectionAddr); Error deregisterEHFrameSection(const void *EHFrameSectionAddr);
/// Supports registration/deregistration of EH-frames in a target process.
class EHFrameRegistrar {
public:
virtual ~EHFrameRegistrar();
virtual Error registerEHFrames(JITTargetAddress EHFrameSectionAddr) = 0;
virtual Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr) = 0;
};
/// Registers / Deregisters EH-frames in the current process.
class InProcessEHFrameRegistrar final : public EHFrameRegistrar {
public:
/// Get a reference to the InProcessEHFrameRegistrar singleton.
static InProcessEHFrameRegistrar &getInstance();
InProcessEHFrameRegistrar(const InProcessEHFrameRegistrar &) = delete;
InProcessEHFrameRegistrar &
operator=(const InProcessEHFrameRegistrar &) = delete;
InProcessEHFrameRegistrar(InProcessEHFrameRegistrar &&) = delete;
InProcessEHFrameRegistrar &operator=(InProcessEHFrameRegistrar &&) = delete;
Error registerEHFrames(JITTargetAddress EHFrameSectionAddr) override {
return registerEHFrameSection(
jitTargetAddressToPointer<void *>(EHFrameSectionAddr));
}
Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr) override {
return deregisterEHFrameSection(
jitTargetAddressToPointer<void *>(EHFrameSectionAddr));
}
private:
InProcessEHFrameRegistrar();
};
using StoreFrameAddressFunction = std::function<void(JITTargetAddress)>; using StoreFrameAddressFunction = std::function<void(JITTargetAddress)>;
/// Creates a pass that records the address of the EH frame section. If no /// Creates a pass that records the address of the EH frame section. If no

View File

@ -33,6 +33,10 @@
namespace llvm { namespace llvm {
namespace jitlink {
class EHFrameRegistrar;
} // namespace jitlink
namespace object { namespace object {
class ObjectFile; class ObjectFile;
} // namespace object } // namespace object
@ -139,8 +143,9 @@ private:
std::vector<std::unique_ptr<Plugin>> Plugins; std::vector<std::unique_ptr<Plugin>> Plugins;
}; };
class LocalEHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin { class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin {
public: public:
EHFrameRegistrationPlugin(jitlink::EHFrameRegistrar &Registrar);
Error notifyEmitted(MaterializationResponsibility &MR) override; Error notifyEmitted(MaterializationResponsibility &MR) override;
void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
jitlink::PassConfiguration &PassConfig) override; jitlink::PassConfiguration &PassConfig) override;
@ -148,9 +153,10 @@ public:
Error notifyRemovingAllModules() override; Error notifyRemovingAllModules() override;
private: private:
DenseMap<MaterializationResponsibility *, const void *> InProcessLinks; jitlink::EHFrameRegistrar &Registrar;
DenseMap<VModuleKey, const void *> TrackedEHFrameAddrs; DenseMap<MaterializationResponsibility *, JITTargetAddress> InProcessLinks;
std::vector<const void *> UntrackedEHFrameAddrs; DenseMap<VModuleKey, JITTargetAddress> TrackedEHFrameAddrs;
std::vector<JITTargetAddress> UntrackedEHFrameAddrs;
}; };
} // end namespace orc } // end namespace orc

View File

@ -508,6 +508,15 @@ Error deregisterEHFrameSection(const void *EHFrameSectionAddr) {
#endif #endif
} }
EHFrameRegistrar::~EHFrameRegistrar() {}
InProcessEHFrameRegistrar &InProcessEHFrameRegistrar::getInstance() {
static InProcessEHFrameRegistrar Instance;
return Instance;
}
InProcessEHFrameRegistrar::InProcessEHFrameRegistrar() {}
AtomGraphPassFunction AtomGraphPassFunction
createEHFrameRecorderPass(const Triple &TT, createEHFrameRecorderPass(const Triple &TT,
StoreFrameAddressFunction StoreFrameAddress) { StoreFrameAddressFunction StoreFrameAddress) {

View File

@ -409,7 +409,11 @@ Error ObjectLinkingLayer::removeAllModules() {
return Err; return Err;
} }
void LocalEHFrameRegistrationPlugin::modifyPassConfig( EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
jitlink::EHFrameRegistrar &Registrar)
: Registrar(Registrar) {}
void EHFrameRegistrationPlugin::modifyPassConfig(
MaterializationResponsibility &MR, const Triple &TT, MaterializationResponsibility &MR, const Triple &TT,
PassConfiguration &PassConfig) { PassConfiguration &PassConfig) {
assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?"); assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
@ -417,18 +421,18 @@ void LocalEHFrameRegistrationPlugin::modifyPassConfig(
PassConfig.PostFixupPasses.push_back( PassConfig.PostFixupPasses.push_back(
createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) { createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) {
if (Addr) if (Addr)
InProcessLinks[&MR] = jitTargetAddressToPointer<void *>(Addr); InProcessLinks[&MR] = Addr;
})); }));
} }
Error LocalEHFrameRegistrationPlugin::notifyEmitted( Error EHFrameRegistrationPlugin::notifyEmitted(
MaterializationResponsibility &MR) { MaterializationResponsibility &MR) {
auto EHFrameAddrItr = InProcessLinks.find(&MR); auto EHFrameAddrItr = InProcessLinks.find(&MR);
if (EHFrameAddrItr == InProcessLinks.end()) if (EHFrameAddrItr == InProcessLinks.end())
return Error::success(); return Error::success();
const void *EHFrameAddr = EHFrameAddrItr->second; auto EHFrameAddr = EHFrameAddrItr->second;
assert(EHFrameAddr && "eh-frame addr to register can not be null"); assert(EHFrameAddr && "eh-frame addr to register can not be null");
InProcessLinks.erase(EHFrameAddrItr); InProcessLinks.erase(EHFrameAddrItr);
@ -437,25 +441,25 @@ Error LocalEHFrameRegistrationPlugin::notifyEmitted(
else else
UntrackedEHFrameAddrs.push_back(EHFrameAddr); UntrackedEHFrameAddrs.push_back(EHFrameAddr);
return registerEHFrameSection(EHFrameAddr); return Registrar.registerEHFrames(EHFrameAddr);
} }
Error LocalEHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) { Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K); auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K);
if (EHFrameAddrItr == TrackedEHFrameAddrs.end()) if (EHFrameAddrItr == TrackedEHFrameAddrs.end())
return Error::success(); return Error::success();
const void *EHFrameAddr = EHFrameAddrItr->second; auto EHFrameAddr = EHFrameAddrItr->second;
assert(EHFrameAddr && "Tracked eh-frame addr must not be null"); assert(EHFrameAddr && "Tracked eh-frame addr must not be null");
TrackedEHFrameAddrs.erase(EHFrameAddrItr); TrackedEHFrameAddrs.erase(EHFrameAddrItr);
return deregisterEHFrameSection(EHFrameAddr); return Registrar.deregisterEHFrames(EHFrameAddr);
} }
Error LocalEHFrameRegistrationPlugin::notifyRemovingAllModules() { Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
std::vector<const void *> EHFrameAddrs = std::move(UntrackedEHFrameAddrs); std::vector<JITTargetAddress> EHFrameAddrs = std::move(UntrackedEHFrameAddrs);
EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size()); EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size());
for (auto &KV : TrackedEHFrameAddrs) for (auto &KV : TrackedEHFrameAddrs)
@ -466,10 +470,10 @@ Error LocalEHFrameRegistrationPlugin::notifyRemovingAllModules() {
Error Err = Error::success(); Error Err = Error::success();
while (!EHFrameAddrs.empty()) { while (!EHFrameAddrs.empty()) {
const void *EHFrameAddr = EHFrameAddrs.back(); auto EHFrameAddr = EHFrameAddrs.back();
assert(EHFrameAddr && "Untracked eh-frame addr must not be null"); assert(EHFrameAddr && "Untracked eh-frame addr must not be null");
EHFrameAddrs.pop_back(); EHFrameAddrs.pop_back();
Err = joinErrors(std::move(Err), deregisterEHFrameSection(EHFrameAddr)); Err = joinErrors(std::move(Err), Registrar.deregisterEHFrames(EHFrameAddr));
} }
return Err; return Err;

View File

@ -14,6 +14,7 @@
#include "llvm-jitlink.h" #include "llvm-jitlink.h"
#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h" #include "llvm/MC/MCContext.h"
@ -232,7 +233,8 @@ Session::Session(Triple TT) : ObjLayer(ES, MemMgr), TT(std::move(TT)) {
}; };
if (!NoExec && !TT.isOSWindows()) if (!NoExec && !TT.isOSWindows())
ObjLayer.addPlugin(llvm::make_unique<LocalEHFrameRegistrationPlugin>()); ObjLayer.addPlugin(llvm::make_unique<EHFrameRegistrationPlugin>(
InProcessEHFrameRegistrar::getInstance()));
ObjLayer.addPlugin(llvm::make_unique<JITLinkSessionPlugin>(*this)); ObjLayer.addPlugin(llvm::make_unique<JITLinkSessionPlugin>(*this));
} }