1 | //===------- MemoryAccess.h - Executor memory access APIs -------*- C++ -*-===// |
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 | // Utilities for accessing memory in the executor processes. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_EXECUTIONENGINE_ORC_MEMORYACCESS_H |
14 | #define LLVM_EXECUTIONENGINE_ORC_MEMORYACCESS_H |
15 | |
16 | #include "llvm/ADT/ArrayRef.h" |
17 | #include "llvm/ADT/FunctionExtras.h" |
18 | #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h" |
19 | #include "llvm/Support/MSVCErrorWorkarounds.h" |
20 | |
21 | #include <future> |
22 | |
23 | namespace llvm::orc { |
24 | |
25 | /// APIs for manipulating memory in the target process. |
26 | class LLVM_ABI MemoryAccess { |
27 | public: |
28 | /// Callback function for asynchronous writes. |
29 | using WriteResultFn = unique_function<void(Error)>; |
30 | |
31 | template <typename T> using ReadUIntsResult = std::vector<T>; |
32 | template <typename T> |
33 | using OnReadUIntsCompleteFn = |
34 | unique_function<void(Expected<ReadUIntsResult<T>>)>; |
35 | |
36 | using ReadPointersResult = std::vector<ExecutorAddr>; |
37 | using OnReadPointersCompleteFn = |
38 | unique_function<void(Expected<ReadPointersResult>)>; |
39 | |
40 | using ReadBuffersResult = std::vector<std::vector<uint8_t>>; |
41 | using OnReadBuffersCompleteFn = |
42 | unique_function<void(Expected<ReadBuffersResult>)>; |
43 | |
44 | using ReadStringsResult = std::vector<std::string>; |
45 | using OnReadStringsCompleteFn = |
46 | unique_function<void(Expected<ReadStringsResult>)>; |
47 | |
48 | virtual ~MemoryAccess(); |
49 | |
50 | virtual void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws, |
51 | WriteResultFn OnWriteComplete) = 0; |
52 | |
53 | virtual void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws, |
54 | WriteResultFn OnWriteComplete) = 0; |
55 | |
56 | virtual void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws, |
57 | WriteResultFn OnWriteComplete) = 0; |
58 | |
59 | virtual void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws, |
60 | WriteResultFn OnWriteComplete) = 0; |
61 | |
62 | virtual void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws, |
63 | WriteResultFn OnWriteComplete) = 0; |
64 | |
65 | virtual void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws, |
66 | WriteResultFn OnWriteComplete) = 0; |
67 | |
68 | virtual void readUInt8sAsync(ArrayRef<ExecutorAddr> Rs, |
69 | OnReadUIntsCompleteFn<uint8_t> OnComplete) = 0; |
70 | |
71 | virtual void readUInt16sAsync(ArrayRef<ExecutorAddr> Rs, |
72 | OnReadUIntsCompleteFn<uint16_t> OnComplete) = 0; |
73 | |
74 | virtual void readUInt32sAsync(ArrayRef<ExecutorAddr> Rs, |
75 | OnReadUIntsCompleteFn<uint32_t> OnComplete) = 0; |
76 | |
77 | virtual void readUInt64sAsync(ArrayRef<ExecutorAddr> Rs, |
78 | OnReadUIntsCompleteFn<uint64_t> OnComplete) = 0; |
79 | |
80 | virtual void readPointersAsync(ArrayRef<ExecutorAddr> Rs, |
81 | OnReadPointersCompleteFn OnComplete) = 0; |
82 | |
83 | virtual void readBuffersAsync(ArrayRef<ExecutorAddrRange> Rs, |
84 | OnReadBuffersCompleteFn OnComplete) = 0; |
85 | |
86 | virtual void readStringsAsync(ArrayRef<ExecutorAddr> Rs, |
87 | OnReadStringsCompleteFn OnComplete) = 0; |
88 | |
89 | Error writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws) { |
90 | std::promise<MSVCPError> ResultP; |
91 | auto ResultF = ResultP.get_future(); |
92 | writeUInt8sAsync(Ws, OnWriteComplete: [&](Error Err) { ResultP.set_value(std::move(Err)); }); |
93 | return ResultF.get(); |
94 | } |
95 | |
96 | Error writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws) { |
97 | std::promise<MSVCPError> ResultP; |
98 | auto ResultF = ResultP.get_future(); |
99 | writeUInt16sAsync(Ws, |
100 | OnWriteComplete: [&](Error Err) { ResultP.set_value(std::move(Err)); }); |
101 | return ResultF.get(); |
102 | } |
103 | |
104 | Error writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws) { |
105 | std::promise<MSVCPError> ResultP; |
106 | auto ResultF = ResultP.get_future(); |
107 | writeUInt32sAsync(Ws, |
108 | OnWriteComplete: [&](Error Err) { ResultP.set_value(std::move(Err)); }); |
109 | return ResultF.get(); |
110 | } |
111 | |
112 | Error writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws) { |
113 | std::promise<MSVCPError> ResultP; |
114 | auto ResultF = ResultP.get_future(); |
115 | writeUInt64sAsync(Ws, |
116 | OnWriteComplete: [&](Error Err) { ResultP.set_value(std::move(Err)); }); |
117 | return ResultF.get(); |
118 | } |
119 | |
120 | Error writePointers(ArrayRef<tpctypes::PointerWrite> Ws) { |
121 | std::promise<MSVCPError> ResultP; |
122 | auto ResultF = ResultP.get_future(); |
123 | writePointersAsync(Ws, |
124 | OnWriteComplete: [&](Error Err) { ResultP.set_value(std::move(Err)); }); |
125 | return ResultF.get(); |
126 | } |
127 | |
128 | Error writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws) { |
129 | std::promise<MSVCPError> ResultP; |
130 | auto ResultF = ResultP.get_future(); |
131 | writeBuffersAsync(Ws, |
132 | OnWriteComplete: [&](Error Err) { ResultP.set_value(std::move(Err)); }); |
133 | return ResultF.get(); |
134 | } |
135 | |
136 | Expected<ReadUIntsResult<uint8_t>> readUInt8s(ArrayRef<ExecutorAddr> Rs) { |
137 | std::promise<MSVCPExpected<ReadUIntsResult<uint8_t>>> P; |
138 | readUInt8sAsync(Rs, OnComplete: [&](Expected<ReadUIntsResult<uint8_t>> Result) { |
139 | P.set_value(std::move(Result)); |
140 | }); |
141 | return P.get_future().get(); |
142 | } |
143 | |
144 | Expected<ReadUIntsResult<uint16_t>> readUInt16s(ArrayRef<ExecutorAddr> Rs) { |
145 | std::promise<MSVCPExpected<ReadUIntsResult<uint16_t>>> P; |
146 | readUInt16sAsync(Rs, OnComplete: [&](Expected<ReadUIntsResult<uint16_t>> Result) { |
147 | P.set_value(std::move(Result)); |
148 | }); |
149 | return P.get_future().get(); |
150 | } |
151 | |
152 | Expected<ReadUIntsResult<uint32_t>> readUInt32s(ArrayRef<ExecutorAddr> Rs) { |
153 | std::promise<MSVCPExpected<ReadUIntsResult<uint32_t>>> P; |
154 | readUInt32sAsync(Rs, OnComplete: [&](Expected<ReadUIntsResult<uint32_t>> Result) { |
155 | P.set_value(std::move(Result)); |
156 | }); |
157 | return P.get_future().get(); |
158 | } |
159 | |
160 | Expected<ReadUIntsResult<uint64_t>> readUInt64s(ArrayRef<ExecutorAddr> Rs) { |
161 | std::promise<MSVCPExpected<ReadUIntsResult<uint64_t>>> P; |
162 | readUInt64sAsync(Rs, OnComplete: [&](Expected<ReadUIntsResult<uint64_t>> Result) { |
163 | P.set_value(std::move(Result)); |
164 | }); |
165 | return P.get_future().get(); |
166 | } |
167 | |
168 | Expected<ReadPointersResult> readPointers(ArrayRef<ExecutorAddr> Rs) { |
169 | std::promise<MSVCPExpected<ReadPointersResult>> P; |
170 | readPointersAsync(Rs, OnComplete: [&](Expected<ReadPointersResult> Result) { |
171 | P.set_value(std::move(Result)); |
172 | }); |
173 | return P.get_future().get(); |
174 | } |
175 | |
176 | Expected<ReadBuffersResult> readBuffers(ArrayRef<ExecutorAddrRange> Rs) { |
177 | std::promise<MSVCPExpected<ReadBuffersResult>> P; |
178 | readBuffersAsync(Rs, OnComplete: [&](Expected<ReadBuffersResult> Result) { |
179 | P.set_value(std::move(Result)); |
180 | }); |
181 | return P.get_future().get(); |
182 | } |
183 | |
184 | Expected<ReadStringsResult> readStrings(ArrayRef<ExecutorAddr> Rs) { |
185 | std::promise<MSVCPExpected<ReadStringsResult>> P; |
186 | readStringsAsync(Rs, OnComplete: [&](Expected<ReadStringsResult> Result) { |
187 | P.set_value(std::move(Result)); |
188 | }); |
189 | return P.get_future().get(); |
190 | } |
191 | }; |
192 | |
193 | } // namespace llvm::orc |
194 | |
195 | #endif // LLVM_EXECUTIONENGINE_ORC_MEMORYACCESS_H |
196 | |