summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2019-08-27 15:50:32 +0000
committerLang Hames <lhames@gmail.com>2019-08-27 15:50:32 +0000
commitc48f1f6da690b721a211f6d5083b6a929b58e803 (patch)
tree1f6d54f630a619ad89e4e1dcdff084b91c2df88e
parentf260630e8f4c07613c11ea9f4b884e58c9683f03 (diff)
downloadbcm5719-llvm-c48f1f6da690b721a211f6d5083b6a929b58e803.tar.gz
bcm5719-llvm-c48f1f6da690b721a211f6d5083b6a929b58e803.zip
[JITLink][ORC] Track eh-frame section size for registration/deregistration.
On MachO, processing of the eh-frame section should stop if the end of the __eh_frame section is reached, regardless of whether or not there is a null CFI length field at the end of the section. This patch tracks the eh-frame section size and threads it through the appropriate APIs so that processing can be terminated correctly. No testcase yet: This patch is all API plumbing (rather than modification of linked memory) which the existing infrastructure does not provide a way of testing. Committing without a testcase until I have an idea of how to write one. llvm-svn: 370074
-rw-r--r--llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h37
-rw-r--r--llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h12
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp32
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp63
4 files changed, 89 insertions, 55 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h b/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
index 8d2f641254b..37293dfb8ed 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
@@ -22,17 +22,21 @@ namespace llvm {
namespace jitlink {
/// Registers all FDEs in the given eh-frame section with the current process.
-Error registerEHFrameSection(const void *EHFrameSectionAddr);
+Error registerEHFrameSection(const void *EHFrameSectionAddr,
+ size_t EHFrameSectionSize);
/// Deregisters all FDEs in the given eh-frame section with the current process.
-Error deregisterEHFrameSection(const void *EHFrameSectionAddr);
+Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
+ size_t EHFrameSectionSize);
/// 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;
+ virtual Error registerEHFrames(JITTargetAddress EHFrameSectionAddr,
+ size_t EHFrameSectionSize) = 0;
+ virtual Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr,
+ size_t EHFrameSectionSize) = 0;
};
/// Registers / Deregisters EH-frames in the current process.
@@ -48,31 +52,38 @@ public:
InProcessEHFrameRegistrar(InProcessEHFrameRegistrar &&) = delete;
InProcessEHFrameRegistrar &operator=(InProcessEHFrameRegistrar &&) = delete;
- Error registerEHFrames(JITTargetAddress EHFrameSectionAddr) override {
+ Error registerEHFrames(JITTargetAddress EHFrameSectionAddr,
+ size_t EHFrameSectionSize) override {
return registerEHFrameSection(
- jitTargetAddressToPointer<void *>(EHFrameSectionAddr));
+ jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
+ EHFrameSectionSize);
}
- Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr) override {
+ Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr,
+ size_t EHFrameSectionSize) override {
return deregisterEHFrameSection(
- jitTargetAddressToPointer<void *>(EHFrameSectionAddr));
+ jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
+ EHFrameSectionSize);
}
private:
InProcessEHFrameRegistrar();
};
-using StoreFrameAddressFunction = std::function<void(JITTargetAddress)>;
+using StoreFrameRangeFunction =
+ std::function<void(JITTargetAddress EHFrameSectionAddr,
+ size_t EHFrameSectionSize)>;
-/// Creates a pass that records the address of the EH frame section. If no
-/// eh-frame section is found, it will set EHFrameAddr to zero.
+/// Creates a pass that records the address and size of the EH frame section.
+/// If no eh-frame section is found then the address and size will both be given
+/// as zero.
///
/// Authors of JITLinkContexts can use this function to register a post-fixup
-/// pass that records the address of the eh-frame section. This address can
+/// pass that records the range of the eh-frame section. This range can
/// be used after finalization to register and deregister the frame.
AtomGraphPassFunction
createEHFrameRecorderPass(const Triple &TT,
- StoreFrameAddressFunction StoreFrameAddress);
+ StoreFrameRangeFunction StoreFrameRange);
} // end namespace jitlink
} // end namespace llvm
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
index c1e7d27f446..0605ee3bb0b 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
@@ -153,10 +153,16 @@ public:
Error notifyRemovingAllModules() override;
private:
+
+ struct EHFrameRange {
+ JITTargetAddress Addr = 0;
+ size_t Size;
+ };
+
jitlink::EHFrameRegistrar &Registrar;
- DenseMap<MaterializationResponsibility *, JITTargetAddress> InProcessLinks;
- DenseMap<VModuleKey, JITTargetAddress> TrackedEHFrameAddrs;
- std::vector<JITTargetAddress> UntrackedEHFrameAddrs;
+ DenseMap<MaterializationResponsibility *, EHFrameRange> InProcessLinks;
+ DenseMap<VModuleKey, EHFrameRange> TrackedEHFrameRanges;
+ std::vector<EHFrameRange> UntrackedEHFrameRanges;
};
} // end namespace orc
diff --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
index 25f0e9040ff..f373f2d92b0 100644
--- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
@@ -451,11 +451,13 @@ static Error deregisterFrameWrapper(const void *P) {
template <typename HandleFDEFn>
Error walkAppleEHFrameSection(const char *const SectionStart,
+ size_t SectionSize,
HandleFDEFn HandleFDE) {
const char *CurCFIRecord = SectionStart;
+ const char *End = SectionStart + SectionSize;
uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
- while (Size != 0) {
+ while (CurCFIRecord != End && Size != 0) {
const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
if (Size == 0xffffffff)
Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
@@ -484,10 +486,12 @@ Error walkAppleEHFrameSection(const char *const SectionStart,
#endif // __APPLE__
-Error registerEHFrameSection(const void *EHFrameSectionAddr) {
+Error registerEHFrameSection(const void *EHFrameSectionAddr,
+ size_t EHFrameSectionSize) {
#ifdef __APPLE__
// On Darwin __register_frame has to be called for each FDE entry.
return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
+ EHFrameSectionSize,
registerFrameWrapper);
#else
// On Linux __register_frame takes a single argument:
@@ -499,9 +503,11 @@ Error registerEHFrameSection(const void *EHFrameSectionAddr) {
#endif
}
-Error deregisterEHFrameSection(const void *EHFrameSectionAddr) {
+Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
+ size_t EHFrameSectionSize) {
#ifdef __APPLE__
return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
+ EHFrameSectionSize,
deregisterFrameWrapper);
#else
return deregisterFrameWrapper(EHFrameSectionAddr);
@@ -519,21 +525,29 @@ InProcessEHFrameRegistrar::InProcessEHFrameRegistrar() {}
AtomGraphPassFunction
createEHFrameRecorderPass(const Triple &TT,
- StoreFrameAddressFunction StoreFrameAddress) {
+ StoreFrameRangeFunction StoreRangeAddress) {
const char *EHFrameSectionName = nullptr;
if (TT.getObjectFormat() == Triple::MachO)
EHFrameSectionName = "__eh_frame";
else
EHFrameSectionName = ".eh_frame";
- auto RecordEHFrame = [EHFrameSectionName,
- StoreFrameAddress](AtomGraph &G) -> Error {
+ auto RecordEHFrame =
+ [EHFrameSectionName,
+ StoreFrameRange = std::move(StoreRangeAddress)](AtomGraph &G) -> Error {
// Search for a non-empty eh-frame and record the address of the first atom
// in it.
JITTargetAddress Addr = 0;
- if (auto *S = G.findSectionByName(EHFrameSectionName))
- Addr = S->getRange().getStart();
- StoreFrameAddress(Addr);
+ size_t Size = 0;
+ if (auto *S = G.findSectionByName(EHFrameSectionName)) {
+ auto R = S->getRange();
+ Addr = R.getStart();
+ Size = R.getSize();
+ }
+ if (Addr == 0 && Size != 0)
+ return make_error<JITLinkError>("__eh_frame section can not have zero "
+ "address with non-zero size");
+ StoreFrameRange(Addr, Size);
return Error::success();
};
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
index 0d0b8a9c227..e1b8d52acb4 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
@@ -58,7 +58,8 @@ public:
auto SharedLookupContinuation =
std::make_shared<JITLinkAsyncLookupContinuation>(
std::move(LookupContinuation));
- auto OnResolve = [SharedLookupContinuation](Expected<SymbolMap> Result) {
+ auto OnResolve = [this, SharedLookupContinuation](Expected<SymbolMap> Result) {
+ auto Main = Layer.getExecutionSession().intern("_main");
if (!Result)
(*SharedLookupContinuation)(Result.takeError());
else {
@@ -126,19 +127,16 @@ public:
if (!ExtraSymbolsToClaim.empty())
if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
return notifyFailed(std::move(Err));
-
if (auto Err = MR.notifyResolved(InternedResult)) {
Layer.getExecutionSession().reportError(std::move(Err));
MR.failMaterialization();
return;
}
-
Layer.notifyLoaded(MR);
}
void notifyFinalized(
std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
-
if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
Layer.getExecutionSession().reportError(std::move(Err));
MR.failMaterialization();
@@ -425,61 +423,66 @@ void EHFrameRegistrationPlugin::modifyPassConfig(
assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
PassConfig.PostFixupPasses.push_back(
- createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) {
+ createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr,
+ size_t Size) {
if (Addr)
- InProcessLinks[&MR] = Addr;
+ InProcessLinks[&MR] = { Addr, Size };
}));
}
Error EHFrameRegistrationPlugin::notifyEmitted(
MaterializationResponsibility &MR) {
- auto EHFrameAddrItr = InProcessLinks.find(&MR);
- if (EHFrameAddrItr == InProcessLinks.end())
+ auto EHFrameRangeItr = InProcessLinks.find(&MR);
+ if (EHFrameRangeItr == InProcessLinks.end())
return Error::success();
- auto EHFrameAddr = EHFrameAddrItr->second;
- assert(EHFrameAddr && "eh-frame addr to register can not be null");
+ auto EHFrameRange = EHFrameRangeItr->second;
+ assert(EHFrameRange.Addr &&
+ "eh-frame addr to register can not be null");
- InProcessLinks.erase(EHFrameAddrItr);
+ InProcessLinks.erase(EHFrameRangeItr);
if (auto Key = MR.getVModuleKey())
- TrackedEHFrameAddrs[Key] = EHFrameAddr;
+ TrackedEHFrameRanges[Key] = EHFrameRange;
else
- UntrackedEHFrameAddrs.push_back(EHFrameAddr);
+ UntrackedEHFrameRanges.push_back(EHFrameRange);
- return Registrar.registerEHFrames(EHFrameAddr);
+ return Registrar.registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
}
Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
- auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K);
- if (EHFrameAddrItr == TrackedEHFrameAddrs.end())
+ auto EHFrameRangeItr = TrackedEHFrameRanges.find(K);
+ if (EHFrameRangeItr == TrackedEHFrameRanges.end())
return Error::success();
- auto EHFrameAddr = EHFrameAddrItr->second;
- assert(EHFrameAddr && "Tracked eh-frame addr must not be null");
+ auto EHFrameRange = EHFrameRangeItr->second;
+ assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null");
- TrackedEHFrameAddrs.erase(EHFrameAddrItr);
+ TrackedEHFrameRanges.erase(EHFrameRangeItr);
- return Registrar.deregisterEHFrames(EHFrameAddr);
+ return Registrar.deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
}
Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
- std::vector<JITTargetAddress> EHFrameAddrs = std::move(UntrackedEHFrameAddrs);
- EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size());
+ std::vector<EHFrameRange> EHFrameRanges =
+ std::move(UntrackedEHFrameRanges);
+ EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size());
- for (auto &KV : TrackedEHFrameAddrs)
- EHFrameAddrs.push_back(KV.second);
+ for (auto &KV : TrackedEHFrameRanges)
+ EHFrameRanges.push_back(KV.second);
- TrackedEHFrameAddrs.clear();
+ TrackedEHFrameRanges.clear();
Error Err = Error::success();
- while (!EHFrameAddrs.empty()) {
- auto EHFrameAddr = EHFrameAddrs.back();
- assert(EHFrameAddr && "Untracked eh-frame addr must not be null");
- EHFrameAddrs.pop_back();
- Err = joinErrors(std::move(Err), Registrar.deregisterEHFrames(EHFrameAddr));
+ while (!EHFrameRanges.empty()) {
+ auto EHFrameRange = EHFrameRanges.back();
+ assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null");
+ EHFrameRanges.pop_back();
+ Err = joinErrors(std::move(Err),
+ Registrar.deregisterEHFrames(EHFrameRange.Addr,
+ EHFrameRange.Size));
}
return Err;
OpenPOWER on IntegriCloud