1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2024-11-29 11:24:19 +01:00

ForcedByRef works; next step will be: returns!

--HG--
branch : hookman_autogen
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/hookman_autogen%40548
This commit is contained in:
Pavol Marko 2007-11-07 16:56:03 +00:00
parent 94223941d2
commit d4bd0261f1
5 changed files with 142 additions and 68 deletions

View File

@ -196,6 +196,39 @@ namespace SourceHook
IA32_Pop_Reg(&m_HookFunc, REG_EDI);
}
short GenContext::GetParamsStackSize()
{
short acc = 0;
for (int i = 0; i < m_Proto.GetNumOfParams(); ++i)
{
acc += GetStackSize(m_Proto.GetParam(i));
}
// Memory return: address is first param
if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)
acc += SIZE_PTR;
// :TODO: cdecl: THIS POINTER AS FIRST PARAM!!!
return acc;
}
short GenContext::GetForcedByRefParamOffset(int p)
{
short off = 0;
for (int i = 0; i < p; ++i)
{
if (m_Proto.GetParam(i).flags & PassFlag_ForcedByRef)
off += GetStackSize(m_Proto.GetParam(i));
}
return off;
}
short GenContext::GetForcedByRefParamsSize()
{
return GetForcedByRefParamOffset(m_Proto.GetNumOfParams());
}
jit_int32_t GenContext::PushRef(jit_int32_t param_offset, const IntPassInfo &pi)
{
// push [ebp+<offset>]
@ -282,23 +315,31 @@ namespace SourceHook
}
}
jit_int32_t GenContext::PushObject(jit_int32_t param_offset, const IntPassInfo &pi)
jit_int32_t GenContext::PushObject(jit_int32_t param_offset, const IntPassInfo &pi, jit_int32_t place_fbrr)
{
// make room on the stack
// sub esp, <size>
IA32_Sub_Rm_ImmAuto(&m_HookFunc, REG_ESP, GetStackSize(pi), MOD_REG);
if ((pi.flags & PassFlag_ForcedByRef) == 0)
{
// make room on the stack
// sub esp, <size>
IA32_Sub_Rm_ImmAuto(&m_HookFunc, REG_ESP, GetStackSize(pi), MOD_REG);
}
// if there is a copy constructor..
if (pi.pCopyCtor)
{
// save eax
// push src addr
// this= target addr = esp+12
// this= target addr = forcedbyref ? ebp+place_fbrr : esp+12
// call copy constructor
// restore eax
IA32_Push_Reg(&m_HookFunc, REG_EAX);
IA32_Lea_Reg_DispRegMultImm8(&m_HookFunc, REG_ECX, REG_NOIDX, REG_ESP, NOSCALE, 4);
if (pi.flags & PassFlag_ForcedByRef)
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, place_fbrr);
else
IA32_Lea_Reg_DispRegMultImm8(&m_HookFunc, REG_ECX, REG_NOIDX, REG_ESP, NOSCALE, 4);
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EAX, REG_EBP, param_offset);
IA32_Push_Reg(&m_HookFunc, REG_EAX);
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
@ -314,19 +355,50 @@ namespace SourceHook
BitwiseCopy_Setup();
//lea edi, [esp+8]
//if forcedbyref:
// lea edi, [ebp_place_fbrr]
//else
// lea edi, [esp+8] - bc_setup pushed two regs onto the stack!
//lea esi, [ebp+<offs>]
IA32_Lea_Reg_DispRegMultImm8(&m_HookFunc, REG_EDI, REG_NOIDX, REG_ESP, NOSCALE, 8);
if (pi.flags & PassFlag_ForcedByRef)
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDI, REG_EBP, place_fbrr);
else
IA32_Lea_Reg_DispRegMultImm8(&m_HookFunc, REG_EDI, REG_NOIDX, REG_ESP, NOSCALE, 8);
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ESI, REG_EBP, param_offset);
BitwiseCopy_Do(pi.size);
}
// forcedref: push reference to ebp+place_fbrr
if (pi.flags & PassFlag_ForcedByRef)
{
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, place_fbrr);
IA32_Push_Reg(&m_HookFunc, REG_ECX);
return SIZE_PTR;
}
return DownCastSize(pi.size);
}
void GenContext::DestroyParams(jit_int32_t fbrr_base)
{
for (int i = m_Proto.GetNumOfParams() - 1; i >= 0; --i)
{
const IntPassInfo &pi = m_Proto.GetParam(i);
if (pi.type == PassInfo::PassType_Object && (pi.flags & PassInfo::PassFlag_ODtor) &&
(pi.flags & PassInfo::PassFlag_ByVal) && (pi.flags & PassFlag_ForcedByRef))
{
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, fbrr_base + GetForcedByRefParamOffset(i));
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(pi.pDtor));
IA32_Call_Reg(&m_HookFunc, REG_EAX);
}
}
}
// May not touch eax!
jit_int32_t GenContext::PushParams(jit_int32_t param_base_offset, jit_int32_t save_ret_to, int v_place_for_memret)
jit_int32_t GenContext::PushParams(jit_int32_t param_base_offset, jit_int32_t save_ret_to, int v_place_for_memret,
jit_int32_t v_place_fbrr_base)
{
jit_int32_t added_to_stack = 0;
jit_int32_t ret = 0;
@ -354,7 +426,7 @@ namespace SourceHook
ret = PushFloat(cur_offset, pi);
break;
case PassInfo::PassType_Object:
ret = PushObject(cur_offset, pi);
ret = PushObject(cur_offset, pi, v_place_fbrr_base + GetForcedByRefParamOffset(i));
break;
}
}
@ -768,7 +840,7 @@ namespace SourceHook
}
void GenContext::GenerateCallHooks(int v_status, int v_prev_res, int v_cur_res, int v_iter,
int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret)
int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base)
{
jitoffs_t counter, tmppos;
jitoffs_t counter2, tmppos2;
@ -815,7 +887,7 @@ namespace SourceHook
// call eax
// gcc: clean up
jit_int32_t gcc_clean_bytes = PushParams(base_param_offset, v_plugin_ret, v_place_for_memret);
jit_int32_t gcc_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);
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
@ -823,11 +895,16 @@ namespace SourceHook
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EAX, 2*SIZE_PTR);
IA32_Call_Reg(&m_HookFunc, REG_EAX);
DestroyParams(v_place_fbrr_base);
SaveRetVal(v_plugin_ret, v_place_for_memret);
// cleanup
#if SH_COMP == SH_COMP_GCC
IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, gcc_clean_bytes + SIZE_PTR, MOD_REG);
#endif
// params + thisptr
GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, gcc_clean_bytes + SIZE_PTR, MOD_REG));
// process meta return:
// prev_res = cur_res
@ -866,25 +943,8 @@ namespace SourceHook
m_HookFunc.rewrite(tmppos, static_cast<jit_int32_t>(counter));
}
short GenContext::GetParamsStackSize()
{
short acc = 0;
for (int i = 0; i < m_Proto.GetNumOfParams(); ++i)
{
acc += GetStackSize(m_Proto.GetParam(i));
}
// Memory return: address is first param
if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)
acc += SIZE_PTR;
// :TODO: cdecl: THIS POINTER AS FIRST PARAM!!!
return acc;
}
void GenContext::GenerateCallOrig(int v_status, int v_pContext, int param_base_offs, int v_this,
int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret)
int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base)
{
jitoffs_t counter, tmppos;
jitoffs_t counter2, tmppos2;
@ -937,7 +997,7 @@ namespace SourceHook
m_HookFunc.start_count(counter2);
// push params
jit_int32_t gcc_clean_bytes = PushParams(param_base_offs, v_orig_ret, v_place_for_memret);
jit_int32_t gcc_clean_bytes = PushParams(param_base_offs, v_orig_ret, v_place_for_memret, v_place_fbrr_base);
// thisptr
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_this);
@ -953,10 +1013,11 @@ namespace SourceHook
// cleanup
#if SH_COMP == SH_COMP_GCC
// params + thisptr
IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, gcc_clean_bytes + SIZE_PTR, MOD_REG);
#endif
DestroyParams(v_place_fbrr_base);
// save retval
SaveRetVal(v_orig_ret, v_place_for_memret);
@ -1166,6 +1227,9 @@ namespace SourceHook
// if required:
// my_rettype place_for_memret ebp - 28 - sizeof(my_rettype)*4 -4
// gcc only: if required:
// place forced byref params ebp - 28 - sizeof(my_rettype)*{4 or 5}
const jit_int8_t v_vfnptr_origentry = -4 + addstackoffset;
@ -1196,11 +1260,14 @@ namespace SourceHook
jit_int32_t v_place_for_memret = -28 + addstackoffset - GetStackSize(m_Proto.GetRet()) * 4;
jit_int32_t v_place_fbrr_base = -28 + addstackoffset - GetStackSize(m_Proto.GetRet()) * (MemRetWithTempObj() ? 5 : 4);
// Hash for temporary storage for byval params with copy constructors
// (param, offset into stack)
short usedStackBytes = 3*SIZE_MWORD + 3*SIZE_PTR // vfnptr_origentry, status, prev_res, cur_res, iter, pContext
+ 3 * GetStackSize(m_Proto.GetRet()) + (m_Proto.GetRet().size == 0 ? 0 : SIZE_PTR) // ret_ptr, orig_ret, override_ret, plugin_ret
+ (MemRetWithTempObj() ? GetStackSize(m_Proto.GetRet()) : 0)
+ GetForcedByRefParamsSize()
- addstackoffset; // msvc: current thisptr
IA32_Sub_Rm_Imm32(&m_HookFunc, REG_ESP, usedStackBytes, MOD_REG);
@ -1244,15 +1311,15 @@ namespace SourceHook
// ********************** call pre hooks **********************
GenerateCallHooks(v_status, v_prev_res, v_cur_res, v_iter, v_pContext, param_base_offs,
v_plugin_ret, v_place_for_memret);
v_plugin_ret, v_place_for_memret, v_place_fbrr_base);
// ********************** call orig func **********************
GenerateCallOrig(v_status, v_pContext, param_base_offs, v_this, v_vfnptr_origentry, v_orig_ret,
v_override_ret, v_place_for_memret);
v_override_ret, v_place_for_memret, v_place_fbrr_base);
// ********************** call post hooks **********************
GenerateCallHooks(v_status, v_prev_res, v_cur_res, v_iter, v_pContext, param_base_offs,
v_plugin_ret, v_place_for_memret);
v_plugin_ret, v_place_for_memret, v_place_fbrr_base);
// ********************** end context and return **********************
@ -1265,8 +1332,9 @@ namespace SourceHook
for (int i = 0; i < m_Proto.GetNumOfParams(); ++i)
{
const IntPassInfo &pi = m_Proto.GetParam(i);
// GCC: NOT of forced byref params. the caller destructs those.
if (pi.type == PassInfo::PassType_Object && (pi.flags & PassInfo::PassFlag_ODtor) &&
(pi.flags & PassInfo::PassFlag_ByVal))
(pi.flags & PassInfo::PassFlag_ByVal) && !(pi.flags & PassFlag_ForcedByRef))
{
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, cur_param_pos);
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(pi.pDtor));
@ -1420,6 +1488,7 @@ namespace SourceHook
pi.type != PassInfo::PassType_Float &&
pi.type != PassInfo::PassType_Object)
{
printf("A\n");
return false;
}
@ -1427,16 +1496,28 @@ namespace SourceHook
(pi.flags & PassInfo::PassFlag_ByVal))
{
if ((pi.flags & PassInfo::PassFlag_CCtor) && !pi.pCopyCtor)
{
printf("B\n");
return false;
}
if ((pi.flags & PassInfo::PassFlag_ODtor) && !pi.pDtor)
{
printf("C\n");
return false;
}
if ((pi.flags & PassInfo::PassFlag_AssignOp) && !pi.pAssignOperator)
{
printf("D\n");
return false;
}
if ((pi.flags & PassInfo::PassFlag_OCtor) && !pi.pNormalCtor)
{
printf("D\n");
return false;
}
}
if ((pi.flags & (PassInfo::PassFlag_ByVal | PassInfo::PassFlag_ByRef)) == 0)
@ -1505,8 +1586,7 @@ namespace SourceHook
if (pi.type == PassInfo::PassType_Object &&
(pi.flags & PassInfo::PassFlag_ODtor))
{
pi.flags &= ~PassInfo::PassFlag_ByVal;
pi.flags |= PassInfo::PassFlag_ByRef;
pi.flags |= PassFlag_ForcedByRef;
}
}
#endif

