LeviLamina
Loading...
Searching...
No Matches
Memory.h
1#pragma once
2
3#include <functional>
4#include <memory>
5#include <optional>
6#include <span>
7#include <string>
8#include <type_traits>
9#include <vector>
10
11#include "ll/api/base/FixedString.h"
12#include "ll/api/base/Macro.h"
13#include "ll/api/base/StdInt.h"
14#include "ll/api/memory/Signature.h"
15#include "ll/api/memory/Symbol.h"
16#include "mc/platform/brstd/function_ref.h"
17
18namespace Bedrock::Memory {
20}
21
22namespace ll::memory {
23
24using FuncPtr = void*;
25
26template <class T>
27 requires(sizeof(T) == sizeof(FuncPtr))
28constexpr FuncPtr toFuncPtr(T t) {
29 union {
30 FuncPtr fp;
31 T t;
32 } u{};
33 u.t = t;
34 return u.fp;
35}
36
37template <class T>
38 requires(std::is_member_function_pointer_v<T> && sizeof(T) == sizeof(FuncPtr) + sizeof(ptrdiff_t))
39constexpr FuncPtr toFuncPtr(T t) {
40 union {
41 struct {
42 FuncPtr fp;
43 ptrdiff_t offset;
44 };
45 T t;
46 } u{};
47 u.t = t;
48 return u.fp;
49}
50
55LLNDAPI std::optional<uint> getVtableIndex(FuncPtr virtualFunction) noexcept;
56
57template <class T>
58 requires std::is_member_function_pointer_v<T>
59[[nodiscard]] inline std::optional<uint> getVtableIndex(T t) noexcept {
60#if defined(_WIN32) && defined(_MSC_VER) && defined(__clang__) && defined(_M_X64)
61 if constexpr (sizeof(T) == sizeof(FuncPtr)) {
62 return getVtableIndex(toFuncPtr(t));
63 }
64#endif
65 return std::nullopt;
66}
67
68template <class T>
69inline void memcpy_t(void* dst, void const* src, size_t count) {
70 memcpy(dst, src, count * sizeof(T));
71}
72
73template <class T>
74inline void memcpy_t(void* dst, void const* src) {
75 memcpy(dst, src, sizeof(T));
76}
84LLAPI void modify(void* ptr, size_t len, brstd::function_ref<void()> callback);
85
86template <class T>
87inline void modify(T& ref, brstd::function_ref<void(std::remove_cv_t<T>&)> f) {
88 modify((void*)std::addressof(ref), sizeof(T), [&] { f((std::remove_cv_t<T>&)(ref)); });
89}
90
91template <class R = void, class... Args>
92constexpr auto addressCall(void const* address, auto&&... args) -> R {
93 return ((R (*)(Args...))address)(std::forward<decltype(args)>(args)...);
94}
95
96template <class R = void, class... Args>
97constexpr auto virtualCall(void const* self, ptrdiff_t vIndex, auto&&... args) -> R {
98 return (*(R(**)(void const*, Args...))(*(uintptr_t**)self + vIndex))(self, std::forward<decltype(args)>(args)...);
99}
100
101template <class T>
102[[nodiscard]] constexpr T& dAccess(void* ptr, ptrdiff_t off) {
103 return *(T*)((uintptr_t)((uintptr_t)ptr + off));
104}
105
106template <class T>
107[[nodiscard]] constexpr T const& dAccess(void const* ptr, ptrdiff_t off) {
108 return *(T*)((uintptr_t)((uintptr_t)ptr + off));
109}
110
111template <class T>
112constexpr void destruct(void* ptr, ptrdiff_t off) noexcept {
113 std::destroy_at(std::launder(reinterpret_cast<T*>((uintptr_t)((uintptr_t)ptr + off))));
114}
115
116template <class T, class... Args>
117constexpr auto construct(void* ptr, ptrdiff_t off, Args&&... args) {
118 return std::construct_at(
119 std::launder(reinterpret_cast<T*>((uintptr_t)((uintptr_t)ptr + off))),
120 std::forward<Args>(args)...
121 );
122}
123
124LLNDAPI ::Bedrock::Memory::IMemoryAllocator& getDefaultAllocator();
125
126[[noreturn]] LLAPI void throwMemoryException(size_t);
127
128LLNDAPI size_t getUsableSize(void* ptr);
129
130template <class T, class D>
131[[nodiscard]] inline size_t getUsableSize(std::unique_ptr<T, D>& ptr) {
132 if (!ptr) {
133 return 0;
134 }
135 return getUsableSize(ptr.get());
136}
137
138#ifdef _MSC_VER
139template <template <class> class P, class T>
140[[nodiscard]] inline size_t getUsableSize(P<T>& ptr)
141 requires(std::derived_from<P<T>, std::_Ptr_base<T>>)
142{
143 auto& refc = dAccess<std::_Ref_count_base*>(std::addressof(ptr), 8);
144 if (!refc) {
145 return 0;
146 }
147 auto& rawptr = dAccess<T*>(std::addressof(ptr), 0);
148 if (!rawptr) {
149 return 0;
150 }
151 if constexpr (!std::is_array_v<T>) {
152 if (rawptr == dAccess<T*>(refc, 8 + 4 * 2)) {
153 return getUsableSize(rawptr);
154 }
155 }
156 // clang-format off
157 return getUsableSize(refc // ptr* 8, rep* 8
158 ) - ( // rep:
159 8 + // vtable
160 4 * 2 + // uses & weaks
161 (std::is_array_v<T> ? 8 : 0)// size
162 /**/ // storage
163 );
164 // clang-format on
165}
166#endif
167
168class DualMapping {
169 void* rw{};
170 void* rx{};
171 size_t memSize{};
172
173public:
174 LLAPI void alloc(size_t size);
175 LLAPI void free();
176
177 DualMapping() = default;
178
179 DualMapping(size_t size) { alloc(size); }
180
181 ~DualMapping() { free(); }
182
183 size_t size() const { return memSize; }
184
185 void* writable() const { return rw; }
186 void* executable() const { return rx; }
187};
188} // namespace ll::memory
Definition IMemoryAllocator.h:7