Skip to content

Commit

Permalink
Add x64 Windows support to DHooks (#2154)
Browse files Browse the repository at this point in the history
* Add x64 Windows support

* undo changes of hook.cpp

* undo changes of hook.h

* undo changes of extension.cpp

* undo changes of listeners.cpp

* undo changes of signatures.cpp

* fix dhooks on x86

* Fix-up dhooks buildscript

---------

Co-authored-by: Kenzzer <[email protected]>
  • Loading branch information
Kenzzer and Kenzzer committed Sep 10, 2024
1 parent 4e6d66b commit 4e15a92
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 100 deletions.
49 changes: 31 additions & 18 deletions extensions/dhooks/AMBuilder
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import os
for cxx in builder.targets:
binary = SM.ExtLibrary(builder, cxx, 'dhooks.ext')

# Only x86 on Linux and Windows is supported.
if binary.compiler.target.platform == 'mac' or binary.compiler.target.arch != 'x86':
# mac isn't supported
if binary.compiler.target.platform == 'mac':
continue
# Presently only x86_64 on Windows is supported
if binary.compiler.target.arch == 'x86_64' and binary.compiler.target.platform != 'windows':
continue

binary.compiler.defines += [
Expand All @@ -21,10 +24,8 @@ for cxx in builder.targets:
os.path.join(SM.mms_root, 'core', 'sourcehook'),
os.path.join(builder.sourcePath, 'extensions', 'dhooks'),
os.path.join(builder.sourcePath, 'public', 'jit'),
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
os.path.join(builder.sourcePath, 'sourcepawn', 'vm'),
os.path.join(builder.sourcePath, 'sourcepawn', 'vm', 'x86'),
os.path.join(builder.sourcePath, 'extensions', 'dhooks', 'DynamicHooks'),
]

Expand All @@ -48,22 +49,34 @@ for cxx in builder.targets:
'libudis86/syn-intel.c',
'libudis86/syn.c',
'libudis86/udis86.c',
'../../sourcepawn/vm/x86/assembler-x86.cpp',
# Dynamic Hooks
os.path.join('DynamicHooks', 'registers.cpp')
]

# DynamicHooks
binary.sources += [
os.path.join('DynamicHooks', 'hook.cpp'),
os.path.join('DynamicHooks', 'manager.cpp'),
os.path.join('DynamicHooks', 'registers.cpp'),
os.path.join('DynamicHooks', 'conventions', 'x86MsCdecl.cpp'),
os.path.join('DynamicHooks', 'conventions', 'x86MsStdcall.cpp'),
os.path.join('DynamicHooks', 'conventions', 'x86MsFastcall.cpp'),
]
if binary.compiler.target.arch == 'x86':
binary.sources += ['../../sourcepawn/vm/x86/assembler-x86.cpp']
binary.compiler.cxxincludes += [
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
os.path.join(builder.sourcePath, 'sourcepawn', 'vm', 'x86')
]
# DynamicHooks
binary.sources += [
os.path.join('DynamicHooks', 'hook.cpp'),
os.path.join('DynamicHooks', 'manager.cpp'),
os.path.join('DynamicHooks', 'conventions', 'x86MsCdecl.cpp'),
os.path.join('DynamicHooks', 'conventions', 'x86MsStdcall.cpp'),
os.path.join('DynamicHooks', 'conventions', 'x86MsFastcall.cpp'),
]

if binary.compiler.target.platform == 'windows':
binary.sources += [os.path.join('DynamicHooks', 'conventions', 'x86MsThiscall.cpp')]
else:
binary.sources += [os.path.join('DynamicHooks', 'conventions', 'x86GccThiscall.cpp')]

# Dynamic detour is only supported on x86
binary.compiler.defines += ['DHOOKS_DYNAMIC_DETOUR']

