The pain begins

This commit is contained in:
rtldg 2025-03-01 13:33:56 +00:00
parent dc41559c79
commit 57929cabcf
5 changed files with 34 additions and 15 deletions

View File

@ -41,7 +41,7 @@ for sdk_target in MMS.sdk_targets:
if cxx.target.arch == 'x86': if cxx.target.arch == 'x86':
binary.sources += ['sourcehook/sourcehook_hookmangen_x86.cpp'] binary.sources += ['sourcehook/sourcehook_hookmangen_x86.cpp']
elif binary.compiler.target.arch == 'x86_64' and binary.compiler.target.platform != 'linux': elif binary.compiler.target.arch == 'x86_64':
binary.sources += ['sourcehook/sourcehook_hookmangen_x86_64.cpp'] binary.sources += ['sourcehook/sourcehook_hookmangen_x86_64.cpp']
nodes = builder.Add(binary) nodes = builder.Add(binary)
MMS.binaries += [nodes] MMS.binaries += [nodes]

View File

@ -84,9 +84,7 @@ static MetamodSourceConVar *mm_basedir = NULL;
static CreateInterfaceFn engine_factory = NULL; static CreateInterfaceFn engine_factory = NULL;
static CreateInterfaceFn physics_factory = NULL; static CreateInterfaceFn physics_factory = NULL;
static CreateInterfaceFn filesystem_factory = NULL; static CreateInterfaceFn filesystem_factory = NULL;
#if !defined( __amd64__ )
static CHookManagerAutoGen g_SH_HookManagerAutoGen(&g_SourceHook); static CHookManagerAutoGen g_SH_HookManagerAutoGen(&g_SourceHook);
#endif
static META_RES last_meta_res; static META_RES last_meta_res;
static IServerPluginCallbacks *vsp_callbacks = NULL; static IServerPluginCallbacks *vsp_callbacks = NULL;
static bool were_plugins_loaded = false; static bool were_plugins_loaded = false;
@ -846,7 +844,6 @@ void *MetamodSource::MetaFactory(const char *iface, int *ret, PluginId *id)
} }
return static_cast<void *>(static_cast<ISmmPluginManager *>(&g_PluginMngr)); return static_cast<void *>(static_cast<ISmmPluginManager *>(&g_PluginMngr));
} }
#if !defined( __amd64__ )
else if (strcmp(iface, MMIFACE_SH_HOOKMANAUTOGEN) == 0) else if (strcmp(iface, MMIFACE_SH_HOOKMANAUTOGEN) == 0)
{ {
if (ret) if (ret)
@ -855,7 +852,7 @@ void *MetamodSource::MetaFactory(const char *iface, int *ret, PluginId *id)
} }
return static_cast<void *>(static_cast<SourceHook::IHookManagerAutoGen *>(&g_SH_HookManagerAutoGen)); return static_cast<void *>(static_cast<SourceHook::IHookManagerAutoGen *>(&g_SH_HookManagerAutoGen));
} }
#endif
CPluginManager::CPlugin *pl; CPluginManager::CPlugin *pl;
List<IMetamodListener *>::iterator event; List<IMetamodListener *>::iterator event;
IMetamodListener *api; IMetamodListener *api;

View File

