mirror of
https://github.com/alliedmodders/sourcemod.git
synced 2025-12-06 18:08:36 +00:00
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:
parent
4e6d66b721
commit
4e15a92984
@ -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,22 +49,34 @@ 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')
|
||||
]
|
||||
|
||||
# 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'),
|
||||
]
|
||||
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', 'conventions', 'x86MsCdecl.cpp'),
|
||||
os.path.join('DynamicHooks', 'conventions', 'x86MsStdcall.cpp'),
|
||||
os.path.join('DynamicHooks', 'conventions', 'x86MsFastcall.cpp'),
|
||||
]
|
||||
|
||||
if binary.compiler.target.platform == 'windows':
|
||||
binary.sources += [os.path.join('DynamicHooks', 'conventions', 'x86MsThiscall.cpp')]
|
||||
else:
|
||||
binary.sources += [os.path.join('DynamicHooks', 'conventions', 'x86GccThiscall.cpp')]
|
||||
if binary.compiler.target.platform == 'windows':
|
||||
binary.sources += [os.path.join('DynamicHooks', 'conventions', 'x86MsThiscall.cpp')]
|
||||
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)]
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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,7 +81,9 @@ 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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user