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