1 //===------------------------ OrcRTBootstrap.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 "OrcRTBootstrap.h"
10 
11 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12 #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
13 #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
14 
15 #define DEBUG_TYPE "orc"
16 
17 using namespace llvm::orc::shared;
18 
19 namespace llvm {
20 namespace orc {
21 namespace rt_bootstrap {
22 
23 static llvm::orc::shared::detail::CWrapperFunctionResult
24 reserveWrapper(const char *ArgData, size_t ArgSize) {
25   return WrapperFunction<rt::SPSMemoryReserveSignature>::handle(
26              ArgData, ArgSize,
27              [](uint64_t Size) -> Expected<ExecutorAddress> {
28                std::error_code EC;
29                auto MB = sys::Memory::allocateMappedMemory(
30                    Size, 0, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
31                if (EC)
32                  return errorCodeToError(EC);
33                return ExecutorAddress::fromPtr(MB.base());
34              })
35       .release();
36 }
37 
38 static llvm::orc::shared::detail::CWrapperFunctionResult
39 finalizeWrapper(const char *ArgData, size_t ArgSize) {
40   return WrapperFunction<rt::SPSMemoryFinalizeSignature>::handle(
41              ArgData, ArgSize,
42              [](const tpctypes::FinalizeRequest &FR) -> Error {
43                for (auto &Seg : FR) {
44                  char *Mem = Seg.Addr.toPtr<char *>();
45                  memcpy(Mem, Seg.Content.data(), Seg.Content.size());
46                  memset(Mem + Seg.Content.size(), 0,
47                         Seg.Size - Seg.Content.size());
48                  assert(Seg.Size <= std::numeric_limits<size_t>::max());
49                  if (auto EC = sys::Memory::protectMappedMemory(
50                          {Mem, static_cast<size_t>(Seg.Size)},
51                          tpctypes::fromWireProtectionFlags(Seg.Prot)))
52                    return errorCodeToError(EC);
53                  if (Seg.Prot & tpctypes::WPF_Exec)
54                    sys::Memory::InvalidateInstructionCache(Mem, Seg.Size);
55                }
56                return Error::success();
57              })
58       .release();
59 }
60 
61 static llvm::orc::shared::detail::CWrapperFunctionResult
62 deallocateWrapper(const char *ArgData, size_t ArgSize) {
63   return WrapperFunction<rt::SPSMemoryDeallocateSignature>::handle(
64              ArgData, ArgSize,
65              [](ExecutorAddress Base, uint64_t Size) -> Error {
66                sys::MemoryBlock MB(Base.toPtr<void *>(), Size);
67                if (auto EC = sys::Memory::releaseMappedMemory(MB))
68                  return errorCodeToError(EC);
69                return Error::success();
70              })
71       .release();
72 }
73 
74 template <typename WriteT, typename SPSWriteT>
75 static llvm::orc::shared::detail::CWrapperFunctionResult
76 writeUIntsWrapper(const char *ArgData, size_t ArgSize) {
77   return WrapperFunction<void(SPSSequence<SPSWriteT>)>::handle(
78              ArgData, ArgSize,
79              [](std::vector<WriteT> Ws) {
80                for (auto &W : Ws)
81                  *jitTargetAddressToPointer<decltype(W.Value) *>(W.Address) =
82                      W.Value;
83              })
84       .release();
85 }
86 
87 static llvm::orc::shared::detail::CWrapperFunctionResult
88 writeBuffersWrapper(const char *ArgData, size_t ArgSize) {
89   return WrapperFunction<void(SPSSequence<SPSMemoryAccessBufferWrite>)>::handle(
90              ArgData, ArgSize,
91              [](std::vector<tpctypes::BufferWrite> Ws) {
92                for (auto &W : Ws)
93                  memcpy(jitTargetAddressToPointer<char *>(W.Address),
94                         W.Buffer.data(), W.Buffer.size());
95              })
96       .release();
97 }
98 
99 static llvm::orc::shared::detail::CWrapperFunctionResult
100 runAsMainWrapper(const char *ArgData, size_t ArgSize) {
101   return WrapperFunction<rt::SPSRunAsMainSignature>::handle(
102              ArgData, ArgSize,
103              [](ExecutorAddress MainAddr,
104                 std::vector<std::string> Args) -> int64_t {
105                return runAsMain(MainAddr.toPtr<int (*)(int, char *[])>(), Args);
106              })
107       .release();
108 }
109 
110 void addTo(StringMap<ExecutorAddress> &M) {
111   M[rt::MemoryReserveWrapperName] = ExecutorAddress::fromPtr(&reserveWrapper);
112   M[rt::MemoryFinalizeWrapperName] = ExecutorAddress::fromPtr(&finalizeWrapper);
113   M[rt::MemoryDeallocateWrapperName] =
114       ExecutorAddress::fromPtr(&deallocateWrapper);
115   M[rt::MemoryWriteUInt8sWrapperName] = ExecutorAddress::fromPtr(
116       &writeUIntsWrapper<tpctypes::UInt8Write,
117                          shared::SPSMemoryAccessUInt8Write>);
118   M[rt::MemoryWriteUInt16sWrapperName] = ExecutorAddress::fromPtr(
119       &writeUIntsWrapper<tpctypes::UInt16Write,
120                          shared::SPSMemoryAccessUInt16Write>);
121   M[rt::MemoryWriteUInt32sWrapperName] = ExecutorAddress::fromPtr(
122       &writeUIntsWrapper<tpctypes::UInt32Write,
123                          shared::SPSMemoryAccessUInt32Write>);
124   M[rt::MemoryWriteUInt64sWrapperName] = ExecutorAddress::fromPtr(
125       &writeUIntsWrapper<tpctypes::UInt64Write,
126                          shared::SPSMemoryAccessUInt64Write>);
127   M[rt::MemoryWriteBuffersWrapperName] =
128       ExecutorAddress::fromPtr(&writeBuffersWrapper);
129   M[rt::RunAsMainWrapperName] = ExecutorAddress::fromPtr(&runAsMainWrapper);
130 }
131 
132 } // end namespace rt_bootstrap
133 } // end namespace orc
134 } // end namespace llvm
135