mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-12-09 19:38:29 +00:00
The pain begins
This commit is contained in:
parent
dc41559c79
commit
57929cabcf
@ -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]
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user