mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-29 15:49:10 -04:00
Merge remote-tracking branch 'origin/main' into 26-07-25-audio-replacements
# Conflicts: # CMakeLists.txt
This commit is contained in:
+24
-1
@@ -148,6 +148,7 @@ typedef enum ModMetaKind {
|
||||
MOD_META_HOOK_FN = 4,
|
||||
MOD_META_HOOK_MEM = 5,
|
||||
MOD_META_HOOK_NAME = 6,
|
||||
MOD_META_HOOK_MEM_EXT = 7,
|
||||
} ModMetaKind;
|
||||
|
||||
typedef struct ModMetaRecord {
|
||||
@@ -203,15 +204,37 @@ static_assert(sizeof(ModMetaHookFn) == 24);
|
||||
* NUL-terminated strings follow `resolved`: the class vtable symbol (empty if the class name is not
|
||||
* representable), then the stringified target for tooling display.
|
||||
*/
|
||||
#define MOD_META_HOOK_MEM_CAPACITY 16u
|
||||
typedef struct MOD_META_ALIGN ModMetaHookMem {
|
||||
ModMetaRecord rec;
|
||||
uint32_t reserved;
|
||||
unsigned char pmf[16];
|
||||
unsigned char pmf[MOD_META_HOOK_MEM_CAPACITY];
|
||||
void* resolved; /* runtime only */
|
||||
} ModMetaHookMem;
|
||||
|
||||
static_assert(sizeof(ModMetaHookMem) == 32);
|
||||
|
||||
/*
|
||||
* Extended member-function hook record. The Microsoft x64 ABI uses a 24-byte member pointer for
|
||||
* classes whose inheritance model was fixed while the class was incomplete. Keep this a distinct
|
||||
* record kind so loaders can continue to consume MOD_META_HOOK_MEM's original 16-byte layout.
|
||||
*
|
||||
* MSVC cannot constant-initialize that member pointer, so materialize points to a compiler-
|
||||
* generated helper that writes its native representation to a caller-provided buffer. The record
|
||||
* itself, including its trailing names and the helper relocation, remains constant-initialized and
|
||||
* available to static tooling. pmf_size is the number of bytes the helper writes.
|
||||
*/
|
||||
#define MOD_META_HOOK_MEM_EXT_CAPACITY 24u
|
||||
typedef void (*ModMetaHookMemMaterializeFn)(unsigned char* out_pmf);
|
||||
typedef struct MOD_META_ALIGN ModMetaHookMemExt {
|
||||
ModMetaRecord rec;
|
||||
uint32_t pmf_size;
|
||||
ModMetaHookMemMaterializeFn materialize;
|
||||
void* resolved; /* runtime only */
|
||||
} ModMetaHookMemExt;
|
||||
|
||||
static_assert(sizeof(ModMetaHookMemExt) == 24);
|
||||
|
||||
/*
|
||||
* Hook on a function by symbol name, for targets that cannot be named in C++ (file-local statics,
|
||||
* private members). One NUL-terminated string follows `resolved`; it may be either the platform
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@@ -185,12 +186,21 @@ struct HookMemRecord {
|
||||
uint32_t reserved;
|
||||
union {
|
||||
F fn;
|
||||
unsigned char raw[16];
|
||||
unsigned char raw[MOD_META_HOOK_MEM_CAPACITY];
|
||||
} pmf;
|
||||
void* resolved;
|
||||
char names[N];
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
struct HookMemExtRecord {
|
||||
ModMetaRecord rec;
|
||||
uint32_t pmfSize;
|
||||
ModMetaHookMemMaterializeFn materialize;
|
||||
void* resolved;
|
||||
char names[N];
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
struct HookNameRecord {
|
||||
ModMetaRecord rec;
|
||||
@@ -232,19 +242,43 @@ consteval auto make_hook_mem_names() {
|
||||
}
|
||||
|
||||
/*
|
||||
* MSVC constant-evaluates a pointer-to-member only when every other operand in the
|
||||
* initializer is a literal: no consteval calls, constexpr-object copies, or default
|
||||
* member initializers.
|
||||
* MSVC constant-evaluates a compact pointer-to-member only when every other operand in the
|
||||
* initializer is a literal: no consteval calls, constexpr-object copies, or default member
|
||||
* initializers. It cannot constant-initialize the 24-byte general representation at all, so the
|
||||
* extended record points at a compiler-generated materializer while keeping the metadata itself
|
||||
* constant-initialized for static tooling.
|
||||
*/
|
||||
template <auto Target, bool Extended, char... Cs>
|
||||
struct HookMemHolderImpl;
|
||||
|
||||
template <auto Target, char... Cs>
|
||||
struct HookMemHolder {
|
||||
struct HookMemHolderImpl<Target, false, Cs...> {
|
||||
using F = decltype(Target);
|
||||
static_assert(sizeof(F) <= 16, "unsupported pointer-to-member representation");
|
||||
MOD_META_RECORD static constinit inline HookMemRecord<F, sizeof...(Cs)> record = {
|
||||
{sizeof(HookMemRecord<F, sizeof...(Cs)>), MOD_META_HOOK_MEM, 0}, 0, {Target}, nullptr,
|
||||
{Cs...}};
|
||||
};
|
||||
|
||||
template <auto Target, char... Cs>
|
||||
struct HookMemHolderImpl<Target, true, Cs...> {
|
||||
using F = decltype(Target);
|
||||
static void materialize(unsigned char* outPmf) {
|
||||
const F target = Target;
|
||||
std::memcpy(outPmf, &target, sizeof(target));
|
||||
}
|
||||
MOD_META_RECORD static constinit inline HookMemExtRecord<sizeof...(Cs)> record = {
|
||||
{sizeof(HookMemExtRecord<sizeof...(Cs)>), MOD_META_HOOK_MEM_EXT, 0}, sizeof(F), materialize,
|
||||
nullptr, {Cs...}};
|
||||
};
|
||||
|
||||
template <auto Target, char... Cs>
|
||||
struct HookMemHolder
|
||||
: HookMemHolderImpl<Target, (sizeof(decltype(Target)) > MOD_META_HOOK_MEM_CAPACITY), Cs...> {
|
||||
using F = decltype(Target);
|
||||
static_assert(sizeof(F) <= MOD_META_HOOK_MEM_EXT_CAPACITY,
|
||||
"unsupported pointer-to-member representation");
|
||||
};
|
||||
|
||||
template <auto Target>
|
||||
struct HookFnHolder {
|
||||
using F = decltype(Target);
|
||||
|
||||
Reference in New Issue
Block a user