diff --git a/AMBuildScript b/AMBuildScript index 27473cf..80e519e 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -270,6 +270,7 @@ 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', 'x86MsFastcall.cpp'), ] if builder.target_platform == 'windows': diff --git a/DynamicHooks/conventions/x86MsFastcall.cpp b/DynamicHooks/conventions/x86MsFastcall.cpp new file mode 100644 index 0000000..0b9d8c0 --- /dev/null +++ b/DynamicHooks/conventions/x86MsFastcall.cpp @@ -0,0 +1,58 @@ +/** +* ============================================================================= +* 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 "x86MsFastcall.h" + + +// ============================================================================ +// >> x86MsFastcall +// ============================================================================ +x86MsFastcall::x86MsFastcall(ke::Vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment) : + x86MsStdcall(vecArgTypes, returnType, iAlignment) +{ + // First argument is passed in ecx. + if (m_vecArgTypes.length() > 0) { + DataTypeSized_t &type = m_vecArgTypes[0]; + // Don't force the register on the user. + // Why choose Fastcall if you set your own argument registers though.. + if (type.custom_register == None) + type.custom_register = ECX; + } + + // Second argument is passed in edx. + if (m_vecArgTypes.length() > 1) { + DataTypeSized_t &type = m_vecArgTypes[1]; + if (type.custom_register == None) + type.custom_register = EDX; + } +} diff --git a/DynamicHooks/conventions/x86MsFastcall.h b/DynamicHooks/conventions/x86MsFastcall.h new file mode 100644 index 0000000..83fdf94 --- /dev/null +++ b/DynamicHooks/conventions/x86MsFastcall.h @@ -0,0 +1,69 @@ +/** +* ============================================================================= +* 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). +*/ + +#ifndef _X86_MS_FASTCALL_H +#define _X86_MS_FASTCALL_H + +// ============================================================================ +// >> INCLUDES +// ============================================================================ +#include "x86MsStdcall.h" + + +// ============================================================================ +// >> CLASSES +// ============================================================================ +/* +Source: DynCall manual and Windows docs + +Registers: + - eax = return value + - edx = return value + - esp = stack pointer + - st0 = floating point return value + +Parameter passing: + - first parameter in ecx, second parameter in edx, rest on the stack + - stack parameter order: right-to-left + - callee cleans up the stack + - alignment: 4 bytes + +Return values: + - return values of pointer or intergral type (<= 32 bits) are returned via the eax register + - integers > 32 bits are returned via the eax and edx registers + - floating pointer types are returned via the st0 register +*/ +class x86MsFastcall: public x86MsStdcall +{ +public: + x86MsFastcall(ke::Vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment=4); +}; + +#endif // _X86_MS_FASTCALL_H \ No newline at end of file diff --git a/dynhooks_sourcepawn.cpp b/dynhooks_sourcepawn.cpp index 9892200..55abc2b 100644 --- a/dynhooks_sourcepawn.cpp +++ b/dynhooks_sourcepawn.cpp @@ -6,17 +6,22 @@ #include "conventions/x86MsCdecl.h" #include "conventions/x86MsThiscall.h" #include "conventions/x86MsStdcall.h" +#include "conventions/x86MsFastcall.h" typedef x86MsCdecl x86DetourCdecl; typedef x86MsThiscall x86DetourThisCall; typedef x86MsStdcall x86DetourStdCall; +typedef x86MsFastcall x86DetourFastCall; #elif defined KE_LINUX #include "conventions/x86GccCdecl.h" #include "conventions/x86GccThiscall.h" #include "conventions/x86MsStdcall.h" +#include "conventions/x86MsFastcall.h" typedef x86GccCdecl x86DetourCdecl; typedef x86GccThiscall x86DetourThisCall; // Uhm, stdcall on linux? typedef x86MsStdcall x86DetourStdCall; +// Uhumm, fastcall on linux? +typedef x86MsFastcall x86DetourFastCall; #else #error "Unsupported platform." #endif @@ -213,6 +218,9 @@ ICallingConvention *ConstructCallingConvention(HookSetup *setup) case CallConv_STDCALL: pCallConv = new x86DetourStdCall(vecArgTypes, returnType); break; + case CallConv_FASTCALL: + pCallConv = new x86DetourFastCall(vecArgTypes, returnType); + break; default: smutils->LogError(myself, "Unknown calling convention %d.", setup->callConv); break; diff --git a/msvc10/sdk.vcxproj b/msvc10/sdk.vcxproj index 057532c..a9b4bbc 100644 --- a/msvc10/sdk.vcxproj +++ b/msvc10/sdk.vcxproj @@ -111,6 +111,7 @@ + diff --git a/msvc10/sdk.vcxproj.filters b/msvc10/sdk.vcxproj.filters index 8d8b328..1335156 100644 --- a/msvc10/sdk.vcxproj.filters +++ b/msvc10/sdk.vcxproj.filters @@ -38,6 +38,9 @@ DynamicHooks\conventions + + DynamicHooks\conventions + diff --git a/signatures.cpp b/signatures.cpp index 1433649..36cf5cf 100644 --- a/signatures.cpp +++ b/signatures.cpp @@ -190,6 +190,8 @@ SMCResult SignatureGameConfig::ReadSMC_KeyValue(const SMCStates *states, const c callConv = CallConv_THISCALL; else if (!strcmp(value, "stdcall")) callConv = CallConv_STDCALL; + else if (!strcmp(value, "fastcall")) + callConv = CallConv_FASTCALL; else { smutils->LogError(myself, "Invalid calling convention \"%s\": line: %i col: %i", value, states->line, states->col); diff --git a/sourcemod/scripting/include/dhooks.inc b/sourcemod/scripting/include/dhooks.inc index 065ee41..9f59605 100644 --- a/sourcemod/scripting/include/dhooks.inc +++ b/sourcemod/scripting/include/dhooks.inc @@ -77,6 +77,7 @@ enum CallingConvention CallConv_CDECL, CallConv_THISCALL, CallConv_STDCALL, + CallConv_FASTCALL, }; enum MRESReturn diff --git a/vhook.h b/vhook.h index 99da530..43ee47d 100644 --- a/vhook.h +++ b/vhook.h @@ -12,6 +12,7 @@ enum CallingConvention CallConv_CDECL, CallConv_THISCALL, CallConv_STDCALL, + CallConv_FASTCALL, }; enum MRESReturn