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