@ -464,7 +464,8 @@ namespace SourceHook
this->write_int32(imm); this->write_int32(imm);
} }
void xor(x86_64_Reg dst, x86_64_Reg src) { // can't name it `xor` because that's a C++ keyword (it works in VS tho but not clang)
void xor_reg(x86_64_Reg dst, x86_64_Reg src) {
this->write_ubyte(w_rex(src, dst)); this->write_ubyte(w_rex(src, dst));
this->write_ubyte(0x31); this->write_ubyte(0x31);
this->write_ubyte(modrm(src, dst)); this->write_ubyte(modrm(src, dst));

View File

@ -238,7 +238,10 @@ namespace SourceHook
} }
// Detect the pass flags (if they're missing) for return and parameters type // Detect the pass flags (if they're missing) for return and parameters type
AutoDetectRetType(); if (!AutoDetectRetType())
{
return nullptr;
}
AutoDetectParamFlags(); AutoDetectParamFlags();
// Calling conventions are gone on x86_64, there's only one to call all functions // Calling conventions are gone on x86_64, there's only one to call all functions
@ -596,7 +599,7 @@ static_assert(false, "Missing parameters destruction for linux");
if (m_Proto.GetRet().size == 0) // void return function if (m_Proto.GetRet().size == 0) // void return function
{ {
// nullptr // nullptr
m_HookFunc.xor(rax, rax); m_HookFunc.xor_reg(rax, rax);
// 9th argument - const void* origRetPtr // 9th argument - const void* origRetPtr
MSVC_ONLY(m_HookFunc.mov(rsp(0x40), rax)); MSVC_ONLY(m_HookFunc.mov(rsp(0x40), rax));
// 10th argument - void* overrideRetPtr // 10th argument - void* overrideRetPtr
@ -1112,7 +1115,7 @@ static_assert(false, "Missing registers saving for linux");
m_HookFunc.mov(rax, rax(getOrigRetPtrMfi.vtblindex * SIZE_PTR)); m_HookFunc.mov(rax, rax(getOrigRetPtrMfi.vtblindex * SIZE_PTR));
m_HookFunc.mov(r8, r8(getOverrideRetPtrMfi.vtblindex * SIZE_PTR)); m_HookFunc.mov(r8, r8(getOverrideRetPtrMfi.vtblindex * SIZE_PTR));
m_HookFunc.xor(r9, r9); m_HookFunc.xor_reg(r9, r9);
m_HookFunc.mov(r9, rbp(v_status)); m_HookFunc.mov(r9, rbp(v_status));
m_HookFunc.cmp(r9, MRES_OVERRIDE); m_HookFunc.cmp(r9, MRES_OVERRIDE);
@ -1236,11 +1239,11 @@ static_assert(false, "Missing registers saving for linux");
&& (retInfo.flags & (PassInfo::PassFlag_ODtor | PassInfo::PassFlag_AssignOp))); && (retInfo.flags & (PassInfo::PassFlag_ODtor | PassInfo::PassFlag_AssignOp)));
} }
void x64GenContext::AutoDetectRetType() { bool x64GenContext::AutoDetectRetType() {
auto& pi = m_Proto.GetRet(); auto& pi = m_Proto.GetRet();
// Void return, ignore // Void return, ignore
if (pi.size == 0) { if (pi.size == 0) {
return; return true;
} }
// Only relevant for byval types // Only relevant for byval types
@ -1283,7 +1286,24 @@ static_assert(false, "Missing registers saving for linux");
pi.flags |= PassInfo::PassFlag_RetReg; pi.flags |= PassInfo::PassFlag_RetReg;
} }
#elif SH_COMP == SH_COMP_GCC #elif SH_COMP == SH_COMP_GCC
static_assert(false, "Missing auto-detect type for linux!"); // It depends on the object layout.
//
//
// typedef struct __attribute__((packed)) { char a; int b; } thing;
// = memory (5 bytes)
//
// typedef struct __attribute__((packed)) { int a; char b; } thing;
// = register (5 bytes)
//
// typedef struct __attribute__((packed)) { char a; short b; char c; } thing;
// = memory (6 bytes)
//
// typedef struct __attribute__((packed)) { char a; short b; int c; char d; } thing;
// = memory (8 bytes)
//
//
// Result: we cannot detect if it should be register or memory without knowing the layout of the object.
return false;
#endif #endif
} }
} }
@ -1294,6 +1314,7 @@ static_assert(false, "Missing auto-detect type for linux!");
pi.flags &= ~PassInfo::PassFlag_RetMem; pi.flags &= ~PassInfo::PassFlag_RetMem;
pi.flags |= PassInfo::PassFlag_RetReg; pi.flags |= PassInfo::PassFlag_RetReg;
} }
return true;
} }
void x64GenContext::AutoDetectParamFlags() void x64GenContext::AutoDetectParamFlags()
@ -1402,7 +1423,7 @@ static_assert(false, "Missing auto-detect type for linux!");
GCC_ONLY(m_PubFunc.pop(rbp)); GCC_ONLY(m_PubFunc.pop(rbp));
// Return 0 // Return 0
m_PubFunc.xor(rax, rax); m_PubFunc.xor_reg(rax, rax);
m_PubFunc.retn(); m_PubFunc.retn();

View File

@ -38,12 +38,12 @@ namespace SourceHook
std::int32_t AddVarToFrame(std::int32_t size); std::int32_t AddVarToFrame(std::int32_t size);
std::int32_t ComputeVarsSize(); std::int32_t ComputeVarsSize();
std::int32_t x64GenContext::GetRealSize(const IntPassInfo& info); std::int32_t GetRealSize(const IntPassInfo& info);
std::int32_t AlignSize(std::int32_t x, std::int32_t boundary); std::int32_t AlignSize(std::int32_t x, std::int32_t boundary);
std::int32_t GetParamStackSize(const IntPassInfo &info); std::int32_t GetParamStackSize(const IntPassInfo &info);
void Clear(); void Clear();
void AutoDetectRetType(); bool AutoDetectRetType();
void AutoDetectParamFlags(); void AutoDetectParamFlags();
bool PassInfoSupported(const IntPassInfo& pi, bool is_ret); bool PassInfoSupported(const IntPassInfo& pi, bool is_ret);
void BuildProtoInfo(); void BuildProtoInfo();