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':
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']
nodes = builder.Add(binary)
MMS.binaries += [nodes]

View File

@ -84,9 +84,7 @@ static MetamodSourceConVar *mm_basedir = NULL;
static CreateInterfaceFn engine_factory = NULL;
static CreateInterfaceFn physics_factory = NULL;
static CreateInterfaceFn filesystem_factory = NULL;
#if !defined( __amd64__ )
static CHookManagerAutoGen g_SH_HookManagerAutoGen(&g_SourceHook);
#endif
static META_RES last_meta_res;
static IServerPluginCallbacks *vsp_callbacks = NULL;
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));
}
#if !defined( __amd64__ )
else if (strcmp(iface, MMIFACE_SH_HOOKMANAUTOGEN) == 0)
{
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));
}
#endif
CPluginManager::CPlugin *pl;
List<IMetamodListener *>::iterator event;
IMetamodListener *api;

View File

@ -464,7 +464,8 @@ namespace SourceHook
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(0x31);
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
AutoDetectRetType();
if (!AutoDetectRetType())
{
return nullptr;
}
AutoDetectParamFlags();
// 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
{
// nullptr
m_HookFunc.xor(rax, rax);
m_HookFunc.xor_reg(rax, rax);
// 9th argument - const void* origRetPtr
MSVC_ONLY(m_HookFunc.mov(rsp(0x40), rax));
// 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(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.cmp(r9, MRES_OVERRIDE);
@ -1236,11 +1239,11 @@ static_assert(false, "Missing registers saving for linux");
&& (retInfo.flags & (PassInfo::PassFlag_ODtor | PassInfo::PassFlag_AssignOp)));
}
void x64GenContext::AutoDetectRetType() {
bool x64GenContext::AutoDetectRetType() {
auto& pi = m_Proto.GetRet();
// Void return, ignore
if (pi.size == 0) {
return;
return true;
}
// Only relevant for byval types
@ -1283,7 +1286,24 @@ static_assert(false, "Missing registers saving for linux");
pi.flags |= PassInfo::PassFlag_RetReg;
}
#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
}
}
@ -1294,6 +1314,7 @@ static_assert(false, "Missing auto-detect type for linux!");
pi.flags &= ~PassInfo::PassFlag_RetMem;
pi.flags |= PassInfo::PassFlag_RetReg;
}
return true;
}
void x64GenContext::AutoDetectParamFlags()
@ -1402,7 +1423,7 @@ static_assert(false, "Missing auto-detect type for linux!");
GCC_ONLY(m_PubFunc.pop(rbp));
// Return 0
m_PubFunc.xor(rax, rax);
m_PubFunc.xor_reg(rax, rax);
m_PubFunc.retn();

View File

@ -38,12 +38,12 @@ namespace SourceHook
std::int32_t AddVarToFrame(std::int32_t size);
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 GetParamStackSize(const IntPassInfo &info);
void Clear();
void AutoDetectRetType();
bool AutoDetectRetType();
void AutoDetectParamFlags();
bool PassInfoSupported(const IntPassInfo& pi, bool is_ret);
void BuildProtoInfo();