mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-02-20 13:54:14 +01:00
16-byte stack alignment on external calls
--HG-- branch : hookman_autogen extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/hookman_autogen%40574
This commit is contained in:
parent
12cb5ea79a
commit
8cb55b818b
@ -203,6 +203,53 @@ namespace SourceHook
|
||||
IA32_Pop_Reg(&m_HookFunc, REG_EDI);
|
||||
}
|
||||
|
||||
jit_int32_t GenContext::AlignStackBeforeCall(int paramsize, int flags)
|
||||
{
|
||||
paramsize +=
|
||||
GCC_ONLY( ((flags & AlignStack_GCC_ThisOnStack)!=0 ? SIZE_PTR : 0) + )
|
||||
MSVC_ONLY( ((flags & AlignStack_MSVC_ThisOnStack)!=0 ? SIZE_PTR : 0) + )
|
||||
((flags & AlignStack_MemRet)!=0 ? SIZE_PTR : 0);
|
||||
|
||||
// At the beginning of the hookfunc, the stack is aligned to a 16 bytes boundary.
|
||||
// Then, m_BytesPushedAfterInitialAlignment were pushed (can also be 0).
|
||||
|
||||
// After this function is called, paramsize bytes will be pushed onto the stack
|
||||
// After that, the alignment has to be a 16 bytes boundary again.
|
||||
|
||||
|
||||
// How many bytes we would subtract if the alignment was alright now:
|
||||
int subtractFromEsp = 16 - (paramsize % 16);
|
||||
if (subtractFromEsp == 16)
|
||||
subtractFromEsp = 0;
|
||||
|
||||
// But: there might be bytes pushed alreay!
|
||||
subtractFromEsp -= m_BytesPushedAfterInitialAlignment;
|
||||
|
||||
// For example: paramsize was 0 and m_BytesPushedAfterInitialAlignment was 4.
|
||||
// we then have to push another 12 bytes to reach 16 bytes alignment again.
|
||||
|
||||
if (subtractFromEsp < 0)
|
||||
subtractFromEsp = 16 - ((-subtractFromEsp) % 16);
|
||||
|
||||
IA32_Sub_Rm_ImmAuto(&m_HookFunc, REG_ESP, subtractFromEsp, MOD_REG);
|
||||
|
||||
return subtractFromEsp;
|
||||
}
|
||||
|
||||
void GenContext::AlignStackAfterCall(jit_int32_t numofbytes)
|
||||
{
|
||||
IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, numofbytes, MOD_REG);
|
||||
}
|
||||
|
||||
void GenContext::CheckAlignmentBeforeCall()
|
||||
{
|
||||
#if 0
|
||||
IA32_Test_Rm_Imm32(&m_HookFunc, REG_ESP, 15, MOD_REG);
|
||||
IA32_Jump_Cond_Imm8(&m_HookFunc, CC_Z, 1);
|
||||
IA32_Int3(&m_HookFunc);
|
||||
#endif
|
||||
}
|
||||
|
||||
short GenContext::GetParamsTotalStackSize()
|
||||
{
|
||||
short acc = 0;
|
||||
@ -220,7 +267,7 @@ namespace SourceHook
|
||||
for (int i = 0; i < p; ++i)
|
||||
{
|
||||
if (m_Proto.GetParam(i).flags & PassFlag_ForcedByRef)
|
||||
off += AlignSize(m_Proto.GetParam(i).size, 4);
|
||||
off += AlignSize(static_cast<jit_int32_t>(m_Proto.GetParam(i).size), 4);
|
||||
}
|
||||
return off;
|
||||
}
|
||||
@ -328,31 +375,35 @@ namespace SourceHook
|
||||
// if there is a copy constructor..
|
||||
if (pi.pCopyCtor)
|
||||
{
|
||||
// save eax
|
||||
// push src addr
|
||||
// this= target addr = forcedbyref ? ebp+place_fbrr : esp+12
|
||||
// call copy constructor
|
||||
// restore eax
|
||||
|
||||
// :TODO: alignment here?
|
||||
// can't use normal alignment methods
|
||||
// because an unknown number of bytes has been pushed already (the other params)
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EAX);
|
||||
|
||||
|
||||
// compute dest addr to ECX
|
||||
// = forcedbyref ? ebp+place_fbrr : esp+12
|
||||
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);
|
||||
|
||||
// compute src addr to EAX
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EAX, REG_EBP, param_offset);
|
||||
|
||||
// push params (gcc: also this)
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
// call
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EDX, DownCastPtr(pi.pCopyCtor));
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EDX);
|
||||
GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, 2 * SIZE_PTR, MOD_REG));
|
||||
|
||||
// restore eax
|
||||
IA32_Pop_Reg(&m_HookFunc, REG_EAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
// bitwise copy
|
||||
|
||||
|
||||
BitwiseCopy_Setup();
|
||||
|
||||
@ -379,7 +430,7 @@ namespace SourceHook
|
||||
return SIZE_PTR;
|
||||
}
|
||||
|
||||
return DownCastSize(pi.size);
|
||||
return GetParamStackSize(pi);
|
||||
}
|
||||
|
||||
void GenContext::DestroyParams(jit_int32_t fbrr_base)
|
||||
@ -391,11 +442,15 @@ namespace SourceHook
|
||||
(pi.flags & PassInfo::PassFlag_ByVal) && (pi.flags & PassFlag_ForcedByRef))
|
||||
{
|
||||
// Actually, this is only for GCC (see line above: ForcedByRef)
|
||||
jit_int32_t tmpAlign = AlignStackBeforeCall(0, AlignStack_GCC_ThisOnStack);
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, fbrr_base + GetForcedByRefParamOffset(i));
|
||||
IA32_Push_Reg(&m_HookFunc, REG_ECX);
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(pi.pDtor));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
IA32_Pop_Reg(&m_HookFunc, REG_ECX);
|
||||
|
||||
AlignStackAfterCall(tmpAlign);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -436,7 +491,7 @@ namespace SourceHook
|
||||
}
|
||||
else if (pi.flags & PassInfo::PassFlag_ByRef)
|
||||
{
|
||||
PushRef(cur_offset, pi);
|
||||
ret = PushRef(cur_offset, pi);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -501,14 +556,19 @@ namespace SourceHook
|
||||
// call it
|
||||
// gcc: clean up
|
||||
|
||||
jit_int32_t tmpAlign = AlignStackBeforeCall(SIZE_PTR, AlignStack_GCC_ThisOnStack);
|
||||
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDX, REG_EBP, v_place_for_memret);
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_where);
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EDX);
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pAssignOperator));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
AlignStackAfterCall(tmpAlign);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -531,11 +591,16 @@ namespace SourceHook
|
||||
//call it
|
||||
//gcc: clean up
|
||||
|
||||
jit_int32_t tmpAlign = AlignStackBeforeCall(0, AlignStack_GCC_ThisOnStack);
|
||||
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_place_for_memret);
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pDtor));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
AlignStackAfterCall(tmpAlign);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -636,7 +701,7 @@ namespace SourceHook
|
||||
tmppos = IA32_Jump_Cond_Imm8(&m_HookFunc, CC_NGE, 0);
|
||||
m_HookFunc.start_count(counter);
|
||||
|
||||
// eax = pContext->GetOverrideRetPtr()
|
||||
// eax = pContext->GetOverrideRetPtr() no alignment needs
|
||||
// ECX = pContext
|
||||
// gcc: push ecx
|
||||
// eax = [ecx]
|
||||
@ -672,6 +737,8 @@ namespace SourceHook
|
||||
// call it
|
||||
// gcc: clean up
|
||||
|
||||
jit_int32_t tmpAlign = AlignStackBeforeCall(SIZE_PTR, AlignStack_GCC_ThisOnStack);
|
||||
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDX, REG_EBP, v_plugin_ret);
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EDX);
|
||||
#if SH_COMP == SH_COMP_MSVC
|
||||
@ -681,8 +748,11 @@ namespace SourceHook
|
||||
#endif
|
||||
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pAssignOperator));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, 2 * SIZE_PTR, MOD_REG));
|
||||
|
||||
AlignStackAfterCall(tmpAlign);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -817,6 +887,8 @@ namespace SourceHook
|
||||
// call it
|
||||
// gcc: clean up
|
||||
|
||||
jit_int32_t tmpAlign = AlignStackBeforeCall(SIZE_PTR, AlignStack_GCC_ThisOnStack);
|
||||
|
||||
IA32_Mov_Reg_Rm(&m_HookFunc, REG_EDX, REG_ECX, MOD_REG);
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EDX);
|
||||
|
||||
@ -827,8 +899,11 @@ namespace SourceHook
|
||||
#endif
|
||||
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pCopyCtor));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, 2 * SIZE_PTR, MOD_REG));
|
||||
|
||||
AlignStackAfterCall(tmpAlign);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -898,6 +973,12 @@ namespace SourceHook
|
||||
// gcc: clean up
|
||||
|
||||
jit_int32_t caller_clean_bytes = 0; // gcc always, msvc never (hooks never have varargs!)
|
||||
|
||||
jit_int32_t alignBytes = AlignStackBeforeCall(
|
||||
GetParamsTotalStackSize() + ((m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt)!=0 ? SIZE_PTR : 0),
|
||||
AlignStack_GCC_ThisOnStack | ((m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem) == 0 ? 0 : AlignStack_MemRet)
|
||||
);
|
||||
|
||||
// vafmt: push va_buf
|
||||
if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt)
|
||||
{
|
||||
@ -914,8 +995,11 @@ namespace SourceHook
|
||||
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_DispAuto(&m_HookFunc, REG_EAX, REG_EAX, 2*SIZE_PTR);
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
|
||||
AlignStackAfterCall(alignBytes);
|
||||
|
||||
DestroyParams(v_place_fbrr_base);
|
||||
|
||||
SaveRetVal(v_plugin_ret, v_place_for_memret);
|
||||
@ -956,7 +1040,7 @@ namespace SourceHook
|
||||
// jump back to loop begin
|
||||
tmppos2 = IA32_Jump_Imm32(&m_HookFunc, 0);
|
||||
m_HookFunc.end_count(loop_begin_counter);
|
||||
m_HookFunc.rewrite(tmppos2, -static_cast<jit_int32_t>(loop_begin_counter));
|
||||
m_HookFunc.rewrite(tmppos2, static_cast<jit_int32_t>(-loop_begin_counter));
|
||||
|
||||
m_HookFunc.end_count(counter);
|
||||
m_HookFunc.rewrite(tmppos, static_cast<jit_int32_t>(counter));
|
||||
@ -1016,7 +1100,14 @@ namespace SourceHook
|
||||
m_HookFunc.start_count(counter2);
|
||||
|
||||
jit_int32_t caller_clean_bytes = 0; // gcc always, msvc when cdecl-like (varargs)
|
||||
|
||||
|
||||
jit_int32_t alignBytes = AlignStackBeforeCall(
|
||||
GetParamsTotalStackSize() + ((m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt)!=0 ? 2*SIZE_PTR : 0),
|
||||
AlignStack_GCC_ThisOnStack |
|
||||
((m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem) == 0 ? 0 : AlignStack_MemRet) |
|
||||
((m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs) == 0 ? 0 : AlignStack_MSVC_ThisOnStack)
|
||||
);
|
||||
|
||||
// vafmt: push va_buf, then "%s"
|
||||
if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt)
|
||||
{
|
||||
@ -1056,8 +1147,11 @@ namespace SourceHook
|
||||
|
||||
// call
|
||||
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_vfnptr_origentry);
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
|
||||
AlignStackAfterCall(alignBytes);
|
||||
|
||||
// cleanup
|
||||
if (SH_COMP == SH_COMP_GCC || (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs))
|
||||
IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, caller_clean_bytes + SIZE_PTR, MOD_REG);
|
||||
@ -1099,14 +1193,19 @@ namespace SourceHook
|
||||
// call it
|
||||
// gcc: clean up
|
||||
|
||||
jit_int32_t tmpAlign = AlignStackBeforeCall(SIZE_PTR, AlignStack_GCC_ThisOnStack);
|
||||
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDX, REG_EBP, v_override_ret);
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_orig_ret);
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EDX);
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pAssignOperator));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, 2*SIZE_PTR, MOD_REG));
|
||||
|
||||
AlignStackAfterCall(tmpAlign);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1390,6 +1489,10 @@ namespace SourceHook
|
||||
|
||||
IA32_Sub_Rm_Imm32(&m_HookFunc, REG_ESP, ComputeVarsSize(), MOD_REG);
|
||||
|
||||
// Initial stack alignment
|
||||
IA32_And_Rm_Imm32(&m_HookFunc, REG_ESP, MOD_REG, -16);
|
||||
m_BytesPushedAfterInitialAlignment = 0;
|
||||
|
||||
// init status localvar
|
||||
IA32_Mov_Rm_Imm32_Disp8(&m_HookFunc, REG_EBP, MRES_IGNORED, v_status);
|
||||
|
||||
@ -1407,6 +1510,8 @@ namespace SourceHook
|
||||
{
|
||||
// vsnprintf
|
||||
|
||||
jit_int32_t tmpAlign = AlignStackBeforeCall(SIZE_PTR*3 + sizeof(size_t), AlignStack_GCC_ThisOnStack);
|
||||
|
||||
// push valist, fmt param, maxsize, buffer
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EAX);
|
||||
IA32_Push_Rm_DispAuto(&m_HookFunc, REG_EBP, param_base_offs + GetParamsTotalStackSize()); // last given param (+4-4, see above)
|
||||
@ -1416,11 +1521,14 @@ namespace SourceHook
|
||||
|
||||
// call
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(&vsnprintf));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
|
||||
// Clean up (cdecl)
|
||||
IA32_Add_Rm_Imm32(&m_HookFunc, REG_ESP, 0x10, MOD_REG);
|
||||
|
||||
AlignStackAfterCall(tmpAlign);
|
||||
|
||||
// Set trailing zero
|
||||
IA32_Xor_Reg_Rm(&m_HookFunc, REG_EDX, REG_EDX, MOD_REG);
|
||||
IA32_Mov_Rm8_Reg8_DispAuto(&m_HookFunc, REG_EBP, REG_EDX, v_va_buf + SourceHook::STRBUF_LEN - 1);
|
||||
@ -1430,10 +1538,13 @@ namespace SourceHook
|
||||
if((m_Proto.GetRet().flags & PassInfo::PassFlag_ByVal) &&
|
||||
m_Proto.GetRet().pNormalCtor)
|
||||
{
|
||||
jit_int32_t tmpAlign = AlignStackBeforeCall(0, AlignStack_GCC_ThisOnStack);
|
||||
|
||||
// orig_reg
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_orig_ret);
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pNormalCtor));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
@ -1441,6 +1552,7 @@ namespace SourceHook
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_override_ret);
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pNormalCtor));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
@ -1448,9 +1560,12 @@ namespace SourceHook
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_plugin_ret);
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pNormalCtor));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
AlignStackAfterCall(tmpAlign);
|
||||
|
||||
// _don't_ call a constructor for v_place_for_memret !
|
||||
}
|
||||
|
||||
@ -1477,6 +1592,9 @@ namespace SourceHook
|
||||
CallEndContext(v_pContext);
|
||||
|
||||
// Call destructors of byval object params which have a destructor
|
||||
|
||||
jit_int32_t tmpAlign = AlignStackBeforeCall(0, AlignStack_GCC_ThisOnStack);
|
||||
|
||||
jit_int32_t cur_param_pos = param_base_offs;
|
||||
for (int i = 0; i < m_Proto.GetNumOfParams(); ++i)
|
||||
{
|
||||
@ -1487,11 +1605,16 @@ namespace SourceHook
|
||||
{
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, cur_param_pos);
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(pi.pDtor));
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX));
|
||||
}
|
||||
cur_param_pos += GetParamStackSize(pi);
|
||||
}
|
||||
|
||||
AlignStackAfterCall(tmpAlign);
|
||||
|
||||
DoReturn(v_ret_ptr, v_memret_addr);
|
||||
|
||||
// Call destructors of orig_ret/ ...
|
||||
@ -1502,26 +1625,37 @@ namespace SourceHook
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EAX);
|
||||
IA32_Push_Reg(&m_HookFunc, REG_EDX);
|
||||
|
||||
m_BytesPushedAfterInitialAlignment += 8;
|
||||
|
||||
jit_int32_t tmpAlign = AlignStackBeforeCall(0, AlignStack_GCC_ThisOnStack);
|
||||
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_plugin_ret);
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pDtor));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_override_ret);
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pDtor));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_orig_ret);
|
||||
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
|
||||
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pDtor));
|
||||
CheckAlignmentBeforeCall();
|
||||
IA32_Call_Reg(&m_HookFunc, REG_EAX);
|
||||
GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX));
|
||||
|
||||
AlignStackAfterCall(tmpAlign);
|
||||
|
||||
IA32_Pop_Reg(&m_HookFunc, REG_EDX);
|
||||
IA32_Pop_Reg(&m_HookFunc, REG_EAX);
|
||||
|
||||
m_BytesPushedAfterInitialAlignment -= 8;
|
||||
}
|
||||
|
||||
// epilogue
|
||||
|
@ -180,6 +180,17 @@ namespace SourceHook
|
||||
int m_RegCounter;
|
||||
jit_int8_t NextRegEBX_ECX_EDX();
|
||||
|
||||
int m_BytesPushedAfterInitialAlignment;
|
||||
enum AlignStackFlags
|
||||
{
|
||||
AlignStack_GCC_ThisOnStack = 1,
|
||||
AlignStack_MSVC_ThisOnStack = 2,
|
||||
AlignStack_MemRet = 4
|
||||
};
|
||||
jit_int32_t AlignStackBeforeCall(int paramsize, int flags);
|
||||
void AlignStackAfterCall(jit_int32_t numofbytes);
|
||||
void CheckAlignmentBeforeCall();
|
||||
|
||||
// size info
|
||||
jit_int32_t GetRealSize(const IntPassInfo &info); // checks for reference
|
||||
jit_int32_t AlignSize(jit_int32_t x, jit_int32_t boundary); // align a size
|
||||
|
@ -111,6 +111,7 @@
|
||||
#define IA32_CMPSB 0xA6 // no extra encoding
|
||||
#define IA32_TEST_RM_REG8 0x84 // encoding is /r
|
||||
#define IA32_TEST_RM_REG 0x85 // encoding is /r
|
||||
#define IA32_TEST_RM_IMM32 0xF7 // encoding is /0 <imm32>
|
||||
#define IA32_JCC_IMM 0x70 // encoding is +cc <imm8>
|
||||
#define IA32_JCC_IMM32_1 0x0F // opcode part 1
|
||||
#define IA32_JCC_IMM32_2 0x80 // encoding is +cc <imm32>
|
||||
@ -1477,6 +1478,13 @@ namespace SourceHook
|
||||
jit->write_ubyte(ia32_modrm(mode, reg2, reg1));
|
||||
}
|
||||
|
||||
inline void IA32_Test_Rm_Imm32(JitWriter *jit, jit_uint8_t operand1, jit_int32_t imm_operand, jit_uint8_t mode)
|
||||
{
|
||||
jit->write_ubyte(IA32_TEST_RM_IMM32);
|
||||
jit->write_ubyte(ia32_modrm(mode, 0, operand1));
|
||||
jit->write_int32(imm_operand);
|
||||
}
|
||||
|
||||
inline void IA32_Cmp_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
|
||||
{
|
||||
jit->write_ubyte(IA32_CMP_RM_REG);
|
||||
|
@ -363,6 +363,9 @@
|
||||
<File
|
||||
RelativePath="..\..\sourcehook_impl_cvfnptr.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sourcehook_pibuilder.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sourcehook_test.h">
|
||||
</File>
|
||||
|
Loading…
x
Reference in New Issue
Block a user