Skip to content

Commit

Permalink
feat: improve Relocation & Utilities (#302)
Browse files Browse the repository at this point in the history
changes:
* add second template arg to applicable `Relocation::write_` funcs for
address offset
* remove `AllocTrampoline` from `stl::write_*` funcs, this is bad
practice
* normalize `stl::write_*` support for structs with `std::uintptr_t`,
`REL::ID`, `REL::Offset`, `REL::Relocation<std::uintptr_t>` static
`address` members
  • Loading branch information
shad0wshayd3 authored Nov 20, 2024
1 parent ed7f15e commit 417c17a
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 24 deletions.
16 changes: 8 additions & 8 deletions include/REL/Relocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,32 +337,32 @@ namespace REL
safe_write(address(), a_data.data(), a_data.size_bytes());
}

template <std::size_t N>
template <std::size_t N, std::ptrdiff_t O = 0>
std::uintptr_t write_branch(const std::uintptr_t a_dst)
requires(std::same_as<value_type, std::uintptr_t>)
{
return SFSE::GetTrampoline().write_branch<N>(address(), a_dst);
return SFSE::GetTrampoline().write_branch<N>(address() + O, a_dst);
}

template <std::size_t N, class F>
template <std::size_t N, std::ptrdiff_t O = 0, class F>
std::uintptr_t write_branch(const F a_dst)
requires(std::same_as<value_type, std::uintptr_t>)
{
return SFSE::GetTrampoline().write_branch<N>(address(), stl::unrestricted_cast<std::uintptr_t>(a_dst));
return SFSE::GetTrampoline().write_branch<N>(address() + O, stl::unrestricted_cast<std::uintptr_t>(a_dst));
}

template <std::size_t N>
template <std::size_t N, std::ptrdiff_t O = 0>
std::uintptr_t write_call(const std::uintptr_t a_dst)
requires(std::same_as<value_type, std::uintptr_t>)
{
return SFSE::GetTrampoline().write_call<N>(address(), a_dst);
return SFSE::GetTrampoline().write_call<N>(address() + O, a_dst);
}

template <std::size_t N, class F>
template <std::size_t N, std::ptrdiff_t O = 0, class F>
std::uintptr_t write_call(const F a_dst)
requires(std::same_as<value_type, std::uintptr_t>)
{
return SFSE::GetTrampoline().write_call<N>(address(), stl::unrestricted_cast<std::uintptr_t>(a_dst));
return SFSE::GetTrampoline().write_call<N>(address() + O, stl::unrestricted_cast<std::uintptr_t>(a_dst));
}

void write_fill(const std::uint8_t a_value, const std::size_t a_count)
Expand Down
77 changes: 61 additions & 16 deletions include/SFSE/Utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,84 @@

namespace SFSE::stl
{
template <class T, std::size_t Size = 5>
template <class T, std::size_t N = 5>
constexpr void write_thunk_call(const std::uintptr_t a_address) noexcept
{
AllocTrampoline(14);
auto& trampoline = GetTrampoline();
T::func = trampoline.write_call<Size>(a_address, T::thunk);
T::func = GetTrampoline().write_call<N>(a_address, T::thunk);
}

template <class T, std::size_t Size = 5>
template <class T, std::size_t N = 5, class U>
constexpr void write_thunk_call(const U a_id) noexcept
requires(std::is_same_v<U, REL::ID> || std::is_same_v<U, REL::Offset>)
{
T::func = GetTrampoline().write_call<N>(a_id.address(), T::thunk);
}

template <class T, std::size_t N = 5, class U>
constexpr void write_thunk_call(const REL::Relocation<U> a_id) noexcept
requires(std::is_same_v<typename REL::Relocation<U>::value_type, std::uintptr_t>)
{
T::func = GetTrampoline().write_call<N>(a_id.address(), T::thunk);
}

template <class T, std::size_t N = 5>
constexpr void write_thunk_call() noexcept
{
write_thunk_call<T, Size>(T::address);
write_thunk_call<T, N>(T::address);
}

template <class T, std::size_t N = 5>
constexpr void write_thunk_jump(const std::uintptr_t a_address) noexcept
{
T::func = GetTrampoline().write_branch<N>(a_address, T::thunk);
}

template <class T, std::size_t N = 5, class U>
constexpr void write_thunk_jump(const U a_id) noexcept
requires(std::is_same_v<U, REL::ID> || std::is_same_v<U, REL::Offset>)
{
T::func = GetTrampoline().write_branch<N>(a_id.address(), T::thunk);
}

template <class T, std::size_t N = 5, class U>
constexpr void write_thunk_jump(const REL::Relocation<U> a_id) noexcept
requires(std::is_same_v<typename REL::Relocation<U>::value_type, std::uintptr_t>)
{
T::func = GetTrampoline().write_branch<N>(a_id.address(), T::thunk);
}

template <class T, std::size_t N = 5>
constexpr void write_thunk_jump() noexcept
{
write_thunk_jump<T, N>(T::address);
}

template <class T>
constexpr void write_vfunc(const REL::ID a_id) noexcept
constexpr void write_vfunc(const std::uintptr_t a_address) noexcept
{
static REL::Relocation<std::uintptr_t> vtbl{ a_id };
static REL::Relocation vtbl{ REL::Offset(a_address) };
T::func = vtbl.write_vfunc(T::idx, T::thunk);
}

template <class To, class From>
constexpr void write_vfunc(const std::size_t a_vtableIdx = 0) noexcept
template <class T, class U>
constexpr void write_vfunc(const U a_id) noexcept
requires(std::is_same_v<U, REL::ID> || std::is_same_v<U, REL::Offset>)
{
write_vfunc<From>(To::VTABLE[a_vtableIdx]);
static REL::Relocation vtbl{ a_id };
T::func = vtbl.write_vfunc(T::idx, T::thunk);
}

template <class T, std::size_t Size = 5>
constexpr void write_thunk_jump(const std::uintptr_t a_src) noexcept
template <class T, class U>
constexpr void write_vfunc(const REL::Relocation<U> a_id) noexcept
requires(std::is_same_v<typename REL::Relocation<U>::value_type, std::uintptr_t>)
{
AllocTrampoline(14);
auto& trampoline = GetTrampoline();
T::func = trampoline.write_branch<Size>(a_src, T::thunk);
T::func = a_id.write_vfunc(T::idx, T::thunk);
}

template <class To, class From>
constexpr void write_vfunc(const std::size_t a_vtableIdx = 0) noexcept
{
write_vfunc<From>(To::VTABLE[a_vtableIdx]);
}

namespace detail
Expand Down

0 comments on commit 417c17a

Please sign in to comment.