144 lines · cpp
1//===-------------- EPCGenericJITLinkMemoryManagerTest.cpp ----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "OrcTestCommon.h"10 11#include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h"12 13#include "llvm/ADT/DenseMap.h"14#include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"15#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"16#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"17#include "llvm/Support/FormatVariadic.h"18#include "llvm/Support/Memory.h"19#include "llvm/Testing/Support/Error.h"20 21#include <limits>22#include <vector>23 24using namespace llvm;25using namespace llvm::orc;26using namespace llvm::orc::shared;27 28namespace {29 30class SimpleAllocator {31public:32 Expected<ExecutorAddr> reserve(uint64_t Size) {33 std::error_code EC;34 auto MB = sys::Memory::allocateMappedMemory(35 Size, 0, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);36 if (EC)37 return errorCodeToError(EC);38 Blocks[MB.base()] = sys::OwningMemoryBlock(std::move(MB));39 return ExecutorAddr::fromPtr(MB.base());40 }41 42 Expected<ExecutorAddr> initialize(tpctypes::FinalizeRequest FR) {43 assert(!FR.Segments.empty());44 ExecutorAddr Base = FR.Segments[0].Addr;45 for (auto &Seg : FR.Segments) {46 Base = std::min(Base, Seg.Addr);47 char *Mem = Seg.Addr.toPtr<char *>();48 memcpy(Mem, Seg.Content.data(), Seg.Content.size());49 memset(Mem + Seg.Content.size(), 0, Seg.Size - Seg.Content.size());50 assert(Seg.Size <= std::numeric_limits<size_t>::max());51 if (auto EC = sys::Memory::protectMappedMemory(52 {Mem, static_cast<size_t>(Seg.Size)},53 toSysMemoryProtectionFlags(Seg.RAG.Prot)))54 return errorCodeToError(EC);55 if ((Seg.RAG.Prot & MemProt::Exec) != MemProt::Exec)56 sys::Memory::InvalidateInstructionCache(Mem, Seg.Size);57 }58 return Base;59 }60 61 Error release(std::vector<ExecutorAddr> &Bases) {62 Error Err = Error::success();63 for (auto &Base : Bases) {64 auto I = Blocks.find(Base.toPtr<void *>());65 if (I == Blocks.end()) {66 Err = joinErrors(67 std::move(Err),68 make_error<StringError>("No allocation for " +69 formatv("{0:x}", Base.getValue()),70 inconvertibleErrorCode()));71 continue;72 }73 auto MB = std::move(I->second);74 Blocks.erase(I);75 if (auto EC = MB.release())76 Err = joinErrors(std::move(Err), errorCodeToError(EC));77 }78 return Err;79 }80 81private:82 DenseMap<void *, sys::OwningMemoryBlock> Blocks;83};84 85CWrapperFunctionResult testReserve(const char *ArgData, size_t ArgSize) {86 return WrapperFunction<rt::SPSSimpleExecutorMemoryManagerReserveSignature>::87 handle(ArgData, ArgSize,88 makeMethodWrapperHandler(&SimpleAllocator::reserve))89 .release();90}91 92CWrapperFunctionResult testInitialize(const char *ArgData, size_t ArgSize) {93 return WrapperFunction<94 rt::SPSSimpleExecutorMemoryManagerInitializeSignature>::95 handle(ArgData, ArgSize,96 makeMethodWrapperHandler(&SimpleAllocator::initialize))97 .release();98}99 100CWrapperFunctionResult testRelease(const char *ArgData, size_t ArgSize) {101 return WrapperFunction<rt::SPSSimpleExecutorMemoryManagerReleaseSignature>::102 handle(ArgData, ArgSize,103 makeMethodWrapperHandler(&SimpleAllocator::release))104 .release();105}106 107TEST(EPCGenericJITLinkMemoryManagerTest, AllocFinalizeFree) {108 auto SelfEPC = cantFail(SelfExecutorProcessControl::Create());109 SimpleAllocator SA;110 111 EPCGenericJITLinkMemoryManager::SymbolAddrs SAs;112 SAs.Allocator = ExecutorAddr::fromPtr(&SA);113 SAs.Reserve = ExecutorAddr::fromPtr(&testReserve);114 SAs.Initialize = ExecutorAddr::fromPtr(&testInitialize);115 SAs.Release = ExecutorAddr::fromPtr(&testRelease);116 117 auto MemMgr = std::make_unique<EPCGenericJITLinkMemoryManager>(*SelfEPC, SAs);118 StringRef Hello = "hello";119 auto SSA = jitlink::SimpleSegmentAlloc::Create(120 *MemMgr, std::make_shared<SymbolStringPool>(),121 Triple("x86_64-apple-darwin"), nullptr,122 {{MemProt::Read, {Hello.size(), Align(1)}}});123 EXPECT_THAT_EXPECTED(SSA, Succeeded());124 auto SegInfo = SSA->getSegInfo(MemProt::Read);125 memcpy(SegInfo.WorkingMem.data(), Hello.data(), Hello.size());126 127 auto FA = SSA->finalize();128 EXPECT_THAT_EXPECTED(FA, Succeeded());129 130 ExecutorAddr TargetAddr(SegInfo.Addr);131 132 const char *TargetMem = TargetAddr.toPtr<const char *>();133 EXPECT_NE(TargetMem, SegInfo.WorkingMem.data());134 StringRef TargetHello(TargetMem, Hello.size());135 EXPECT_EQ(Hello, TargetHello);136 137 auto Err2 = MemMgr->deallocate(std::move(*FA));138 EXPECT_THAT_ERROR(std::move(Err2), Succeeded());139 140 cantFail(SelfEPC->disconnect());141}142 143} // namespace144