if binary.compiler.target.platform == 'windows':
binary.sources += [os.path.join('DynamicHooks', 'conventions', 'x86MsThiscall.cpp')]
else:
binary.sources += [os.path.join('DynamicHooks', 'conventions', 'x86GccThiscall.cpp')]
elif binary.compiler.target.arch == 'x86_64':
binary.compiler.defines += ['PLATFORM_X64']

SM.extensions += [builder.Add(binary)]
8 changes: 4 additions & 4 deletions extensions/dhooks/DynamicHooks/convention.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ The data type you would like to get the size of.
@param <alignment>:
The alignment that should be used.
*/
inline int GetDataTypeSize(DataTypeSized_t type, int iAlignment=4)
inline size_t GetDataTypeSize(DataTypeSized_t type, int iAlignment=4)
{
switch(type.type)
{
Expand Down Expand Up @@ -257,9 +257,9 @@ class ICallingConvention
int size = GetArgStackSize() + GetArgRegisterSize();
std::unique_ptr<uint8_t[]> pSavedCallArguments = std::make_unique<uint8_t[]>(size);
size_t offset = 0;
for (size_t i = 0; i < m_vecArgTypes.size(); i++) {
for (unsigned int i = 0; i < m_vecArgTypes.size(); i++) {
DataTypeSized_t &type = m_vecArgTypes[i];
memcpy((void *)((unsigned long)pSavedCallArguments.get() + offset), GetArgumentPtr(i, pRegisters), type.size);
memcpy((void *)((uintptr_t)pSavedCallArguments.get() + offset), GetArgumentPtr(i, pRegisters), type.size);
offset += type.size;
}
m_pSavedCallArguments.push_back(std::move(pSavedCallArguments));
Expand All @@ -271,7 +271,7 @@ class ICallingConvention
size_t offset = 0;
for (size_t i = 0; i < m_vecArgTypes.size(); i++) {
DataTypeSized_t &type = m_vecArgTypes[i];
memcpy(GetArgumentPtr(i, pRegisters), (void *)((unsigned long)pSavedCallArguments + offset), type.size);
memcpy(GetArgumentPtr((unsigned int)i, pRegisters), (void *)((uintptr_t)pSavedCallArguments + offset), type.size);
offset += type.size;
}
m_pSavedCallArguments.pop_back();
Expand Down
23 changes: 9 additions & 14 deletions extensions/dhooks/DynamicHooks/registers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ CRegisters::CRegisters(std::vector<Register_t> registers)
// >> 64-bit General purpose registers
// ========================================================================
// 64-bit mode only
/*
#ifdef PLATFORM_X64
m_rax = CreateRegister(registers, RAX, 8);
m_rcx = CreateRegister(registers, RCX, 8);
m_rdx = CreateRegister(registers, RDX, 8);
Expand All @@ -125,10 +125,7 @@ CRegisters::CRegisters(std::vector<Register_t> registers)
m_rbp = CreateRegister(registers, RBP, 8);
m_rsi = CreateRegister(registers, RSI, 8);
m_rdi = CreateRegister(registers, RDI, 8);
*/

// 64-bit mode only
/*

m_r8 = CreateRegister(registers, R8, 8);
m_r9 = CreateRegister(registers, R9, 8);
m_r10 = CreateRegister(registers, R10, 8);
Expand All @@ -137,7 +134,7 @@ CRegisters::CRegisters(std::vector<Register_t> registers)
m_r13 = CreateRegister(registers, R13, 8);
m_r14 = CreateRegister(registers, R14, 8);
m_r15 = CreateRegister(registers, R15, 8);
*/
#endif

// ========================================================================
// >> 64-bit MM (MMX) registers
Expand Down Expand Up @@ -165,7 +162,7 @@ CRegisters::CRegisters(std::vector<Register_t> registers)
m_xmm7 = CreateRegister(registers, XMM7, 16, 16);

// 64-bit mode only
/*
#ifdef PLATFORM_X64
m_xmm8 = CreateRegister(registers, XMM8, 16);
m_xmm9 = CreateRegister(registers, XMM9, 16);
m_xmm10 = CreateRegister(registers, XMM10, 16);
Expand All @@ -174,7 +171,7 @@ CRegisters::CRegisters(std::vector<Register_t> registers)
m_xmm13 = CreateRegister(registers, XMM13, 16);
m_xmm14 = CreateRegister(registers, XMM14, 16);
m_xmm15 = CreateRegister(registers, XMM15, 16);
*/
#endif

// ========================================================================
// >> 16-bit Segment registers
Expand Down Expand Up @@ -282,7 +279,7 @@ CRegisters::~CRegisters()
// >> 64-bit General purpose registers
// ========================================================================
// 64-bit mode only
/*
#ifdef PLATFORM_X64
DeleteRegister(m_rax);
DeleteRegister(m_rcx);
DeleteRegister(m_rdx);
Expand All @@ -291,10 +288,8 @@ CRegisters::~CRegisters()
DeleteRegister(m_rbp);
DeleteRegister(m_rsi);
DeleteRegister(m_rdi);
*/

// 64-bit mode only
/*
DeleteRegister(m_r8);
DeleteRegister(m_r9);
DeleteRegister(m_r10);
Expand All @@ -303,7 +298,7 @@ CRegisters::~CRegisters()
DeleteRegister(m_r13);
DeleteRegister(m_r14);
DeleteRegister(m_r15);
*/
#endif

// ========================================================================
// >> 64-bit MM (MMX) registers
Expand All @@ -330,7 +325,7 @@ CRegisters::~CRegisters()
DeleteRegister(m_xmm7);

// 64-bit mode only
/*
#ifdef PLATFORM_X64
DeleteRegister(m_xmm8);
DeleteRegister(m_xmm9);
DeleteRegister(m_xmm10);
Expand All @@ -339,7 +334,7 @@ CRegisters::~CRegisters()
DeleteRegister(m_xmm13);
DeleteRegister(m_xmm14);
DeleteRegister(m_xmm15);
*/
#endif

// ========================================================================
// >> 2-bit Segment registers
Expand Down
23 changes: 8 additions & 15 deletions extensions/dhooks/DynamicHooks/registers.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ enum Register_t
// ========================================================================
// >> 64-bit General purpose registers
// ========================================================================
// 64-bit mode only
/*
#ifdef PLATFORM_X64
RAX,
RCX,
RDX,
Expand All @@ -142,10 +141,7 @@ enum Register_t
RBP,
RSI,
RDI,
*/

// 64-bit mode only
/*
R8,
R9,
R10,
Expand All @@ -154,7 +150,7 @@ enum Register_t
R13,
R14,
R15,
*/
#endif

// ========================================================================
// >> 64-bit MM (MMX) registers
Expand All @@ -181,7 +177,7 @@ enum Register_t
XMM7,

// 64-bit mode only
/*
#ifdef PLATFORM_X64
XMM8,
XMM9,
XMM10,
Expand All @@ -190,7 +186,7 @@ enum Register_t
XMM13,
XMM14,
XMM15,
*/
#endif

// ========================================================================
// >> 16-bit Segment registers
Expand Down Expand Up @@ -377,7 +373,7 @@ class CRegisters
// >> 64-bit General purpose registers
// ========================================================================
// 64-bit mode only
/*
#ifdef PLATFORM_X64
CRegister* m_rax;
CRegister* m_rcx;
CRegister* m_rdx;
Expand All @@ -386,10 +382,7 @@ class CRegisters
CRegister* m_rbp;
CRegister* m_rsi;
CRegister* m_rdi;
*/

// 64-bit mode only
/*
CRegister* m_r8;
CRegister* m_r9;
CRegister* m_r10;
Expand All @@ -398,7 +391,7 @@ class CRegisters
CRegister* m_r13;
CRegister* m_r14;
CRegister* m_r15;
*/
#endif

// ========================================================================
// >> 64-bit MM (MMX) registers
Expand All @@ -425,7 +418,7 @@ class CRegisters
CRegister* m_xmm7;

// 64-bit mode only
/*
#ifdef PLATFORM_X64
CRegister* m_xmm8;
CRegister* m_xmm9;
CRegister* m_xmm10;
Expand All @@ -434,7 +427,7 @@ class CRegisters
CRegister* m_xmm13;
CRegister* m_xmm14;
CRegister* m_xmm15;
*/
#endif

// ========================================================================
// >> 16-bit Segment registers
Expand Down
20 changes: 20 additions & 0 deletions extensions/dhooks/dynhooks_sourcepawn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,18 @@ DetourMap g_pPostDetours;

void UnhookFunction(HookType_t hookType, CHook *pDetour)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
CHookManager *pDetourManager = GetHookManager();
pDetour->RemoveCallback(hookType, (HookHandlerFn *)(void *)&HandleDetour);
// Only disable the detour if there are no more listeners.
if (!pDetour->AreCallbacksRegistered())
pDetourManager->UnhookFunction(pDetour->m_pFunc);
#endif
}

bool AddDetourPluginHook(HookType_t hookType, CHook *pDetour, HookSetup *setup, IPluginFunction *pCallback)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
DetourMap *map;
if (hookType == HOOKTYPE_PRE)
map = &g_pPreDetours;
Expand Down Expand Up @@ -102,10 +105,14 @@ bool AddDetourPluginHook(HookType_t hookType, CHook *pDetour, HookSetup *setup,
wrappers->push_back(pWrapper);

return true;
#else
return false;
#endif
}

bool RemoveDetourPluginHook(HookType_t hookType, CHook *pDetour, IPluginFunction *pCallback)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
DetourMap *map;
if (hookType == HOOKTYPE_PRE)
map = &g_pPreDetours;
Expand Down Expand Up @@ -139,10 +146,14 @@ bool RemoveDetourPluginHook(HookType_t hookType, CHook *pDetour, IPluginFunction
}

return bRemoved;
#else
return false;
#endif
}

void RemoveAllCallbacksForContext(HookType_t hookType, DetourMap *map, IPluginContext *pContext)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
PluginCallbackList *wrappers;
CDynamicHooksSourcePawn *pWrapper;
DetourMap::iterator it = map->iter();
Expand Down Expand Up @@ -170,16 +181,20 @@ void RemoveAllCallbacksForContext(HookType_t hookType, DetourMap *map, IPluginCo
it.erase();
}
}
#endif
}

