Skip to content

Commit e50b6ce

Browse files
committed
Added recursive thiscalls tests
1 parent af3da38 commit e50b6ce

File tree

5 files changed

+395
-1
lines changed

5 files changed

+395
-1
lines changed

tests/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ If(WIN32)
4848
create_dynamic_hooks_test(test_ms_cdecl1 ms_cdecl1.cpp)
4949
create_dynamic_hooks_test(test_ms_cdecl2 ms_cdecl2.cpp)
5050
create_dynamic_hooks_test(test_ms_thiscall1 ms_thiscall1.cpp)
51+
create_dynamic_hooks_test(test_ms_thiscall2 ms_thiscall2.cpp)
5152
Else()
5253
create_dynamic_hooks_test(test_gcc_cdecl1 gcc_cdecl1.cpp)
5354
create_dynamic_hooks_test(test_gcc_cdecl2 gcc_cdecl2.cpp)
55+
create_dynamic_hooks_test(test_gcc_thiscall1 gcc_thiscall1.cpp)
56+
create_dynamic_hooks_test(test_gcc_thiscall2 gcc_thiscall2.cpp)
5457
Endif()

tests/gcc_thiscall1.cpp

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/**
2+
* =============================================================================
3+
* DynamicHooks
4+
* Copyright (C) 2015 Robin Gohmert. All rights reserved.
5+
* =============================================================================
6+
*
7+
* This software is provided 'as-is', without any express or implied warranty.
8+
* In no event will the authors be held liable for any damages arising from
9+
* the use of this software.
10+
*
11+
* Permission is granted to anyone to use this software for any purpose,
12+
* including commercial applications, and to alter it and redistribute it
13+
* freely, subject to the following restrictions:
14+
*
15+
* 1. The origin of this software must not be misrepresented; you must not
16+
* claim that you wrote the original software. If you use this software in a
17+
* product, an acknowledgment in the product documentation would be
18+
* appreciated but is not required.
19+
*
20+
* 2. Altered source versions must be plainly marked as such, and must not be
21+
* misrepresented as being the original software.
22+
*
23+
* 3. This notice may not be removed or altered from any source distribution.
24+
*
25+
* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc
26+
* -fPIC thunks correctly
27+
*
28+
* Idea and trampoline code taken from DynDetours (thanks your-name-here).
29+
*/
30+
31+
// ============================================================================
32+
// >> INCLUDES
33+
// ============================================================================
34+
#include "assert.h"
35+
36+
#include "manager.h"
37+
#include "conventions/x86GccThiscall.h"
38+
39+
40+
// ============================================================================
41+
// >> GLOBAL VARIABLES
42+
// ============================================================================
43+
int g_iMyFuncCallCount = 0;
44+
int g_iPreMyFuncCallCount = 0;
45+
int g_iPostMyFuncCallCount = 0;
46+
47+
48+
// ============================================================================
49+
// >> cdecl test
50+
// ============================================================================
51+
class MyClass;
52+
MyClass* g_pMyClass = NULL;
53+
54+
class MyClass
55+
{
56+
public:
57+
int MyFunc(int x, int y)
58+
{
59+
g_iMyFuncCallCount++;
60+
assert(this == g_pMyClass);
61+
assert(x == 3);
62+
assert(y == 10);
63+
64+
int result = x + y;
65+
assert(result == 13);
66+
67+
return result;
68+
}
69+
};
70+
71+
bool PreMyFunc(HookType_t eHookType, CHook* pHook)
72+
{
73+
g_iPreMyFuncCallCount++;
74+
MyClass* pMyClass = pHook->GetArgument<MyClass *>(0);
75+
assert(pMyClass == g_pMyClass);
76+
77+
int x = pHook->GetArgument<int>(1);
78+
assert(x == 3);
79+
80+
int y = pHook->GetArgument<int>(2);
81+
assert(y == 10);
82+
return false;
83+
}
84+
85+
bool PostMyFunc(HookType_t eHookType, CHook* pHook)
86+
{
87+
g_iPostMyFuncCallCount++;
88+
int x = pHook->GetArgument<int>(1);
89+
assert(x == 3);
90+
91+
int y = pHook->GetArgument<int>(2);
92+
assert(y == 10);
93+
94+
int return_value = pHook->GetReturnValue<int>();
95+
assert(return_value == 13);
96+
97+
pHook->SetReturnValue<int>(1337);
98+
return false;
99+
}
100+
101+
102+
// ============================================================================
103+
// >> main
104+
// ============================================================================
105+
int main()
106+
{
107+
CHookManager* pHookMngr = GetHookManager();
108+
109+
int (MyClass::*MyFunc)(int, int) = &MyClass::MyFunc;
110+
111+
// Prepare calling convention
112+
std::vector<DataType_t> vecArgTypes;
113+
vecArgTypes.push_back(DATA_TYPE_POINTER);
114+
vecArgTypes.push_back(DATA_TYPE_INT);
115+
vecArgTypes.push_back(DATA_TYPE_INT);
116+
117+
// Hook the function
118+
CHook* pHook = pHookMngr->HookFunction(
119+
(void *&) MyFunc,
120+
new x86GccThiscall(vecArgTypes, DATA_TYPE_INT)
121+
);
122+
123+
pHook->AddCallback(HOOKTYPE_PRE, (HookHandlerFn *) (void *) &PreMyFunc);
124+
pHook->AddCallback(HOOKTYPE_POST, (HookHandlerFn *) (void *) &PostMyFunc);
125+
126+
// Call the function
127+
MyClass a;
128+
g_pMyClass = &a;
129+
130+
int return_value = a.MyFunc(3, 10);
131+
132+
assert(g_iMyFuncCallCount == 1);
133+
assert(g_iPreMyFuncCallCount == 1);
134+
assert(g_iPostMyFuncCallCount == 1);
135+
assert(return_value == 1337);
136+
137+
pHookMngr->UnhookAllFunctions();
138+
return 0;
139+
}

