mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-01-19 08:52:34 +01:00
void vafmt works on msvc
--HG-- branch : hookman_autogen extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/hookman_autogen%40565
This commit is contained in:
parent
3de86ccca8
commit
184232777a
@ -20,6 +20,7 @@
|
|||||||
#include "sourcehook_hookmangen_x86.h"
|
#include "sourcehook_hookmangen_x86.h"
|
||||||
#include "sh_memory.h"
|
#include "sh_memory.h"
|
||||||
#include <stdarg.h> // we might need the address of vsnprintf
|
#include <stdarg.h> // we might need the address of vsnprintf
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#if SH_COMP == SH_COMP_MSVC
|
#if SH_COMP == SH_COMP_MSVC
|
||||||
# define GCC_ONLY(x)
|
# define GCC_ONLY(x)
|
||||||
@ -895,20 +896,21 @@ namespace SourceHook
|
|||||||
// call eax
|
// call eax
|
||||||
// gcc: clean up
|
// gcc: clean up
|
||||||
|
|
||||||
jit_int32_t gcc_clean_bytes = 0;
|
jit_int32_t caller_clean_bytes = 0; // gcc always, msvc never (hooks never have varargs!)
|
||||||
// vafmt: push va_buf
|
// vafmt: push va_buf
|
||||||
if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt)
|
if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt)
|
||||||
{
|
{
|
||||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_va_buf);
|
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_va_buf);
|
||||||
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
||||||
gcc_clean_bytes += SIZE_PTR;
|
caller_clean_bytes += SIZE_PTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_clean_bytes += PushParams(base_param_offset, v_plugin_ret, v_place_for_memret, v_place_fbrr_base);
|
caller_clean_bytes += PushParams(base_param_offset, v_plugin_ret, v_place_for_memret, v_place_fbrr_base);
|
||||||
|
|
||||||
IA32_Mov_Reg_Rm(&m_HookFunc, REG_ECX, REG_EAX, MOD_REG);
|
IA32_Mov_Reg_Rm(&m_HookFunc, REG_ECX, REG_EAX, MOD_REG);
|
||||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
if (SH_COMP == SH_COMP_GCC)
|
||||||
gcc_clean_bytes += PushMemRetPtr(v_plugin_ret, v_place_for_memret);
|
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
||||||
|
caller_clean_bytes += PushMemRetPtr(v_plugin_ret, v_place_for_memret);
|
||||||
IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_ECX, MOD_MEM_REG);
|
IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_ECX, MOD_MEM_REG);
|
||||||
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EAX, 2*SIZE_PTR);
|
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EAX, 2*SIZE_PTR);
|
||||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||||
@ -917,12 +919,10 @@ namespace SourceHook
|
|||||||
|
|
||||||
SaveRetVal(v_plugin_ret, v_place_for_memret);
|
SaveRetVal(v_plugin_ret, v_place_for_memret);
|
||||||
|
|
||||||
// cleanup
|
// cleanup (gcc only)
|
||||||
#if SH_COMP == SH_COMP_GCC
|
|
||||||
IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, gcc_clean_bytes + SIZE_PTR, MOD_REG);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// params + thisptr
|
// params + thisptr
|
||||||
|
if (SH_COMP == SH_COMP_GCC)
|
||||||
|
IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, caller_clean_bytes + SIZE_PTR, MOD_REG);
|
||||||
|
|
||||||
// process meta return:
|
// process meta return:
|
||||||
// prev_res = cur_res
|
// prev_res = cur_res
|
||||||
@ -1014,7 +1014,7 @@ namespace SourceHook
|
|||||||
tmppos2 = IA32_Jump_Cond_Imm32(&m_HookFunc, CC_Z, 0);
|
tmppos2 = IA32_Jump_Cond_Imm32(&m_HookFunc, CC_Z, 0);
|
||||||
m_HookFunc.start_count(counter2);
|
m_HookFunc.start_count(counter2);
|
||||||
|
|
||||||
jit_int32_t gcc_clean_bytes = 0;
|
jit_int32_t caller_clean_bytes = 0; // gcc always, msvc when cdecl-like (varargs)
|
||||||
|
|
||||||
// vafmt: push va_buf, then "%s"
|
// vafmt: push va_buf, then "%s"
|
||||||
if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt)
|
if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt)
|
||||||
@ -1022,29 +1022,29 @@ namespace SourceHook
|
|||||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_va_buf);
|
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_va_buf);
|
||||||
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
||||||
IA32_Push_Imm32(&m_HookFunc, DownCastPtr("%s"));
|
IA32_Push_Imm32(&m_HookFunc, DownCastPtr("%s"));
|
||||||
gcc_clean_bytes += 2*SIZE_PTR;
|
caller_clean_bytes += 2*SIZE_PTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// push params
|
// push params
|
||||||
gcc_clean_bytes += PushParams(param_base_offs, v_orig_ret, v_place_for_memret, v_place_fbrr_base);
|
caller_clean_bytes += PushParams(param_base_offs, v_orig_ret, v_place_for_memret, v_place_fbrr_base);
|
||||||
|
|
||||||
// thisptr
|
// thisptr
|
||||||
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_this);
|
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_this);
|
||||||
#if SH_COMP == SH_COMP_GCC
|
if (SH_COMP == SH_COMP_GCC || (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs))
|
||||||
// on gcc/mingw, this is the first parameter
|
{
|
||||||
|
// on gcc/mingw or msvc with varargs, this is the first parameter
|
||||||
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
||||||
// on msvc, simply leave it in ecx
|
// on msvc without varargs, simply leave it in ecx
|
||||||
#endif
|
}
|
||||||
gcc_clean_bytes += PushMemRetPtr(v_orig_ret, v_place_for_memret);
|
caller_clean_bytes += PushMemRetPtr(v_orig_ret, v_place_for_memret);
|
||||||
|
|
||||||
// call
|
// call
|
||||||
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_vfnptr_origentry);
|
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_vfnptr_origentry);
|
||||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
#if SH_COMP == SH_COMP_GCC
|
if (SH_COMP == SH_COMP_GCC || (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs))
|
||||||
IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, gcc_clean_bytes + SIZE_PTR, MOD_REG);
|
IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, caller_clean_bytes + SIZE_PTR, MOD_REG);
|
||||||
#endif
|
|
||||||
|
|
||||||
DestroyParams(v_place_fbrr_base);
|
DestroyParams(v_place_fbrr_base);
|
||||||
|
|
||||||
@ -1239,21 +1239,27 @@ namespace SourceHook
|
|||||||
IA32_Push_Reg(&m_HookFunc, REG_EBX);
|
IA32_Push_Reg(&m_HookFunc, REG_EBX);
|
||||||
IA32_Mov_Reg_Rm(&m_HookFunc, REG_EBP, REG_ESP, MOD_REG);
|
IA32_Mov_Reg_Rm(&m_HookFunc, REG_EBP, REG_ESP, MOD_REG);
|
||||||
|
|
||||||
|
jit_int32_t v_this = 0;
|
||||||
// on msvc, save thisptr
|
jit_int32_t param_base_offs = 0;
|
||||||
#if SH_COMP == SH_COMP_MSVC
|
if (SH_COMP == SH_COMP_GCC || (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs))
|
||||||
jit_int32_t v_this = -4;
|
{
|
||||||
|
// gcc or msvc with varargs:
|
||||||
|
v_this = 12; // first param
|
||||||
|
param_base_offs = 16;
|
||||||
|
ResetFrame(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// on msvc without varargs, save thisptr
|
||||||
|
v_this = -4;
|
||||||
|
param_base_offs = 12;
|
||||||
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
||||||
#elif SH_COMP == SH_COMP_GCC
|
ResetFrame(-4); // start placing local vars on offset -4
|
||||||
jit_int32_t v_this = 12; // first param
|
// because there already is the thisptr variable
|
||||||
#endif
|
}
|
||||||
|
|
||||||
ResetFrame(
|
|
||||||
(SH_COMP==SH_COMP_MSVC) ? -4 : 0
|
|
||||||
); // on msvc, start on offset -4 because there already is the thisptr variable
|
|
||||||
|
|
||||||
// ********************** stack frame **********************
|
// ********************** stack frame **********************
|
||||||
// MSVC
|
// MSVC without varargs
|
||||||
// second param (gcc: first real param) ebp + 16
|
// second param (gcc: first real param) ebp + 16
|
||||||
// first param (gcc: thisptr) ebp + 12
|
// first param (gcc: thisptr) ebp + 12
|
||||||
// ret address: ebp + 8
|
// ret address: ebp + 8
|
||||||
@ -1293,27 +1299,24 @@ namespace SourceHook
|
|||||||
const jit_int8_t v_iter = AddVarToFrame(SIZE_PTR);
|
const jit_int8_t v_iter = AddVarToFrame(SIZE_PTR);
|
||||||
const jit_int8_t v_pContext = AddVarToFrame(SIZE_PTR);
|
const jit_int8_t v_pContext = AddVarToFrame(SIZE_PTR);
|
||||||
|
|
||||||
#if SH_COMP == SH_COMP_GCC
|
|
||||||
jit_int32_t param_base_offs = 16;
|
|
||||||
#elif SH_COMP == SH_COMP_MSVC
|
|
||||||
jit_int32_t param_base_offs = 12;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Memory return: first param is the address
|
// Memory return: first param is the address
|
||||||
jit_int32_t v_memret_addr = 0;
|
jit_int32_t v_memret_addr = 0;
|
||||||
if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)
|
if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)
|
||||||
{
|
{
|
||||||
#if SH_COMP == SH_COMP_GCC
|
if (SH_COMP == SH_COMP_GCC || (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs))
|
||||||
|
{
|
||||||
// gcc: now: first param = mem ret addr
|
// gcc: now: first param = mem ret addr
|
||||||
// second param = this pointer
|
// second param = this pointer
|
||||||
// third param = actual first param
|
// third param = actual first param
|
||||||
v_memret_addr = 12;
|
v_memret_addr = 12;
|
||||||
v_this += 4;
|
v_this += 4;
|
||||||
param_base_offs += SIZE_PTR;
|
param_base_offs += SIZE_PTR;
|
||||||
#elif SH_COMP == SH_COMP_MSVC
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
v_memret_addr = param_base_offs;
|
v_memret_addr = param_base_offs;
|
||||||
param_base_offs += SIZE_PTR;
|
param_base_offs += SIZE_PTR;
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jit_int32_t v_ret_ptr = 0;
|
jit_int32_t v_ret_ptr = 0;
|
||||||
@ -1494,14 +1497,23 @@ namespace SourceHook
|
|||||||
IA32_Mov_Reg_Rm(&m_HookFunc, REG_ESP, REG_EBP, MOD_REG);
|
IA32_Mov_Reg_Rm(&m_HookFunc, REG_ESP, REG_EBP, MOD_REG);
|
||||||
IA32_Pop_Reg(&m_HookFunc, REG_EBX);
|
IA32_Pop_Reg(&m_HookFunc, REG_EBX);
|
||||||
IA32_Pop_Reg(&m_HookFunc, REG_EBP);
|
IA32_Pop_Reg(&m_HookFunc, REG_EBP);
|
||||||
MSVC_ONLY(IA32_Return_Popstack(&m_HookFunc, GetParamsStackSize()));
|
|
||||||
// gcc: Remove 4 bytes from stack on memory return
|
if (SH_COMP == SH_COMP_MSVC && !(m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs))
|
||||||
#if SH_COMP == SH_COMP_GCC
|
{
|
||||||
if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)
|
// msvc without varargs:
|
||||||
|
// callee cleans the stack
|
||||||
|
IA32_Return_Popstack(&m_HookFunc, GetParamsStackSize());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// gcc or msvc with varargs: caller cleans the stack
|
||||||
|
// exception: gcc removes the memret addr on memret:
|
||||||
|
if (SH_COMP == SH_COMP_GCC && (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem))
|
||||||
IA32_Return_Popstack(&m_HookFunc, SIZE_PTR);
|
IA32_Return_Popstack(&m_HookFunc, SIZE_PTR);
|
||||||
else
|
else
|
||||||
IA32_Return(&m_HookFunc);
|
IA32_Return(&m_HookFunc);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
|
||||||
// Store pointer for later use
|
// Store pointer for later use
|
||||||
// m_HookfuncVfnPtr is a pointer to a void* because SH expects a pointer
|
// m_HookfuncVfnPtr is a pointer to a void* because SH expects a pointer
|
||||||
|
Loading…
x
Reference in New Issue
Block a user