Add x64 Windows support to DHooks (#2154)

* Add x64 Windows support

* undo changes of hook.cpp

* undo changes of hook.h

* undo changes of extension.cpp

* undo changes of listeners.cpp

* undo changes of signatures.cpp

* fix dhooks on x86

* Fix-up dhooks buildscript

---------

Co-authored-by: Kenzzer <kenzzer@users.noreply.github.com>
This commit is contained in:
Benoist 2024-09-11 01:26:30 +02:00 committed by GitHub
parent 4e6d66b721
commit 4e15a92984
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 283 additions and 100 deletions

View File

@ -4,8 +4,11 @@ import os
for cxx in builder.targets:
binary = SM.ExtLibrary(builder, cxx, 'dhooks.ext')
# Only x86 on Linux and Windows is supported.
if binary.compiler.target.platform == 'mac' or binary.compiler.target.arch != 'x86':
# mac isn't supported
if binary.compiler.target.platform == 'mac':
continue
# Presently only x86_64 on Windows is supported
if binary.compiler.target.arch == 'x86_64' and binary.compiler.target.platform != 'windows':
continue
binary.compiler.defines += [
@ -21,10 +24,8 @@ for cxx in builder.targets:
os.path.join(SM.mms_root, 'core', 'sourcehook'),
os.path.join(builder.sourcePath, 'extensions', 'dhooks'),
os.path.join(builder.sourcePath, 'public', 'jit'),
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
os.path.join(builder.sourcePath, 'sourcepawn', 'vm'),
os.path.join(builder.sourcePath, 'sourcepawn', 'vm', 'x86'),
os.path.join(builder.sourcePath, 'extensions', 'dhooks', 'DynamicHooks'),
]
@ -48,14 +49,20 @@ for cxx in builder.targets:
'libudis86/syn-intel.c',
'libudis86/syn.c',
'libudis86/udis86.c',
'../../sourcepawn/vm/x86/assembler-x86.cpp',
# Dynamic Hooks
os.path.join('DynamicHooks', 'registers.cpp')
]
if binary.compiler.target.arch == 'x86':
binary.sources += ['../../sourcepawn/vm/x86/assembler-x86.cpp']
binary.compiler.cxxincludes += [
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
os.path.join(builder.sourcePath, 'sourcepawn', 'vm', 'x86')
]
# DynamicHooks
binary.sources += [
os.path.join('DynamicHooks', 'hook.cpp'),
os.path.join('DynamicHooks', 'manager.cpp'),
os.path.join('DynamicHooks', 'registers.cpp'),
os.path.join('DynamicHooks', 'conventions', 'x86MsCdecl.cpp'),
os.path.join('DynamicHooks', 'conventions', 'x86MsStdcall.cpp'),
os.path.join('DynamicHooks', 'conventions', 'x86MsFastcall.cpp'),
@ -66,4 +73,10 @@ for cxx in builder.targets:
else:
binary.sources += [os.path.join('DynamicHooks', 'conventions', 'x86GccThiscall.cpp')]
# Dynamic detour is only supported on x86
binary.compiler.defines += ['DHOOKS_DYNAMIC_DETOUR']
elif binary.compiler.target.arch == 'x86_64':
binary.compiler.defines += ['PLATFORM_X64']
SM.extensions += [builder.Add(binary)]

View File

@ -111,7 +111,7 @@ The data type you would like to get the size of.
@param <alignment>:
The alignment that should be used.
*/
inline int GetDataTypeSize(DataTypeSized_t type, int iAlignment=4)
inline size_t GetDataTypeSize(DataTypeSized_t type, int iAlignment=4)
{
switch(type.type)
{
@ -257,9 +257,9 @@ public:
int size = GetArgStackSize() + GetArgRegisterSize();
std::unique_ptr<uint8_t[]> pSavedCallArguments = std::make_unique<uint8_t[]>(size);
size_t offset = 0;
for (size_t i = 0; i < m_vecArgTypes.size(); i++) {
for (unsigned int i = 0; i < m_vecArgTypes.size(); i++) {
DataTypeSized_t &type = m_vecArgTypes[i];
memcpy((void *)((unsigned long)pSavedCallArguments.get() + offset), GetArgumentPtr(i, pRegisters), type.size);
memcpy((void *)((uintptr_t)pSavedCallArguments.get() + offset), GetArgumentPtr(i, pRegisters), type.size);
offset += type.size;
}
m_pSavedCallArguments.push_back(std::move(pSavedCallArguments));
@ -271,7 +271,7 @@ public:
size_t offset = 0;
for (size_t i = 0; i < m_vecArgTypes.size(); i++) {
DataTypeSized_t &type = m_vecArgTypes[i];
memcpy(GetArgumentPtr(i, pRegisters), (void *)((unsigned long)pSavedCallArguments + offset), type.size);
memcpy(GetArgumentPtr((unsigned int)i, pRegisters), (void *)((uintptr_t)pSavedCallArguments + offset), type.size);
offset += type.size;
}
m_pSavedCallArguments.pop_back();

View File

@ -116,7 +116,7 @@ CRegisters::CRegisters(std::vector<Register_t> registers)
// >> 64-bit General purpose registers
// ========================================================================
// 64-bit mode only
/*
#ifdef PLATFORM_X64
m_rax = CreateRegister(registers, RAX, 8);
m_rcx = CreateRegister(registers, RCX, 8);
m_rdx = CreateRegister(registers, RDX, 8);
@ -125,10 +125,7 @@ CRegisters::CRegisters(std::vector<Register_t> registers)
m_rbp = CreateRegister(registers, RBP, 8);
m_rsi = CreateRegister(registers, RSI, 8);
m_rdi = CreateRegister(registers, RDI, 8);
*/
// 64-bit mode only
/*
m_r8 = CreateRegister(registers, R8, 8);
m_r9 = CreateRegister(registers, R9, 8);
m_r10 = CreateRegister(registers, R10, 8);
@ -137,7 +134,7 @@ CRegisters::CRegisters(std::vector<Register_t> registers)
m_r13 = CreateRegister(registers, R13, 8);
m_r14 = CreateRegister(registers, R14, 8);
m_r15 = CreateRegister(registers, R15, 8);
*/
#endif
// ========================================================================
// >> 64-bit MM (MMX) registers
@ -165,7 +162,7 @@ CRegisters::CRegisters(std::vector<Register_t> registers)
m_xmm7 = CreateRegister(registers, XMM7, 16, 16);
// 64-bit mode only
/*
#ifdef PLATFORM_X64
m_xmm8 = CreateRegister(registers, XMM8, 16);
m_xmm9 = CreateRegister(registers, XMM9, 16);
m_xmm10 = CreateRegister(registers, XMM10, 16);
@ -174,7 +171,7 @@ CRegisters::CRegisters(std::vector<Register_t> registers)
m_xmm13 = CreateRegister(registers, XMM13, 16);
m_xmm14 = CreateRegister(registers, XMM14, 16);
m_xmm15 = CreateRegister(registers, XMM15, 16);
*/
#endif
// ========================================================================
// >> 16-bit Segment registers
@ -282,7 +279,7 @@ CRegisters::~CRegisters()
// >> 64-bit General purpose registers
// ========================================================================
// 64-bit mode only
/*
#ifdef PLATFORM_X64
DeleteRegister(m_rax);
DeleteRegister(m_rcx);
DeleteRegister(m_rdx);
@ -291,10 +288,8 @@ CRegisters::~CRegisters()
DeleteRegister(m_rbp);
DeleteRegister(m_rsi);
DeleteRegister(m_rdi);
*/
// 64-bit mode only
/*
DeleteRegister(m_r8);
DeleteRegister(m_r9);
DeleteRegister(m_r10);
@ -303,7 +298,7 @@ CRegisters::~CRegisters()
DeleteRegister(m_r13);
DeleteRegister(m_r14);
DeleteRegister(m_r15);
*/
#endif
// ========================================================================
// >> 64-bit MM (MMX) registers
@ -330,7 +325,7 @@ CRegisters::~CRegisters()
DeleteRegister(m_xmm7);
// 64-bit mode only
/*
#ifdef PLATFORM_X64
DeleteRegister(m_xmm8);
DeleteRegister(m_xmm9);
DeleteRegister(m_xmm10);
@ -339,7 +334,7 @@ CRegisters::~CRegisters()
DeleteRegister(m_xmm13);
DeleteRegister(m_xmm14);
DeleteRegister(m_xmm15);
*/
#endif
// ========================================================================
// >> 2-bit Segment registers

View File

@ -132,8 +132,7 @@ enum Register_t
// ========================================================================
// >> 64-bit General purpose registers
// ========================================================================
// 64-bit mode only
/*
#ifdef PLATFORM_X64
RAX,
RCX,
RDX,
@ -142,10 +141,7 @@ enum Register_t
RBP,
RSI,
RDI,
*/
// 64-bit mode only
/*
R8,
R9,
R10,
@ -154,7 +150,7 @@ enum Register_t
R13,
R14,
R15,
*/
#endif
// ========================================================================
// >> 64-bit MM (MMX) registers
@ -181,7 +177,7 @@ enum Register_t
XMM7,
// 64-bit mode only
/*
#ifdef PLATFORM_X64
XMM8,
XMM9,
XMM10,
@ -190,7 +186,7 @@ enum Register_t
XMM13,
XMM14,
XMM15,
*/
#endif
// ========================================================================
// >> 16-bit Segment registers
@ -377,7 +373,7 @@ public:
// >> 64-bit General purpose registers
// ========================================================================
// 64-bit mode only
/*
#ifdef PLATFORM_X64
CRegister* m_rax;
CRegister* m_rcx;
CRegister* m_rdx;
@ -386,10 +382,7 @@ public:
CRegister* m_rbp;
CRegister* m_rsi;
CRegister* m_rdi;
*/
// 64-bit mode only
/*
CRegister* m_r8;
CRegister* m_r9;
CRegister* m_r10;
@ -398,7 +391,7 @@ public:
CRegister* m_r13;
CRegister* m_r14;
CRegister* m_r15;
*/
#endif
// ========================================================================
// >> 64-bit MM (MMX) registers
@ -425,7 +418,7 @@ public:
CRegister* m_xmm7;
// 64-bit mode only
/*
#ifdef PLATFORM_X64
CRegister* m_xmm8;
CRegister* m_xmm9;
CRegister* m_xmm10;
@ -434,7 +427,7 @@ public:
CRegister* m_xmm13;
CRegister* m_xmm14;
CRegister* m_xmm15;
*/
#endif
// ========================================================================
// >> 16-bit Segment registers

View File

@ -63,15 +63,18 @@ DetourMap g_pPostDetours;
void UnhookFunction(HookType_t hookType, CHook *pDetour)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
CHookManager *pDetourManager = GetHookManager();
pDetour->RemoveCallback(hookType, (HookHandlerFn *)(void *)&HandleDetour);
// Only disable the detour if there are no more listeners.
if (!pDetour->AreCallbacksRegistered())
pDetourManager->UnhookFunction(pDetour->m_pFunc);
#endif
}
bool AddDetourPluginHook(HookType_t hookType, CHook *pDetour, HookSetup *setup, IPluginFunction *pCallback)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
DetourMap *map;
if (hookType == HOOKTYPE_PRE)
map = &g_pPreDetours;
@ -102,10 +105,14 @@ bool AddDetourPluginHook(HookType_t hookType, CHook *pDetour, HookSetup *setup,
wrappers->push_back(pWrapper);
return true;
#else
return false;
#endif
}
bool RemoveDetourPluginHook(HookType_t hookType, CHook *pDetour, IPluginFunction *pCallback)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
DetourMap *map;
if (hookType == HOOKTYPE_PRE)
map = &g_pPreDetours;
@ -139,10 +146,14 @@ bool RemoveDetourPluginHook(HookType_t hookType, CHook *pDetour, IPluginFunction
}
return bRemoved;
#else
return false;
#endif
}
void RemoveAllCallbacksForContext(HookType_t hookType, DetourMap *map, IPluginContext *pContext)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
PluginCallbackList *wrappers;
CDynamicHooksSourcePawn *pWrapper;
DetourMap::iterator it = map->iter();
@ -170,16 +181,20 @@ void RemoveAllCallbacksForContext(HookType_t hookType, DetourMap *map, IPluginCo
it.erase();
}
}
#endif
}
void RemoveAllCallbacksForContext(IPluginContext *pContext)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
RemoveAllCallbacksForContext(HOOKTYPE_PRE, &g_pPreDetours, pContext);
RemoveAllCallbacksForContext(HOOKTYPE_POST, &g_pPostDetours, pContext);
#endif
}
void CleanupDetours(HookType_t hookType, DetourMap *map)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
PluginCallbackList *wrappers;
CDynamicHooksSourcePawn *pWrapper;
DetourMap::iterator it = map->iter();
@ -199,14 +214,18 @@ void CleanupDetours(HookType_t hookType, DetourMap *map)
UnhookFunction(hookType, it->key);
}
map->clear();
#endif
}
void CleanupDetours()
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
CleanupDetours(HOOKTYPE_PRE, &g_pPreDetours);
CleanupDetours(HOOKTYPE_POST, &g_pPostDetours);
#endif
}
#if defined( DHOOKS_DYNAMIC_DETOUR )
ICallingConvention *ConstructCallingConvention(HookSetup *setup)
{
// Convert function parameter types into DynamicHooks structures.
@ -249,6 +268,7 @@ ICallingConvention *ConstructCallingConvention(HookSetup *setup)
return pCallConv;
}
#endif
// Some arguments might be optimized to be passed in registers instead of the stack.
bool UpdateRegisterArgumentSizes(CHook* pDetour, HookSetup *setup)