void RemoveAllCallbacksForContext(IPluginContext *pContext)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
RemoveAllCallbacksForContext(HOOKTYPE_PRE, &g_pPreDetours, pContext);
RemoveAllCallbacksForContext(HOOKTYPE_POST, &g_pPostDetours, pContext);
#endif
}

void CleanupDetours(HookType_t hookType, DetourMap *map)
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
PluginCallbackList *wrappers;
CDynamicHooksSourcePawn *pWrapper;
DetourMap::iterator it = map->iter();
Expand All @@ -199,14 +214,18 @@ void CleanupDetours(HookType_t hookType, DetourMap *map)
UnhookFunction(hookType, it->key);
}
map->clear();
#endif
}

void CleanupDetours()
{
#if defined( DHOOKS_DYNAMIC_DETOUR )
CleanupDetours(HOOKTYPE_PRE, &g_pPreDetours);
CleanupDetours(HOOKTYPE_POST, &g_pPostDetours);
#endif
}

#if defined( DHOOKS_DYNAMIC_DETOUR )
ICallingConvention *ConstructCallingConvention(HookSetup *setup)
{
// Convert function parameter types into DynamicHooks structures.
Expand Down Expand Up @@ -249,6 +268,7 @@ ICallingConvention *ConstructCallingConvention(HookSetup *setup)

return pCallConv;
}
#endif

// Some arguments might be optimized to be passed in registers instead of the stack.
bool UpdateRegisterArgumentSizes(CHook* pDetour, HookSetup *setup)
Expand Down
Loading

0 comments on commit 4e15a92

Please sign in to comment.