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