View File

@ -62,7 +62,9 @@ public:
CallingConvention callConv;
};
#if defined( DHOOKS_DYNAMIC_DETOUR )
ICallingConvention *ConstructCallingConvention(HookSetup *setup);
#endif
bool UpdateRegisterArgumentSizes(CHook* pDetour, HookSetup *setup);
ReturnAction_t HandleDetour(HookType_t hookType, CHook* pDetour);
bool AddDetourPluginHook(HookType_t hookType, CHook *pDetour, HookSetup *setup, IPluginFunction *pCallback);

View File

@ -338,6 +338,7 @@ cell_t Native_AddParam(IPluginContext *pContext, const cell_t *params)
// native bool:DHookEnableDetour(Handle:setup, bool:post, DHookCallback:callback);
cell_t Native_EnableDetour(IPluginContext *pContext, const cell_t *params)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
HookSetup *setup;
if (!GetHandleIfValidOrError(g_HookSetupHandle, (void **)&setup, pContext, params[1]))
@ -377,11 +378,15 @@ cell_t Native_EnableDetour(IPluginContext *pContext, const cell_t *params)
// Add the plugin callback to the map.
return AddDetourPluginHook(hookType, pDetour, setup, callback);
#else
return pContext->ThrowNativeError("Dynamic detours are not enabled for this mod!");
#endif
}
// native bool:DHookDisableDetour(Handle:setup, bool:post, DHookCallback:callback);
cell_t Native_DisableDetour(IPluginContext *pContext, const cell_t *params)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
HookSetup *setup;
if (!GetHandleIfValidOrError(g_HookSetupHandle, (void **)&setup, pContext, params[1]))
@ -414,6 +419,9 @@ cell_t Native_DisableDetour(IPluginContext *pContext, const cell_t *params)
// Remove the callback from the hook.
return RemoveDetourPluginHook(hookType, pDetour, callback);
#else
return pContext->ThrowNativeError("Dynamic detours are not enabled for this mod!");
#endif
}
cell_t HookEntityImpl(IPluginContext *pContext, const cell_t *params, uint32_t callbackIndex, uint32_t removalcbIndex)

