WEB开发网
开发学院软件开发VC 通用Thunk 阅读

通用Thunk

 2010-07-15 20:45:23 来源:WEB开发网   
核心提示:优化sizeof(ThisToCdecl)==36 , 我认为这是不可接受的,如果我们使用PUSH old_return 来代替 MOV DWORD PTR[ESP],old_return,可以节省2字节(因此,通用Thunk(10),我们必须在保存old_esp之前弹栈),于此同时,3. 将ECX设置为this指针,

优化

sizeof(ThisToCdecl)==36 , 我认为这是不可接受的。

如果我们使用PUSH old_return 来代替 MOV DWORD PTR[ESP],old_return,可以节省2字节(因此,我们必须在保存old_esp之前弹栈),于此同时,也增加了一个额外的堆栈操作。(见 ThisToCdecl 34.h)

在这种情况下,相对于时间上的优化,我更加倾向空间上的优化。所以第3个实现如下:

我们可以使用一个叫做Hook的函数来准备this指针,保存old_esp和返回地址,设置被调用者的返回地址,然后跳转到被调用者。这样,thunk对象将包含更少的指令,而变的更小。(23字节)ThisToCdecl.h
#define THIS_TO_CDECL_CODES()
/*  CALL Hook  */
CONST  CODE_FIRST(byte,CALL,0xE8)
CONST  CODE(dword,HOOK,0)

/*  this and member function  */
    CODE(dword,m_memFunc,0)
    CODE(dword_ptr,m_this,0)

/*  member function return here!  */
/*  MOV ESP,oldESP  */
CONST  CODE(byte,MOV_ESP,0xBC)
CONST  CODE(dword,oldESP,0)

/*  JMP oldRet  */
CONST  CODE(byte,JMP,0xE9)
CONST  CODE(dword,oldRet,0)
这些机器码首先调用“Hook”函数,这个函数做如下工作:

1. 保存 the oldESP 和 oldRet。

2. 将被调用者的返回地址设置到 “member function return here!”。

3. 将ECX设置为this指针。

4. 跳转到成员函数

当成员函数返回后,剩下的thunk代码将修改ESP然后返回到调用者。

Hook函数被实现为:void __declspec( naked ) ThisToCdecl::Hook() {
  _asm {
    POP EAX      //1
    // p=&m_memFunc; &m_this=p+4; &oldESP=p+9; &oldRet=p+14

    // Save ESP
    MOV DWORD PTR [EAX+9],ESP  //3
    ADD DWORD PTR [EAX+9],4    //4
    // Save CallerReturn(by offset)
    //src=&JMP=p+13,dst=CallerReturn,offset=CallerReturn-p-13-5
    MOV ECX,DWORD PTR [ESP]    //3
    SUB ECX,EAX          //2
    SUB ECX,18          //3
    MOV DWORD PTR [EAX+14],ECX  //3
    // Set CalleeReturn
    MOV DWORD PTR [ESP],EAX    //3
    ADD DWORD PTR [ESP],8    //4
    // Set m_this
    MOV ECX,DWORD PTR [EAX+4]  //3
    // Jump to m_memFunc
    JMP DWORD PTR[EAX ]      //2
  }
}

上一页  5 6 7 8 9 10 11 12  下一页

Tags:通用 Thunk

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接