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