3 #if defined(SKSE_SUPPORT_XBYAK)
15 using deleter_type = std::function<void(
void* a_mem, std::size_t a_size)>;
32 if (
this != std::addressof(a_rhs)) {
33 move_from(std::move(a_rhs));
38 void create(std::size_t a_size) {
return create(a_size,
nullptr); }
39 void create(std::size_t a_size,
void* a_module);
43 auto trampoline =
static_cast<std::byte*
>(a_trampoline);
45 constexpr
auto INT3 =
static_cast<int>(0xCC);
46 std::memset(trampoline,
INT3, a_size);
51 _deleter = std::move(a_deleter);
59 [[nodiscard]]
void*
allocate(std::size_t a_size)
61 auto result = do_allocate(a_size);
66 #ifdef SKSE_SUPPORT_XBYAK
67 [[nodiscard]]
void*
allocate(Xbyak::CodeGenerator& a_code);
73 return static_cast<T*
>(
allocate(
sizeof(T)));
76 [[nodiscard]] constexpr std::size_t
empty() const noexcept {
return _capacity == 0; }
77 [[nodiscard]] constexpr std::size_t
capacity() const noexcept {
return _capacity; }
78 [[nodiscard]] constexpr std::size_t
allocated_size() const noexcept {
return _size; }
79 [[nodiscard]] constexpr std::size_t
free_size() const noexcept {
return _capacity - _size; }
81 template <std::
size_t N>
82 std::uintptr_t
write_branch(std::uintptr_t a_src, std::uintptr_t a_dst)
84 std::uint8_t data = 0;
85 if constexpr (N == 5) {
89 }
else if constexpr (N == 6) {
94 static_assert(
false && N,
"invalid branch size");
97 return write_branch<N>(a_src, a_dst, data);
100 template <std::
size_t N,
class F>
103 return write_branch<N>(a_src, stl::unrestricted_cast<std::uintptr_t>(a_dst));
106 template <std::
size_t N>
107 std::uintptr_t
write_call(std::uintptr_t a_src, std::uintptr_t a_dst)
109 std::uint8_t data = 0;
110 if constexpr (N == 5) {
114 }
else if constexpr (N == 6) {
119 static_assert(
false && N,
"invalid call size");
122 return write_branch<N>(a_src, a_dst, data);
125 template <std::
size_t N,
class F>
128 return write_call<N>(a_src, stl::unrestricted_cast<std::uintptr_t>(a_dst));
132 [[nodiscard]]
void* do_create(std::size_t a_size, std::uintptr_t a_address);
133 [[nodiscard]]
void* do_allocate(std::size_t a_size);
135 void write_5branch(std::uintptr_t a_src, std::uintptr_t a_dst, std::uint8_t a_opcode);
136 void write_6branch(std::uintptr_t a_src, std::uintptr_t a_dst, std::uint8_t a_modrm);
138 template <std::
size_t N>
139 [[nodiscard]] std::uintptr_t
write_branch(std::uintptr_t a_src, std::uintptr_t a_dst, std::uint8_t a_data)
141 const auto isNop = *
reinterpret_cast<std::int8_t*
>(a_src) == 0x90;
142 const auto disp =
reinterpret_cast<std::int32_t*
>(a_src + N - 4);
143 const auto nextOp = a_src + N;
144 const auto func = isNop ? 0 : nextOp + *disp;
146 if constexpr (N == 5) {
147 write_5branch(a_src, a_dst, a_data);
148 }
else if constexpr (N == 6) {
149 write_6branch(a_src, a_dst, a_data);
151 static_assert(
false && N,
"invalid branch size");
159 _5branches = std::move(a_rhs._5branches);
160 _6branches = std::move(a_rhs._6branches);
161 _name = std::move(a_rhs._name);
163 _deleter = std::move(a_rhs._deleter);
166 a_rhs._data =
nullptr;
168 _capacity = a_rhs._capacity;
175 void log_stats()
const;
177 [[nodiscard]]
bool in_range(std::ptrdiff_t a_disp)
const
182 return min <= a_disp && a_disp <=
max;
187 if (_data && _deleter) {
188 _deleter(_data, _capacity);
198 std::map<std::uintptr_t, std::byte*> _5branches;
199 std::map<std::uintptr_t, std::byte*> _6branches;
202 std::byte* _data{
nullptr };
203 std::size_t _capacity{ 0 };
204 std::size_t _size{ 0 };
Definition: Trampoline.h:13
std::uintptr_t write_call(std::uintptr_t a_src, std::uintptr_t a_dst)
Definition: Trampoline.h:107
constexpr std::size_t allocated_size() const noexcept
Definition: Trampoline.h:78
std::function< void(void *a_mem, std::size_t a_size)> deleter_type
Definition: Trampoline.h:15
T * allocate()
Definition: Trampoline.h:71
void * allocate(std::size_t a_size)
Definition: Trampoline.h:59
~Trampoline()
Definition: Trampoline.h:26
std::uintptr_t write_branch(std::uintptr_t a_src, std::uintptr_t a_dst)
Definition: Trampoline.h:82
Trampoline(std::string_view a_name)
Definition: Trampoline.h:22
Trampoline(const Trampoline &)=delete
void set_trampoline(void *a_trampoline, std::size_t a_size, deleter_type a_deleter={})
Definition: Trampoline.h:41
Trampoline(Trampoline &&a_rhs) noexcept
Definition: Trampoline.h:20
std::uintptr_t write_branch(std::uintptr_t a_src, F a_dst)
Definition: Trampoline.h:101
void create(std::size_t a_size)
Definition: Trampoline.h:38
Trampoline & operator=(Trampoline &&a_rhs) noexcept
Definition: Trampoline.h:30
constexpr std::size_t capacity() const noexcept
Definition: Trampoline.h:77
std::uintptr_t write_call(std::uintptr_t a_src, F a_dst)
Definition: Trampoline.h:126
constexpr std::size_t empty() const noexcept
Definition: Trampoline.h:76
constexpr std::size_t free_size() const noexcept
Definition: Trampoline.h:79
void create(std::size_t a_size, void *a_module)
Trampoline & operator=(const Trampoline &)=delete
constexpr std::uint8_t INT3
Definition: Relocation.h:172
NiColor min(const NiColor &a_lhs, const NiColor &a_rhs)
Definition: ColorUtil.h:63
NiColor max(const NiColor &a_lhs, const NiColor &a_rhs)
Definition: ColorUtil.h:71
string(const CharT(&)[N]) -> string< CharT, N - 1 >
Trampoline & GetTrampoline()