我们现在的引擎中,所有的单件由一个管理类来管理。任何一个模块想取到一个单件,都可以通过一个统一的方法从管理类中拿到。
在调试程序的过程中,我遇到了一个奇怪的需求。我需要在一个单件的方法被调用时,程序都会停下来,进入调试器。
诚然,如果每次单件都通过 get_instance
取得,然后调用其方法的话,我们在 get_instance
里设置断点即可。但是,在我们的引擎中,每个模块都是在初始化阶段,拿到单件的指针。然后放在了全局变量中。单件的使用,直接运用这个指针。这样,就对监视这个单件的调用造成了麻烦。
为了解决这个问题,我用了一个很 trick 的方法,下面列出代码。
#include
#include
#include
#include
struct i_foobar {
virtual void foo(int arg)=0;
virtual void bar()=0;
};
class foobar : public i_foobar {
public:
virtual void foo(int arg) {
printf("%d",arg);
}
virtual void bar() {
printf("bar");
}
};
#define MAX_METHOD 64
#pragma pack(push,1)
struct __proxy_code {
unsigned char mov_edx;
unsigned long index;
unsigned char jmp;
unsigned long offset;
unsigned char nop1;
unsigned char nop2;
};
#pragma pack(pop)
static const void* __proxy_virtual_table[MAX_METHOD];
static __proxy_code __proxy_bridge_code[MAX_METHOD];
__declspec(naked) void __proxy_gate()
{
__asm {
int 3 // 断点
mov ecx,[ecx-4]
mov eax,[ecx]
add eax,edx
mov eax,[eax]
jmp eax
}
}
struct __proxy_t {
void *__instance;
void *__vtbl;
};
void init_proxy()
{
int i;
for (i=0;i
T* create_proxy(T* instance)
{
__proxy_t *p=new __proxy_t;
p->__instance=instance;
p->__vtbl=__proxy_virtual_table;
return (T*)&(p->__vtbl);
}
void main()
{
init_proxy();
i_foobar *foo=new foobar;
i_foobar *proxy=create_proxy(foo);
proxy->foo(100);
proxy->bar();
}
我们给出了一个简单的例子,这个程序有很多问题,比如单件 foo 在程序开始构造出来,却没有在最后释放。我们只是用它说明这个技巧。这里我们拥有一个单件的接口 i_foobar
,它有两个方法 foo 和 bar 。下面有一个简单的实现 foobar 。接下来我不希望对 i_foorbar
以及 foobar 的实现做任何修改了。
通过两个数组,__proxy_virtual_table , __proxy_code __proxy_bridge_code
我们得到了一个假的 foobar 对象。实际上它可以伪装任何一个接口类(有虚函数上限64个的限制)。有了这个东西,我们可以为 foobar 这个单件创建一个 proxy 了。proxy 这个名字可能不太恰当,姑且如此了。 这里的 proxy 的行为和 foo 完全一致,唯一不同的是,每次调用都会产生一个 int 3 :)
实际上,这个技巧可以被更广泛的使用,比如对特定函数做钩子,或者有更灵活的断点设置方法等。
Comments
Posted by: 凄临雨 | (17) April 23, 2012 12:47 AM
Posted by: yongzhi.wu | (16) September 20, 2007 02:16 PM
Posted by: jiffwan | (15) October 30, 2006 11:37 AM
Posted by: chloe | (14) May 7, 2006 05:08 PM
Posted by: Dragon | (13) March 31, 2006 01:26 PM
Posted by: Cloud | (12) March 23, 2006 07:14 PM
Posted by: 林悠雨 | (11) March 23, 2006 04:28 PM
Posted by: Cloud | (10) March 14, 2006 03:40 PM
Posted by: Cloud | (9) March 14, 2006 03:34 PM
Posted by: Atry | (8) March 14, 2006 03:13 PM
Posted by: 不空 | (7) March 14, 2006 09:43 AM
Posted by: Cloud | (6) March 13, 2006 01:09 PM
Posted by: John Fractal | (5) March 13, 2006 11:15 AM
Posted by: mouse | (4) March 13, 2006 09:50 AM
Posted by: Atry | (3) March 13, 2006 09:33 AM
Posted by: Atry | (2) March 13, 2006 09:27 AM
Posted by: Atry | (1) March 13, 2006 09:23 AM