diff --git a/extensions/dhooks/AMBuilder b/extensions/dhooks/AMBuilder index 7f15a0669f..8c09573755 100644 --- a/extensions/dhooks/AMBuilder +++ b/extensions/dhooks/AMBuilder @@ -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')] + + # Dynamic detour is only supported on x86 + binary.compiler.defines += ['DHOOKS_DYNAMIC_DETOUR'] - 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')] + elif binary.compiler.target.arch == 'x86_64': + binary.compiler.defines += ['PLATFORM_X64'] SM.extensions += [builder.Add(binary)] diff --git a/extensions/dhooks/DynamicHooks/convention.h b/extensions/dhooks/DynamicHooks/convention.h index ae4d613884..e9a63ed479 100644 --- a/extensions/dhooks/DynamicHooks/convention.h +++ b/extensions/dhooks/DynamicHooks/convention.h @@ -111,7 +111,7 @@ The data type you would like to get the size of. @param : 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 @@ class ICallingConvention int size = GetArgStackSize() + GetArgRegisterSize(); std::unique_ptr pSavedCallArguments = std::make_unique(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 @@ class ICallingConvention 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(); diff --git a/extensions/dhooks/DynamicHooks/registers.cpp b/extensions/dhooks/DynamicHooks/registers.cpp index f2200630c3..25c45b5821 100644 --- a/extensions/dhooks/DynamicHooks/registers.cpp +++ b/extensions/dhooks/DynamicHooks/registers.cpp @@ -116,7 +116,7 @@ CRegisters::CRegisters(std::vector 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 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 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 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 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 diff --git a/extensions/dhooks/DynamicHooks/registers.h b/extensions/dhooks/DynamicHooks/registers.h index 854c40f98b..e65ee36193 100644 --- a/extensions/dhooks/DynamicHooks/registers.h +++ b/extensions/dhooks/DynamicHooks/registers.h @@ -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 @@ class CRegisters // >> 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 @@ class CRegisters 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 @@ class CRegisters CRegister* m_r13; CRegister* m_r14; CRegister* m_r15; - */ +#endif // ======================================================================== // >> 64-bit MM (MMX) registers @@ -425,7 +418,7 @@ class CRegisters CRegister* m_xmm7; // 64-bit mode only - /* +#ifdef PLATFORM_X64 CRegister* m_xmm8; CRegister* m_xmm9; CRegister* m_xmm10; @@ -434,7 +427,7 @@ class CRegisters CRegister* m_xmm13; CRegister* m_xmm14; CRegister* m_xmm15; - */ +#endif // ======================================================================== // >> 16-bit Segment registers diff --git a/extensions/dhooks/dynhooks_sourcepawn.cpp b/extensions/dhooks/dynhooks_sourcepawn.cpp index 8b148fe7d8..2149a00c73 100644 --- a/extensions/dhooks/dynhooks_sourcepawn.cpp +++ b/extensions/dhooks/dynhooks_sourcepawn.cpp @@ -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) diff --git a/extensions/dhooks/dynhooks_sourcepawn.h b/extensions/dhooks/dynhooks_sourcepawn.h index 43428a4d33..2f04204860 100644 --- a/extensions/dhooks/dynhooks_sourcepawn.h +++ b/extensions/dhooks/dynhooks_sourcepawn.h @@ -62,7 +62,9 @@ class CDynamicHooksSourcePawn : public DHooksInfo { 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); diff --git a/extensions/dhooks/natives.cpp b/extensions/dhooks/natives.cpp index 8757e8319d..f228fcf306 100644 --- a/extensions/dhooks/natives.cpp +++ b/extensions/dhooks/natives.cpp @@ -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) diff --git a/extensions/dhooks/util.cpp b/extensions/dhooks/util.cpp index 9b08fa8a2d..e1c8df2e16 100644 --- a/extensions/dhooks/util.cpp +++ b/extensions/dhooks/util.cpp @@ -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; diff --git a/extensions/dhooks/vfunc_call.h b/extensions/dhooks/vfunc_call.h index 1604c13e83..d12ebae447 100644 --- a/extensions/dhooks/vfunc_call.h +++ b/extensions/dhooks/vfunc_call.h @@ -200,8 +200,8 @@ SDKVector CallVFunction(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(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) { diff --git a/extensions/dhooks/vhook.cpp b/extensions/dhooks/vhook.cpp index 1be1d528fa..d4a6f38e08 100644 --- a/extensions/dhooks/vhook.cpp +++ b/extensions/dhooks/vhook.cpp @@ -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 +#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); diff --git a/extensions/dhooks/vhook.h b/extensions/dhooks/vhook.h index 6146d1ad6a..b58f9c4ff1 100644 --- a/extensions/dhooks/vhook.h +++ b/extensions/dhooks/vhook.h @@ -39,6 +39,10 @@ #include #include +#ifdef PLATFORM_X64 +#include "sh_asm_x86_64.h" +#endif + enum CallingConvention { CallConv_CDECL, @@ -163,11 +167,20 @@ class DHooksInfo 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 @@ class DHooksCallback : public SourceHook::ISHDelegate, public DHooksInfo 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 @@ class HookSetup 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: