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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "OrcTestCommon.h" 10 11 #include "llvm/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManager.h" 12 #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h" 13 #include "llvm/Support/Memory.h" 14 #include "llvm/Testing/Support/Error.h" 15 16 #include <limits> 17 18 using namespace llvm; 19 using namespace llvm::orc; 20 using namespace llvm::orc::shared; 21 22 namespace { 23 24 llvm::orc::shared::detail::CWrapperFunctionResult 25 testReserve(const char *ArgData, size_t ArgSize) { 26 return WrapperFunction<SPSOrcTargetProcessAllocate>::handle( 27 ArgData, ArgSize, 28 [](uint64_t Size) -> Expected<ExecutorAddress> { 29 std::error_code EC; 30 auto MB = sys::Memory::allocateMappedMemory( 31 Size, 0, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC); 32 if (EC) 33 return errorCodeToError(EC); 34 return ExecutorAddress::fromPtr(MB.base()); 35 }) 36 .release(); 37 } 38 39 llvm::orc::shared::detail::CWrapperFunctionResult 40 testFinalize(const char *ArgData, size_t ArgSize) { 41 return WrapperFunction<SPSOrcTargetProcessFinalize>::handle( 42 ArgData, ArgSize, 43 [](const tpctypes::FinalizeRequest &FR) -> Error { 44 for (auto &Seg : FR) { 45 char *Mem = Seg.Addr.toPtr<char *>(); 46 memcpy(Mem, Seg.Content.data(), Seg.Content.size()); 47 memset(Mem + Seg.Content.size(), 0, 48 Seg.Size - Seg.Content.size()); 49 assert(Seg.Size <= std::numeric_limits<size_t>::max()); 50 if (auto EC = sys::Memory::protectMappedMemory( 51 {Mem, static_cast<size_t>(Seg.Size)}, 52 tpctypes::fromWireProtectionFlags(Seg.Prot))) 53 return errorCodeToError(EC); 54 if (Seg.Prot & tpctypes::WPF_Exec) 55 sys::Memory::InvalidateInstructionCache(Mem, Seg.Size); 56 } 57 return Error::success(); 58 }) 59 .release(); 60 } 61 62 llvm::orc::shared::detail::CWrapperFunctionResult 63 testDeallocate(const char *ArgData, size_t ArgSize) { 64 return WrapperFunction<SPSOrcTargetProcessDeallocate>::handle( 65 ArgData, ArgSize, 66 [](ExecutorAddress Base, uint64_t Size) -> Error { 67 sys::MemoryBlock MB(Base.toPtr<void *>(), Size); 68 if (auto EC = sys::Memory::releaseMappedMemory(MB)) 69 return errorCodeToError(EC); 70 return Error::success(); 71 }) 72 .release(); 73 } 74 75 TEST(EPCGenericJITLinkMemoryManagerTest, AllocFinalizeFree) { 76 auto SelfEPC = cantFail(SelfExecutorProcessControl::Create()); 77 78 EPCGenericJITLinkMemoryManager::FuncAddrs FAs; 79 FAs.Reserve = ExecutorAddress::fromPtr(&testReserve); 80 FAs.Finalize = ExecutorAddress::fromPtr(&testFinalize); 81 FAs.Deallocate = ExecutorAddress::fromPtr(&testDeallocate); 82 83 auto MemMgr = std::make_unique<EPCGenericJITLinkMemoryManager>(*SelfEPC, FAs); 84 85 jitlink::JITLinkMemoryManager::SegmentsRequestMap SRM; 86 StringRef Hello = "hello"; 87 SRM[sys::Memory::MF_READ] = {8, Hello.size(), 8}; 88 auto Alloc = MemMgr->allocate(nullptr, SRM); 89 EXPECT_THAT_EXPECTED(Alloc, Succeeded()); 90 91 MutableArrayRef<char> WorkingMem = 92 (*Alloc)->getWorkingMemory(sys::Memory::MF_READ); 93 memcpy(WorkingMem.data(), Hello.data(), Hello.size()); 94 95 auto Err = (*Alloc)->finalize(); 96 EXPECT_THAT_ERROR(std::move(Err), Succeeded()); 97 98 ExecutorAddress TargetAddr((*Alloc)->getTargetMemory(sys::Memory::MF_READ)); 99 100 const char *TargetMem = TargetAddr.toPtr<const char *>(); 101 EXPECT_NE(TargetMem, WorkingMem.data()); 102 StringRef TargetHello(TargetMem, Hello.size()); 103 EXPECT_EQ(Hello, TargetHello); 104 105 auto Err2 = (*Alloc)->deallocate(); 106 EXPECT_THAT_ERROR(std::move(Err2), Succeeded()); 107 } 108 109 } // namespace 110