View File

@ -62,7 +62,11 @@ size_t GetStackParamOffset(HookParamsStruct *paramStruct, unsigned int index)
continue;
}
#endif
#ifdef PLATFORM_X64
offset += 8;
#else
offset += paramStruct->dg->params[i].size;
#endif
}
return offset;
}
@ -77,8 +81,10 @@ size_t GetRegisterParamOffset(HookParamsStruct *paramStruct, unsigned int index)
for (int i = paramStruct->dg->params.size() - 1; i >= 0; i--)
{
if (paramStruct->dg->params[i].custom_register == None)
{
stackSize += paramStruct->dg->params[i].size;
}
}
size_t offset = stackSize;
for (unsigned int i = 0; i < index; i++)

View File

@ -200,8 +200,8 @@ SDKVector CallVFunction<SDKVector>(DHooksCallback *dg, HookParamsStruct *paramSt
{
size_t offset = GetParamOffset(paramStruct, i);
void *orgAddr = *(void **)((intptr_t)paramStruct->orgParams + offset);
void *newAddr = *(void **)((intptr_t)paramStruct->newParams + offset);
void *orgAddr = (void **)((intptr_t)paramStruct->orgParams + offset);
void *newAddr = (void **)((intptr_t)paramStruct->newParams + offset);
switch (dg->params.at(i).type)
{
@ -291,8 +291,8 @@ string_t CallVFunction<string_t>(DHooksCallback *dg, HookParamsStruct *paramStru
{
size_t offset = GetParamOffset(paramStruct, i);
void *orgAddr = *(void **)((intptr_t)paramStruct->orgParams + offset);
void *newAddr = *(void **)((intptr_t)paramStruct->newParams + offset);
void *orgAddr = (void **)((intptr_t)paramStruct->orgParams + offset);
void *newAddr = (void **)((intptr_t)paramStruct->newParams + offset);
switch (dg->params.at(i).type)
{

View File

@ -32,7 +32,11 @@
#include "vhook.h"
#include "vfunc_call.h"
#include "util.h"
#ifdef PLATFORM_X64
#include "sh_asm_x86_64.h"
#else
#include <macro-assembler-x86.h>
#endif
SourceHook::IHookManagerAutoGen *g_pHookManager = NULL;
@ -47,9 +51,111 @@ using namespace sp;
#define OBJECT_OFFSET (sizeof(void *)*2)
#endif
#ifndef WIN32
void *GenerateThunk(ReturnType type)
#ifdef PLATFORM_X64
using namespace SourceHook::Asm;
SourceHook::CPageAlloc GenBuffer::ms_Allocator(16);
void test_func(void* rcx, void* rdx, SDKVector* r8, bool r9)
{
//g_pSM->LogMessage(myself, "rcx(%p) - rdx(%p) - r8(%p) - r9(%p)", rcx, rdx, r8, r9);
}
SourceHook::Asm::x64JitWriter* GenerateThunk(HookSetup* hook)
{
auto masm = new x64JitWriter();
auto type = hook->returnType;
/*if (type == ReturnType_Vector)
{
masm->push(rcx);
masm->push(rdx);
masm->push(r8);
masm->push(r9);
masm->sub(rsp, 40);
masm->mov(rax, (uintptr_t)test_func);
masm->call(rax);
masm->add(rsp, 40);
masm->pop(r9);
masm->pop(r8);
masm->pop(rdx);
masm->pop(rcx);
}*/
// We're going to transform rbp into our stack
masm->push(rbp);
// Copy all the arguments into the stack
// 8 bytes per parameter + 8 bytes for potential return value
int32_t fakeStackSize = ke::Align((int32_t)hook->params.size() * 8 + 8, 16) + 8; // Add another +8 bytes to realign on 16 bytes, due to 'push rbp' earlier
int32_t parameterOffset = fakeStackSize + 8 /* push rbp */ + 8 /* return address */ + 32 /* shadow space */;
masm->sub(rsp, fakeStackSize);
masm->mov(rbp, rsp);
static x86_64_Reg arg_reg[] = { rcx, rdx, r8, r9 };
static x86_64_FloatReg arg_reg_float[] = { xmm0, xmm1, xmm2, xmm3 };
int stack_index = 0;
int fake_stack_index = 0;
int reg_index = 1; // Account |this| right away
if (type == ReturnType_Vector) { // Special return types occupy another register
masm->mov(rbp(8 * fake_stack_index), rdx); // Store return ptr at the bottom of the stack
reg_index++;
fake_stack_index++;
}
for (int i = 0; i < hook->params.size(); i++, fake_stack_index++) {
if (reg_index < 4) {
if (hook->params[i].type == HookParamType_Float && hook->params[i].flags == PASSFLAG_BYVAL) {
masm->movsd(rbp(8 * fake_stack_index), arg_reg_float[reg_index]);
} else {
masm->mov(rax, arg_reg[reg_index]);
masm->mov(rbp(8 * fake_stack_index), rax);
}
reg_index++;
} else {
masm->mov(rax, rbp(parameterOffset + 8 * stack_index));
masm->mov(rbp(8 * fake_stack_index), rax);
stack_index++;
}
}
//masm->mov(rbp(8 * 2), 0x7777777777777777);
//masm->mov(rbp(8 * 1), 0xDEADBEEFDEADBEEF);
// Setup 2nd parameter (our fake stack)
masm->mov(rdx, rbp);
if (type == ReturnType_Float)
{
masm->mov(rax, (uintptr_t)Callback_float);
}
else if (type == ReturnType_Vector)
{
masm->mov(rax, (uintptr_t)Callback_vector);
}
/*else if (type == ReturnType_String)
{
masm->mov(rax, (uintptr_t)Callback_stringt);
}*/
else
{
masm->mov(rax, (uintptr_t)Callback);
}
masm->sub(rsp, 40);
masm->call(rax);
masm->add(rsp, 40);
masm->add(rsp, fakeStackSize);
masm->pop(rbp);
masm->retn();
masm->SetRE();
return masm;
}
#elif !defined( WIN32 )
void *GenerateThunk(HookSetup* hook)
{
auto type = hook->returnType;
sp::MacroAssembler masm;
static const size_t kStackNeeded = (2) * 4; // 2 args max
static const size_t kReserve = ke::Align(kStackNeeded + 8, 16) - 8;
@ -97,8 +203,9 @@ void *GenerateThunk(ReturnType type)
}
#else
// HUGE THANKS TO BAILOPAN (dvander)!
void *GenerateThunk(ReturnType type)
void *GenerateThunk(HookSetup* hook)
{
auto type = hook->returnType;
sp::MacroAssembler masm;
static const size_t kStackNeeded = (3 + 1) * 4; // 3 args max, 1 locals max
static const size_t kReserve = ke::Align(kStackNeeded + 8, 16) - 8;
@ -138,7 +245,7 @@ void *GenerateThunk(ReturnType type)
DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *remove_callback, IPluginFunction *plugincb, bool post)
{
this->callback = MakeHandler(setup->returnType);
this->callback = MakeHandler(setup);
this->hookid = 0;
this->remove_callback = remove_callback;
this->callback->offset = setup->offset;
@ -232,11 +339,11 @@ SourceHook::PassInfo::PassType GetParamTypePassType(HookParamType type)
size_t GetStackArgsSize(DHooksCallback *dg)
{
size_t res = GetParamsSize(dg);
#ifdef WIN32
#ifdef WIN32
if(dg->returnType == ReturnType_Vector)//Account for result vector ptr.
#else
#else
if(dg->returnType == ReturnType_Vector || dg->returnType == ReturnType_String)
#endif
#endif
{
res += OBJECT_OFFSET;
}
@ -272,11 +379,11 @@ HookParamsStruct *GetParamStruct(DHooksCallback *dg, void **argStack, size_t arg
{
HookParamsStruct *params = new HookParamsStruct();
params->dg = dg;
#ifdef WIN32
#ifdef WIN32
if(dg->returnType != ReturnType_Vector)
#else
#else
if(dg->returnType != ReturnType_Vector && dg->returnType != ReturnType_String)
#endif
#endif
{
params->orgParams = (void **)malloc(argStackSize);
memcpy(params->orgParams, argStack, argStackSize);
@ -284,7 +391,7 @@ HookParamsStruct *GetParamStruct(DHooksCallback *dg, void **argStack, size_t arg
else //Offset result ptr
{
params->orgParams = (void **)malloc(argStackSize-OBJECT_OFFSET);
memcpy(params->orgParams, argStack+OBJECT_OFFSET, argStackSize-OBJECT_OFFSET);
memcpy(params->orgParams, (void*)((uintptr_t)argStack + OBJECT_OFFSET), argStackSize - OBJECT_OFFSET);
}
size_t paramsSize = GetParamsSize(dg);
@ -388,11 +495,14 @@ cell_t GetThisPtr(void *iface, ThisPointerType type)
return -1;
return gamehelpers->EntityToBCompatRef((CBaseEntity *)iface);
}
#ifdef PLATFORM_X64
return g_pSM->ToPseudoAddress(iface);
#else
return (cell_t)iface;
#endif
}
#ifdef WIN32
#if defined( WIN32 ) && !defined( PLATFORM_X64 )
void *Callback(DHooksCallback *dg, void **argStack, size_t *argsizep)
#else
void *Callback(DHooksCallback *dg, void **argStack)
@ -403,11 +513,12 @@ void *Callback(DHooksCallback *dg, void **argStack)
Handle_t rHndl;
Handle_t pHndl;
#ifdef WIN32
#if defined( WIN32 ) && !defined( PLATFORM_X64 )
*argsizep = GetStackArgsSize(dg);
#else
#else
size_t argsize = GetStackArgsSize(dg);
#endif
#endif
//g_pSM->LogMessage(myself, "[DEFAULT]DHooksCallback(%p) argStack(%p) - argsize(%d)", dg, argStack, argsize);
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
{
@ -430,15 +541,15 @@ void *Callback(DHooksCallback *dg, void **argStack)
dg->plugin_callback->PushCell(rHndl);
}
#ifdef WIN32
#if defined( WIN32 ) && !defined( PLATFORM_X64 )
if(*argsizep > 0)
{
paramStruct = GetParamStruct(dg, argStack, *argsizep);
#else
#else
if(argsize > 0)
{
paramStruct = GetParamStruct(dg, argStack, argsize);
#endif
#endif
pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
if(!pHndl)
{
@ -575,7 +686,7 @@ void *Callback(DHooksCallback *dg, void **argStack)
}
return ret;
}
#ifdef WIN32
#if defined( WIN32 ) && !defined( PLATFORM_X64 )
float Callback_float(DHooksCallback *dg, void **argStack, size_t *argsizep)
#else
float Callback_float(DHooksCallback *dg, void **argStack)
@ -586,11 +697,12 @@ float Callback_float(DHooksCallback *dg, void **argStack)
Handle_t rHndl;
Handle_t pHndl;
#ifdef WIN32
#if defined( WIN32 ) && !defined( PLATFORM_X64 )
*argsizep = GetStackArgsSize(dg);
#else
#else
size_t argsize = GetStackArgsSize(dg);
#endif
#endif
//g_pSM->LogMessage(myself, "[FLOAT]DHooksCallback(%p) argStack(%p) - argsize(%d)", dg, argStack, argsize);
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
{
@ -612,7 +724,7 @@ float Callback_float(DHooksCallback *dg, void **argStack)
}
dg->plugin_callback->PushCell(rHndl);
#ifdef WIN32
#if defined( WIN32 ) && !defined( PLATFORM_X64 )
if(*argsizep > 0)
{
paramStruct = GetParamStruct(dg, argStack, *argsizep);
@ -729,24 +841,25 @@ float Callback_float(DHooksCallback *dg, void **argStack)
}
return *(float *)ret;
}
#ifdef WIN32
#if defined( WIN32 ) && !defined( PLATFORM_X64 )
SDKVector *Callback_vector(DHooksCallback *dg, void **argStack, size_t *argsizep)
#else
SDKVector *Callback_vector(DHooksCallback *dg, void **argStack)
#endif
{
SDKVector *vec_result = (SDKVector *)argStack[0]; // Save the result
SDKVector *vec_result = (SDKVector *)argStack[0];
HookReturnStruct *returnStruct = NULL;
HookParamsStruct *paramStruct = NULL;
Handle_t rHndl;
Handle_t pHndl;
#ifdef WIN32
#if defined( WIN32 ) && !defined( PLATFORM_X64 )
*argsizep = GetStackArgsSize(dg);
#else
#else
size_t argsize = GetStackArgsSize(dg);
#endif
#endif
//g_pSM->LogMessage(myself, "[VECTOR]DHooksCallback(%p) argStack(%p) - argsize(%d) - params count %d", dg, argStack, argsize, dg->params.size());
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
{
@ -768,7 +881,7 @@ SDKVector *Callback_vector(DHooksCallback *dg, void **argStack)
}
dg->plugin_callback->PushCell(rHndl);
#ifdef WIN32
#if defined( WIN32 ) && !defined( PLATFORM_X64 )
if(*argsizep > 0)
{
paramStruct = GetParamStruct(dg, argStack, *argsizep);

View File

@ -39,6 +39,10 @@
#include <registers.h>
#include <vector>
#ifdef PLATFORM_X64
#include "sh_asm_x86_64.h"
#endif
enum CallingConvention
{
CallConv_CDECL,
@ -163,11 +167,20 @@ public:
class DHooksCallback : public SourceHook::ISHDelegate, public DHooksInfo
{
public:
DHooksCallback()
{
//g_pSM->LogMessage(myself, "DHooksCallback(%p)", this);
}
virtual bool IsEqual(ISHDelegate *pOtherDeleg){return false;};
virtual void DeleteThis()
{
*(void ***)this = this->oldvtable;
#ifdef PLATFORM_X64
delete callThunk;
#else
g_pSM->GetScriptingEngine()->FreePageMemory(this->newvtable[2]);
#endif
delete this->newvtable;
delete this;
};
@ -175,9 +188,12 @@ public:
public:
void **newvtable;
void **oldvtable;
#ifdef PLATFORM_X64
SourceHook::Asm::x64JitWriter* callThunk;
#endif
};
#ifdef WIN32
#if defined( WIN32 ) && !defined( PLATFORM_X64 )
void *Callback(DHooksCallback *dg, void **stack, size_t *argsizep);
float Callback_float(DHooksCallback *dg, void **stack, size_t *argsizep);
SDKVector *Callback_vector(DHooksCallback *dg, void **stack, size_t *argsizep);
@ -192,20 +208,6 @@ bool SetupHookManager(ISmmAPI *ismm);
void CleanupHooks(IPluginContext *pContext = NULL);
size_t GetParamTypeSize(HookParamType type);
SourceHook::PassInfo::PassType GetParamTypePassType(HookParamType type);
void *GenerateThunk(ReturnType type);
static DHooksCallback *MakeHandler(ReturnType type)
{
DHooksCallback *dg = new DHooksCallback();
dg->returnType = type;
dg->oldvtable = *(void ***)dg;
dg->newvtable = new void *[3];
dg->newvtable[0] = dg->oldvtable[0];
dg->newvtable[1] = dg->oldvtable[1];
dg->newvtable[2] = GenerateThunk(type);
*(void ***)dg = dg->newvtable;
return dg;
}
class HookParamsStruct
{
@ -276,6 +278,37 @@ public:
HookMethod hookMethod;
};
#ifdef PLATFORM_X64
SourceHook::Asm::x64JitWriter* GenerateThunk(HookSetup* type);
static DHooksCallback *MakeHandler(HookSetup* hook)
{
DHooksCallback *dg = new DHooksCallback();
dg->returnType = hook->returnType;
dg->oldvtable = *(void ***)dg;
dg->newvtable = new void *[3];
dg->newvtable[0] = dg->oldvtable[0];
dg->newvtable[1] = dg->oldvtable[1];
dg->callThunk = GenerateThunk(hook);
dg->newvtable[2] = dg->callThunk->GetData();
*(void ***)dg = dg->newvtable;
return dg;
}
#else
void *GenerateThunk(HookSetup* type);
static DHooksCallback *MakeHandler(HookSetup* hook)
{
DHooksCallback *dg = new DHooksCallback();
dg->returnType = hook->returnType;
dg->oldvtable = *(void ***)dg;
dg->newvtable = new void *[3];
dg->newvtable[0] = dg->oldvtable[0];
dg->newvtable[1] = dg->oldvtable[1];
dg->newvtable[2] = GenerateThunk(hook);
*(void ***)dg = dg->newvtable;
return dg;
}
#endif
class DHooksManager
{
public: