From 9da7e666f605b7aa63f1b334d3641de01ef96a37 Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Sat, 2 Jun 2018 13:36:52 +0200 Subject: [PATCH] Fix |thiscall| on linux for functions with arguments The previous fix messed up parameter getters and setters. --- AMBuildScript | 6 +- DynamicHooks/conventions/x86GccThiscall.cpp | 66 +++++++++++++++++++++ DynamicHooks/conventions/x86GccThiscall.h | 15 ++--- DynamicHooks/conventions/x86MsCdecl.cpp | 1 + dynhooks_sourcepawn.cpp | 8 +-- 5 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 DynamicHooks/conventions/x86GccThiscall.cpp diff --git a/AMBuildScript b/AMBuildScript index 1e8f8d4..27473cf 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -270,9 +270,13 @@ program.sources += [ os.path.join('DynamicHooks', 'utilities.cpp'), os.path.join('DynamicHooks', 'conventions', 'x86MsCdecl.cpp'), os.path.join('DynamicHooks', 'conventions', 'x86MsStdcall.cpp'), - os.path.join('DynamicHooks', 'conventions', 'x86MsThiscall.cpp'), ] +if builder.target_platform == 'windows': + program.sources += [os.path.join('DynamicHooks', 'conventions', 'x86MsThiscall.cpp')] +else: + program.sources += [os.path.join('DynamicHooks', 'conventions', 'x86GccThiscall.cpp')] + program.sources += [os.path.join(DHooks.sm_root, 'public', 'smsdk_ext.cpp')] if os.path.isfile(os.path.join(DHooks.sm_root, 'sourcepawn', 'vm', 'x86', 'assembler-x86.cpp')): diff --git a/DynamicHooks/conventions/x86GccThiscall.cpp b/DynamicHooks/conventions/x86GccThiscall.cpp new file mode 100644 index 0000000..7dce3de --- /dev/null +++ b/DynamicHooks/conventions/x86GccThiscall.cpp @@ -0,0 +1,66 @@ +/** +* ============================================================================= +* DynamicHooks +* Copyright (C) 2015 Robin Gohmert. All rights reserved. +* ============================================================================= +* +* This software is provided 'as-is', without any express or implied warranty. +* In no event will the authors be held liable for any damages arising from +* the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software in a +* product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc +* -fPIC thunks correctly +* +* Idea and trampoline code taken from DynDetours (thanks your-name-here). +*/ + +// ============================================================================ +// >> INCLUDES +// ============================================================================ +#include "x86GccThiscall.h" + + +// ============================================================================ +// >> CLASSES +// ============================================================================ + +x86GccThiscall::x86GccThiscall(ke::Vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment) : + x86GccCdecl(vecArgTypes, returnType, iAlignment) +{ + // Always add the |this| pointer. + DataTypeSized_t type; + type.type = DATA_TYPE_POINTER; + type.size = GetDataTypeSize(type, iAlignment); + type.custom_register = None; + m_vecArgTypes.insert(0, type); +} + +int x86GccThiscall::GetArgStackSize() +{ + // Remove the this pointer from the arguments size. + DataTypeSized_t type; + type.type = DATA_TYPE_POINTER; + return x86GccCdecl::GetArgStackSize() - GetDataTypeSize(type, m_iAlignment); +} + +void** x86GccThiscall::GetStackArgumentPtr(CRegisters* pRegisters) +{ + // Skip return address and this pointer. + DataTypeSized_t type; + type.type = DATA_TYPE_POINTER; + return (void **)(pRegisters->m_esp->GetValue() + 4 + GetDataTypeSize(type, m_iAlignment)); +} diff --git a/DynamicHooks/conventions/x86GccThiscall.h b/DynamicHooks/conventions/x86GccThiscall.h index a742157..2e6487e 100644 --- a/DynamicHooks/conventions/x86GccThiscall.h +++ b/DynamicHooks/conventions/x86GccThiscall.h @@ -40,19 +40,14 @@ // ============================================================================ // >> CLASSES // ============================================================================ +// |this| pointer is always passed as implicit first argument on the stack. class x86GccThiscall: public x86GccCdecl { public: - x86GccThiscall(ke::Vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment = 4) : - x86GccCdecl(vecArgTypes, returnType, iAlignment) - { - // Always add the |this| pointer. - DataTypeSized_t type; - type.type = DATA_TYPE_POINTER; - type.size = GetDataTypeSize(type, iAlignment); - type.custom_register = None; - m_vecArgTypes.insert(0, type); - } + x86GccThiscall(ke::Vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment = 4); + + virtual int GetArgStackSize(); + virtual void** GetStackArgumentPtr(CRegisters* pRegisters); }; #endif // _X86_GCC_THISCALL_H \ No newline at end of file diff --git a/DynamicHooks/conventions/x86MsCdecl.cpp b/DynamicHooks/conventions/x86MsCdecl.cpp index 1136d08..71d59ba 100644 --- a/DynamicHooks/conventions/x86MsCdecl.cpp +++ b/DynamicHooks/conventions/x86MsCdecl.cpp @@ -142,6 +142,7 @@ void* x86MsCdecl::GetArgumentPtr(unsigned int iIndex, CRegisters* pRegisters) return pRegister->m_pAddress; } + // Skip return address. size_t iOffset = 4; for(unsigned int i=0; i < iIndex; i++) { diff --git a/dynhooks_sourcepawn.cpp b/dynhooks_sourcepawn.cpp index 1d9158a..89a0c13 100644 --- a/dynhooks_sourcepawn.cpp +++ b/dynhooks_sourcepawn.cpp @@ -2,17 +2,17 @@ #include "util.h" #include +#ifdef KE_WINDOWS #include "conventions/x86MsCdecl.h" #include "conventions/x86MsThiscall.h" #include "conventions/x86MsStdcall.h" -#include "conventions/x86GccCdecl.h" -#include "conventions/x86GccThiscall.h" - -#ifdef KE_WINDOWS typedef x86MsCdecl x86DetourCdecl; typedef x86MsThiscall x86DetourThisCall; typedef x86MsStdcall x86DetourStdCall; #elif defined KE_LINUX +#include "conventions/x86GccCdecl.h" +#include "conventions/x86GccThiscall.h" +#include "conventions/x86MsStdcall.h" typedef x86GccCdecl x86DetourCdecl; typedef x86GccThiscall x86DetourThisCall; // Uhm, stdcall on linux?