View File

@ -156,6 +156,7 @@ namespace SourceHook
{
const static int SIZE_MWORD = 4;
const static int SIZE_PTR = sizeof(void*);
const static int PassFlag_ForcedByRef = (1<<30); // ByVal in source, but actually passed by reference (GCC) -> private pass, destruct
CProto m_Proto;
int m_VtblOffs;
@ -180,19 +181,22 @@ namespace SourceHook
// size info
jit_int32_t GetRealSize(const IntPassInfo &info);
jit_int32_t GetStackSize(const IntPassInfo &info);
short GetParamsStackSize(); // sum(GetStackSize(i), 0 <= i < numOfParams)
short GetParamsStackSize(); // sum(GetStackSize(param[i]), 0 <= i < numOfParams)
// Helpers
void BitwiseCopy_Setup();
void BitwiseCopy_Do(size_t size);
// Param push
short GetForcedByRefParamsSize(); // sum(param[i] is forcedbyref ? GetStackSize(param[i]) : 0, 0 <= i < numOfParams)
short GetForcedByRefParamOffset(int p); // sum(param[i] is forcedbyref ? GetStackSize(param[i]) : 0, 0 <= i < p)
jit_int32_t PushParams(jit_int32_t param_base_offset, jit_int32_t save_ret_to,
jit_int32_t v_place_for_memret); // save_ret_to and v_place_for_memret only used for memory returns
jit_int32_t v_place_for_memret, jit_int32_t v_place_fbrr_base); // save_ret_to and v_place_for_memret only used for memory returns
jit_int32_t PushRef(jit_int32_t param_offset, const IntPassInfo &pi);
jit_int32_t PushBasic(jit_int32_t param_offset, const IntPassInfo &pi);
jit_int32_t PushFloat(jit_int32_t param_offset, const IntPassInfo &pi);
jit_int32_t PushObject(jit_int32_t param_offset, const IntPassInfo &pi);
jit_int32_t PushObject(jit_int32_t param_offset, const IntPassInfo &pi, jit_int32_t v_place_fbrr);
void DestroyParams(jit_int32_t fbrr_base);
// Ret val processing
void SaveRetVal(jit_int32_t v_where, jit_int32_t v_place_for_memret);
@ -205,11 +209,11 @@ namespace SourceHook
// Call hooks
void GenerateCallHooks(int v_status, int v_prev_res, int v_cur_res, int v_iter,
int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret);
int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base);
// Call orig
void GenerateCallOrig(int v_status, int v_pContext, int param_base_offs, int v_this,
int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret);
int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base);
// Hook loop
void CallSetupHookLoop(int v_orig_ret, int v_override_ret,

View File

@ -114,7 +114,7 @@ namespace
template <int MYSIZE>
std::ostream& operator <<(std::ostream &os, const Object<MYSIZE> &obj)
{
os << "Some Obj!";
os << "Some Obj" << static_cast<int>(obj.x[0]);
return os;
}

View File

@ -40,18 +40,13 @@ public:
template <class T>
void *FindFuncAddr(T mfp)
{
if (sizeof(mfp) != sizeof(void*))
return NULL;
else
union
{
union
{
T a;
void *b;
} u;
u.a = mfp;
return u.b;
}
T a;
void *b;
} u;
u.a = mfp;
return u.b;
}
// Reference carrier

View File

@ -40,18 +40,13 @@ public:
template <class T>
void *FindFuncAddr(T mfp)
{
if (sizeof(mfp) != sizeof(void*))
return NULL;
else
union
{
union
{
T a;
void *b;
} u;
u.a = mfp;
return u.b;
}
T a;
void *b;
} u;
u.a = mfp;
return u.b;
}
// Reference carrier