core: Add Insurgency support for amd64 Windows (#1295)

* Add basic Insurgency support on Windows x64

This allows SourceMod to load on x64 Insurgency. There are still a lot of variable truncation warnings that have to be dealt with.

* Fix 32bit builds

* Compile MySQL extension as well

The hack for __iob_func being removed from the core runtime, but required by the old mysql we're building against can be simplified a lot due to the `_ReturnAddress` intrinsic available since MSVC 2015.

* Don't include the offset we want to extract in the signature
This commit is contained in:
peace-maker 2020-08-07 04:53:06 +02:00 committed by GitHub
parent c5619f887d
commit 510bd261f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 117 additions and 83 deletions

View File

@ -97,6 +97,8 @@ def SetArchFlags(compiler, arch, platform):
compiler.linkflags += ['/MACHINE:X86']
elif builder.target.arch == 'x64':
compiler.linkflags += ['/MACHINE:X64']
if arch == 'x64':
compiler.defines += ['WIN64']
def AppendArchSuffix(binary, name, arch):
if arch == 'x64':
@ -180,19 +182,19 @@ class SMConfig(object):
self.mms_root = Normalize(self.mms_root)
if builder.options.hasMySql:
if builder.options.mysql_path:
self.mysql_root['x86'] = builder.options.mysql_path
else:
for i in range(10):
self.mysql_root['x86'] = ResolveEnvPath('MYSQL55', 'mysql-5.' + str(i))
if self.mysql_root['x86']:
break
if not self.mysql_root['x86'] or not os.path.isdir(self.mysql_root['x86']):
raise Exception('Could not find a path to MySQL!')
self.mysql_root['x86'] = Normalize(self.mysql_root['x86'])
if 'x86' in self.archs:
if builder.options.mysql_path:
self.mysql_root['x86'] = builder.options.mysql_path
else:
for i in range(10):
self.mysql_root['x86'] = ResolveEnvPath('MYSQL55', 'mysql-5.' + str(i))
if self.mysql_root['x86']:
break
if not self.mysql_root['x86'] or not os.path.isdir(self.mysql_root['x86']):
raise Exception('Could not find a path to MySQL!')
self.mysql_root['x86'] = Normalize(self.mysql_root['x86'])
# For now, ignore 64-bit MySQL on Windows
if 'x64' in self.archs and builder.target.platform != 'windows':
if 'x64' in self.archs:
if builder.options.mysql64_path:
self.mysql_root['x64'] = builder.options.mysql64_path
else:
@ -490,6 +492,7 @@ class SMConfig(object):
def ExtLibrary(self, context, name, arch):
binary = self.Library(context, name, arch)
SetArchFlags(binary.compiler, arch, builder.target.platform)
self.ConfigureForExtension(context, binary.compiler)
return binary
@ -533,7 +536,11 @@ class SMConfig(object):
compiler.defines.remove('_vsnprintf=vsnprintf')
if compiler.like('msvc'):
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
compiler.defines += ['COMPILER_MSVC']
if arch == 'x86':
compiler.defines += ['COMPILER_MSVC32']
elif arch == 'x64':
compiler.defines += ['COMPILER_MSVC64']
compiler.linkflags += ['legacy_stdio_definitions.lib']
else:
compiler.defines += ['COMPILER_GCC']
@ -611,7 +618,10 @@ class SMConfig(object):
if sdk.name in ['swarm', 'blade', 'insurgency', 'doi', 'csgo']:
libs.append('interfaces')
for lib in libs:
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
if arch == 'x86':
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
elif arch == 'x64':
lib_path = os.path.join(sdk.path, 'lib', 'public', 'win64', lib) + '.lib'
compiler.linkflags.append(compiler.Dep(lib_path))
for library in dynamic_libs:

View File

@ -79,7 +79,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s." PLATFORM_LIB_EXT,
"extensions/" PLATFORM_ARCH_FOLDER "%s." PLATFORM_LIB_EXT,
filename);
}
else
@ -88,7 +88,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.%s." PLATFORM_LIB_EXT,
"extensions/" PLATFORM_ARCH_FOLDER "%s.%s." PLATFORM_LIB_EXT,
filename,
bridge->gamesuffix);
@ -103,7 +103,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
"extensions/" PLATFORM_ARCH_FOLDER "%s.2.ep2v." PLATFORM_LIB_EXT,
filename);
}
else if (strcmp(bridge->gamesuffix, "2.nd") == 0)
@ -111,7 +111,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
"extensions/" PLATFORM_ARCH_FOLDER "%s.2.l4d2." PLATFORM_LIB_EXT,
filename);
}
@ -122,7 +122,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/auto.%s/%s." PLATFORM_LIB_EXT,
"extensions/" PLATFORM_ARCH_FOLDER "auto.%s/%s." PLATFORM_LIB_EXT,
filename,
bridge->gamesuffix);
@ -132,7 +132,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s." PLATFORM_LIB_EXT,
"extensions/" PLATFORM_ARCH_FOLDER "%s." PLATFORM_LIB_EXT,
filename);
}
}

