diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-03-20 11:40:34 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-05-14 11:43:05 +0000 |
commit | 349cc55c9796c4596a5b9904cd3281af295f878f (patch) | |
tree | 410c5a785075730a35f1272ca6a7adf72222ad03 /contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp | |
parent | cb2ae6163174b90e999326ecec3699ee093a5d43 (diff) | |
parent | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp | 135 |
1 files changed, 72 insertions, 63 deletions
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp index 36efc744bf30..fcfe389f82a8 100644 --- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp +++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp @@ -1,10 +1,15 @@ -//===---- DebugObjectManagerPlugin.h - JITLink debug objects ---*- C++ -*-===// +//===------- DebugObjectManagerPlugin.cpp - JITLink debug objects ---------===// // // 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 // //===----------------------------------------------------------------------===// +// +// FIXME: Update Plugin to poke the debug object into a new JITLink section, +// rather than creating a new allocation. +// +//===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" @@ -108,70 +113,77 @@ void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) { } } -static constexpr sys::Memory::ProtectionFlags ReadOnly = - static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ); - enum class Requirement { // Request final target memory load-addresses for all sections. ReportFinalSectionLoadAddresses, }; -/// The plugin creates a debug object from JITLinkContext when JITLink starts -/// processing the corresponding LinkGraph. It provides access to the pass -/// configuration of the LinkGraph and calls the finalization function, once -/// the resulting link artifact was emitted. +/// The plugin creates a debug object from when JITLink starts processing the +/// corresponding LinkGraph. It provides access to the pass configuration of +/// the LinkGraph and calls the finalization function, once the resulting link +/// artifact was emitted. /// class DebugObject { public: - DebugObject(JITLinkContext &Ctx, ExecutionSession &ES) : Ctx(Ctx), ES(ES) {} + DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD, + ExecutionSession &ES) + : MemMgr(MemMgr), JD(JD), ES(ES) {} void set(Requirement Req) { Reqs.insert(Req); } bool has(Requirement Req) const { return Reqs.count(Req) > 0; } - using FinalizeContinuation = std::function<void(Expected<sys::MemoryBlock>)>; + using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>; + void finalizeAsync(FinalizeContinuation OnFinalize); virtual ~DebugObject() { - if (Alloc) - if (Error Err = Alloc->deallocate()) + if (Alloc) { + std::vector<FinalizedAlloc> Allocs; + Allocs.push_back(std::move(Alloc)); + if (Error Err = MemMgr.deallocate(std::move(Allocs))) ES.reportError(std::move(Err)); + } } virtual void reportSectionTargetMemoryRange(StringRef Name, SectionRange TargetMem) {} protected: - using Allocation = JITLinkMemoryManager::Allocation; + using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc; + using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc; - virtual Expected<std::unique_ptr<Allocation>> - finalizeWorkingMemory(JITLinkContext &Ctx) = 0; + virtual Expected<SimpleSegmentAlloc> finalizeWorkingMemory() = 0; + + JITLinkMemoryManager &MemMgr; + const JITLinkDylib *JD = nullptr; private: - JITLinkContext &Ctx; ExecutionSession &ES; std::set<Requirement> Reqs; - std::unique_ptr<Allocation> Alloc{nullptr}; + FinalizedAlloc Alloc; }; // Finalize working memory and take ownership of the resulting allocation. Start // copying memory over to the target and pass on the result once we're done. // Ownership of the allocation remains with us for the rest of our lifetime. void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) { - assert(Alloc == nullptr && "Cannot finalize more than once"); - - auto AllocOrErr = finalizeWorkingMemory(Ctx); - if (!AllocOrErr) - OnFinalize(AllocOrErr.takeError()); - Alloc = std::move(*AllocOrErr); - - Alloc->finalizeAsync([this, OnFinalize](Error Err) { - if (Err) - OnFinalize(std::move(Err)); - else - OnFinalize(sys::MemoryBlock( - jitTargetAddressToPointer<void *>(Alloc->getTargetMemory(ReadOnly)), - Alloc->getWorkingMemory(ReadOnly).size())); - }); + assert(!Alloc && "Cannot finalize more than once"); + + if (auto SimpleSegAlloc = finalizeWorkingMemory()) { + auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read); + ExecutorAddrRange DebugObjRange(ExecutorAddr(ROSeg.Addr), + ExecutorAddrDiff(ROSeg.WorkingMem.size())); + SimpleSegAlloc->finalize( + [this, DebugObjRange, + OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) { + if (FA) { + Alloc = std::move(*FA); + OnFinalize(DebugObjRange); + } else + OnFinalize(FA.takeError()); + }); + } else + OnFinalize(SimpleSegAlloc.takeError()); } /// The current implementation of ELFDebugObject replicates the approach used in @@ -190,8 +202,7 @@ public: StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); } protected: - Expected<std::unique_ptr<Allocation>> - finalizeWorkingMemory(JITLinkContext &Ctx) override; + Expected<SimpleSegmentAlloc> finalizeWorkingMemory() override; template <typename ELFT> Error recordSection(StringRef Name, @@ -201,15 +212,16 @@ protected: private: template <typename ELFT> static Expected<std::unique_ptr<ELFDebugObject>> - CreateArchType(MemoryBufferRef Buffer, JITLinkContext &Ctx, - ExecutionSession &ES); + CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr, + const JITLinkDylib *JD, ExecutionSession &ES); static std::unique_ptr<WritableMemoryBuffer> CopyBuffer(MemoryBufferRef Buffer, Error &Err); ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer, - JITLinkContext &Ctx, ExecutionSession &ES) - : DebugObject(Ctx, ES), Buffer(std::move(Buffer)) { + JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD, + ExecutionSession &ES) + : DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) { set(Requirement::ReportFinalSectionLoadAddresses); } @@ -244,13 +256,14 @@ ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) { template <typename ELFT> Expected<std::unique_ptr<ELFDebugObject>> -ELFDebugObject::CreateArchType(MemoryBufferRef Buffer, JITLinkContext &Ctx, - ExecutionSession &ES) { +ELFDebugObject::CreateArchType(MemoryBufferRef Buffer, + JITLinkMemoryManager &MemMgr, + const JITLinkDylib *JD, ExecutionSession &ES) { using SectionHeader = typename ELFT::Shdr; Error Err = Error::success(); std::unique_ptr<ELFDebugObject> DebugObj( - new ELFDebugObject(CopyBuffer(Buffer, Err), Ctx, ES)); + new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES)); if (Err) return std::move(Err); @@ -299,23 +312,26 @@ ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, if (Class == ELF::ELFCLASS32) { if (Endian == ELF::ELFDATA2LSB) - return CreateArchType<ELF32LE>(Buffer, Ctx, ES); + return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(), + Ctx.getJITLinkDylib(), ES); if (Endian == ELF::ELFDATA2MSB) - return CreateArchType<ELF32BE>(Buffer, Ctx, ES); + return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(), + Ctx.getJITLinkDylib(), ES); return nullptr; } if (Class == ELF::ELFCLASS64) { if (Endian == ELF::ELFDATA2LSB) - return CreateArchType<ELF64LE>(Buffer, Ctx, ES); + return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(), + Ctx.getJITLinkDylib(), ES); if (Endian == ELF::ELFDATA2MSB) - return CreateArchType<ELF64BE>(Buffer, Ctx, ES); + return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(), + Ctx.getJITLinkDylib(), ES); return nullptr; } return nullptr; } -Expected<std::unique_ptr<DebugObject::Allocation>> -ELFDebugObject::finalizeWorkingMemory(JITLinkContext &Ctx) { +Expected<SimpleSegmentAlloc> ELFDebugObject::finalizeWorkingMemory() { LLVM_DEBUG({ dbgs() << "Section load-addresses in debug object for \"" << Buffer->getBufferIdentifier() << "\":\n"; @@ -324,28 +340,21 @@ ELFDebugObject::finalizeWorkingMemory(JITLinkContext &Ctx) { }); // TODO: This works, but what actual alignment requirements do we have? - unsigned Alignment = sys::Process::getPageSizeEstimate(); - JITLinkMemoryManager &MemMgr = Ctx.getMemoryManager(); - const JITLinkDylib *JD = Ctx.getJITLinkDylib(); + unsigned PageSize = sys::Process::getPageSizeEstimate(); size_t Size = Buffer->getBufferSize(); // Allocate working memory for debug object in read-only segment. - JITLinkMemoryManager::SegmentsRequestMap SingleReadOnlySegment; - SingleReadOnlySegment[ReadOnly] = - JITLinkMemoryManager::SegmentRequest(Alignment, Size, 0); - - auto AllocOrErr = MemMgr.allocate(JD, SingleReadOnlySegment); - if (!AllocOrErr) - return AllocOrErr.takeError(); + auto Alloc = SimpleSegmentAlloc::Create( + MemMgr, JD, {{MemProt::Read, {Size, Align(PageSize)}}}); + if (!Alloc) + return Alloc; // Initialize working memory with a copy of our object buffer. - // TODO: Use our buffer as working memory directly. - std::unique_ptr<Allocation> Alloc = std::move(*AllocOrErr); - MutableArrayRef<char> WorkingMem = Alloc->getWorkingMemory(ReadOnly); - memcpy(WorkingMem.data(), Buffer->getBufferStart(), Size); + auto SegInfo = Alloc->getSegInfo(MemProt::Read); + memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size); Buffer.reset(); - return std::move(Alloc); + return Alloc; } void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name, @@ -447,7 +456,7 @@ Error DebugObjectManagerPlugin::notifyEmitted( std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future(); It->second->finalizeAsync( - [this, &FinalizePromise, &MR](Expected<sys::MemoryBlock> TargetMem) { + [this, &FinalizePromise, &MR](Expected<ExecutorAddrRange> TargetMem) { // Any failure here will fail materialization. if (!TargetMem) { FinalizePromise.set_value(TargetMem.takeError()); |