xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/EPCGenericJITLinkMemoryManagerTest.cpp (revision 02b462034875dcf8f73b80d746e1fe40cdb22fd6)
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