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