Fix detour of functions returning a float
Floats are always returned in FPU register st0. Since the value in st0 doesn't matter in a pre-hook before the function was executed, don't try to save and restore the value of the FPU stack top for a pre-hook. Only replace st0 after a post hook.
This commit is contained in:
parent
6a98d26307
commit
a89eb67124
@ -227,7 +227,7 @@ void* CHook::CreateBridge()
|
||||
masm.cmpb(r8_al, ReturnAction_Supercede);
|
||||
|
||||
// Restore the previously saved registers, so any changes will be applied
|
||||
Write_RestoreRegisters(masm);
|
||||
Write_RestoreRegisters(masm, HOOKTYPE_PRE);
|
||||
|
||||
masm.j(equal, &label_supercede);
|
||||
|
||||
@ -293,7 +293,7 @@ void* CHook::CreatePostCallback()
|
||||
Write_CallHandler(masm, HOOKTYPE_POST);
|
||||
|
||||
// Restore the previously saved registers, so any changes will be applied
|
||||
Write_RestoreRegisters(masm);
|
||||
Write_RestoreRegisters(masm, HOOKTYPE_POST);
|
||||
|
||||
// Save scratch registers that are used by GetReturnAddress
|
||||
static void* pEAX = NULL;
|
||||
@ -337,16 +337,19 @@ void CHook::Write_CallHandler(sp::MacroAssembler& masm, HookType_t type)
|
||||
ReturnAction_t (__cdecl CHook::*HookHandler)(HookType_t) = &CHook::HookHandler;
|
||||
|
||||
// Save the registers so that we can access them in our handlers
|
||||
Write_SaveRegisters(masm);
|
||||
Write_SaveRegisters(masm, type);
|
||||
|
||||
// Align the stack to 16 bytes.
|
||||
masm.subl(esp, 8);
|
||||
|
||||
// Call the global hook handler
|
||||
masm.push(type);
|
||||
masm.push(intptr_t(this));
|
||||
masm.call(ExternalAddress((void *&)HookHandler));
|
||||
masm.addl(esp, 8);
|
||||
masm.addl(esp, 16);
|
||||
}
|
||||
|
||||
void CHook::Write_SaveRegisters(sp::MacroAssembler& masm)
|
||||
void CHook::Write_SaveRegisters(sp::MacroAssembler& masm, HookType_t type)
|
||||
{
|
||||
ke::Vector<Register_t> vecRegistersToSave = m_pCallingConvention->GetRegisters();
|
||||
for(size_t i = 0; i < vecRegistersToSave.length(); i++)
|
||||
@ -394,7 +397,12 @@ void CHook::Write_SaveRegisters(sp::MacroAssembler& masm)
|
||||
// ========================================================================
|
||||
// >> 80-bit FPU registers
|
||||
// ========================================================================
|
||||
case ST0: masm.fst32(Operand(ExternalAddress(m_pRegisters->m_st0->m_pAddress))); break;
|
||||
case ST0:
|
||||
// Don't mess with the FPU stack in a pre-hook. The float return is returned in st0,
|
||||
// so only load it in a post hook to avoid writing back NaN.
|
||||
if (type == HOOKTYPE_POST)
|
||||
masm.fst32(Operand(ExternalAddress(m_pRegisters->m_st0->m_pAddress)));
|
||||
break;
|
||||
//case ST1: masm.movl(tword_ptr_abs(Ptr(m_pRegisters->m_st1->m_pAddress)), st1); break;
|
||||
//case ST2: masm.movl(tword_ptr_abs(Ptr(m_pRegisters->m_st2->m_pAddress)), st2); break;
|
||||
//case ST3: masm.movl(tword_ptr_abs(Ptr(m_pRegisters->m_st3->m_pAddress)), st3); break;
|
||||
@ -408,7 +416,7 @@ void CHook::Write_SaveRegisters(sp::MacroAssembler& masm)
|
||||
}
|
||||
}
|
||||
|
||||
void CHook::Write_RestoreRegisters(sp::MacroAssembler& masm)
|
||||
void CHook::Write_RestoreRegisters(sp::MacroAssembler& masm, HookType_t type)
|
||||
{
|
||||
ke::Vector<Register_t> vecRegistersToSave = m_pCallingConvention->GetRegisters();
|
||||
for (size_t i = 0; i < vecRegistersToSave.length(); i++)
|
||||
@ -456,7 +464,17 @@ void CHook::Write_RestoreRegisters(sp::MacroAssembler& masm)
|
||||
// ========================================================================
|
||||
// >> 80-bit FPU registers
|
||||
// ========================================================================
|
||||
case ST0: masm.fld32(Operand(ExternalAddress(m_pRegisters->m_st0->m_pAddress))); break;
|
||||
case ST0:
|
||||
if (type == HOOKTYPE_POST) {
|
||||
// Replace the top of the FPU stack.
|
||||
// Copy st0 to st0 and pop -> just pop the FPU stack.
|
||||
masm.fstp(st0);
|
||||
// Push a value to the FPU stack.
|
||||
// TODO: Only write back when changed? Save full 80bits for that case.
|
||||
// Avoid truncation of the data if it's unchanged.
|
||||
masm.fld32(Operand(ExternalAddress(m_pRegisters->m_st0->m_pAddress)));
|
||||
}
|
||||
break;
|
||||
//case ST1: masm.movl(st1, tword_ptr_abs(Ptr(m_pRegisters->m_st1->m_pAddress))); break;
|
||||
//case ST2: masm.movl(st2, tword_ptr_abs(Ptr(m_pRegisters->m_st2->m_pAddress))); break;
|
||||
//case ST3: masm.movl(st3, tword_ptr_abs(Ptr(m_pRegisters->m_st3->m_pAddress))); break;
|
||||
|
@ -174,8 +174,8 @@ private:
|
||||
|
||||
void Write_ModifyReturnAddress(sp::MacroAssembler& masm);
|
||||
void Write_CallHandler(sp::MacroAssembler& masm, HookType_t type);
|
||||
void Write_SaveRegisters(sp::MacroAssembler& masm);
|
||||
void Write_RestoreRegisters(sp::MacroAssembler& masm);
|
||||
void Write_SaveRegisters(sp::MacroAssembler& masm, HookType_t type);
|
||||
void Write_RestoreRegisters(sp::MacroAssembler& masm, HookType_t type);
|
||||
|
||||
void* CreatePostCallback();
|
||||
|
||||
|
@ -387,7 +387,7 @@ ReturnAction_t HandleDetour(HookType_t hookType, CHook* pDetour)
|
||||
}
|
||||
else if (pWrapper->returnType == ReturnType_Float)
|
||||
{
|
||||
*(float *)tempRetBuf = *(float *)returnStruct->newResult;
|
||||
*(float *)&tempRetBuf = *(float *)returnStruct->newResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user