64-bit support for CSGO on Linux and macOS (#705)
This commit is contained in:
+53
-43
@@ -44,60 +44,70 @@ project.sources += [
|
||||
|
||||
for sdk_name in SM.sdks:
|
||||
sdk = SM.sdks[sdk_name]
|
||||
binary_name = 'sourcemod.' + sdk.ext
|
||||
for arch in SM.archs:
|
||||
if not arch in sdk.platformSpec[builder.target.platform]:
|
||||
continue
|
||||
|
||||
binary = SM.HL2Config(project, binary_name, sdk)
|
||||
compiler = binary.compiler
|
||||
binary_name = 'sourcemod.' + sdk.ext
|
||||
|
||||
compiler.cxxincludes += [
|
||||
builder.sourcePath
|
||||
]
|
||||
binary = SM.HL2Config(project, binary_name, sdk, arch)
|
||||
compiler = binary.compiler
|
||||
|
||||
if sdk.name == 'csgo':
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||
builder.sourcePath
|
||||
]
|
||||
|
||||
if builder.target.platform == 'linux':
|
||||
compiler.postlink += ['-lpthread', '-lrt']
|
||||
if sdk.name == 'csgo':
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||
]
|
||||
|
||||
if sdk.name == 'csgo':
|
||||
if builder.target.platform == 'linux':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
|
||||
compiler.linkflags += ['-Wl,--exclude-libs=libprotobuf.a']
|
||||
elif builder.target.platform == 'mac':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
|
||||
elif builder.target.platform == 'windows':
|
||||
msvc_ver = compiler.version
|
||||
vs_year = ''
|
||||
if msvc_ver == 1800:
|
||||
vs_year = '2013'
|
||||
elif msvc_ver == 1900:
|
||||
vs_year = '2015'
|
||||
elif msvc_ver == 1910:
|
||||
vs_year = '2017'
|
||||
else:
|
||||
raise Exception('Cannot find libprotobuf for MSVC version "' + str(compiler.version) + '"')
|
||||
compiler.postlink += ['-lpthread', '-lrt']
|
||||
|
||||
if 'DEBUG' in compiler.defines:
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs' + vs_year, 'libprotobuf.lib')
|
||||
else:
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib')
|
||||
compiler.linkflags.insert(0, binary.Dep(lib_path))
|
||||
if sdk.name == 'csgo':
|
||||
if builder.target.platform == 'linux':
|
||||
if arch == 'x86':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
|
||||
elif arch == 'x64':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'linux64', 'release', 'libprotobuf.a')
|
||||
compiler.linkflags += ['-Wl,--exclude-libs=libprotobuf.a']
|
||||
elif builder.target.platform == 'mac':
|
||||
if arch == 'x86':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
|
||||
elif arch == 'x64':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf.a')
|
||||
elif builder.target.platform == 'windows':
|
||||
msvc_ver = compiler.version
|
||||
vs_year = ''
|
||||
if msvc_ver == 1800:
|
||||
vs_year = '2013'
|
||||
elif msvc_ver == 1900:
|
||||
vs_year = '2015'
|
||||
elif msvc_ver == 1910:
|
||||
vs_year = '2017'
|
||||
else:
|
||||
raise Exception('Cannot find libprotobuf for MSVC version "' + str(compiler.version) + '"')
|
||||
|
||||
if 'DEBUG' in compiler.defines:
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs' + vs_year, 'libprotobuf.lib')
|
||||
else:
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib')
|
||||
compiler.linkflags.insert(0, binary.Dep(lib_path))
|
||||
|
||||
if sdk.name == 'csgo':
|
||||
binary.sources += ['smn_protobuf.cpp']
|
||||
else:
|
||||
binary.sources += ['smn_bitbuffer.cpp']
|
||||
if sdk.name == 'csgo':
|
||||
binary.sources += ['smn_protobuf.cpp']
|
||||
else:
|
||||
binary.sources += ['smn_bitbuffer.cpp']
|
||||
|
||||
if sdk.name == 'csgo':
|
||||
binary.sources += [
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
||||
]
|
||||
if sdk.name == 'csgo':
|
||||
binary.sources += [
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
||||
]
|
||||
|
||||
SM.binaries += builder.Add(project)
|
||||
|
||||
|
||||
@@ -364,8 +364,8 @@ void EventManager::FireEvent(EventInfo *pInfo, bool bDontBroadcast)
|
||||
|
||||
void EventManager::FireEventToClient(EventInfo *pInfo, IClient *pClient)
|
||||
{
|
||||
// The IClient vtable is +4 from the IGameEventListener2 (CBaseClient) vtable due to multiple inheritance.
|
||||
IGameEventListener2 *pGameClient = (IGameEventListener2 *)((intptr_t)pClient - 4);
|
||||
// The IClient vtable is +sizeof(void *) from the IGameEventListener2 (CBaseClient) vtable due to multiple inheritance.
|
||||
IGameEventListener2 *pGameClient = (IGameEventListener2 *)((intptr_t)pClient - sizeof(void *));
|
||||
pGameClient->FireGameEvent(pInfo->pEvent);
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -245,7 +245,12 @@ void CHalfLife2::InitLogicalEntData()
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
g_EntList = *reinterpret_cast<void **>(addr + offset);
|
||||
#elif defined PLATFORM_X64
|
||||
int32_t varOffset = *reinterpret_cast<int32_t *>(addr + offset);
|
||||
g_EntList = reinterpret_cast<void *>(addr + offset + sizeof(int32_t) + varOffset);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1357,7 +1362,7 @@ string_t CHalfLife2::AllocPooledString(const char *pszValue)
|
||||
|
||||
bool CHalfLife2::GetServerSteam3Id(char *pszOut, size_t len) const
|
||||
{
|
||||
CSteamID sid(GetServerSteamId64());
|
||||
CSteamID sid((uint64)GetServerSteamId64());
|
||||
|
||||
switch (sid.GetEAccountType())
|
||||
{
|
||||
|
||||
@@ -102,7 +102,7 @@ class KickPlayerTimer : public ITimedEvent
|
||||
public:
|
||||
ResultType OnTimer(ITimer *pTimer, void *pData)
|
||||
{
|
||||
int userid = (int)pData;
|
||||
int userid = (int)(intptr_t)pData;
|
||||
int client = g_Players.GetClientOfUserId(userid);
|
||||
if (client)
|
||||
{
|
||||
@@ -2480,7 +2480,7 @@ void CPlayer::DoBasicAdminChecks()
|
||||
if (!g_Players.CheckSetAdminName(client, this, id))
|
||||
{
|
||||
int userid = engine->GetPlayerUserId(m_pEdict);
|
||||
g_Timers.CreateTimer(&s_KickPlayerTimer, 0.1f, (void *)userid, 0);
|
||||
g_Timers.CreateTimer(&s_KickPlayerTimer, 0.1f, (void *)(intptr_t)userid, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
+90
-85
@@ -1,92 +1,97 @@
|
||||
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||
import os
|
||||
|
||||
binary = SM.Library(builder, 'sourcemod.logic')
|
||||
binary.compiler.cxxincludes += [
|
||||
builder.sourcePath,
|
||||
os.path.join(builder.sourcePath, 'core', 'logic'),
|
||||
os.path.join(builder.sourcePath, 'public'),
|
||||
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||
os.path.join(SM.mms_root, 'core', 'sourcehook')
|
||||
]
|
||||
binary.compiler.defines += [
|
||||
'SM_DEFAULT_THREADER',
|
||||
'SM_LOGIC'
|
||||
]
|
||||
for arch in SM.archs:
|
||||
binary = SM.Library(builder, 'sourcemod.logic', arch)
|
||||
binary.compiler.cxxincludes += [
|
||||
builder.sourcePath,
|
||||
os.path.join(builder.sourcePath, 'core', 'logic'),
|
||||
os.path.join(builder.sourcePath, 'public'),
|
||||
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||
os.path.join(SM.mms_root, 'core', 'sourcehook')
|
||||
]
|
||||
binary.compiler.defines += [
|
||||
'SM_DEFAULT_THREADER',
|
||||
'SM_LOGIC'
|
||||
]
|
||||
|
||||
if builder.target.platform == 'linux':
|
||||
binary.compiler.postlink += ['-lpthread', '-lrt']
|
||||
elif builder.target.platform == 'mac':
|
||||
binary.compiler.cflags += ['-Wno-deprecated-declarations']
|
||||
binary.compiler.postlink += ['-framework', 'CoreServices']
|
||||
if builder.target.platform == 'linux':
|
||||
binary.compiler.postlink += ['-lpthread', '-lrt']
|
||||
elif builder.target.platform == 'mac':
|
||||
binary.compiler.cflags += ['-Wno-deprecated-declarations']
|
||||
binary.compiler.postlink += ['-framework', 'CoreServices']
|
||||
|
||||
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.family == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.family == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
|
||||
binary.sources += [
|
||||
'common_logic.cpp',
|
||||
'smn_adt_array.cpp',
|
||||
'smn_sorting.cpp',
|
||||
'smn_maplists.cpp',
|
||||
'ADTFactory.cpp',
|
||||
'smn_adt_stack.cpp',
|
||||
'thread/ThreadWorker.cpp',
|
||||
'thread/BaseWorker.cpp',
|
||||
'ThreadSupport.cpp',
|
||||
'smn_float.cpp',
|
||||
'TextParsers.cpp',
|
||||
'smn_textparse.cpp',
|
||||
'smn_adt_trie.cpp',
|
||||
'smn_functions.cpp',
|
||||
'smn_timers.cpp',
|
||||
'smn_players.cpp',
|
||||
'MemoryUtils.cpp',
|
||||
'smn_admin.cpp',
|
||||
'smn_banning.cpp',
|
||||
'smn_filesystem.cpp',
|
||||
'stringutil.cpp',
|
||||
'Translator.cpp',
|
||||
'PhraseCollection.cpp',
|
||||
'smn_lang.cpp',
|
||||
'smn_string.cpp',
|
||||
'smn_handles.cpp',
|
||||
'smn_datapacks.cpp',
|
||||
'smn_gameconfigs.cpp',
|
||||
'smn_fakenatives.cpp',
|
||||
'GameConfigs.cpp',
|
||||
'sm_crc32.cpp',
|
||||
'smn_profiler.cpp',
|
||||
'ShareSys.cpp',
|
||||
'PluginSys.cpp',
|
||||
'HandleSys.cpp',
|
||||
'NativeOwner.cpp',
|
||||
'ExtensionSys.cpp',
|
||||
'DebugReporter.cpp',
|
||||
'Database.cpp',
|
||||
'smn_database.cpp',
|
||||
'ForwardSys.cpp',
|
||||
'AdminCache.cpp',
|
||||
'sm_trie.cpp',
|
||||
'smn_console.cpp',
|
||||
'ProfileTools.cpp',
|
||||
'Logger.cpp',
|
||||
'smn_core.cpp',
|
||||
'smn_menus.cpp',
|
||||
'sprintf.cpp',
|
||||
'LibrarySys.cpp',
|
||||
'RootConsoleMenu.cpp',
|
||||
'CDataPack.cpp',
|
||||
'frame_tasks.cpp',
|
||||
'smn_halflife.cpp',
|
||||
'FrameIterator.cpp',
|
||||
]
|
||||
if builder.target.platform == 'windows':
|
||||
binary.sources += ['thread/WinThreads.cpp']
|
||||
else:
|
||||
binary.sources += ['thread/PosixThreads.cpp']
|
||||
binary.sources += [
|
||||
'common_logic.cpp',
|
||||
'smn_adt_array.cpp',
|
||||
'smn_sorting.cpp',
|
||||
'smn_maplists.cpp',
|
||||
'ADTFactory.cpp',
|
||||
'smn_adt_stack.cpp',
|
||||
'thread/ThreadWorker.cpp',
|
||||
'thread/BaseWorker.cpp',
|
||||
'ThreadSupport.cpp',
|
||||
'smn_float.cpp',
|
||||
'TextParsers.cpp',
|
||||
'smn_textparse.cpp',
|
||||
'smn_adt_trie.cpp',
|
||||
'smn_functions.cpp',
|
||||
'smn_timers.cpp',
|
||||
'smn_players.cpp',
|
||||
'MemoryUtils.cpp',
|
||||
'smn_admin.cpp',
|
||||
'smn_banning.cpp',
|
||||
'smn_filesystem.cpp',
|
||||
'stringutil.cpp',
|
||||
'Translator.cpp',
|
||||
'PhraseCollection.cpp',
|
||||
'smn_lang.cpp',
|
||||
'smn_string.cpp',
|
||||
'smn_handles.cpp',
|
||||
'smn_datapacks.cpp',
|
||||
'smn_gameconfigs.cpp',
|
||||
'smn_fakenatives.cpp',
|
||||
'GameConfigs.cpp',
|
||||
'sm_crc32.cpp',
|
||||
'smn_profiler.cpp',
|
||||
'ShareSys.cpp',
|
||||
'PluginSys.cpp',
|
||||
'HandleSys.cpp',
|
||||
'NativeOwner.cpp',
|
||||
'ExtensionSys.cpp',
|
||||
'DebugReporter.cpp',
|
||||
'Database.cpp',
|
||||
'smn_database.cpp',
|
||||
'ForwardSys.cpp',
|
||||
'AdminCache.cpp',
|
||||
'sm_trie.cpp',
|
||||
'smn_console.cpp',
|
||||
'ProfileTools.cpp',
|
||||
'Logger.cpp',
|
||||
'smn_core.cpp',
|
||||
'smn_menus.cpp',
|
||||
'sprintf.cpp',
|
||||
'LibrarySys.cpp',
|
||||
'RootConsoleMenu.cpp',
|
||||
'CDataPack.cpp',
|
||||
'frame_tasks.cpp',
|
||||
'smn_halflife.cpp',
|
||||
'FrameIterator.cpp',
|
||||
]
|
||||
|
||||
SM.binaries += [builder.Add(binary)]
|
||||
if arch == 'x64':
|
||||
binary.sources += ['PseudoAddrManager.cpp']
|
||||
|
||||
if builder.target.platform == 'windows':
|
||||
binary.sources += ['thread/WinThreads.cpp']
|
||||
else:
|
||||
binary.sources += ['thread/PosixThreads.cpp']
|
||||
|
||||
SM.binaries += [builder.Add(binary)]
|
||||
|
||||
@@ -80,7 +80,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);
|
||||
|
||||
@@ -98,7 +98,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);
|
||||
|
||||
if (libsys->IsPathFile(path))
|
||||
@@ -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);
|
||||
|
||||
if (libsys->IsPathFile(path))
|
||||
@@ -124,7 +124,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);
|
||||
|
||||
@@ -135,7 +135,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,16 +76,22 @@ static const char *g_pParseEngine = NULL;
|
||||
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS 13
|
||||
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ 14
|
||||
|
||||
#if defined PLATFORM_X86
|
||||
#define PLATFORM_ARCH_SUFFIX ""
|
||||
#elif defined PLATFORM_X64
|
||||
#define PLATFORM_ARCH_SUFFIX "64"
|
||||
#endif
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
#define PLATFORM_NAME "windows"
|
||||
#define PLATFORM_NAME "windows" PLATFORM_ARCH_SUFFIX
|
||||
#define PLATFORM_SERVER_BINARY "server.dll"
|
||||
#elif defined PLATFORM_LINUX
|
||||
#define PLATFORM_NAME "linux"
|
||||
#define PLATFORM_COMPAT_ALT "mac" /* Alternate platform name if game data is missing for primary one */
|
||||
#define PLATFORM_NAME "linux" PLATFORM_ARCH_SUFFIX
|
||||
#define PLATFORM_COMPAT_ALT "mac" PLATFORM_ARCH_SUFFIX /* Alternate platform name if game data is missing for primary one */
|
||||
#define PLATFORM_SERVER_BINARY "server_i486.so"
|
||||
#elif defined PLATFORM_APPLE
|
||||
#define PLATFORM_NAME "mac"
|
||||
#define PLATFORM_COMPAT_ALT "linux"
|
||||
#define PLATFORM_NAME "mac" PLATFORM_ARCH_SUFFIX
|
||||
#define PLATFORM_COMPAT_ALT "linux" PLATFORM_ARCH_SUFFIX
|
||||
#define PLATFORM_SERVER_BINARY "server.dylib"
|
||||
#endif
|
||||
|
||||
@@ -338,7 +344,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0)
|
||||
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0 &&
|
||||
strcmp(name, "linux64") != 0 && strcmp(name, "windows64") != 0 && strcmp(name, "mac64") != 0)
|
||||
{
|
||||
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
|
||||
logger->LogError("[SM] Unrecognized platform \"%s\"", name);
|
||||
|
||||
@@ -125,7 +125,9 @@ bool CDirectory::IsEntryDirectory()
|
||||
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
|
||||
#elif defined PLATFORM_POSIX
|
||||
char temppath[PLATFORM_MAX_PATH];
|
||||
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
int ret = snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
if (static_cast<size_t>(ret) >= sizeof(temppath))
|
||||
return false;
|
||||
return ke::file::IsDirectory(temppath);
|
||||
#endif
|
||||
}
|
||||
@@ -136,7 +138,9 @@ bool CDirectory::IsEntryFile()
|
||||
return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE));
|
||||
#elif defined PLATFORM_POSIX
|
||||
char temppath[PLATFORM_MAX_PATH];
|
||||
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
int ret = snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
if (static_cast<size_t>(ret) >= sizeof(temppath))
|
||||
return false;
|
||||
return ke::file::IsFile(temppath);
|
||||
#endif
|
||||
}
|
||||
|
||||
+112
-76
@@ -43,18 +43,6 @@
|
||||
#include <mach-o/dyld_images.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/nlist.h>
|
||||
|
||||
/* Define things from 10.6 SDK for older SDKs */
|
||||
#ifndef MAC_OS_X_VERSION_10_6
|
||||
struct task_dyld_info
|
||||
{
|
||||
mach_vm_address_t all_image_info_addr;
|
||||
mach_vm_size_t all_image_info_size;
|
||||
};
|
||||
typedef struct task_dyld_info task_dyld_info_data_t;
|
||||
#define TASK_DYLD_INFO 17
|
||||
#define TASK_DYLD_INFO_COUNT (sizeof(task_dyld_info_data_t) / sizeof(natural_t))
|
||||
#endif // MAC_OS_X_VERSION_10_6
|
||||
#endif // PLATFORM_APPLE
|
||||
|
||||
MemoryUtils g_MemUtils;
|
||||
@@ -63,25 +51,10 @@ MemoryUtils::MemoryUtils()
|
||||
{
|
||||
#ifdef PLATFORM_APPLE
|
||||
|
||||
Gestalt(gestaltSystemVersionMajor, &m_OSXMajor);
|
||||
Gestalt(gestaltSystemVersionMinor, &m_OSXMinor);
|
||||
|
||||
/* Get pointer to struct that describes all loaded mach-o images in process */
|
||||
if ((m_OSXMajor == 10 && m_OSXMinor >= 6) || m_OSXMajor > 10)
|
||||
{
|
||||
task_dyld_info_data_t dyld_info;
|
||||
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
|
||||
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
|
||||
m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct nlist list[2];
|
||||
memset(list, 0, sizeof(list));
|
||||
list[0].n_un.n_name = (char *)"_dyld_all_image_infos";
|
||||
nlist("/usr/lib/dyld", list);
|
||||
m_ImageList = (struct dyld_all_image_infos *)list[0].n_value;
|
||||
}
|
||||
task_dyld_info_data_t dyld_info;
|
||||
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
|
||||
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
|
||||
m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -147,13 +120,25 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
typedef Elf32_Ehdr ElfHeader;
|
||||
typedef Elf32_Shdr ElfSHeader;
|
||||
typedef Elf32_Sym ElfSymbol;
|
||||
#define ELF_SYM_TYPE ELF32_ST_TYPE
|
||||
#else
|
||||
typedef Elf64_Ehdr ElfHeader;
|
||||
typedef Elf64_Shdr ElfSHeader;
|
||||
typedef Elf64_Sym ElfSymbol;
|
||||
#define ELF_SYM_TYPE ELF64_ST_TYPE
|
||||
#endif
|
||||
|
||||
struct link_map *dlmap;
|
||||
struct stat dlstat;
|
||||
int dlfile;
|
||||
uintptr_t map_base;
|
||||
Elf32_Ehdr *file_hdr;
|
||||
Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
|
||||
Elf32_Sym *symtab;
|
||||
ElfHeader *file_hdr;
|
||||
ElfSHeader *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
|
||||
ElfSymbol *symtab;
|
||||
const char *shstrtab, *strtab;
|
||||
uint16_t section_count;
|
||||
uint32_t symbol_count;
|
||||
@@ -204,7 +189,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
}
|
||||
|
||||
/* Map library file into memory */
|
||||
file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
|
||||
file_hdr = (ElfHeader *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
|
||||
map_base = (uintptr_t)file_hdr;
|
||||
if (file_hdr == MAP_FAILED)
|
||||
{
|
||||
@@ -219,7 +204,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff);
|
||||
sections = (ElfSHeader *)(map_base + file_hdr->e_shoff);
|
||||
section_count = file_hdr->e_shnum;
|
||||
/* Get ELF section header string table */
|
||||
shstrtab_hdr = §ions[file_hdr->e_shstrndx];
|
||||
@@ -228,7 +213,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
/* Iterate sections while looking for ELF symbol table and string table */
|
||||
for (uint16_t i = 0; i < section_count; i++)
|
||||
{
|
||||
Elf32_Shdr &hdr = sections[i];
|
||||
ElfSHeader &hdr = sections[i];
|
||||
const char *section_name = shstrtab + hdr.sh_name;
|
||||
|
||||
if (strcmp(section_name, ".symtab") == 0)
|
||||
@@ -248,15 +233,15 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset);
|
||||
symtab = (ElfSymbol *)(map_base + symtab_hdr->sh_offset);
|
||||
strtab = (const char *)(map_base + strtab_hdr->sh_offset);
|
||||
symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
|
||||
|
||||
/* Iterate symbol table starting from the position we were at last time */
|
||||
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
|
||||
{
|
||||
Elf32_Sym &sym = symtab[i];
|
||||
unsigned char sym_type = ELF32_ST_TYPE(sym.st_info);
|
||||
ElfSymbol &sym = symtab[i];
|
||||
unsigned char sym_type = ELF_SYM_TYPE(sym.st_info);
|
||||
const char *sym_name = strtab + sym.st_name;
|
||||
Symbol *cur_sym;
|
||||
|
||||
@@ -280,14 +265,29 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
return symbol_entry ? symbol_entry->address : NULL;
|
||||
|
||||
#elif defined PLATFORM_APPLE
|
||||
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
typedef struct mach_header MachHeader;
|
||||
typedef struct segment_command MachSegment;
|
||||
typedef struct nlist MachSymbol;
|
||||
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT;
|
||||
#else
|
||||
typedef struct mach_header_64 MachHeader;
|
||||
typedef struct segment_command_64 MachSegment;
|
||||
typedef struct nlist_64 MachSymbol;
|
||||
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT_64;
|
||||
#endif
|
||||
|
||||
typedef struct load_command MachLoadCmd;
|
||||
typedef struct symtab_command MachSymHeader;
|
||||
|
||||
uintptr_t dlbase, linkedit_addr;
|
||||
uint32_t image_count;
|
||||
struct mach_header *file_hdr;
|
||||
struct load_command *loadcmds;
|
||||
struct segment_command *linkedit_hdr;
|
||||
struct symtab_command *symtab_hdr;
|
||||
struct nlist *symtab;
|
||||
MachHeader *file_hdr;
|
||||
MachLoadCmd *loadcmds;
|
||||
MachSegment *linkedit_hdr;
|
||||
MachSymHeader *symtab_hdr;
|
||||
MachSymbol *symtab;
|
||||
const char *strtab;
|
||||
uint32_t loadcmd_count;
|
||||
uint32_t symbol_count;
|
||||
@@ -357,16 +357,16 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
|
||||
/* If symbol isn't in our table, then we have to locate it in memory */
|
||||
|
||||
file_hdr = (struct mach_header *)dlbase;
|
||||
loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header));
|
||||
file_hdr = (MachHeader *)dlbase;
|
||||
loadcmds = (MachLoadCmd *)(dlbase + sizeof(MachHeader));
|
||||
loadcmd_count = file_hdr->ncmds;
|
||||
|
||||
/* Loop through load commands until we find the ones for the symbol table */
|
||||
for (uint32_t i = 0; i < loadcmd_count; i++)
|
||||
{
|
||||
if (loadcmds->cmd == LC_SEGMENT && !linkedit_hdr)
|
||||
if (loadcmds->cmd == MACH_LOADCMD_SEGMENT && !linkedit_hdr)
|
||||
{
|
||||
struct segment_command *seg = (struct segment_command *)loadcmds;
|
||||
MachSegment *seg = (MachSegment *)loadcmds;
|
||||
if (strcmp(seg->segname, "__LINKEDIT") == 0)
|
||||
{
|
||||
linkedit_hdr = seg;
|
||||
@@ -378,7 +378,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
}
|
||||
else if (loadcmds->cmd == LC_SYMTAB)
|
||||
{
|
||||
symtab_hdr = (struct symtab_command *)loadcmds;
|
||||
symtab_hdr = (MachSymHeader *)loadcmds;
|
||||
if (linkedit_hdr)
|
||||
{
|
||||
break;
|
||||
@@ -386,7 +386,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
}
|
||||
|
||||
/* Load commands are not of a fixed size which is why we add the size */
|
||||
loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize);
|
||||
loadcmds = (MachLoadCmd *)((uintptr_t)loadcmds + loadcmds->cmdsize);
|
||||
}
|
||||
|
||||
if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
|
||||
@@ -396,14 +396,14 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
}
|
||||
|
||||
linkedit_addr = dlbase + linkedit_hdr->vmaddr;
|
||||
symtab = (struct nlist *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
|
||||
symtab = (MachSymbol *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
|
||||
strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff);
|
||||
symbol_count = symtab_hdr->nsyms;
|
||||
|
||||
/* Iterate symbol table starting from the position we were at last time */
|
||||
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
|
||||
{
|
||||
struct nlist &sym = symtab[i];
|
||||
MachSymbol &sym = symtab[i];
|
||||
/* Ignore the prepended underscore on all symbols, so +1 here */
|
||||
const char *sym_name = strtab + sym.n_un.n_strx + 1;
|
||||
Symbol *cur_sym;
|
||||
@@ -440,6 +440,12 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_I386;
|
||||
#else
|
||||
const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_AMD64;
|
||||
#endif
|
||||
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
IMAGE_DOS_HEADER *dos;
|
||||
IMAGE_NT_HEADERS *pe;
|
||||
@@ -465,10 +471,8 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check architecture, which is 32-bit/x86 right now
|
||||
* Should change this for 64-bit if Valve gets their act together
|
||||
*/
|
||||
if (file->Machine != IMAGE_FILE_MACHINE_I386)
|
||||
/* Check architecture */
|
||||
if (file->Machine != PE_FILE_MACHINE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -484,9 +488,21 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
typedef Elf32_Ehdr ElfHeader;
|
||||
typedef Elf32_Phdr ElfPHeader;
|
||||
const unsigned char ELF_CLASS = ELFCLASS32;
|
||||
const uint16_t ELF_MACHINE = EM_386;
|
||||
#else
|
||||
typedef Elf64_Ehdr ElfHeader;
|
||||
typedef Elf64_Phdr ElfPHeader;
|
||||
const unsigned char ELF_CLASS = ELFCLASS64;
|
||||
const uint16_t ELF_MACHINE = EM_X86_64;
|
||||
#endif
|
||||
|
||||
Dl_info info;
|
||||
Elf32_Ehdr *file;
|
||||
Elf32_Phdr *phdr;
|
||||
ElfHeader *file;
|
||||
ElfPHeader *phdr;
|
||||
uint16_t phdrCount;
|
||||
|
||||
if (!dladdr(libPtr, &info))
|
||||
@@ -501,7 +517,7 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
|
||||
/* This is for our insane sanity checks :o */
|
||||
baseAddr = reinterpret_cast<uintptr_t>(info.dli_fbase);
|
||||
file = reinterpret_cast<Elf32_Ehdr *>(baseAddr);
|
||||
file = reinterpret_cast<ElfHeader *>(baseAddr);
|
||||
|
||||
/* Check ELF magic */
|
||||
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
|
||||
@@ -514,11 +530,15 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check ELF endianness */
|
||||
if (file->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check ELF architecture, which is 32-bit/x86 right now
|
||||
* Should change this for 64-bit if Valve gets their act together
|
||||
*/
|
||||
if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||
/* Check ELF architecture */
|
||||
if (file->e_ident[EI_CLASS] != ELF_CLASS || file->e_machine != ELF_MACHINE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -530,11 +550,11 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
}
|
||||
|
||||
phdrCount = file->e_phnum;
|
||||
phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff);
|
||||
phdr = reinterpret_cast<ElfPHeader *>(baseAddr + file->e_phoff);
|
||||
|
||||
for (uint16_t i = 0; i < phdrCount; i++)
|
||||
{
|
||||
Elf32_Phdr &hdr = phdr[i];
|
||||
ElfPHeader &hdr = phdr[i];
|
||||
|
||||
/* We only really care about the segment with executable code */
|
||||
if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R))
|
||||
@@ -553,9 +573,25 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
|
||||
#elif defined PLATFORM_APPLE
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
typedef struct mach_header MachHeader;
|
||||
typedef struct segment_command MachSegment;
|
||||
const uint32_t MACH_MAGIC = MH_MAGIC;
|
||||
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT;
|
||||
const cpu_type_t MACH_CPU_TYPE = CPU_TYPE_I386;
|
||||
const cpu_subtype_t MACH_CPU_SUBTYPE = CPU_SUBTYPE_I386_ALL;
|
||||
#else
|
||||
typedef struct mach_header_64 MachHeader;
|
||||
typedef struct segment_command_64 MachSegment;
|
||||
const uint32_t MACH_MAGIC = MH_MAGIC_64;
|
||||
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT_64;
|
||||
const cpu_type_t MACH_CPU_TYPE = CPU_TYPE_X86_64;
|
||||
const cpu_subtype_t MACH_CPU_SUBTYPE = CPU_SUBTYPE_X86_64_ALL;
|
||||
#endif
|
||||
|
||||
Dl_info info;
|
||||
struct mach_header *file;
|
||||
struct segment_command *seg;
|
||||
MachHeader *file;
|
||||
MachSegment *seg;
|
||||
uint32_t cmd_count;
|
||||
|
||||
if (!dladdr(libPtr, &info))
|
||||
@@ -570,16 +606,16 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
|
||||
/* This is for our insane sanity checks :o */
|
||||
baseAddr = (uintptr_t)info.dli_fbase;
|
||||
file = (struct mach_header *)baseAddr;
|
||||
file = (MachHeader *)baseAddr;
|
||||
|
||||
/* Check Mach-O magic */
|
||||
if (file->magic != MH_MAGIC)
|
||||
if (file->magic != MACH_MAGIC)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check architecture (32-bit/x86) */
|
||||
if (file->cputype != CPU_TYPE_I386 || file->cpusubtype != CPU_SUBTYPE_I386_ALL)
|
||||
/* Check architecture */
|
||||
if (file->cputype != MACH_CPU_TYPE || file->cpusubtype != MACH_CPU_SUBTYPE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -591,17 +627,17 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
}
|
||||
|
||||
cmd_count = file->ncmds;
|
||||
seg = (struct segment_command *)(baseAddr + sizeof(struct mach_header));
|
||||
seg = (MachSegment *)(baseAddr + sizeof(MachHeader));
|
||||
|
||||
/* Add up memory sizes of mapped segments */
|
||||
for (uint32_t i = 0; i < cmd_count; i++)
|
||||
{
|
||||
if (seg->cmd == LC_SEGMENT)
|
||||
if (seg->cmd == MACH_LOADCMD_SEGMENT)
|
||||
{
|
||||
lib.memorySize += seg->vmsize;
|
||||
}
|
||||
|
||||
seg = (struct segment_command *)((uintptr_t)seg + seg->cmdsize);
|
||||
seg = (MachSegment *)((uintptr_t)seg + seg->cmdsize);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2017 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#include "PseudoAddrManager.h"
|
||||
#ifdef PLATFORM_APPLE
|
||||
#include <mach/mach.h>
|
||||
#include <mach/vm_region.h>
|
||||
#endif
|
||||
#ifdef PLATFORM_LINUX
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
PseudoAddressManager::PseudoAddressManager() : m_NumEntries(0)
|
||||
{
|
||||
}
|
||||
|
||||
// A pseudo address consists of a table index in the upper 6 bits and an offset in the
|
||||
// lower 26 bits. The table consists of memory allocation base addresses.
|
||||
void *PseudoAddressManager::FromPseudoAddress(uint32_t paddr)
|
||||
{
|
||||
#ifdef PLATFORM_X64
|
||||
uint8_t index = paddr >> PSEUDO_OFFSET_BITS;
|
||||
uint32_t offset = paddr & ((1 << PSEUDO_OFFSET_BITS) - 1);
|
||||
|
||||
if (index >= m_NumEntries)
|
||||
return nullptr;
|
||||
|
||||
return reinterpret_cast<void *>(uintptr_t(m_AllocBases[index]) + offset);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t PseudoAddressManager::ToPseudoAddress(void *addr)
|
||||
{
|
||||
#ifdef PLATFORM_X64
|
||||
uint8_t index = 0;
|
||||
uint32_t offset = 0;
|
||||
bool hasEntry = false;
|
||||
void *base = GetAllocationBase(addr);
|
||||
|
||||
if (base) {
|
||||
for (int i = 0; i < m_NumEntries; i++) {
|
||||
if (m_AllocBases[i] == base) {
|
||||
index = i;
|
||||
hasEntry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hasEntry) {
|
||||
index = m_NumEntries;
|
||||
if (m_NumEntries < SM_ARRAYSIZE(m_AllocBases))
|
||||
m_AllocBases[m_NumEntries++] = base;
|
||||
else
|
||||
return 0; // Table is full
|
||||
}
|
||||
|
||||
ptrdiff_t diff = uintptr_t(addr) - uintptr_t(base);
|
||||
|
||||
// Ensure difference fits in 26 bits
|
||||
if (diff > (UINT32_MAX >> PSEUDO_INDEX_BITS))
|
||||
return 0;
|
||||
|
||||
return (index << PSEUDO_OFFSET_BITS) | diff;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void *PseudoAddressManager::GetAllocationBase(void *ptr)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
if (!VirtualQuery(ptr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
|
||||
return nullptr;
|
||||
return info.AllocationBase;
|
||||
|
||||
#elif defined PLATFORM_APPLE
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
typedef vm_region_info_t mach_vm_region_info_t;
|
||||
typedef vm_region_basic_info_data_t mach_vm_region_basic_info_data_t;
|
||||
const vm_region_flavor_t MACH_VM_REGION_BASIC_INFO = VM_REGION_BASIC_INFO;
|
||||
const mach_msg_type_number_t MACH_VM_REGION_BASIC_INFO_COUNT = VM_REGION_BASIC_INFO_COUNT;
|
||||
#define mach_vm_region vm_region
|
||||
#elif defined PLATFORM_X64
|
||||
typedef vm_region_info_64_t mach_vm_region_info_t ;
|
||||
typedef vm_region_basic_info_data_64_t mach_vm_region_basic_info_data_t;
|
||||
const vm_region_flavor_t MACH_VM_REGION_BASIC_INFO = VM_REGION_BASIC_INFO_64;
|
||||
const mach_msg_type_number_t MACH_VM_REGION_BASIC_INFO_COUNT = VM_REGION_BASIC_INFO_COUNT_64;
|
||||
#define mach_vm_region vm_region_64
|
||||
#endif
|
||||
vm_size_t size;
|
||||
vm_address_t vmaddr = reinterpret_cast<vm_address_t>(ptr);
|
||||
mach_vm_region_basic_info_data_t info;
|
||||
memory_object_name_t obj;
|
||||
vm_region_flavor_t flavor = MACH_VM_REGION_BASIC_INFO;
|
||||
mach_msg_type_number_t count = MACH_VM_REGION_BASIC_INFO_COUNT;
|
||||
|
||||
kern_return_t kr = mach_vm_region(mach_task_self(), &vmaddr, &size, flavor,
|
||||
reinterpret_cast<mach_vm_region_info_t>(&info),
|
||||
&count, &obj);
|
||||
|
||||
if (kr != KERN_SUCCESS)
|
||||
return nullptr;
|
||||
|
||||
return reinterpret_cast<void *>(vmaddr);
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
|
||||
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
|
||||
|
||||
// Format:
|
||||
// lower upper prot stuff path
|
||||
// 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat
|
||||
FILE *fp = fopen("/proc/self/maps", "r");
|
||||
if (fp) {
|
||||
uintptr_t lower, upper;
|
||||
while (fscanf(fp, "%" PRIxPTR "-%" PRIxPTR, &lower, &upper) != EOF) {
|
||||
if (addr >= lower && addr <= upper) {
|
||||
fclose(fp);
|
||||
return reinterpret_cast<void *>(lower);
|
||||
}
|
||||
|
||||
// Read to end of line
|
||||
int c;
|
||||
while ((c = fgetc(fp)) != '\n') {
|
||||
if (c == EOF)
|
||||
break;
|
||||
}
|
||||
if (c == EOF)
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2017 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
|
||||
#define _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
|
||||
|
||||
#include "common_logic.h"
|
||||
|
||||
class PseudoAddressManager
|
||||
{
|
||||
public:
|
||||
PseudoAddressManager();
|
||||
public:
|
||||
void *FromPseudoAddress(uint32_t paddr);
|
||||
uint32_t ToPseudoAddress(void *addr);
|
||||
private:
|
||||
void *GetAllocationBase(void *ptr);
|
||||
private:
|
||||
static constexpr uint8_t PSEUDO_OFFSET_BITS = 26;
|
||||
static constexpr uint8_t PSEUDO_INDEX_BITS = sizeof(uint32_t) * 8 - PSEUDO_OFFSET_BITS;
|
||||
void *m_AllocBases[1 << PSEUDO_INDEX_BITS];
|
||||
uint8_t m_NumEntries;
|
||||
};
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
|
||||
@@ -86,6 +86,9 @@ IScriptManager *scripts = &g_PluginSys;
|
||||
IExtensionSys *extsys = &g_Extensions;
|
||||
ILogger *logger = &g_Logger;
|
||||
CNativeOwner g_CoreNatives;
|
||||
#ifdef PLATFORM_X64
|
||||
PseudoAddressManager pseudoAddr;
|
||||
#endif
|
||||
|
||||
static void AddCorePhraseFile(const char *filename)
|
||||
{
|
||||
@@ -115,6 +118,24 @@ static void RegisterProfiler(IProfilingTool *tool)
|
||||
g_ProfileToolManager.RegisterTool(tool);
|
||||
}
|
||||
|
||||
static void *FromPseudoAddress(uint32_t paddr)
|
||||
{
|
||||
#ifdef PLATFORM_X64
|
||||
return pseudoAddr.FromPseudoAddress(paddr);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t ToPseudoAddress(void *addr)
|
||||
{
|
||||
#ifdef PLATFORM_X64
|
||||
return pseudoAddr.ToPseudoAddress(addr);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Defined in smn_filesystem.cpp.
|
||||
extern bool OnLogPrint(const char *msg);
|
||||
|
||||
@@ -150,6 +171,8 @@ static sm_logic_t logic =
|
||||
CDataPack::Free,
|
||||
CellArray::New,
|
||||
CellArray::Free,
|
||||
FromPseudoAddress,
|
||||
ToPseudoAddress,
|
||||
&g_PluginSys,
|
||||
&g_ShareSys,
|
||||
&g_Extensions,
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#define _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_
|
||||
|
||||
#include "../sm_globals.h"
|
||||
#ifdef PLATFORM_X64
|
||||
#include "PseudoAddrManager.h"
|
||||
#endif
|
||||
|
||||
namespace SourceMod {
|
||||
class CoreProvider;
|
||||
@@ -57,6 +60,7 @@ class IVEngineServerBridge;
|
||||
#endif
|
||||
} // namespace SourceMod
|
||||
struct ServerGlobals;
|
||||
class PseudoAddressManager;
|
||||
|
||||
extern SourceMod::CoreProvider *bridge;
|
||||
extern SourceMod::IHandleSys *handlesys;
|
||||
@@ -76,6 +80,7 @@ extern SourceMod::IScriptManager *scripts;
|
||||
extern SourceMod::IExtensionSys *extsys;
|
||||
extern SourceMod::ILogger *logger;
|
||||
extern SourceMod::IMenuManager *menus;
|
||||
extern PseudoAddressManager pseudoAddr;
|
||||
|
||||
#if defined SM_LOGIC
|
||||
extern SourceMod::IVEngineServerBridge *engine;
|
||||
|
||||
@@ -708,7 +708,11 @@ enum NumberType
|
||||
|
||||
static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
void *addr = reinterpret_cast<void*>(params[1]);
|
||||
#else
|
||||
void *addr = pseudoAddr.FromPseudoAddress(params[1]);
|
||||
#endif
|
||||
|
||||
if (addr == NULL)
|
||||
{
|
||||
@@ -736,7 +740,11 @@ static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
#ifdef PLATFORM_X86
|
||||
void *addr = reinterpret_cast<void*>(params[1]);
|
||||
#else
|
||||
void *addr = pseudoAddr.FromPseudoAddress(params[1]);
|
||||
#endif
|
||||
|
||||
if (addr == NULL)
|
||||
{
|
||||
|
||||
@@ -152,7 +152,11 @@ static cell_t smn_GameConfGetAddress(IPluginContext *pCtx, const cell_t *params)
|
||||
if (!gc->GetAddress(key, &val))
|
||||
return 0;
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
return (cell_t)val;
|
||||
#else
|
||||
return pseudoAddr.ToPseudoAddress(val);
|
||||
#endif
|
||||
}
|
||||
|
||||
static GameConfigsNatives s_GameConfigsNatives;
|
||||
|
||||
@@ -653,7 +653,7 @@ void CoreProviderImpl::InitializeBridge()
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
ke::path::Format(path, sizeof(path),
|
||||
"%s/bin/matchmaking_ds%s.%s",
|
||||
"%s/bin/" PLATFORM_FOLDER "matchmaking_ds%s.%s",
|
||||
g_SMAPI->GetBaseDir(),
|
||||
MATCHMAKINGDS_SUFFIX,
|
||||
MATCHMAKINGDS_EXT);
|
||||
@@ -691,7 +691,7 @@ bool CoreProviderImpl::LoadBridge(char *error, size_t maxlength)
|
||||
/* Now it's time to load the logic binary */
|
||||
g_SMAPI->PathFormat(file,
|
||||
sizeof(file),
|
||||
"%s/bin/sourcemod.logic." PLATFORM_LIB_EXT,
|
||||
"%s/bin/" PLATFORM_ARCH_FOLDER "sourcemod.logic." PLATFORM_LIB_EXT,
|
||||
g_SourceMod.GetSourceModPath());
|
||||
|
||||
char myerror[255];
|
||||
|
||||
@@ -2609,7 +2609,12 @@ static cell_t GetEntityAddress(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
return reinterpret_cast<cell_t>(pEntity);
|
||||
#else
|
||||
return g_SourceMod.ToPseudoAddress(pEntity);
|
||||
#endif
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(entityNatives)
|
||||
|
||||
+12
-2
@@ -185,7 +185,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
|
||||
/* Attempt to load the JIT! */
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
char myerror[255];
|
||||
g_SMAPI->PathFormat(file, sizeof(file), "%s/bin/sourcepawn.jit.x86.%s",
|
||||
g_SMAPI->PathFormat(file, sizeof(file), "%s/bin/" PLATFORM_ARCH_FOLDER "sourcepawn.jit.x86.%s",
|
||||
GetSourceModPath(),
|
||||
PLATFORM_LIB_EXT
|
||||
);
|
||||
@@ -195,7 +195,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
|
||||
{
|
||||
if (error && maxlength)
|
||||
{
|
||||
ke::SafeSprintf(error, maxlength, "%s (failed to load bin/sourcepawn.jit.x86.%s)",
|
||||
ke::SafeSprintf(error, maxlength, "%s (failed to load bin/" PLATFORM_ARCH_FOLDER "sourcepawn.jit.x86.%s)",
|
||||
myerror,
|
||||
PLATFORM_LIB_EXT);
|
||||
}
|
||||
@@ -745,6 +745,16 @@ bool SourceModBase::IsMapRunning()
|
||||
return g_OnMapStarted;
|
||||
}
|
||||
|
||||
void *SourceModBase::FromPseudoAddress(uint32_t pseudoAddr)
|
||||
{
|
||||
return logicore.FromPseudoAddress(pseudoAddr);
|
||||
}
|
||||
|
||||
uint32_t SourceModBase::ToPseudoAddress(void *addr)
|
||||
{
|
||||
return logicore.ToPseudoAddress(addr);
|
||||
}
|
||||
|
||||
class ConVarRegistrar :
|
||||
public IConCommandBaseAccessor,
|
||||
public SMGlobalClass
|
||||
|
||||
@@ -135,6 +135,8 @@ public: // ISourceMod
|
||||
int GetPluginId();
|
||||
int GetShApiVersion();
|
||||
bool IsMapRunning();
|
||||
void *FromPseudoAddress(uint32_t pseudoAddr);
|
||||
uint32_t ToPseudoAddress(void *addr);
|
||||
private:
|
||||
void ShutdownServices();
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user