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