ReXGlue SDK
Loading...
Searching...
No Matches
memory_view.h
Go to the documentation of this file.
1
10
11#pragma once
12
13#include <cstddef>
14#include <cstring>
15#include <optional>
16#include <string_view>
17#include <type_traits>
18
19#include <rex/kernel/heap.h>
20#include <rex/types.h>
21#include <rex/assert.h>
22#include <rex/kernel/thread_state.h>
23
24namespace rex::kernel {
25
26namespace detail {
27
29template <typename T>
30concept GuestScalar = std::is_arithmetic_v<T> && !std::is_same_v<T, bool>;
31
32} // namespace detail
33
38class MemoryView {
39 public:
40 explicit MemoryView(const GuestAddressSpace& memory)
41 : memory_(&memory), membase_(memory.GetMembase()) {}
42
43 u8* GetVirtualMembase() const { return membase_.GetBase(); }
44
45 template <typename T = u8*>
46 T TranslateVirtual(u32 address) const {
47 return membase_.TranslateVirtual<T>(address);
48 }
49
58 template <typename T = u8*>
59 T TryTranslateVirtual(u32 address, u32 required = kMemoryProtectRead) const {
60 return memory_->TryTranslateVirtual<T>(address, required);
61 }
62
66 u32 HostToGuestVirtual(const void* host_address) const {
67 return membase_.HostToGuestVirtual(host_address);
68 }
69
76 template <typename T>
77 requires(detail::GuestScalar<T>)
78 T Load(u32 address) const {
79 BE<T> raw;
80 std::memcpy(&raw, TranslateVirtual<const u8*>(address), sizeof(raw));
81 return raw.Get();
82 }
83
90 template <typename T>
91 requires(detail::GuestScalar<T>)
92 void Store(u32 address, T value) const {
93 const BE<T> raw(value);
94 std::memcpy(TranslateVirtual<u8*>(address), &raw, sizeof(raw));
95 }
96
104 template <typename T>
105 requires(detail::GuestScalar<T>)
106 std::optional<T> TryLoad(u32 address) const {
107 if (!IsAccessible(address, sizeof(T), kMemoryProtectRead)) {
108 return std::nullopt;
109 }
110 return Load<T>(address);
111 }
112
122 template <typename T>
123 requires(detail::GuestScalar<T>)
124 bool TryStore(u32 address, T value) const {
125 if (!IsAccessible(address, sizeof(T), kMemoryProtectRead | kMemoryProtectWrite)) {
126 return false;
127 }
128 Store<T>(address, value);
129 return true;
130 }
131
138 std::string_view GetCString(u32 address) const {
139 if (address == 0) {
140 return {};
141 }
142 return std::string_view(TranslateVirtual<const char*>(address));
143 }
144
152 std::optional<std::string_view> TryGetCString(u32 address,
153 size_t max_length = std::string_view::npos) const {
154 const char* start = memory_->TryTranslateVirtual<const char*>(address);
155 if (start == nullptr) {
156 return std::nullopt;
157 }
158 constexpr u64 kBlock = 0x1000;
159 size_t length = 0;
160 while (length < max_length) {
161 const u64 current = static_cast<u64>(address) + length;
162 if (current > 0xFFFFFFFFull) {
163 break;
164 }
165 if (length != 0 && current % kBlock == 0 &&
166 memory_->TryTranslateVirtual<const char*>(static_cast<u32>(current)) != start + length) {
167 break;
168 }
169 const size_t block = static_cast<size_t>(kBlock - current % kBlock);
170 const size_t count = max_length - length < block ? max_length - length : block;
171 if (const void* end = std::memchr(start + length, '\0', count)) {
172 length = static_cast<size_t>(static_cast<const char*>(end) - start);
173 break;
174 }
175 length += count;
176 }
177 return std::string_view(start, length);
178 }
179
180 private:
181 bool IsAccessible(u32 address, u32 size, u32 required) const {
182 const u32 last = address + (size - 1);
183 return last >= address && memory_->TryTranslateVirtual<const u8*>(address, required) &&
184 memory_->TryTranslateVirtual<const u8*>(last, required);
185 }
186
187 const GuestAddressSpace* memory_;
189};
190
191} // namespace rex::kernel
192
193namespace rex::kernel {
194
200template <typename T, u32 Address>
202 static_assert(Address != 0, "A guest global needs a nonzero address");
203 static_assert(Address % alignof(T) == 0, "A guest global address must be aligned for its type");
204 static_assert(std::is_trivially_copyable_v<T>, "A guest global holds a trivially copyable type");
205
206 static constexpr u32 GetAddress() { return Address; }
207
209 T* GetHost() const {
210 auto* thread_state = rex::kernel::ThreadState::Get();
211 REX_ASSERT(thread_state != nullptr);
212 return rex::memory::GuestPtr<T*>(thread_state->GetAddressSpace()->GetVirtualMembase(), Address);
213 }
214
216 T* GetHost(const rex::kernel::MemoryView& view) const {
217 return view.TranslateVirtual<T*>(Address);
218 }
219
226 T* TryGetHost() const {
227 auto* thread_state = rex::kernel::ThreadState::Get();
228 if (thread_state == nullptr || thread_state->GetAddressSpace() == nullptr) {
229 return nullptr;
230 }
231 return thread_state->GetAddressSpace()->TryTranslateVirtual<T*>(Address);
232 }
233
239 T* TryGetHost(const rex::kernel::MemoryView& view) const {
240 return view.TryTranslateVirtual<T*>(Address);
241 }
242
243 T* operator->() const { return GetHost(); }
244
245 T& operator*() const { return *GetHost(); }
246};
247
248} // namespace rex::kernel
249
261#define REX_GUEST_GLOBAL(type, name, address) \
262 inline constexpr rex::kernel::GuestGlobal<type, address> name {}
#define REX_ASSERT(cond,...)
Definition assert.h:84
Definition heap.h:594
T TryTranslateVirtual(u32 guest_address, u32 required=kMemoryProtectRead) const
Definition heap.h:637
Definition memory_view.h:38
std::optional< T > TryLoad(u32 address) const
Definition memory_view.h:106
std::string_view GetCString(u32 address) const
Definition memory_view.h:138
bool TryStore(u32 address, T value) const
Definition memory_view.h:124
void Store(u32 address, T value) const
Definition memory_view.h:92
u32 HostToGuestVirtual(const void *host_address) const
Definition memory_view.h:66
T Load(u32 address) const
Definition memory_view.h:78
std::optional< std::string_view > TryGetCString(u32 address, size_t max_length=std::string_view::npos) const
Definition memory_view.h:152
T TryTranslateVirtual(u32 address, u32 required=kMemoryProtectRead) const
Definition memory_view.h:59
static ThreadState * Get()
Definition mapped_ptr.h:412
Definition export.h:24
Definition endian.h:27
T GuestPtr(u8 *base, u32 guest_address) noexcept
Definition mapped_ptr.h:393
T Get() const
Definition types.h:93
Definition memory_view.h:201
T * GetHost() const
Definition memory_view.h:209
T * TryGetHost(const rex::kernel::MemoryView &view) const
Definition memory_view.h:239
T * GetHost(const rex::kernel::MemoryView &view) const
Definition memory_view.h:216
T * TryGetHost() const
Definition memory_view.h:226
Integer types, byte order wrappers and size literals.