116 lines
3.6 KiB
C++
116 lines
3.6 KiB
C++
//===--------- EHFrameRegistrationPlugin.cpp - Register eh-frames ---------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ExecutionEngine/Orc/EHFrameRegistrationPlugin.h"
|
|
|
|
#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
|
|
|
|
#define DEBUG_TYPE "orc"
|
|
|
|
using namespace llvm::jitlink;
|
|
|
|
namespace llvm::orc {
|
|
|
|
EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
|
|
ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
|
|
: ES(ES), Registrar(std::move(Registrar)) {}
|
|
|
|
void EHFrameRegistrationPlugin::modifyPassConfig(
|
|
MaterializationResponsibility &MR, LinkGraph &G,
|
|
PassConfiguration &PassConfig) {
|
|
|
|
PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
|
|
G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
|
|
if (Addr) {
|
|
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
|
|
assert(!InProcessLinks.count(&MR) &&
|
|
"Link for MR already being tracked?");
|
|
InProcessLinks[&MR] = {Addr, Size};
|
|
}
|
|
}));
|
|
}
|
|
|
|
Error EHFrameRegistrationPlugin::notifyEmitted(
|
|
MaterializationResponsibility &MR) {
|
|
|
|
ExecutorAddrRange EmittedRange;
|
|
{
|
|
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
|
|
|
|
auto EHFrameRangeItr = InProcessLinks.find(&MR);
|
|
if (EHFrameRangeItr == InProcessLinks.end())
|
|
return Error::success();
|
|
|
|
EmittedRange = EHFrameRangeItr->second;
|
|
assert(EmittedRange.Start && "eh-frame addr to register can not be null");
|
|
InProcessLinks.erase(EHFrameRangeItr);
|
|
}
|
|
|
|
if (auto Err = MR.withResourceKeyDo(
|
|
[&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
|
|
return Err;
|
|
|
|
return Registrar->registerEHFrames(EmittedRange);
|
|
}
|
|
|
|
Error EHFrameRegistrationPlugin::notifyFailed(
|
|
MaterializationResponsibility &MR) {
|
|
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
|
|
InProcessLinks.erase(&MR);
|
|
return Error::success();
|
|
}
|
|
|
|
Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD,
|
|
ResourceKey K) {
|
|
std::vector<ExecutorAddrRange> RangesToRemove;
|
|
|
|
ES.runSessionLocked([&] {
|
|
auto I = EHFrameRanges.find(K);
|
|
if (I != EHFrameRanges.end()) {
|
|
RangesToRemove = std::move(I->second);
|
|
EHFrameRanges.erase(I);
|
|
}
|
|
});
|
|
|
|
Error Err = Error::success();
|
|
while (!RangesToRemove.empty()) {
|
|
auto RangeToRemove = RangesToRemove.back();
|
|
RangesToRemove.pop_back();
|
|
assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
|
|
Err = joinErrors(std::move(Err),
|
|
Registrar->deregisterEHFrames(RangeToRemove));
|
|
}
|
|
|
|
return Err;
|
|
}
|
|
|
|
void EHFrameRegistrationPlugin::notifyTransferringResources(
|
|
JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
|
|
auto SI = EHFrameRanges.find(SrcKey);
|
|
if (SI == EHFrameRanges.end())
|
|
return;
|
|
|
|
auto DI = EHFrameRanges.find(DstKey);
|
|
if (DI != EHFrameRanges.end()) {
|
|
auto &SrcRanges = SI->second;
|
|
auto &DstRanges = DI->second;
|
|
DstRanges.reserve(DstRanges.size() + SrcRanges.size());
|
|
for (auto &SrcRange : SrcRanges)
|
|
DstRanges.push_back(std::move(SrcRange));
|
|
EHFrameRanges.erase(SI);
|
|
} else {
|
|
// We need to move SrcKey's ranges over without invalidating the SI
|
|
// iterator.
|
|
auto Tmp = std::move(SI->second);
|
|
EHFrameRanges.erase(SI);
|
|
EHFrameRanges[DstKey] = std::move(Tmp);
|
|
}
|
|
}
|
|
|
|
} // namespace llvm::orc
|