From f2ba0f136d7667883afdaee23e88959b4b26f095 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 16 Feb 2014 19:18:08 -0800 Subject: [PATCH] Fix stack overflow on x64 with memchecks, darn it. --- Common/ArmThunk.cpp | 20 ++++++++++++++++++++ Common/Thunk.cpp | 35 ++++++++++++++++++++++++++--------- Common/Thunk.h | 16 ++++++++-------- Core/MIPS/x86/Jit.cpp | 8 ++++---- 4 files changed, 58 insertions(+), 21 deletions(-) diff --git a/Common/ArmThunk.cpp b/Common/ArmThunk.cpp index 4d25fb9150..8be655b4d9 100644 --- a/Common/ArmThunk.cpp +++ b/Common/ArmThunk.cpp @@ -47,8 +47,28 @@ void ThunkManager::Shutdown() FreeCodeSpace(); } +int ThunkManager::ThunkStackOffset() +{ + return 0; +} + +int ThunkManager::ThunkBytesNeeded() +{ + return 0; +} + const void *ThunkManager::ProtectFunction(const void *function, int num_params) { _dbg_assert_msg_(JIT, false, "Arm ThunkManager not implemented? Will crash."); return NULL; } + +void Enter(ThunkEmitter *emit) +{ + _dbg_assert_msg_(JIT, false, "Arm ThunkManager not implemented? Will crash."); +} + +void Leave(ThunkEmitter *emit) +{ + _dbg_assert_msg_(JIT, false, "Arm ThunkManager not implemented? Will crash."); +} diff --git a/Common/Thunk.cpp b/Common/Thunk.cpp index 1e66caf287..9bd24c5c09 100644 --- a/Common/Thunk.cpp +++ b/Common/Thunk.cpp @@ -151,16 +151,11 @@ const void *ThunkManager::ProtectFunction(const void *function, int num_params) PanicAlert("Trying to protect functions before the emu is started. Bad bad bad."); const u8 *call_point = GetCodePtr(); - // Make sure to align stack. + Enter(this); + #ifdef _M_X64 - SUB(64, R(ESP), Imm32(ThunkStackOffset() + ThunkBytesNeeded())); - ABI_CallFunction(save_regs); ABI_CallFunction(function); - ABI_CallFunction(load_regs); - ADD(64, R(ESP), Imm32(ThunkStackOffset() + ThunkBytesNeeded())); - RET(); #else - CALL((const void *)save_regs); // Since parameters are in the previous stack frame, not in registers, this takes some // trickery : we simply re-push the parameters. might not be optimal, but that doesn't really // matter. @@ -172,10 +167,32 @@ const void *ThunkManager::ProtectFunction(const void *function, int num_params) } CALL(function); ABI_RestoreStack(num_params * 4); - CALL((void*)load_regs); - RET(); #endif + Leave(this); + RET(); + thunks[function] = call_point; return (const void *)call_point; } + +void ThunkManager::Enter(ThunkEmitter *emit) +{ +#ifdef _M_X64 + // Make sure to align stack. + emit->SUB(64, R(ESP), Imm32(ThunkStackOffset() + ThunkBytesNeeded())); + emit->ABI_CallFunction(save_regs); +#else + emit->CALL((const void *)save_regs); +#endif +} + +void ThunkManager::Leave(ThunkEmitter *emit) +{ +#ifdef _M_X64 + emit->ABI_CallFunction(load_regs); + emit->ADD(64, R(ESP), Imm32(ThunkStackOffset() + ThunkBytesNeeded())); +#else + emit->CALL((void*)load_regs); +#endif +} diff --git a/Common/Thunk.h b/Common/Thunk.h index b6513a2d10..63d6427126 100644 --- a/Common/Thunk.h +++ b/Common/Thunk.h @@ -39,10 +39,14 @@ // NOT THREAD SAFE. This may only be used from the CPU thread. // Any other thread using this stuff will be FATAL. #if defined(ARM) -class ThunkManager : public ArmGen::ARMXCodeBlock +typedef ArmGen::ARMXEmitter ThunkEmitter; +typedef ArmGen::ARMXCodeBlock ThunkCodeBlock; #else -class ThunkManager : public Gen::XCodeBlock +typedef Gen::XEmitter ThunkEmitter; +typedef Gen::XCodeBlock ThunkCodeBlock; #endif + +class ThunkManager : public ThunkCodeBlock { std::map thunks; @@ -83,12 +87,8 @@ public: return ProtectFunction((const void *)func, 4); } - const u8 *GetSaveRegsFunction() const { - return save_regs; - } - const u8 *GetLoadRegsFunction() const { - return load_regs; - } + void Enter(ThunkEmitter *emit); + void Leave(ThunkEmitter *emit); private: void Init(); diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 79c89170b1..0e7471d3be 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -999,17 +999,17 @@ void Jit::CallProtectedFunction(const void *func, const OpArg &arg1, const OpArg void Jit::CallProtectedFunction(const void *func, const u32 arg1, const u32 arg2, const u32 arg3) { // On x64, we need to save R8, which is caller saved. - ABI_CallFunction(thunks.GetSaveRegsFunction()); + thunks.Enter(this); ABI_CallFunctionCCC(func, arg1, arg2, arg3); - ABI_CallFunction(thunks.GetLoadRegsFunction()); + thunks.Leave(this); } void Jit::CallProtectedFunction(const void *func, const OpArg &arg1, const u32 arg2, const u32 arg3) { // On x64, we need to save R8, which is caller saved. - ABI_CallFunction(thunks.GetSaveRegsFunction()); + thunks.Enter(this); ABI_CallFunctionACC(func, arg1, arg2, arg3); - ABI_CallFunction(thunks.GetLoadRegsFunction()); + thunks.Leave(this); } void Jit::Comp_DoNothing(MIPSOpcode op) { }