diff --git a/core/AMBuilder b/core/AMBuilder index 112bcdd..626a375 100644 --- a/core/AMBuilder +++ b/core/AMBuilder @@ -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] diff --git a/core/metamod.cpp b/core/metamod.cpp index 226be81..da8a630 100644 --- a/core/metamod.cpp +++ b/core/metamod.cpp @@ -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(static_cast(&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(static_cast(&g_SH_HookManagerAutoGen)); } -#endif + CPluginManager::CPlugin *pl; List::iterator event; IMetamodListener *api; diff --git a/core/sourcehook/sh_asm_x86_64.h b/core/sourcehook/sh_asm_x86_64.h index 1b559de..7da5dc9 100644 --- a/core/sourcehook/sh_asm_x86_64.h +++ b/core/sourcehook/sh_asm_x86_64.h @@ -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)); diff --git a/core/sourcehook/sourcehook_hookmangen_x86_64.cpp b/core/sourcehook/sourcehook_hookmangen_x86_64.cpp index 3c748f6..3a12379 100644 --- a/core/sourcehook/sourcehook_hookmangen_x86_64.cpp +++ b/core/sourcehook/sourcehook_hookmangen_x86_64.cpp @@ -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(); diff --git a/core/sourcehook/sourcehook_hookmangen_x86_64.h b/core/sourcehook/sourcehook_hookmangen_x86_64.h index 37c56fb..ac59407 100644 --- a/core/sourcehook/sourcehook_hookmangen_x86_64.h +++ b/core/sourcehook/sourcehook_hookmangen_x86_64.h @@ -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();