Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp
35266 views
//===----- EPCGenericRTDyldMemoryManager.cpp - EPC-bbasde MemMgr -----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.h"9#include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"10#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"11#include "llvm/Support/Alignment.h"12#include "llvm/Support/FormatVariadic.h"1314#define DEBUG_TYPE "orc"1516using namespace llvm::orc::shared;1718namespace llvm {19namespace orc {2021Expected<std::unique_ptr<EPCGenericRTDyldMemoryManager>>22EPCGenericRTDyldMemoryManager::CreateWithDefaultBootstrapSymbols(23ExecutorProcessControl &EPC) {24SymbolAddrs SAs;25if (auto Err = EPC.getBootstrapSymbols(26{{SAs.Instance, rt::SimpleExecutorMemoryManagerInstanceName},27{SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},28{SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName},29{SAs.Deallocate,30rt::SimpleExecutorMemoryManagerDeallocateWrapperName},31{SAs.RegisterEHFrame, rt::RegisterEHFrameSectionWrapperName},32{SAs.DeregisterEHFrame, rt::DeregisterEHFrameSectionWrapperName}}))33return std::move(Err);34return std::make_unique<EPCGenericRTDyldMemoryManager>(EPC, std::move(SAs));35}3637EPCGenericRTDyldMemoryManager::EPCGenericRTDyldMemoryManager(38ExecutorProcessControl &EPC, SymbolAddrs SAs)39: EPC(EPC), SAs(std::move(SAs)) {40LLVM_DEBUG(dbgs() << "Created remote allocator " << (void *)this << "\n");41}4243EPCGenericRTDyldMemoryManager::~EPCGenericRTDyldMemoryManager() {44LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << (void *)this << "\n");45if (!ErrMsg.empty())46errs() << "Destroying with existing errors:\n" << ErrMsg << "\n";4748Error Err = Error::success();49if (auto Err2 = EPC.callSPSWrapper<50rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(51SAs.Reserve, Err, SAs.Instance, FinalizedAllocs)) {52// FIXME: Report errors through EPC once that functionality is available.53logAllUnhandledErrors(std::move(Err2), errs(), "");54return;55}5657if (Err)58logAllUnhandledErrors(std::move(Err), errs(), "");59}6061uint8_t *EPCGenericRTDyldMemoryManager::allocateCodeSection(62uintptr_t Size, unsigned Alignment, unsigned SectionID,63StringRef SectionName) {64std::lock_guard<std::mutex> Lock(M);65LLVM_DEBUG({66dbgs() << "Allocator " << (void *)this << " allocating code section "67<< SectionName << ": size = " << formatv("{0:x}", Size)68<< " bytes, alignment = " << Alignment << "\n";69});70auto &Seg = Unmapped.back().CodeAllocs;71Seg.emplace_back(Size, Alignment);72return reinterpret_cast<uint8_t *>(73alignAddr(Seg.back().Contents.get(), Align(Alignment)));74}7576uint8_t *EPCGenericRTDyldMemoryManager::allocateDataSection(77uintptr_t Size, unsigned Alignment, unsigned SectionID,78StringRef SectionName, bool IsReadOnly) {79std::lock_guard<std::mutex> Lock(M);80LLVM_DEBUG({81dbgs() << "Allocator " << (void *)this << " allocating "82<< (IsReadOnly ? "ro" : "rw") << "-data section " << SectionName83<< ": size = " << formatv("{0:x}", Size) << " bytes, alignment "84<< Alignment << ")\n";85});8687auto &Seg =88IsReadOnly ? Unmapped.back().RODataAllocs : Unmapped.back().RWDataAllocs;8990Seg.emplace_back(Size, Alignment);91return reinterpret_cast<uint8_t *>(92alignAddr(Seg.back().Contents.get(), Align(Alignment)));93}9495void EPCGenericRTDyldMemoryManager::reserveAllocationSpace(96uintptr_t CodeSize, Align CodeAlign, uintptr_t RODataSize,97Align RODataAlign, uintptr_t RWDataSize, Align RWDataAlign) {9899{100std::lock_guard<std::mutex> Lock(M);101// If there's already an error then bail out.102if (!ErrMsg.empty())103return;104105if (CodeAlign > EPC.getPageSize()) {106ErrMsg = "Invalid code alignment in reserveAllocationSpace";107return;108}109if (RODataAlign > EPC.getPageSize()) {110ErrMsg = "Invalid ro-data alignment in reserveAllocationSpace";111return;112}113if (RWDataAlign > EPC.getPageSize()) {114ErrMsg = "Invalid rw-data alignment in reserveAllocationSpace";115return;116}117}118119uint64_t TotalSize = 0;120TotalSize += alignTo(CodeSize, EPC.getPageSize());121TotalSize += alignTo(RODataSize, EPC.getPageSize());122TotalSize += alignTo(RWDataSize, EPC.getPageSize());123124LLVM_DEBUG({125dbgs() << "Allocator " << (void *)this << " reserving "126<< formatv("{0:x}", TotalSize) << " bytes.\n";127});128129Expected<ExecutorAddr> TargetAllocAddr((ExecutorAddr()));130if (auto Err = EPC.callSPSWrapper<131rt::SPSSimpleExecutorMemoryManagerReserveSignature>(132SAs.Reserve, TargetAllocAddr, SAs.Instance, TotalSize)) {133std::lock_guard<std::mutex> Lock(M);134ErrMsg = toString(std::move(Err));135return;136}137if (!TargetAllocAddr) {138std::lock_guard<std::mutex> Lock(M);139ErrMsg = toString(TargetAllocAddr.takeError());140return;141}142143std::lock_guard<std::mutex> Lock(M);144Unmapped.push_back(SectionAllocGroup());145Unmapped.back().RemoteCode = {146*TargetAllocAddr, ExecutorAddrDiff(alignTo(CodeSize, EPC.getPageSize()))};147Unmapped.back().RemoteROData = {148Unmapped.back().RemoteCode.End,149ExecutorAddrDiff(alignTo(RODataSize, EPC.getPageSize()))};150Unmapped.back().RemoteRWData = {151Unmapped.back().RemoteROData.End,152ExecutorAddrDiff(alignTo(RWDataSize, EPC.getPageSize()))};153}154155bool EPCGenericRTDyldMemoryManager::needsToReserveAllocationSpace() {156return true;157}158159void EPCGenericRTDyldMemoryManager::registerEHFrames(uint8_t *Addr,160uint64_t LoadAddr,161size_t Size) {162LLVM_DEBUG({163dbgs() << "Allocator " << (void *)this << " added unfinalized eh-frame "164<< formatv("[ {0:x} {1:x} ]", LoadAddr, LoadAddr + Size) << "\n";165});166std::lock_guard<std::mutex> Lock(M);167// Bail out early if there's already an error.168if (!ErrMsg.empty())169return;170171ExecutorAddr LA(LoadAddr);172for (auto &SecAllocGroup : llvm::reverse(Unfinalized)) {173if (SecAllocGroup.RemoteCode.contains(LA) ||174SecAllocGroup.RemoteROData.contains(LA) ||175SecAllocGroup.RemoteRWData.contains(LA)) {176SecAllocGroup.UnfinalizedEHFrames.push_back({LA, Size});177return;178}179}180ErrMsg = "eh-frame does not lie inside unfinalized alloc";181}182183void EPCGenericRTDyldMemoryManager::deregisterEHFrames() {184// This is a no-op for us: We've registered a deallocation action for it.185}186187void EPCGenericRTDyldMemoryManager::notifyObjectLoaded(188RuntimeDyld &Dyld, const object::ObjectFile &Obj) {189std::lock_guard<std::mutex> Lock(M);190LLVM_DEBUG(dbgs() << "Allocator " << (void *)this << " applied mappings:\n");191for (auto &ObjAllocs : Unmapped) {192mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,193ObjAllocs.RemoteCode.Start);194mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,195ObjAllocs.RemoteROData.Start);196mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,197ObjAllocs.RemoteRWData.Start);198Unfinalized.push_back(std::move(ObjAllocs));199}200Unmapped.clear();201}202203bool EPCGenericRTDyldMemoryManager::finalizeMemory(std::string *ErrMsg) {204LLVM_DEBUG(dbgs() << "Allocator " << (void *)this << " finalizing:\n");205206// If there's an error then bail out here.207std::vector<SectionAllocGroup> SecAllocGroups;208{209std::lock_guard<std::mutex> Lock(M);210if (ErrMsg && !this->ErrMsg.empty()) {211*ErrMsg = std::move(this->ErrMsg);212return true;213}214std::swap(SecAllocGroups, Unfinalized);215}216217// Loop over unfinalized objects to make finalization requests.218for (auto &SecAllocGroup : SecAllocGroups) {219220MemProt SegMemProts[3] = {MemProt::Read | MemProt::Exec, MemProt::Read,221MemProt::Read | MemProt::Write};222223ExecutorAddrRange *RemoteAddrs[3] = {&SecAllocGroup.RemoteCode,224&SecAllocGroup.RemoteROData,225&SecAllocGroup.RemoteRWData};226227std::vector<SectionAlloc> *SegSections[3] = {&SecAllocGroup.CodeAllocs,228&SecAllocGroup.RODataAllocs,229&SecAllocGroup.RWDataAllocs};230231tpctypes::FinalizeRequest FR;232std::unique_ptr<char[]> AggregateContents[3];233234for (unsigned I = 0; I != 3; ++I) {235FR.Segments.push_back({});236auto &Seg = FR.Segments.back();237Seg.RAG = SegMemProts[I];238Seg.Addr = RemoteAddrs[I]->Start;239for (auto &SecAlloc : *SegSections[I]) {240Seg.Size = alignTo(Seg.Size, SecAlloc.Align);241Seg.Size += SecAlloc.Size;242}243AggregateContents[I] = std::make_unique<char[]>(Seg.Size);244size_t SecOffset = 0;245for (auto &SecAlloc : *SegSections[I]) {246SecOffset = alignTo(SecOffset, SecAlloc.Align);247memcpy(&AggregateContents[I][SecOffset],248reinterpret_cast<const char *>(249alignAddr(SecAlloc.Contents.get(), Align(SecAlloc.Align))),250SecAlloc.Size);251SecOffset += SecAlloc.Size;252// FIXME: Can we reset SecAlloc.Content here, now that it's copied into253// the aggregated content?254}255Seg.Content = {AggregateContents[I].get(), SecOffset};256}257258for (auto &Frame : SecAllocGroup.UnfinalizedEHFrames)259FR.Actions.push_back(260{cantFail(261WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(262SAs.RegisterEHFrame, Frame)),263cantFail(264WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(265SAs.DeregisterEHFrame, Frame))});266267// We'll also need to make an extra allocation for the eh-frame wrapper call268// arguments.269Error FinalizeErr = Error::success();270if (auto Err = EPC.callSPSWrapper<271rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>(272SAs.Finalize, FinalizeErr, SAs.Instance, std::move(FR))) {273std::lock_guard<std::mutex> Lock(M);274this->ErrMsg = toString(std::move(Err));275dbgs() << "Serialization error: " << this->ErrMsg << "\n";276if (ErrMsg)277*ErrMsg = this->ErrMsg;278return true;279}280if (FinalizeErr) {281std::lock_guard<std::mutex> Lock(M);282this->ErrMsg = toString(std::move(FinalizeErr));283dbgs() << "Finalization error: " << this->ErrMsg << "\n";284if (ErrMsg)285*ErrMsg = this->ErrMsg;286return true;287}288}289290return false;291}292293void EPCGenericRTDyldMemoryManager::mapAllocsToRemoteAddrs(294RuntimeDyld &Dyld, std::vector<SectionAlloc> &Allocs,295ExecutorAddr NextAddr) {296for (auto &Alloc : Allocs) {297NextAddr.setValue(alignTo(NextAddr.getValue(), Alloc.Align));298LLVM_DEBUG({299dbgs() << " " << static_cast<void *>(Alloc.Contents.get()) << " -> "300<< format("0x%016" PRIx64, NextAddr.getValue()) << "\n";301});302Dyld.mapSectionAddress(reinterpret_cast<const void *>(alignAddr(303Alloc.Contents.get(), Align(Alloc.Align))),304NextAddr.getValue());305Alloc.RemoteAddr = NextAddr;306// Only advance NextAddr if it was non-null to begin with,307// otherwise leave it as null.308if (NextAddr)309NextAddr += ExecutorAddrDiff(Alloc.Size);310}311}312313} // end namespace orc314} // end namespace llvm315316317