View File

@ -442,8 +442,10 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
#ifdef PLATFORM_X86
const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_I386;
const WORD PE_NT_OPTIONAL_HDR_MAGIC = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
#else
const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_AMD64;
const WORD PE_NT_OPTIONAL_HDR_MAGIC = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
#endif
MEMORY_BASIC_INFORMATION info;
@ -466,7 +468,7 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
opt = &pe->OptionalHeader;
/* Check PE magic and signature */
if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != PE_NT_OPTIONAL_HDR_MAGIC)
{
return false;
}

View File

@ -1,79 +1,37 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdlib.h>
#include <corecrt_wstdio.h>
#include <intrin.h>
// Fix from from https://stackoverflow.com/a/34655235.
//
// __iob_func required by the MySQL we use,
// but no longer exists in the VS 14.0+ crt.
#pragma comment(lib, "DbgHelp.lib")
#pragma warning(disable:4091) // 'typedef ': ignored on left of '' when no variable is declared
#include <DbgHelp.h>
#include <corecrt_wstdio.h>
#define GET_CURRENT_CONTEXT(c, contextFlags) \
do { \
c.ContextFlags = contextFlags; \
__asm call x \
__asm x: pop eax \
__asm mov c.Eip, eax \
__asm mov c.Ebp, ebp \
__asm mov c.Esp, esp \
} while(0);
#pragma intrinsic(_ReturnAddress)
FILE * __cdecl __iob_func(void)
{
CONTEXT c = { 0 };
STACKFRAME64 s = { 0 };
DWORD imageType;
HANDLE hThread = GetCurrentThread();
HANDLE hProcess = GetCurrentProcess();
GET_CURRENT_CONTEXT(c, CONTEXT_FULL);
imageType = IMAGE_FILE_MACHINE_I386;
s.AddrPC.Offset = c.Eip;
s.AddrPC.Mode = AddrModeFlat;
s.AddrFrame.Offset = c.Ebp;
s.AddrFrame.Mode = AddrModeFlat;
s.AddrStack.Offset = c.Esp;
s.AddrStack.Mode = AddrModeFlat;
if (!StackWalk64(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
unsigned char const * assembly = (unsigned char const *)_ReturnAddress();
if (!assembly)
{
return NULL;
}
if (s.AddrReturn.Offset == 0)
if (*assembly == 0x83 && *(assembly + 1) == 0xC0 && (*(assembly + 2) == 0x20 || *(assembly + 2) == 0x40))
{
return NULL;
}
{
unsigned char const * assembly = (unsigned char const *)(s.AddrReturn.Offset);
if (*assembly == 0x83 && *(assembly + 1) == 0xC0 && (*(assembly + 2) == 0x20 || *(assembly + 2) == 0x40))
if (*(assembly + 2) == 32)
{
if (*(assembly + 2) == 32)
{
return (FILE*)((unsigned char *)stdout - 32);
}
if (*(assembly + 2) == 64)
{
return (FILE*)((unsigned char *)stderr - 64);
}
return (FILE*)((unsigned char *)stdout - 32);
}
else
if (*(assembly + 2) == 64)
{
return stdin;
return (FILE*)((unsigned char *)stderr - 64);
}
}
return NULL;
return stdin;
}
// Adapted from dosmap.c in Visual Studio 12.0 CRT sources.

View File

@ -185,7 +185,7 @@ bool MyDatabase::DoSimpleQuery(const char *query)
IQuery *MyDatabase::DoQuery(const char *query)
{
if (mysql_real_query(m_mysql, query, strlen(query)) != 0)
if (mysql_real_query(m_mysql, query, static_cast<unsigned long>(strlen(query))) != 0)
{
return NULL;
}
@ -216,7 +216,7 @@ bool MyDatabase::DoSimpleQueryEx(const char *query, size_t len)
IQuery *MyDatabase::DoQueryEx(const char *query, size_t len)
{
if (mysql_real_query(m_mysql, query, len) != 0)
if (mysql_real_query(m_mysql, query, static_cast<unsigned long>(len)) != 0)
{
return NULL;
}
@ -258,7 +258,7 @@ IPreparedQuery *MyDatabase::PrepareQuery(const char *query, char *error, size_t
return NULL;
}
if (mysql_stmt_prepare(stmt, query, strlen(query)) != 0)
if (mysql_stmt_prepare(stmt, query, static_cast<unsigned long>(strlen(query))) != 0)
{
if (error)
{

View File

@ -224,7 +224,7 @@ void MyDriver::ShutdownThreadSafety()
mysql_thread_end();
}
unsigned int strncopy(char *dest, const char *src, size_t count)
size_t strncopy(char *dest, const char *src, size_t count)
{
if (!count)
{

View File

@ -88,6 +88,6 @@ private:
extern MyDriver g_MyDriver;
unsigned int strncopy(char *dest, const char *src, size_t count);
size_t strncopy(char *dest, const char *src, size_t count);
#endif //_INCLUDE_SM_MYSQL_DRIVER_H_

View File

@ -66,7 +66,12 @@ void InitializeValveGlobals()
{
return;
}
#ifdef PLATFORM_X86
g_ppGameRules = *reinterpret_cast<void ***>(addr + offset);
#else
int32_t varOffset = *(int32_t *) ((unsigned char *) addr + offset);
g_ppGameRules = *reinterpret_cast<void ***>((unsigned char *) addr + offset + sizeof(int32_t) + varOffset);
#endif
}
}

View File

@ -112,6 +112,7 @@
"GetDataDescMap"
{
"windows" "11"
"windows64" "11"
"linux" "12"
"linux64" "12"
"mac" "12"

View File

@ -20,11 +20,13 @@
"gEntList"
{
"windows" "11"
"windows64" "13"
}
"EntInfo"
{
"windows" "4"
"windows" "4"
"windows64" "8"
"linux" "4"
"mac" "4"
}
@ -36,6 +38,7 @@
{
"library" "server"
"windows" "\xE8\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xE8"
"windows64" "\xE8\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x48\x8D\x0D\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xE8"
}
"gEntList"
{

View File

@ -7,144 +7,168 @@
"Blocked"
{
"windows" "108"
"windows64" "108"
"linux" "109"
"mac" "109"
}
"EndTouch"
{
"windows" "106"
"windows64" "106"
"linux" "107"
"mac" "107"
}
"FireBullets"
{
"windows" "119"
"windows64" "119"
"linux" "120"
"mac" "120"
}
"GetMaxHealth"
{
"windows" "123"
"windows64" "123"
"linux" "124"
"mac" "124"
}
"GroundEntChanged"
{
"windows" "177"
"windows64" "177"
"linux" "179"
"mac" "179"
}
"OnTakeDamage"
{
"windows" "67"
"windows64" "67"
"linux" "68"
"mac" "68"
}
"OnTakeDamage_Alive"
{
"windows" "292"
"windows64" "292"
"linux" "293"
"mac" "293"
}
"PreThink"
{
"windows" "361"
"windows64" "361"
"linux" "362"
"mac" "362"
}
"PostThink"
{
"windows" "362"
"windows64" "362"
"linux" "363"
"mac" "363"
}
"Reload"
{
"windows" "284"
"windows64" "284"
"linux" "285"
"mac" "285"
}
"SetTransmit"
{
"windows" "20"
"windows64" "20"
"linux" "21"
"mac" "21"
}
"ShouldCollide"
{
"windows" "16"
"windows64" "16"
"linux" "17"
"mac" "17"
}
"Spawn"
{
"windows" "22"
"windows64" "22"
"linux" "23"
"mac" "23"
}
"StartTouch"
{
"windows" "104"
"windows64" "104"
"linux" "105"
"mac" "105"
}
"Think"
{
"windows" "51"
"windows64" "51"
"linux" "52"
"mac" "52"
}
"Touch"
{
"windows" "105"
"windows64" "105"
"linux" "106"
"mac" "106"
}
"TraceAttack"
{
"windows" "65"
"windows64" "65"
"linux" "66"
"mac" "66"
}
"Use"
{
"windows" "103"
"windows64" "103"
"linux" "104"
"mac" "104"
}
"VPhysicsUpdate"
{
"windows" "156"
"windows64" "156"
"linux" "157"
"mac" "157"
}
"Weapon_CanSwitchTo"
{
"windows" "286"
"windows64" "286"
"linux" "287"
"mac" "287"
}
"Weapon_CanUse"
{
"windows" "280"
"windows64" "280"
"linux" "281"
"mac" "281"
}
"Weapon_Drop"
{
"windows" "283"
"windows64" "283"
"linux" "284"
"mac" "284"
}
"Weapon_Equip"
{
"windows" "281"
"windows64" "281"
"linux" "282"
"mac" "282"
}
"Weapon_Switch"
{
"windows" "284"
"windows64" "284"
"linux" "285"
"mac" "285"
}
@ -158,6 +182,7 @@
"EntityListeners"
{
"windows" "196644"
"windows64" "393272"
"linux" "196644"
"mac" "196644"
}

View File

@ -36,22 +36,26 @@
"s_pTempEntities"
{
"windows" "16"
"windows64" "17"
}
"GetTEName"
{
"windows" "4"
"windows64" "8"
"linux" "4"
"mac" "4"
}
"GetTENext"
{
"windows" "8"
"windows64" "16"
"linux" "8"
"mac" "8"
}
"TE_GetServerClass"
{
"windows" "0"
"windows64" "0"
"linux" "0"
"mac" "0"
}
@ -63,6 +67,7 @@
{
"library" "server"
"windows" "\x55\x8B\xEC\x8B\x45\x08\x89\x41\x04\xC7\x01\x2A\x2A\x2A\x2A\xA1"
"windows64" "\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x89\x51\x08\x48\x89\x01\x48\x8B\x05"
}
"s_pTempEntities"
{
@ -83,6 +88,7 @@
{
"library" "server"
"windows" "\x55\x8B\xEC\x53\x56\x8B\xF1\x8B\x4D\x08\x57\x85\xC9\x74\x26\x8B\x01\xFF\x50\x08\x8B\x00\x83\xF8\xFF\x75\x0E\xB8\xFF\x1F\x00\x00\x8D\x04\x40\x8B\x74\xC6\x10\xEB\x12\x0F\xB7\xC0\x8D\x04\x40\x8B\x74\xC6\x10\xEB\x06\x8B\xB6\x2A\x2A\x2A\x2A\x85\xF6\x74\x4C"
"windows64" "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x20\x49\x8B\xF0\x48\x8B\xF9\x48\x85\xD2\x74\x2A\x48\x8B\x02\x48\x8B\xCA\xFF\x50\x10\x8B\x08\xB8\xFF\x1F\x00\x00\x83\xF9\xFF\x74\x2A\x0F\xB7\xC1\x48\x98\x48\x8D\x1C\x40\x48\x03\xDB\x48\x8B\x5C\xDF\x20\xEB\x2A\x48\x8B\x99\x08\x00\x06\x00\x48\x85\xDB\x74\x2A\x66\x90\x48\x8B\x3B\x48\x85\xFF\x75\x2A\x48\x8D\x0D\xE9\xD8\x4C\x00"
"linux" "@_ZN17CGlobalEntityList21FindEntityByClassnameEP11CBaseEntityPKc"
"mac" "@_ZN17CGlobalEntityList21FindEntityByClassnameEP11CBaseEntityPKc"
}
@ -103,6 +109,7 @@
"g_pGameRules"
{
"windows" "5"
"windows64" "16"
}
}
@ -120,6 +127,7 @@
{
"library" "server"
"windows" "\x55\x8B\xEC\x8B\x0D\x2A\x2A\x2A\x2A\x85\xC9\x74\x07\x8B"
"windows64" "\x48\x89\x5C\x24\x08\x57\x48\x83\xEC\x30\x48\x8B\xF9\x48\x8B\x0D\x2A\x2A\x2A\x2A\x48\x85\xC9"
}
"g_pGameRules"
{
@ -139,6 +147,7 @@
{
"library" "server"
"windows" "\xA1\x2A\x2A\x2A\x2A\xA8\x01\x75\x1F\x83\xC8\x01\xB9\x2A\x2A\x2A\x2A\xA3\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x68\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x83\xC4\x04\xB8"
"windows64" "\x48\x83\xEC\x28\x8B\x05\x2A\x2A\x2A\x2A\xA8\x01\x75\x72"
"linux" "@_Z23EntityFactoryDictionaryv"
"mac" "@_Z23EntityFactoryDictionaryv"
}
@ -154,6 +163,7 @@
{
"library" "server"
"windows" "\x55\x8B\xEC\x81\xEC\x20\x01\x00\x00\x53\x8B\xC1"
"windows64" "\x4C\x8B\xDC\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x49\x8D\xAB\x18\xFF\xFF\xFF"
"linux" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
"mac" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
}
@ -174,6 +184,7 @@
"SetUserCvar"
{
"windows" "22"
"windows64" "22"
"linux" "69"
"mac" "69"
}
@ -185,6 +196,7 @@
"SetClientName"
{
"windows" "21"
"windows64" "21"
"linux" "68"
"mac" "68"
}
@ -199,6 +211,7 @@
"InfoChanged"
{
"windows" "176"
"windows64" "208"
"linux" "176"
"mac" "176"
}
@ -212,84 +225,98 @@
"GiveNamedItem"
{
"windows" "441"
"windows64" "441"
"linux" "442"
"mac" "442"
}
"RemovePlayerItem"
{
"windows" "290"
"windows64" "290"
"linux" "291"
"mac" "291"
}
"Weapon_GetSlot"
{
"windows" "288"
"windows64" "288"
"linux" "289"
"mac" "289"
}
"Ignite"
{
"windows" "223"
"windows64" "223"
"linux" "224"
"mac" "224"
}
"Extinguish"
{
"windows" "226"
"windows64" "226"
"linux" "227"
"mac" "227"
}
"Teleport"
{
"windows" "115"
"windows64" "115"
"linux" "116"
"mac" "116"
}
"CommitSuicide"
{
"windows" "490"
"windows64" "490"
"linux" "490"
"mac" "490"
}
"GetVelocity"
{
"windows" "140"
"windows64" "140"
"linux" "141"
"mac" "141"
}
"EyeAngles"
{
"windows" "131"
"windows64" "131"
"linux" "132"
"mac" "132"
}
"AcceptInput"
{
"windows" "40"
"windows64" "40"
"linux" "41"
"mac" "41"
}
"SetEntityModel"
{
"windows" "24"
"windows64" "24"
"linux" "25"
"mac" "25"
}
"WeaponEquip"
{
"windows" "281"
"windows64" "281"
"linux" "282"
"mac" "282"
}
"Activate"
{
"windows" "35"
"windows64" "35"
"linux" "36"
"mac" "36"
}
"PlayerRunCmd"
{
"windows" "460"
"windows64" "460"
"linux" "461"
"mac" "461"
}

View File

@ -73,7 +73,10 @@ mysqlfolder=mysql-5.5-x86_64
if [ $ismac -eq 1 ]; then
mysqlver=mysql-5.5.28-osx10.5-x86_64
mysqlurl=https://cdn.mysql.com/archives/mysql-5.5/$mysqlver.$archive_ext
elif [ $iswin -eq 0 ]; then
elif [ $iswin -eq 1 ]; then
mysqlver=mysql-5.5.54-winx64
mysqlurl=https://cdn.mysql.com/archives/mysql-5.5/$mysqlver.$archive_ext
else
mysqlver=mysql-5.6.15-linux-glibc2.5-x86_64
mysqlurl=https://cdn.mysql.com/archives/mysql-5.6/$mysqlver.$archive_ext
fi