# cpp-stub **Repository Path**: dongbo_89/cpp-stub ## Basic Information - **Project Name**: cpp-stub - **Description**: c++ unit testing stub(mock) - **Primary Language**: C++ - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2019-07-09 - **Last Updated**: 2021-11-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ![](https://github.com/coolxv/cpp-stub/blob/master/mm.png) **说明:** - 只适用linux,和windows的x86、x64架构 - stub.h(windows、linux)相关方法基于C++03;使用Inline Hook方式(参考:[http://jbremer.org/x86-api-hooking-demystified/#ah-other-2](http://jbremer.org/x86-api-hooking-demystified/#ah-other-2)、[https://www.codeproject.com/Articles/70302/Redirecting-functions-in-shared-ELF-libraries](https://www.codeproject.com/Articles/70302/Redirecting-functions-in-shared-ELF-libraries)) - addr_pri.h(windows、linux)相关方法基于C++11(参考:[https://github.com/martong/access_private](https://github.com/martong/access_private)) - addr.h(linux) 相关方法基于C++03,使用elfio库(参考:[https://github.com/serge1/ELFIO)) - windows和linux的用法会稍微不同,原因是获取不同类型函数地址的方法不同,且调用约定有时不一样 **不可以打桩的情况:** - 不可以对exit函数打桩,编译器做了特殊优化 - 不可以对纯虚函数打桩,纯虚函数没有地址 - static声明的普通内部函数不能打桩,内部函数地址不可见(linux可使用addr.h来获取地址) ![](https://github.com/coolxv/cpp-stub/blob/master/intel.png) *** ## 普通函数打桩(非static) ``` //for linux and windows #include #include "stub.h" using namespace std; int foo(int a) { cout<<"I am foo"< #include "stub.h" using namespace std; class A{ int i; public: int foo(int a){ cout<<"I am A_foo"< #include "stub.h" using namespace std; class A{ int i; public: int foo(int a){ cout<<"I am A_foo"< #include "stub.h" using namespace std; class A{ int i; public: static int foo(int a){ cout<<"I am A_foo"< #include "stub.h" using namespace std; class A{ public: template int foo(T a) { cout<<"I am A_foo"< #include "stub.h" using namespace std; class A{ public: template int foo(T a) { cout<<"I am A_foo"< #include "stub.h" using namespace std; class A{ int i; public: int foo(int a){ cout<<"I am A_foo_int"< #include "stub.h" using namespace std; class A{ int i; public: int foo(int a){ cout<<"I am A_foo_int"< #include "stub.h" using namespace std; class A{ public: virtual int foo(int a){ cout<<"I am A_foo"< #include "stub.h" using namespace std; class A { public: virtual int foo(int a) { cout << "I am A_foo" << endl; return 0; } }; class B { public: int foo_stub(int a) { cout << "I am foo_stub" << endl; return 0; } }; int main() { unsigned long addr; _asm {mov eax, A::foo} _asm {mov addr, eax} Stub stub; stub.set(addr, ADDR(B, foo_stub)); A a; a.foo(1); return 0; } ``` ``` //for windows x64(64位),VS编译器不支持内嵌汇编。有解决方案自行搜索。 ``` ## 内联函数打桩 ``` //for linux //添加-fno-inline编译选项,禁止内联,能获取到函数地址,打桩参考上面。 ``` ``` //for windows //添加/Ob0禁用内联展开。 ``` ## 第三方库私有成员函数打桩 ``` //for linux //被测代码添加-fno-access-private编译选项,禁用访问权限控制,成员函数都为公有的 //无源码的动态库或静态库无法自己编译,需要特殊技巧获取函数地址 #include #include "stub.h" using namespace std; class A{ int a; int foo(int x){ cout<<"I am A_foo "<< a << endl; return 0; } static int b; static int bar(int x){ cout<<"I am A_bar "<< b << endl; return 0; } }; ACCESS_PRIVATE_FIELD(A, int, a); ACCESS_PRIVATE_FUN(A, int(int), foo); ACCESS_PRIVATE_STATIC_FIELD(A, int, b); ACCESS_PRIVATE_STATIC_FUN(A, int(int), bar); int foo_stub(void* obj, int x) { A* o= (A*)obj; cout<<"I am foo_stub"< #include "stub.h" using namespace std; class A{ int a; int foo(int x){ cout<<"I am A_foo "<< a << endl; return 0; } static int b; static int bar(int x){ cout<<"I am A_bar "<< b << endl; return 0; } }; ACCESS_PRIVATE_FIELD(A, int, a); ACCESS_PRIVATE_FUN(A, int(int), foo); ACCESS_PRIVATE_STATIC_FIELD(A, int, b); ACCESS_PRIVATE_STATIC_FUN(A, int(int), bar); class B { public: int foo_stub(int x) { cout << "I am foo_stub" << endl; return 0; } }; int bar_stub(int x) { cout<<"I am bar_stub"<