7 #define REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL(a_nopropQual, a_propQual, ...) \
12 struct member_function_pod_type<R (Cls::*)(Args...) __VA_ARGS__ a_nopropQual a_propQual> \
14 using type = R(__VA_ARGS__ Cls*, Args...) a_propQual; \
21 struct member_function_pod_type<R (Cls::*)(Args..., ...) __VA_ARGS__ a_nopropQual a_propQual> \
23 using type = R(__VA_ARGS__ Cls*, Args..., ...) a_propQual; \
26 #define REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(a_qualifer, ...) \
27 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL(a_qualifer, , ##__VA_ARGS__) \
28 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL(a_qualifer, noexcept, ##__VA_ARGS__)
30 #define REL_MAKE_MEMBER_FUNCTION_POD_TYPE(...) \
31 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(, __VA_ARGS__) \
32 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(&, ##__VA_ARGS__) \
33 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(&&, ##__VA_ARGS__)
35 #define REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL(a_nopropQual, a_propQual, ...) \
40 struct member_function_non_pod_type<R (Cls::*)(Args...) __VA_ARGS__ a_nopropQual a_propQual> \
42 using type = R&(__VA_ARGS__ Cls*, void*, Args...)a_propQual; \
49 struct member_function_non_pod_type<R (Cls::*)(Args..., ...) __VA_ARGS__ a_nopropQual a_propQual> \
51 using type = R&(__VA_ARGS__ Cls*, void*, Args..., ...)a_propQual; \
54 #define REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(a_qualifer, ...) \
55 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL(a_qualifer, , ##__VA_ARGS__) \
56 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL(a_qualifer, noexcept, ##__VA_ARGS__)
58 #define REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE(...) \
59 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(, __VA_ARGS__) \
60 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(&, ##__VA_ARGS__) \
61 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(&&, ##__VA_ARGS__)
94 std::bool_constant<sizeof(T) == 1>,
95 std::bool_constant<sizeof(T) == 2>,
96 std::bool_constant<sizeof(T) == 4>,
97 std::bool_constant<sizeof(T) == 8>>
103 std::is_trivially_constructible<T>,
104 std::is_trivially_destructible<T>,
105 std::is_trivially_copy_assignable<T>,
107 std::is_polymorphic<T>>>
112 std::is_standard_layout<T>
115 template <
class T,
class =
void>
124 std::is_union_v<T>>> :
132 std::is_class_v<T>>> :
135 meets_function_req<T>,
147 noexcept(
std::is_nothrow_invocable_v<F, First, Rest...>)
149 using result_t = std::invoke_result_t<F, First, Rest...>;
150 std::aligned_storage_t<
sizeof(result_t),
alignof(result_t)> result;
153 auto func = stl::unrestricted_cast<func_t*>(std::forward<F>(a_func));
155 return func(std::forward<First>(a_first), std::addressof(result), std::forward<Rest>(a_rest)...);
159 inline constexpr std::uint8_t
NOP = 0x90;
160 inline constexpr std::uint8_t
NOP2[] = { 0x66, 0x90 };
161 inline constexpr std::uint8_t
NOP3[] = { 0x0F, 0x1F, 0x00 };
162 inline constexpr std::uint8_t
NOP4[] = { 0x0F, 0x1F, 0x40, 0x00 };
163 inline constexpr std::uint8_t
NOP5[] = { 0x0F, 0x1F, 0x44, 0x00, 0x00 };
164 inline constexpr std::uint8_t
NOP6[] = { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 };
165 inline constexpr std::uint8_t
NOP7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 };
166 inline constexpr std::uint8_t
NOP8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
167 inline constexpr std::uint8_t
NOP9[] = { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
169 inline constexpr std::uint8_t
JMP8 = 0xEB;
170 inline constexpr std::uint8_t
JMP32 = 0xE9;
171 inline constexpr std::uint8_t
RET = 0xC3;
172 inline constexpr std::uint8_t
INT3 = 0xCC;
174 template <
class F,
class... Args>
175 std::invoke_result_t<F, Args...>
invoke(F&& a_func, Args&&... a_args)
176 noexcept(std::is_nothrow_invocable_v<F, Args...>)
177 requires(std::invocable<F, Args...>)
179 if constexpr (std::is_member_function_pointer_v<std::decay_t<F>>) {
182 auto func = stl::unrestricted_cast<func_t*>(std::forward<F>(a_func));
183 return func(std::forward<Args>(a_args)...);
188 return std::forward<F>(a_func)(std::forward<Args>(a_args)...);
192 void safe_write(std::uintptr_t a_dst,
const void* a_src, std::size_t a_count);
194 template <std::
integral T>
197 safe_write(a_dst, std::addressof(a_data),
sizeof(T));
203 safe_write(a_dst, a_data.data(), a_data.size_bytes());
206 void safe_fill(std::uintptr_t a_dst, std::uint8_t a_value, std::size_t a_count);
208 template <
class T = std::u
intptr_t>
214 std::is_member_pointer_v<T> || std::is_function_v<std::remove_pointer_t<T>>,
233 _impl{ a_id.
address() + a_offset }
254 template <
class U = value_type>
255 [[nodiscard]] decltype(
auto) operator*() const noexcept
261 template <
class U = value_type>
268 template <
class... Args>
270 noexcept(std::is_nothrow_invocable_v<const value_type&, Args...>)
requires(std::invocable<const value_type&, Args...>)
275 [[nodiscard]] constexpr std::uintptr_t
address() const noexcept {
return _impl; }
276 [[nodiscard]] std::size_t
offset()
const {
return _impl - base(); }
282 return stl::unrestricted_cast<value_type>(_impl);
285 template <std::ptrdiff_t O = 0>
286 void replace_func(
const std::size_t a_count,
const std::uintptr_t a_dst)
requires(std::same_as<value_type, std::uintptr_t>)
288 #pragma pack(push, 1)
296 static_assert(
sizeof(Assembly) == 0xE);
300 .jmp =
static_cast<std::uint8_t
>(0xFF),
301 .modrm =
static_cast<std::uint8_t
>(0x25),
302 .disp =
static_cast<std::int32_t
>(0),
303 .addr =
static_cast<std::uint64_t
>(a_dst),
310 template <std::ptrdiff_t O = 0,
class F>
313 replace_func<O>(a_count, stl::unrestricted_cast<std::uintptr_t>(a_dst));
316 template <std::
integral U>
317 void write(
const U& a_data)
requires(std::same_as<value_type, std::uintptr_t>)
323 void write(
const std::span<U> a_data)
requires(std::same_as<value_type, std::uintptr_t>)
328 template <std::
size_t N>
334 template <std::
size_t N,
class F>
340 template <std::
size_t N>
341 std::uintptr_t
write_call(
const std::uintptr_t a_dst)
requires(std::same_as<value_type, std::uintptr_t>)
346 template <std::
size_t N,
class F>
352 void write_fill(
const std::uint8_t a_value,
const std::size_t a_count)
requires(std::same_as<value_type, std::uintptr_t>)
357 template <
class U = value_type>
358 std::uintptr_t
write_vfunc(
const std::size_t a_idx,
const std::uintptr_t a_newFunc)
requires(std::same_as<U, std::uintptr_t>)
360 const auto addr =
address() + (
sizeof(
void*) * a_idx);
361 const auto result = *
reinterpret_cast<std::uintptr_t*
>(addr);
367 std::uintptr_t
write_vfunc(
const std::size_t a_idx,
const F a_newFunc)
requires(std::same_as<value_type, std::uintptr_t>)
369 return write_vfunc(a_idx, stl::unrestricted_cast<std::uintptr_t>(a_newFunc));
374 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
377 std::uintptr_t _impl{ 0 };
381 #undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE
382 #undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER
383 #undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL
385 #undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE
386 #undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER
387 #undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL
std::uintptr_t address() const
Definition: ID.h:365
static Module & get()
Definition: Module.h:54
std::uintptr_t base() const noexcept
Definition: Module.h:60
std::uintptr_t address() const
Definition: Offset.h:22
Definition: Relocation.h:210
void write(const std::span< U > a_data) requires(std
Definition: Relocation.h:323
constexpr std::uintptr_t address() const noexcept
Definition: Relocation.h:275
std::uintptr_t write_branch(const F a_dst) requires(std
Definition: Relocation.h:335
auto operator->() const noexcept requires(std
Definition: Relocation.h:262
std::uintptr_t write_call(const F a_dst) requires(std
Definition: Relocation.h:347
std::conditional_t< std::is_member_pointer_v< T >||std::is_function_v< std::remove_pointer_t< T > >, std::decay_t< T >, T > value_type
Definition: Relocation.h:216
constexpr Relocation & operator=(std::uintptr_t a_address) noexcept
Definition: Relocation.h:236
std::invoke_result_t< const value_type &, Args... > operator()(Args &&... a_args) const noexcept(std::is_nothrow_invocable_v< const value_type &, Args... >) requires(std
Definition: Relocation.h:269
std::uintptr_t write_vfunc(const std::size_t a_idx, const std::uintptr_t a_newFunc) requires(std
Definition: Relocation.h:358
std::uintptr_t write_branch(const std::uintptr_t a_dst) requires(std
Definition: Relocation.h:329
std::uintptr_t write_call(const std::uintptr_t a_dst) requires(std
Definition: Relocation.h:341
value_type get() const noexcept(std::is_nothrow_copy_constructible_v< value_type >)
Definition: Relocation.h:278
Relocation(Offset a_offset)
Definition: Relocation.h:224
Relocation(ID a_id, std::ptrdiff_t a_offset)
Definition: Relocation.h:232
Relocation & operator=(Offset a_offset)
Definition: Relocation.h:242
void write_fill(const std::uint8_t a_value, const std::size_t a_count) requires(std
Definition: Relocation.h:352
constexpr Relocation() noexcept=default
void write(const U &a_data) requires(std
Definition: Relocation.h:317
Relocation(ID a_id)
Definition: Relocation.h:228
void replace_func(const std::size_t a_count, const F a_dst) requires(std
Definition: Relocation.h:311
void replace_func(const std::size_t a_count, const std::uintptr_t a_dst) requires(std
Definition: Relocation.h:286
Relocation & operator=(ID a_id)
Definition: Relocation.h:248
std::uintptr_t write_vfunc(const std::size_t a_idx, const F a_newFunc) requires(std
Definition: Relocation.h:367
std::size_t offset() const
Definition: Relocation.h:276
std::uintptr_t write_call(std::uintptr_t a_src, std::uintptr_t a_dst)
Definition: Trampoline.h:107
std::uintptr_t write_branch(std::uintptr_t a_src, std::uintptr_t a_dst)
Definition: Trampoline.h:82
typename member_function_non_pod_type< F >::type member_function_non_pod_type_t
Definition: Relocation.h:87
decltype(auto) invoke_member_function_non_pod(F &&a_func, First &&a_first, Rest &&... a_rest) noexcept(std::is_nothrow_invocable_v< F, First, Rest... >)
Definition: Relocation.h:146
typename member_function_pod_type< F >::type member_function_pod_type_t
Definition: Relocation.h:76
constexpr bool is_x64_pod_v
Definition: Relocation.h:140
REL_MAKE_MEMBER_FUNCTION_POD_TYPE()
REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE()
constexpr std::uint8_t NOP6[]
Definition: Relocation.h:164
constexpr std::uint8_t JMP8
Definition: Relocation.h:169
constexpr std::uint8_t NOP
Definition: Relocation.h:159
constexpr std::uint8_t NOP4[]
Definition: Relocation.h:162
constexpr std::uint8_t INT3
Definition: Relocation.h:172
constexpr std::uint8_t NOP8[]
Definition: Relocation.h:166
constexpr std::uint8_t NOP2[]
Definition: Relocation.h:160
void safe_fill(std::uintptr_t a_dst, std::uint8_t a_value, std::size_t a_count)
void safe_write(std::uintptr_t a_dst, const void *a_src, std::size_t a_count)
constexpr std::uint8_t NOP5[]
Definition: Relocation.h:163
constexpr std::uint8_t NOP3[]
Definition: Relocation.h:161
constexpr std::uint8_t NOP9[]
Definition: Relocation.h:167
std::invoke_result_t< F, Args... > invoke(F &&a_func, Args &&... a_args) noexcept(std::is_nothrow_invocable_v< F, Args... >) requires(std
Definition: Relocation.h:175
constexpr std::uint8_t RET
Definition: Relocation.h:171
constexpr std::uint8_t JMP32
Definition: Relocation.h:170
constexpr std::uint8_t NOP7[]
Definition: Relocation.h:165
requires(std::invocable< std::remove_reference_t< EF >>) class scope_exit
Definition: PCH.h:153
Trampoline & GetTrampoline()
Definition: EffectArchetypes.h:65
Definition: Relocation.h:118
Definition: Relocation.h:108
Definition: Relocation.h:98
Definition: Relocation.h:113
Definition: Relocation.h:79
Definition: Relocation.h:68