gmock
借助于C++运行时多态实现,派生需要打桩的类,使用桩函数覆盖原来的实现,将指向原类的指针指向桩类
mockcpp
// src/UnixCodeModifier.cpp
bool CodeModifier::modify(void *dest, const void *src, size_t size)
{
// 将 TEXT 段访问权限修改从 x 修改为 rwx
if(::mprotect(ALIGN_TO_PAGE_BOUNDARY(dest), PAGE_SIZE * 2, PROT_EXEC | PROT_WRITE | PROT_READ ) != 0)
{
return false;
}
::memcpy(dest, src, size);
}
// src/JmpCodeX86.h, 相对跳转指令
const unsigned char jmpCodeTemplate[] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
#define SET_JMP_CODE(base, from, to) do { \
*(unsigned long*)(base + 1) = \
(unsigned long)to - (unsigned long)from - sizeof(jmpCodeTemplate); \
} while(0)
// src/JmpCodeX64.h 绝对跳转指令
// FF 25 : JMP /4 jmp absolute indirect
// bytes 2 ~ 5 : operand of jmp, relative to the memory that recorded the thunk addr. it should be zero.
// bytes 6 ~ 13 : the absolute addr of thunk.
const unsigned char jmpCodeTemplate[] =
{ 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
#define SET_JMP_CODE(base, from, to) do { \
*(uintptr_t *)(base + 6) = (uintptr_t)to; \
} while(0)
mockcpp打桩c++成员函数
gtest+mockcpp,修改mockcpp以支持C++中类成员函数的mock_XiaoH0_0的博客-CSDN博客_mocker_cpp_virtual
通过成员函数指针获取成员函数的存储位置,然后使用 mockcpp 的打桩机制,将成员函数的入口替换为跳转到桩函数的跳转指令
class A
{
public:
A(int a): a(a) { cnt++; }
virtual ~A() {}
string _A() { return "in A"; }
virtual string str()
{
stringstream ss;
ss << a;
return ss.str();
}
static int getCnt() { return cnt; }
protected:
int a;
static int cnt;
};
int A::cnt = 0;
class B : public A
{
public:
B(int a): A(a) {}
virtual ~B() {}
string _B() { return "in B"; }
virtual string str()
{
stringstream ss;
ss << "0x" << std::hex << a << std::dec;
return ss.str();
}
};
int main()
{
A a(1);
B b(2);
// 静态成员函数的函数指针, 可以认为是普通的函数指针
int (*pgetCnt)() = &A::getCnt;
36f9: 48 8d 05 b7 09 00 00 lea 0x9b7(%rip),%rax # 40b7 <_ZN1A6getCntEv>
3700: 48 89 85 50 ff ff ff mov %rax,-0xb0(%rbp)
// 非 virtual 的成员函数
string (A::*p_A)() = &A::_A;
3707: 48 8d 05 4a 08 00 00 lea 0x84a(%rip),%rax # 3f58 <_ZN1A2_AB5cxx11Ev>
370e: 48 89 45 80 mov %rax,-0x80(%rbp)
3712: 48 c7 45 88 00 00 00 movq $0x0,-0x78(%rbp)
3719: 00
// virtual 的成员函数
string (A::*p_Astr)() = &A::str;
3747: 48 c7 45 80 11 00 00 movq $0x11,-0x80(%rbp)
374e: 00
374f: 48 c7 45 88 00 00 00 movq $0x0,-0x78(%rbp)
3756: 00
string (B::*p_Bstr)() = &B::str;
3757: 48 c7 45 90 11 00 00 movq $0x11,-0x70(%rbp)
375e: 00
375f: 48 c7 45 98 00 00 00 movq $0x0,-0x68(%rbp)
((&b)->*p_Astr)();
3767: 48 8b 45 88 mov -0x78(%rbp),%rax
376b: 48 89 c2 mov %rax,%rdx
376e: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
3775: 48 8d 0c 10 lea (%rax,%rdx,1),%rcx
3779: 48 8b 45 80 mov -0x80(%rbp),%rax
377d: 83 e0 01 and $0x1,%eax
3780: 48 85 c0 test %rax,%rax
3783: 74 24 je 37a9 <main+0xf7>
3785: 48 8b 45 88 mov -0x78(%rbp),%rax
3789: 48 89 c2 mov %rax,%rdx
378c: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
3793: 48 01 d0 add %rdx,%rax
3796: 48 8b 00 mov (%rax),%rax
3799: 48 8b 55 80 mov -0x80(%rbp),%rdx
379d: 48 83 ea 01 sub $0x1,%rdx
37a1: 48 01 d0 add %rdx,%rax
37a4: 48 8b 00 mov (%rax),%rax
37a7: eb 04 jmp 37ad <main+0xfb>
37a9: 48 8b 45 80 mov -0x80(%rbp),%rax
37ad: 48 8d 55 a0 lea -0x60(%rbp),%rdx
37b1: 48 89 ce mov %rcx,%rsi
37b4: 48 89 d7 mov %rdx,%rdi
37b7: ff d0 callq *%rax
37b9: 48 8d 45 a0 lea -0x60(%rbp),%rax
37bd: 48 89 c7 mov %rax,%rdi
37c0: e8 0b fb ff ff callq 32d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
((&a)->*p_Astr)();
37c5: 48 8b 45 88 mov -0x78(%rbp),%rax
37c9: 48 89 c2 mov %rax,%rdx
37cc: 48 8d 85 40 ff ff ff lea -0xc0(%rbp),%rax
37d3: 48 8d 0c 10 lea (%rax,%rdx,1),%rcx
37d7: 48 8b 45 80 mov -0x80(%rbp),%rax
37db: 83 e0 01 and $0x1,%eax
37de: 48 85 c0 test %rax,%rax
37e1: 74 24 je 3807 <main+0x155>
37e3: 48 8b 45 88 mov -0x78(%rbp),%rax
37e7: 48 89 c2 mov %rax,%rdx
37ea: 48 8d 85 40 ff ff ff lea -0xc0(%rbp),%rax
37f1: 48 01 d0 add %rdx,%rax
37f4: 48 8b 00 mov (%rax),%rax
37f7: 48 8b 55 80 mov -0x80(%rbp),%rdx
37fb: 48 83 ea 01 sub $0x1,%rdx
37ff: 48 01 d0 add %rdx,%rax
3802: 48 8b 00 mov (%rax),%rax
3805: eb 04 jmp 380b <main+0x159>
3807: 48 8b 45 80 mov -0x80(%rbp),%rax
380b: 48 8d 55 c0 lea -0x40(%rbp),%rdx
380f: 48 89 ce mov %rcx,%rsi
3812: 48 89 d7 mov %rdx,%rdi
3815: ff d0 callq *%rax
3817: 48 8d 45 c0 lea -0x40(%rbp),%rax
381b: 48 89 c7 mov %rax,%rdi
381e: e8 ad fa ff ff callq 32d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>
return 0;
}