From a75ff4f9b64b2456b834f0bda5ab0a1ef0418c9a Mon Sep 17 00:00:00 2001 From: bottiger1 <55270538+bottiger1@users.noreply.github.com> Date: Tue, 7 May 2024 14:23:41 -0700 Subject: [PATCH 1/3] update for 64 bits --- AMBuildScript | 13 +- Extension/AMBuilder | 21 +- Extension/CDetour/detourhelpers.h | 100 ------- Extension/CDetour/detours.cpp | 228 ---------------- Extension/CDetour/detours.h | 249 ------------------ Extension/asm/asm.c | 418 ------------------------------ Extension/asm/asm.h | 40 --- Extension/gsnatives.cpp | 2 +- Extension/swgsdetours.cpp | 2 + Extension/swgsdetours.h | 3 +- Extension/swhttp.h | 4 +- Extension/swhttprequest.h | 2 +- build/build | 11 + build/clean | 4 + 14 files changed, 47 insertions(+), 1050 deletions(-) delete mode 100644 Extension/CDetour/detourhelpers.h delete mode 100644 Extension/CDetour/detours.cpp delete mode 100644 Extension/CDetour/detours.h delete mode 100644 Extension/asm/asm.c delete mode 100644 Extension/asm/asm.h create mode 100755 build/build create mode 100755 build/clean diff --git a/AMBuildScript b/AMBuildScript index db084e2f..160976e9 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -147,17 +147,17 @@ class SteamWorksConfig(object): '-pipe', '-fno-strict-aliasing', '-Wall', - '-Werror', + #'-Werror', '-Wno-unused', '-Wno-switch', '-Wno-format', '-Wno-format-security', '-Wno-array-bounds', '-msse', - '-m32', + '-fPIC', ] cxx.cxxflags += [ - '-std=c++11', + '-std=c++17', ] have_gcc = cxx.vendor == 'gcc' @@ -179,7 +179,6 @@ class SteamWorksConfig(object): cxx.cxxflags += ['-Wno-deprecated'] cxx.cflags += ['-Wno-sometimes-uninitialized'] - cxx.linkflags += ['-m32'] cxx.cxxflags += [ '-fno-exceptions', '-fno-threadsafe-statics', @@ -269,12 +268,14 @@ class SteamWorksConfig(object): cxx.defines += ['WIN32', '_WINDOWS'] def ConfigureForExtension(self, context, compiler): - compiler.cxxincludes += [ + compiler.includes += [ os.path.join(context.currentSourcePath), os.path.join(context.currentSourcePath, 'sdk'), os.path.join(self.sm_root, 'public'), os.path.join(self.sm_root, 'public', 'extensions'), - os.path.join(self.sm_root, 'public', 'sourcepawn'), + os.path.join(self.sm_root, 'sourcepawn', 'include'), + os.path.join(self.sm_root, 'public', 'amtl'), + os.path.join(self.sm_root, 'public', 'amtl', 'amtl'), ] return compiler diff --git a/Extension/AMBuilder b/Extension/AMBuilder index 64d57e02..71aa9b96 100644 --- a/Extension/AMBuilder +++ b/Extension/AMBuilder @@ -16,8 +16,15 @@ project.sources += [ 'swhttprequest.cpp', 'swgchooks.cpp', 'sdk/smsdk_ext.cpp', - 'CDetour/detours.cpp', - 'asm/asm.c' + + os.path.join(SteamWorks.sm_root, 'public', 'CDetour', 'detours.cpp'), + os.path.join(SteamWorks.sm_root, 'public', 'asm', 'asm.c'), + os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'decode.c'), + os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'itab.c'), + os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'syn-att.c'), + os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'syn-intel.c'), + os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'syn.c'), + os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'udis86.c'), ] for sdk_name in SteamWorks.sdks: @@ -29,10 +36,16 @@ for sdk_name in SteamWorks.sdks: binary.compiler.cxxincludes += [os.path.join(SteamWorks.steamworks_root, 'public', 'steam'), os.path.join(sdk.path, 'public', 'steam')]; if binary.compiler.target.platform == 'linux': - binary.compiler.postlink += os.path.join(SteamWorks.steamworks_root, 'redistributable_bin', 'linux32', 'libsteam_api.so'),; + if binary.compiler.target.arch == 'x86_64': + binary.compiler.postlink += os.path.join(SteamWorks.steamworks_root, 'redistributable_bin', 'linux64', 'libsteam_api.so'),; + else: + binary.compiler.postlink += os.path.join(SteamWorks.steamworks_root, 'redistributable_bin', 'linux32', 'libsteam_api.so'),; if binary.compiler.target.platform == 'windows': - binary.compiler.postlink += os.path.join(SteamWorks.steamworks_root, 'redistributable_bin', 'steam_api.lib'),; + if binary.compiler.target.arch == 'x86_64': + binary.compiler.postlink += os.path.join(SteamWorks.steamworks_root, 'redistributable_bin', 'win64', 'steam_api64.lib'),; + else: + binary.compiler.postlink += os.path.join(SteamWorks.steamworks_root, 'redistributable_bin', 'steam_api.lib'),; if binary.compiler.target.platform == 'mac': binary.compiler.postlink += os.path.join(SteamWorks.steamworks_root, 'redistributable_bin', 'osx', 'libsteam_api.dylib'),; diff --git a/Extension/CDetour/detourhelpers.h b/Extension/CDetour/detourhelpers.h deleted file mode 100644 index cff73cc7..00000000 --- a/Extension/CDetour/detourhelpers.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod - * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id: detourhelpers.h 248 2008-08-27 00:56:22Z pred $ - */ - -#ifndef _INCLUDE_SOURCEMOD_DETOURHELPERS_H_ -#define _INCLUDE_SOURCEMOD_DETOURHELPERS_H_ - -#if defined PLATFORM_POSIX -#include -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif -#define ALIGN(ar) ((long)ar & ~(PAGE_SIZE-1)) -#define PAGE_EXECUTE_READWRITE PROT_READ|PROT_WRITE|PROT_EXEC -#endif - -struct patch_t -{ - patch_t() - { - patch[0] = 0; - bytes = 0; - } - unsigned char patch[20]; - size_t bytes; -}; - -inline void ProtectMemory(void *addr, int length, int prot) -{ -#if defined PLATFORM_POSIX - void *addr2 = (void *)ALIGN(addr); - mprotect(addr2, sysconf(_SC_PAGESIZE), prot); -#elif defined PLATFORM_WINDOWS - DWORD old_prot; - VirtualProtect(addr, length, prot, &old_prot); -#endif -} - -inline void SetMemPatchable(void *address, size_t size) -{ - ProtectMemory(address, (int)size, PAGE_EXECUTE_READWRITE); -} - -inline void DoGatePatch(unsigned char *target, void *callback) -{ - SetMemPatchable(target, 20); - - target[0] = 0xFF; /* JMP */ - target[1] = 0x25; /* MEM32 */ - *(void **)(&target[2]) = callback; -} - -inline void ApplyPatch(void *address, int offset, const patch_t *patch, patch_t *restore) -{ - ProtectMemory(address, 20, PAGE_EXECUTE_READWRITE); - - unsigned char *addr = (unsigned char *)address + offset; - if (restore) - { - for (size_t i=0; ibytes; i++) - { - restore->patch[i] = addr[i]; - } - restore->bytes = patch->bytes; - } - - for (size_t i=0; ibytes; i++) - { - addr[i] = patch->patch[i]; - } -} - -#endif //_INCLUDE_SOURCEMOD_DETOURHELPERS_H_ diff --git a/Extension/CDetour/detours.cpp b/Extension/CDetour/detours.cpp deleted file mode 100644 index 9e304149..00000000 --- a/Extension/CDetour/detours.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/** -* vim: set ts=4 : -* ============================================================================= -* SourceMod -* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This program is free software; you can redistribute it and/or modify it under -* the terms of the GNU General Public License, version 3.0, as published by the -* Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -* details. -* -* You should have received a copy of the GNU General Public License along with -* this program. If not, see . -* -* As a special exception, AlliedModders LLC gives you permission to link the -* code of this program (as well as its derivative works) to "Half-Life 2," the -* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software -* by the Valve Corporation. You must obey the GNU General Public License in -* all respects for all other code used. Additionally, AlliedModders LLC grants -* this exception to all derivative works. AlliedModders LLC defines further -* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), -* or . -* -* Version: $Id: detours.cpp 248 2008-08-27 00:56:22Z pred $ -*/ - -#include "detours.h" -#include - -ISourcePawnEngine *CDetourManager::spengine = NULL; -IGameConfig *CDetourManager::gameconf = NULL; - -void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf) -{ - CDetourManager::spengine = spengine; - CDetourManager::gameconf = gameconf; -} - -CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, const char *signame) -{ - CDetour *detour = new CDetour(callbackfunction, trampoline, signame); - if (detour) - { - if (!detour->Init(spengine, gameconf)) - { - delete detour; - return NULL; - } - - return detour; - } - - return NULL; -} - -CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, void *address) -{ - CDetour *detour = new CDetour(callbackfunction, trampoline, address); - if (detour) - { - if (!detour->Init(spengine, gameconf)) - { - delete detour; - return NULL; - } - - return detour; - } - - return NULL; -} - -CDetour::CDetour(void *callbackfunction, void **trampoline, const char *signame) -{ - enabled = false; - detoured = false; - detour_address = NULL; - detour_trampoline = NULL; - this->signame = signame; - this->address = NULL; - this->detour_callback = callbackfunction; - spengine = NULL; - gameconf = NULL; - this->trampoline = trampoline; -} - -CDetour::CDetour(void *callbackfunction, void **trampoline, void *pAddress) -{ - enabled = false; - detoured = false; - detour_address = NULL; - detour_trampoline = NULL; - this->signame = NULL; - this->address = pAddress; - this->detour_callback = callbackfunction; - spengine = NULL; - gameconf = NULL; - this->trampoline = trampoline; -} - -bool CDetour::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf) -{ - this->spengine = spengine; - this->gameconf = gameconf; - - if (!CreateDetour()) - { - enabled = false; - return enabled; - } - - enabled = true; - - return enabled; -} - -void CDetour::Destroy() -{ - DeleteDetour(); - delete this; -} - -bool CDetour::IsEnabled() -{ - return enabled; -} - -bool CDetour::CreateDetour() -{ - if (signame != NULL && !gameconf->GetMemSig(signame, &detour_address)) - { - g_pSM->LogError(myself, "Could not locate %s - Disabling detour", signame); - return false; - } - else if (address != NULL) - { - detour_address = address; - } - - if (!detour_address) - { - g_pSM->LogError(myself, "Sigscan for %s failed - Disabling detour to prevent crashes", signame); - return false; - } - - detour_restore.bytes = copy_bytes((unsigned char *)detour_address, NULL, OP_JMP_SIZE+1); - - /* First, save restore bits */ - for (size_t i=0; iAllocatePageMemory(CodeSize); - spengine->SetReadWrite(wr.outbase); - wr.outptr = wr.outbase; - detour_trampoline = wr.outbase; - goto jit_rewind; - } - - spengine->SetReadExecute(wr.outbase); - - *trampoline = detour_trampoline; - - return true; -} - -void CDetour::DeleteDetour() -{ - if (detoured) - { - DisableDetour(); - } - - if (detour_trampoline) - { - /* Free the allocated trampoline memory */ - spengine->FreePageMemory(detour_trampoline); - detour_trampoline = NULL; - } -} - -void CDetour::EnableDetour() -{ - if (!detoured) - { - DoGatePatch((unsigned char *)detour_address, &detour_callback); - detoured = true; - } -} - -void CDetour::DisableDetour() -{ - if (detoured) - { - /* Remove the patch */ - ApplyPatch(detour_address, 0, &detour_restore, NULL); - detoured = false; - } -} diff --git a/Extension/CDetour/detours.h b/Extension/CDetour/detours.h deleted file mode 100644 index c68d299b..00000000 --- a/Extension/CDetour/detours.h +++ /dev/null @@ -1,249 +0,0 @@ -/** -* vim: set ts=4 : -* ============================================================================= -* SourceMod -* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This program is free software; you can redistribute it and/or modify it under -* the terms of the GNU General Public License, version 3.0, as published by the -* Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -* details. -* -* You should have received a copy of the GNU General Public License along with -* this program. If not, see . -* -* As a special exception, AlliedModders LLC gives you permission to link the -* code of this program (as well as its derivative works) to "Half-Life 2," the -* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software -* by the Valve Corporation. You must obey the GNU General Public License in -* all respects for all other code used. Additionally, AlliedModders LLC grants -* this exception to all derivative works. AlliedModders LLC defines further -* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), -* or . -* -* Version: $Id: detours.h 257 2008-09-23 03:12:13Z pred $ -*/ - -#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_ -#define _INCLUDE_SOURCEMOD_DETOURS_H_ - -#include "smsdk_ext.h" -#include -#include -#include "detourhelpers.h" - -/** - * CDetours class for SourceMod Extensions by pRED* - * detourhelpers.h entirely stolen from CSS:DM and were written by BAILOPAN (I assume). - * asm.h/c from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -fPIC thunks correctly - * Concept by Nephyrin Zey (http://www.doublezen.net/) and Windows Detour Library (http://research.microsoft.com/sn/detours/) - * Member function pointer ideas by Don Clugston (http://www.codeproject.com/cpp/FastDelegate.asp) - */ - -#define DETOUR_MEMBER_CALL(name) (this->*name##_Actual) -#define DETOUR_STATIC_CALL(name) (name##_Actual) - -#define DETOUR_DECL_STATIC0(name, ret) \ -ret (*name##_Actual)(void) = NULL; \ -ret name(void) - -#define DETOUR_DECL_STATIC1(name, ret, p1type, p1name) \ -ret (*name##_Actual)(p1type) = NULL; \ -ret name(p1type p1name) - -#define DETOUR_DECL_STATIC4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \ -ret (*name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \ -ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name) - -#define DETOUR_DECL_STATIC6(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name) \ -ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type) = NULL; \ -ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name) - -#define DETOUR_DECL_MEMBER0(name, ret) \ -class name##Class \ -{ \ -public: \ - ret name(); \ - static ret (name##Class::* name##_Actual)(void); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(void) = NULL; \ -ret name##Class::name() - -#define DETOUR_DECL_MEMBER1(name, ret, p1type, p1name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name); \ - static ret (name##Class::* name##_Actual)(p1type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type) = NULL; \ -ret name##Class::name(p1type p1name) - -#define DETOUR_DECL_MEMBER2(name, ret, p1type, p1name, p2type, p2name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name) - -#define DETOUR_DECL_MEMBER3(name, ret, p1type, p1name, p2type, p2name, p3type, p3name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name) - -#define DETOUR_DECL_MEMBER4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name) - - -#define GET_MEMBER_CALLBACK(name) (void *)GetCodeAddress(&name##Class::name) -#define GET_MEMBER_TRAMPOLINE(name) (void **)(&name##Class::name##_Actual) - -#define GET_STATIC_CALLBACK(name) (void *)&name -#define GET_STATIC_TRAMPOLINE(name) (void **)&name##_Actual - -#define DETOUR_CREATE_MEMBER(name, gamedata) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata); -#define DETOUR_CREATE_STATIC(name, gamedata) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata); -#define DETOUR_CREATE_STATIC_FIXED(name, address) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), address); - - -class GenericClass {}; -typedef void (GenericClass::*VoidFunc)(); - -inline void *GetCodeAddr(VoidFunc mfp) -{ - return *(void **)&mfp; -} - -/** - * Converts a member function pointer to a void pointer. - * This relies on the assumption that the code address lies at mfp+0 - * This is the case for both g++ and later MSVC versions on non virtual functions but may be different for other compilers - * Based on research by Don Clugston : http://www.codeproject.com/cpp/FastDelegate.asp - */ -#define GetCodeAddress(mfp) GetCodeAddr(reinterpret_cast(mfp)) - -class CDetourManager; - -class CDetour -{ -public: - - bool IsEnabled(); - - /** - * These would be somewhat self-explanatory I hope - */ - void EnableDetour(); - void DisableDetour(); - - void Destroy(); - - friend class CDetourManager; - -protected: - CDetour(void *callbackfunction, void **trampoline, const char *signame); - CDetour(void *callbackfunction, void **trampoline, void *address); - - bool Init(ISourcePawnEngine *spengine, IGameConfig *gameconf); -private: - - /* These create/delete the allocated memory */ - bool CreateDetour(); - void DeleteDetour(); - - bool enabled; - bool detoured; - - patch_t detour_restore; - /* Address of the detoured function */ - void *detour_address; - /* Address of the allocated trampoline function */ - void *detour_trampoline; - /* Address of the callback handler */ - void *detour_callback; - /* The function pointer used to call our trampoline */ - void **trampoline; - - const char *signame; - void *address; - ISourcePawnEngine *spengine; - IGameConfig *gameconf; -}; - -class CDetourManager -{ -public: - - static void Init(ISourcePawnEngine *spengine, IGameConfig *gameconf); - - /** - * Creates a new detour - * - * @param callbackfunction Void pointer to your detour callback function. - * @param trampoline Address of the trampoline pointer - * @param signame Section name containing a signature to fetch from the gamedata file. - * @return A new CDetour pointer to control your detour. - * - * Example: - * - * CBaseServer::ConnectClient(netadr_s &, int, int, int, char const*, char const*, char const*, int) - * - * Define a new class with the required function and a member function pointer to the same type: - * - * class CBaseServerDetour - * { - * public: - * bool ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int); - * static bool (CBaseServerDetour::* ConnectClient_Actual)(void *netaddr_s, int, int, int, char const*, char const*, char const*, int); - * } - * - * void *callbackfunc = GetCodeAddress(&CBaseServerDetour::ConnectClient); - * void **trampoline = (void **)(&CBaseServerDetour::ConnectClient_Actual); - * - * Creation: - * CDetourManager::CreateDetour(callbackfunc, trampoline, "ConnectClient"); - * - * Usage: - * - * CBaseServerDetour::ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int) - * { - * //pre hook code - * bool result = (this->*ConnectClient_Actual)(netaddr_s, rest of params); - * //post hook code - * return result; - * } - * - * Note we changed the netadr_s reference into a void* to avoid needing to define the type - */ - static CDetour *CreateDetour(void *callbackfunction, void **trampoline, const char *signame); - static CDetour *CreateDetour(void *callbackfunction, void **trampoline, void *address); - - friend class CBlocker; - friend class CDetour; - -private: - static ISourcePawnEngine *spengine; - static IGameConfig *gameconf; -}; - -#endif // _INCLUDE_SOURCEMOD_DETOURS_H_ diff --git a/Extension/asm/asm.c b/Extension/asm/asm.c deleted file mode 100644 index 7e92d23d..00000000 --- a/Extension/asm/asm.c +++ /dev/null @@ -1,418 +0,0 @@ -#include "asm.h" - -#ifndef WIN32 -#define _GNU_SOURCE -#include -#include - -#define REG_EAX 0 -#define REG_ECX 1 -#define REG_EDX 2 -#define REG_EBX 3 - -#define IA32_MOV_REG_IMM 0xB8 // encoding is +r -#endif - -/** -* Checks if a call to a fpic thunk has just been written into dest. -* If found replaces it with a direct mov that sets the required register to the value of pc. -* -* @param dest Destination buffer where a call opcode + addr (5 bytes) has just been written. -* @param pc The program counter value that needs to be set (usually the next address from the source). -* @noreturn -*/ -void check_thunks(unsigned char *dest, unsigned char *pc) -{ -#if defined WIN32 - return; -#else - /* Step write address back 4 to the start of the function address */ - unsigned char *writeaddr = dest - 4; - unsigned char *calloffset = *(unsigned char **)writeaddr; - unsigned char *calladdr = (unsigned char *)(dest + (unsigned int)calloffset); - - /* Lookup name of function being called */ - if ((*calladdr == 0x8B) && (*(calladdr+2) == 0x24) && (*(calladdr+3) == 0xC3)) - { - //a thunk maybe? - char movByte = IA32_MOV_REG_IMM; - - /* Calculate the correct mov opcode */ - switch (*(calladdr+1)) - { - case 0x04: - { - movByte += REG_EAX; - break; - } - case 0x1C: - { - movByte += REG_EBX; - break; - } - case 0x0C: - { - movByte += REG_ECX; - break; - } - case 0x14: - { - movByte += REG_EDX; - break; - } - default: - { - break; - } - } - - /* Move our write address back one to where the call opcode was */ - writeaddr--; - - - /* Write our mov */ - *writeaddr = movByte; - writeaddr++; - - /* Write the value - The provided program counter value */ - *(void **)writeaddr = (void *)pc; - writeaddr += 4; - } - - return; -#endif -} - -//if dest is NULL, returns minimum number of bytes needed to be copied -//if dest is not NULL, it will copy the bytes to dest as well as fix CALLs and JMPs -//http://www.devmaster.net/forums/showthread.php?t=2311 -int copy_bytes(unsigned char *func, unsigned char* dest, int required_len) { - int bytecount = 0; - - while(bytecount < required_len && *func != 0xCC) - { - // prefixes F0h, F2h, F3h, 66h, 67h, D8h-DFh, 2Eh, 36h, 3Eh, 26h, 64h and 65h - int operandSize = 4; - int FPU = 0; - int twoByte = 0; - unsigned char opcode = 0x90; - unsigned char modRM = 0xFF; - while(*func == 0xF0 || - *func == 0xF2 || - *func == 0xF3 || - (*func & 0xFC) == 0x64 || - (*func & 0xF8) == 0xD8 || - (*func & 0x7E) == 0x62) - { - if(*func == 0x66) - { - operandSize = 2; - } - else if((*func & 0xF8) == 0xD8) - { - FPU = *func; - if (dest) - *dest++ = *func++; - else - func++; - bytecount++; - break; - } - - if (dest) - *dest++ = *func++; - else - func++; - bytecount++; - } - - // two-byte opcode byte - if(*func == 0x0F) - { - twoByte = 1; - if (dest) - *dest++ = *func++; - else - func++; - bytecount++; - } - - // opcode byte - opcode = *func++; - if (dest) *dest++ = opcode; - bytecount++; - - // mod R/M byte - modRM = 0xFF; - if(FPU) - { - if((opcode & 0xC0) != 0xC0) - { - modRM = opcode; - } - } - else if(!twoByte) - { - if((opcode & 0xC4) == 0x00 || - ((opcode & 0xF4) == 0x60 && ((opcode & 0x0A) == 0x02 || (opcode & 0x09) == 0x09)) || - (opcode & 0xF0) == 0x80 || - ((opcode & 0xF8) == 0xC0 && (opcode & 0x0E) != 0x02) || - (opcode & 0xFC) == 0xD0 || - (opcode & 0xF6) == 0xF6) - { - modRM = *func++; - if (dest) *dest++ = modRM; - bytecount++; - } - } - else - { - if(((opcode & 0xF0) == 0x00 && (opcode & 0x0F) >= 0x04 && (opcode & 0x0D) != 0x0D) || - (opcode & 0xF0) == 0x30 || - opcode == 0x77 || - (opcode & 0xF0) == 0x80 || - ((opcode & 0xF0) == 0xA0 && (opcode & 0x07) <= 0x02) || - (opcode & 0xF8) == 0xC8) - { - // No mod R/M byte - } - else - { - modRM = *func++; - if (dest) *dest++ = modRM; - bytecount++; - } - } - - // SIB - if((modRM & 0x07) == 0x04 && - (modRM & 0xC0) != 0xC0) - { - if (dest) - *dest++ = *func++; //SIB - else - func++; - bytecount++; - } - - // mod R/M displacement - - // Dword displacement, no base - if((modRM & 0xC5) == 0x05) { - if (dest) { - *(unsigned int*)dest = *(unsigned int*)func; - dest += 4; - } - func += 4; - bytecount += 4; - } - - // Byte displacement - if((modRM & 0xC0) == 0x40) { - if (dest) - *dest++ = *func++; - else - func++; - bytecount++; - } - - // Dword displacement - if((modRM & 0xC0) == 0x80) { - if (dest) { - *(unsigned int*)dest = *(unsigned int*)func; - dest += 4; - } - func += 4; - bytecount += 4; - } - - // immediate - if(FPU) - { - // Can't have immediate operand - } - else if(!twoByte) - { - if((opcode & 0xC7) == 0x04 || - (opcode & 0xFE) == 0x6A || // PUSH/POP/IMUL - (opcode & 0xF0) == 0x70 || // Jcc - opcode == 0x80 || - opcode == 0x83 || - (opcode & 0xFD) == 0xA0 || // MOV - opcode == 0xA8 || // TEST - (opcode & 0xF8) == 0xB0 || // MOV - (opcode & 0xFE) == 0xC0 || // RCL - opcode == 0xC6 || // MOV - opcode == 0xCD || // INT - (opcode & 0xFE) == 0xD4 || // AAD/AAM - (opcode & 0xF8) == 0xE0 || // LOOP/JCXZ - opcode == 0xEB || - (opcode == 0xF6 && (modRM & 0x30) == 0x00)) // TEST - { - if (dest) - *dest++ = *func++; - else - func++; - bytecount++; - } - else if((opcode & 0xF7) == 0xC2) // RET - { - if (dest) { - *(unsigned short*)dest = *(unsigned short*)func; - dest += 2; - } - func += 2; - bytecount += 2; - } - else if((opcode & 0xFC) == 0x80 || - (opcode & 0xC7) == 0x05 || - (opcode & 0xF8) == 0xB8 || - (opcode & 0xFE) == 0xE8 || // CALL/Jcc - (opcode & 0xFE) == 0x68 || - (opcode & 0xFC) == 0xA0 || - (opcode & 0xEE) == 0xA8 || - opcode == 0xC7 || - (opcode == 0xF7 && (modRM & 0x30) == 0x00)) - { - if (dest) { - //Fix CALL/JMP offset - if ((opcode & 0xFE) == 0xE8) { - if (operandSize == 4) - { - *(long*)dest = ((func + *(long*)func) - dest); - - //pRED* edit. func is the current address of the call address, +4 is the next instruction, so the value of $pc - check_thunks(dest+4, func+4); - } - else - *(short*)dest = ((func + *(short*)func) - dest); - - } else { - if (operandSize == 4) - *(unsigned long*)dest = *(unsigned long*)func; - else - *(unsigned short*)dest = *(unsigned short*)func; - } - dest += operandSize; - } - func += operandSize; - bytecount += operandSize; - - } - } - else - { - if(opcode == 0xBA || // BT - opcode == 0x0F || // 3DNow! - (opcode & 0xFC) == 0x70 || // PSLLW - (opcode & 0xF7) == 0xA4 || // SHLD - opcode == 0xC2 || - opcode == 0xC4 || - opcode == 0xC5 || - opcode == 0xC6) - { - if (dest) - *dest++ = *func++; - else - func++; - } - else if((opcode & 0xF0) == 0x80) // Jcc -i - { - if (dest) { - if (operandSize == 4) - *(unsigned long*)dest = *(unsigned long*)func; - else - *(unsigned short*)dest = *(unsigned short*)func; - - dest += operandSize; - } - func += operandSize; - bytecount += operandSize; - } - } - } - - return bytecount; -} - -//insert a specific JMP instruction at the given location -void inject_jmp(void* src, void* dest) { - *(unsigned char*)src = OP_JMP; - *(long*)((unsigned char*)src+1) = (long)((unsigned char*)dest - ((unsigned char*)src + OP_JMP_SIZE)); -} - -//fill a given block with NOPs -void fill_nop(void* src, unsigned int len) { - unsigned char* src2 = (unsigned char*)src; - while (len) { - *src2++ = OP_NOP; - --len; - } -} - -void* eval_jump(void* src) { - unsigned char* addr = (unsigned char*)src; - - if (!addr) return 0; - - //import table jump - if (addr[0] == OP_PREFIX && addr[1] == OP_JMP_SEG) { - addr += 2; - addr = *(unsigned char**)addr; - //TODO: if addr points into the IAT - return *(void**)addr; - } - - //8bit offset - else if (addr[0] == OP_JMP_BYTE) { - addr = &addr[OP_JMP_BYTE_SIZE] + *(char*)&addr[1]; - //mangled 32bit jump? - if (addr[0] == OP_JMP) { - addr = addr + *(int*)&addr[1]; - } - return addr; - } - /* - //32bit offset - else if (addr[0] == OP_JMP) { - addr = &addr[OP_JMP_SIZE] + *(int*)&addr[1]; - } - */ - - return addr; -} -/* -from ms detours package -static bool detour_is_imported(PBYTE pbCode, PBYTE pbAddress) -{ - MEMORY_BASIC_INFORMATION mbi; - VirtualQuery((PVOID)pbCode, &mbi, sizeof(mbi)); - __try { - PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase; - if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { - return false; - } - - PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + - pDosHeader->e_lfanew); - if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { - return false; - } - - if (pbAddress >= ((PBYTE)pDosHeader + - pNtHeader->OptionalHeader - .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) && - pbAddress < ((PBYTE)pDosHeader + - pNtHeader->OptionalHeader - .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress + - pNtHeader->OptionalHeader - .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size)) { - return true; - } - return false; - } - __except(EXCEPTION_EXECUTE_HANDLER) { - return false; - } -} -*/ diff --git a/Extension/asm/asm.h b/Extension/asm/asm.h deleted file mode 100644 index 838e6916..00000000 --- a/Extension/asm/asm.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __ASM_H__ -#define __ASM_H__ - -#define OP_JMP 0xE9 -#define OP_JMP_SIZE 5 - -#define OP_NOP 0x90 -#define OP_NOP_SIZE 1 - -#define OP_PREFIX 0xFF -#define OP_JMP_SEG 0x25 - -#define OP_JMP_BYTE 0xEB -#define OP_JMP_BYTE_SIZE 2 - -#ifdef __cplusplus -extern "C" { -#endif - -void check_thunks(unsigned char *dest, unsigned char *pc); - -//if dest is NULL, returns minimum number of bytes needed to be copied -//if dest is not NULL, it will copy the bytes to dest as well as fix CALLs and JMPs -//http://www.devmaster.net/forums/showthread.php?t=2311 -int copy_bytes(unsigned char *func, unsigned char* dest, int required_len); - -//insert a specific JMP instruction at the given location -void inject_jmp(void* src, void* dest); - -//fill a given block with NOPs -void fill_nop(void* src, unsigned int len); - -//evaluate a JMP at the target -void* eval_jump(void* src); - -#ifdef __cplusplus -} -#endif - -#endif //__ASM_H__ diff --git a/Extension/gsnatives.cpp b/Extension/gsnatives.cpp index 9c0db4cc..1b00c988 100644 --- a/Extension/gsnatives.cpp +++ b/Extension/gsnatives.cpp @@ -199,7 +199,7 @@ static cell_t sm_ForceHeartbeat(IPluginContext *pContext, const cell_t *params) return 0; } - pServer->ForceHeartbeat(); + //pServer->ForceHeartbeat(); return 1; } diff --git a/Extension/swgsdetours.cpp b/Extension/swgsdetours.cpp index 1bad31cd..0e73f95a 100644 --- a/Extension/swgsdetours.cpp +++ b/Extension/swgsdetours.cpp @@ -17,6 +17,8 @@ */ #include "swgsdetours.h" +#include "CDetour/detours.h" +#define DETOUR_CREATE_STATIC_FIXED(name, address) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), address); DETOUR_DECL_STATIC0(SteamAPIShutdown, void) { diff --git a/Extension/swgsdetours.h b/Extension/swgsdetours.h index 48aebb02..e758fe7c 100644 --- a/Extension/swgsdetours.h +++ b/Extension/swgsdetours.h @@ -19,7 +19,8 @@ #pragma once #include "smsdk_ext.h" #include "steam_gameserver.h" -#include "CDetour/detours.h" + +class CDetour; class SteamWorksGSDetours { diff --git a/Extension/swhttp.h b/Extension/swhttp.h index e9e64ea0..82a79ea1 100644 --- a/Extension/swhttp.h +++ b/Extension/swhttp.h @@ -26,7 +26,7 @@ class SteamWorksHTTP : { public: SteamWorksHTTP(); - ~SteamWorksHTTP(); + virtual ~SteamWorksHTTP(); public: void OnHandleDestroy(HandleType_t type, void *object); @@ -40,4 +40,4 @@ class SteamWorksHTTP : }; #include "swhttprequest.h" -#include "extension.h" \ No newline at end of file +#include "extension.h" diff --git a/Extension/swhttprequest.h b/Extension/swhttprequest.h index 78d14e29..2981c206 100644 --- a/Extension/swhttprequest.h +++ b/Extension/swhttprequest.h @@ -54,4 +54,4 @@ class SteamWorksHTTPNatives ~SteamWorksHTTPNatives(); }; -#include "extension.h" \ No newline at end of file +#include "extension.h" diff --git a/build/build b/build/build new file mode 100755 index 00000000..cd034230 --- /dev/null +++ b/build/build @@ -0,0 +1,11 @@ +#!/bin/bash + +ln -s ../sdk/hl2sdk-manifests ../ + +python3 ../configure.py -s tf2 \ + --hl2sdk-root `realpath ../../sdk` \ + --mms-path ../../sdk/mmsource \ + --sm-path ../../sdk/sourcemod \ + --steamworks-path ../../sdk/steamworks \ + --targets x86,x86_64 +ambuild diff --git a/build/clean b/build/clean new file mode 100755 index 00000000..e2fe98a7 --- /dev/null +++ b/build/clean @@ -0,0 +1,4 @@ +#!/bin/bash +rm -rf package .ambuild2 Extension Package +cd .. +rm -rf hl2sdk-manifests exception From bcb600462fdf7f74f2eeadcf3de91d1f4d17768e Mon Sep 17 00:00:00 2001 From: bottiger1 <55270538+bottiger1@users.noreply.github.com> Date: Tue, 7 May 2024 14:31:17 -0700 Subject: [PATCH 2/3] fix build file --- build/build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/build b/build/build index cd034230..f229b1aa 100755 --- a/build/build +++ b/build/build @@ -2,10 +2,10 @@ ln -s ../sdk/hl2sdk-manifests ../ -python3 ../configure.py -s tf2 \ +python3 ../configure.py -s sdk2013 \ --hl2sdk-root `realpath ../../sdk` \ --mms-path ../../sdk/mmsource \ --sm-path ../../sdk/sourcemod \ --steamworks-path ../../sdk/steamworks \ - --targets x86,x86_64 + --target x86_64 ambuild From 8428a712d010432b81bcea21251339018ada1d3d Mon Sep 17 00:00:00 2001 From: bottiger1 <55270538+bottiger1@users.noreply.github.com> Date: Mon, 27 May 2024 22:51:37 -0700 Subject: [PATCH 3/3] switch to safetyhook. fix automatic detection of libsteam_api --- AMBuildScript | 4 +++- Extension/AMBuilder | 11 +++-------- Extension/swgameserver.cpp | 34 ++++++++++++++++++++++++++++++++-- build/build | 1 + 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/AMBuildScript b/AMBuildScript index 160976e9..66717910 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -157,7 +157,7 @@ class SteamWorksConfig(object): '-fPIC', ] cxx.cxxflags += [ - '-std=c++17', + '-std=c++20', ] have_gcc = cxx.vendor == 'gcc' @@ -271,6 +271,8 @@ class SteamWorksConfig(object): compiler.includes += [ os.path.join(context.currentSourcePath), os.path.join(context.currentSourcePath, 'sdk'), + os.path.join(context.currentSourcePath, 'CDetour'), + os.path.join(self.sm_root, 'public'), os.path.join(self.sm_root, 'public', 'extensions'), os.path.join(self.sm_root, 'sourcepawn', 'include'), diff --git a/Extension/AMBuilder b/Extension/AMBuilder index 71aa9b96..a16f21a8 100644 --- a/Extension/AMBuilder +++ b/Extension/AMBuilder @@ -17,14 +17,9 @@ project.sources += [ 'swgchooks.cpp', 'sdk/smsdk_ext.cpp', - os.path.join(SteamWorks.sm_root, 'public', 'CDetour', 'detours.cpp'), - os.path.join(SteamWorks.sm_root, 'public', 'asm', 'asm.c'), - os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'decode.c'), - os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'itab.c'), - os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'syn-att.c'), - os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'syn-intel.c'), - os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'syn.c'), - os.path.join(SteamWorks.sm_root, 'public', 'libudis86', 'udis86.c'), + 'CDetour/Zydis.c', + 'CDetour/safetyhook.cpp', + 'CDetour/detours.cpp', ] for sdk_name in SteamWorks.sdks: diff --git a/Extension/swgameserver.cpp b/Extension/swgameserver.cpp index aa66b353..55f7377a 100644 --- a/Extension/swgameserver.cpp +++ b/Extension/swgameserver.cpp @@ -17,6 +17,8 @@ */ #include "swgameserver.h" +#include +#include static void GetGameSpecificConfigInterface(const char *pName, const char *&pVersion) { @@ -62,7 +64,9 @@ void SteamWorksGameServer::Reset(void) ISteamClient *SteamWorksGameServer::GetSteamClient(void) { if (g_pSteamClientGameServer != NULL) + { return g_pSteamClientGameServer; + } /* The following is assumed from an unreleased version of the SteamWorks SDK, first seen (and reversed) in CS:GO. @@ -105,10 +109,14 @@ ISteamClient *SteamWorksGameServer::GetSteamClient(void) } if (pGSInternalCreateAddress != NULL) + { this->m_pClient = static_cast((*pGSInternalCreateAddress)(STEAMCLIENT_INTERFACE_VERSION)); + } if (this->m_pClient == NULL && pInternalCreateAddress != NULL) + { this->m_pClient = static_cast((*pInternalCreateAddress)(STEAMCLIENT_INTERFACE_VERSION)); + } } return this->m_pClient; @@ -123,7 +131,7 @@ ISteamGameServer *SteamWorksGameServer::GetGameServer(void) GetUserAndPipe(hSteamUser, hSteamPipe); const char *pVersion = STEAMGAMESERVER_INTERFACE_VERSION; - GetGameSpecificConfigInterface("SteamGameServerInterfaceVersion", pVersion); + //GetGameSpecificConfigInterface("SteamGameServerInterfaceVersion", pVersion); this->m_pGameServer = this->GetSteamClient()->GetISteamGameServer(hSteamUser, hSteamPipe, pVersion); } @@ -230,14 +238,36 @@ void SteamWorksGameServer::GetUserAndPipe(HSteamUser &hSteamUser, HSteamPipe &hS hSteamPipe = SteamGameServer_GetHSteamPipe(); } +std::string get_loaded_library_path(const std::string& libname) { + struct search_data_t { + const std::string& name; + std::string path; + } search_data { libname, "" }; + + auto callback = [](struct dl_phdr_info *info, size_t size, void *data) -> int { + search_data_t *search_data = static_cast(data); + if (strstr(info->dlpi_name, search_data->name.c_str())) { + search_data->path = info->dlpi_name; + return 1; // Stop iteration + } + return 0; // Continue iteration + }; + + dl_iterate_phdr(callback, &search_data); + + return search_data.path; +} + const char *SteamWorksGameServer::GetLibraryPath(void) { static const char *pLibSteamPath = NULL; + static std::string libSteamPath; if (pLibSteamPath == NULL) { #if defined POSIX - pLibSteamPath = "./bin/libsteam_api.so"; + libSteamPath = get_loaded_library_path("libsteam_api.so"); + pLibSteamPath = libSteamPath.c_str(); #elif defined WIN32_LEAN_AND_MEAN pLibSteamPath = "./bin/steam_api.dll"; /* Naming from SteamTools. */ #endif diff --git a/build/build b/build/build index f229b1aa..d011c995 100755 --- a/build/build +++ b/build/build @@ -1,6 +1,7 @@ #!/bin/bash ln -s ../sdk/hl2sdk-manifests ../ +ln -s ../../sdk/CDetour ../Extension python3 ../configure.py -s sdk2013 \ --hl2sdk-root `realpath ../../sdk` \