tests/gcc_thiscall2.cpp

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/**
2+
* =============================================================================
3+
* DynamicHooks
4+
* Copyright (C) 2015 Robin Gohmert. All rights reserved.
5+
* =============================================================================
6+
*
7+
* This software is provided 'as-is', without any express or implied warranty.
8+
* In no event will the authors be held liable for any damages arising from
9+
* the use of this software.
10+
*
11+
* Permission is granted to anyone to use this software for any purpose,
12+
* including commercial applications, and to alter it and redistribute it
13+
* freely, subject to the following restrictions:
14+
*
15+
* 1. The origin of this software must not be misrepresented; you must not
16+
* claim that you wrote the original software. If you use this software in a
17+
* product, an acknowledgment in the product documentation would be
18+
* appreciated but is not required.
19+
*
20+
* 2. Altered source versions must be plainly marked as such, and must not be
21+
* misrepresented as being the original software.
22+
*
23+
* 3. This notice may not be removed or altered from any source distribution.
24+
*
25+
* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc
26+
* -fPIC thunks correctly
27+
*
28+
* Idea and trampoline code taken from DynDetours (thanks your-name-here).
29+
*/
30+
31+
// ============================================================================
32+
// >> INCLUDES
33+
// ============================================================================
34+
#include "assert.h"
35+
36+
#include "manager.h"
37+
#include "conventions/x86GccThiscall.h"
38+
39+
40+
// ============================================================================
41+
// >> GLOBAL VARIABLES
42+
// ============================================================================
43+
int g_iMyFuncCallCount = 0;
44+
int g_iPreMyFuncCallCount = 0;
45+
int g_iPostMyFuncCallCount = 0;
46+
47+
48+
// ============================================================================
49+
// >> thiscall test
50+
// ============================================================================
51+
class MyClass;
52+
MyClass* g_pMyClass = NULL;
53+
54+
class MyClass
55+
{
56+
public:
57+
int MyFunc(int x)
58+
{
59+
g_iMyFuncCallCount++;
60+
assert(this == g_pMyClass);
61+
assert(x >= 0 && x <= 3);
62+
if (x == 3)
63+
return x;
64+
65+
return MyFunc(x + 1);
66+
}
67+
};
68+
69+
bool PreMyFunc(HookType_t eHookType, CHook* pHook)
70+
{
71+
g_iPreMyFuncCallCount++;
72+
73+
MyClass* pMyClass = pHook->GetArgument<MyClass *>(0);
74+
assert(pMyClass == g_pMyClass);
75+
76+
int x = pHook->GetArgument<int>(1);
77+
assert(x >= 0 && x <= 3);
78+
return false;
79+
}
80+
81+
bool PostMyFunc(HookType_t eHookType, CHook* pHook)
82+
{
83+
g_iPostMyFuncCallCount++;
84+
int return_value = pHook->GetReturnValue<int>();
85+
assert(return_value == 3);
86+
return false;
87+
}
88+
89+
90+
// ============================================================================
91+
// >> main
92+
// ============================================================================
93+
int main()
94+
{
95+
CHookManager* pHookMngr = GetHookManager();
96+
97+
int (MyClass::*MyFunc)(int) = &MyClass::MyFunc;
98+
99+
// Prepare calling convention
100+
std::vector<DataType_t> vecArgTypes;
101+
vecArgTypes.push_back(DATA_TYPE_POINTER);
102+
vecArgTypes.push_back(DATA_TYPE_INT);
103+
104+
// Hook the function
105+
CHook* pHook = pHookMngr->HookFunction(
106+
(void *&) MyFunc,
107+
new x86GccThiscall(vecArgTypes, DATA_TYPE_INT)
108+
);
109+
110+
pHook->AddCallback(HOOKTYPE_PRE, (HookHandlerFn *) (void *) &PreMyFunc);
111+
pHook->AddCallback(HOOKTYPE_POST, (HookHandlerFn *) (void *) &PostMyFunc);
112+
113+
// Call the function
114+
MyClass a;
115+
g_pMyClass = &a;
116+
117+
int return_value = a.MyFunc(0);
118+
119+
assert(g_iMyFuncCallCount == 4);
120+
assert(g_iPreMyFuncCallCount == 4);
121+
assert(g_iPostMyFuncCallCount == 4);
122+
assert(return_value == 3);
123+
124+
pHookMngr->UnhookAllFunctions();
125+
return 0;
126+
}

tests/ms_thiscall1.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ int g_iPostMyFuncCallCount = 0;
4646

4747

4848
// ============================================================================
49-
// >> cdecl test
49+
// >> thiscall test
5050
// ============================================================================
5151
class MyClass;
5252
MyClass* g_pMyClass = NULL;

0 commit comments

Comments
 (0)