开发学院软件开发VC Thunk技术的一个改进 阅读

Thunk技术的一个改进

 2010-08-15 20:46:25 来源:WEB开发网 闂傚倸鍊搁崐椋庢濮橆兗缂氱憸宥堢亱闂佸湱铏庨崰鏍不椤栫偞鐓ラ柣鏇炲€圭€氾拷闂傚倸鍊搁崐椋庣矆娓氣偓楠炲鏁撻悩鎻掔€梺姹囧灩閻忔艾鐣烽弻銉︾厵闁规鍠栭。濂告煕鎼达紕校闁靛洤瀚伴獮鎺楀箣濠靛啫浜鹃柣銏⑶圭壕濠氭煙閻愵剚鐏辨俊鎻掔墛缁绘盯宕卞Δ鍐冣剝绻涘畝濠佺敖缂佽鲸鎹囧畷鎺戭潩閹典焦鐎搁梻浣烘嚀閸ゆ牠骞忛敓锟�婵犵數濮烽弫鍛婃叏椤撱垹绠柛鎰靛枛瀹告繃銇勯幘瀵哥畼闁硅娲熷缁樼瑹閳ь剙岣胯鐓ら柕鍫濇偪濞差亜惟闁宠桨鑳堕崝锕€顪冮妶鍡楃瑐闁煎啿鐖奸崺濠囧即閵忥紕鍘梺鎼炲劗閺呮稒绂掕缁辨帗娼忛埡浣锋闂佽桨鐒﹂幑鍥极閹剧粯鏅搁柨鐕傛嫹闂傚倸鍊搁崐椋庢濮橆兗缂氱憸宥堢亱闂佸湱铏庨崰鏍不椤栫偞鐓ラ柣鏇炲€圭€氾拷  闂傚倸鍊搁崐鐑芥嚄閼哥數浠氱紓鍌欒兌缁垶銆冮崨鏉戠厺鐎广儱顦崡鎶芥煏韫囨洖校闁诲寒鍓熷铏圭磼濡搫顫岄梺鍦拡閸嬪棝鎯€椤忓浂妯勯梺鍝勬湰濞叉ḿ鎹㈠┑濠勭杸闁哄洨濮烽悰銉╂⒒娴e搫甯跺鐟帮攻缁傚秴饪伴崼姘e亾閺冨牆绀冩い蹇庣娴滈箖鏌ㄥ┑鍡涱€楀褜鍠栭湁闁绘ɑ鐟ョ€氼喚绮绘ィ鍐╃厱妞ゆ劑鍊曢弸搴ㄦ煟韫囧鍔滈柕鍥у瀵潙螣閸濆嫬袝婵$偑鍊戦崹娲偡閳哄懎绠栭柍鈺佸暞閸庣喖鏌曢崶褍绨婚柟鍑ゆ嫹
核心提示:Thunk技术,一般认为是在程序中直接构造出可执行代码的技术(在正常情况 下,Thunk技术的一个改进,这是编译器的任务),《深度探索C++对象模型》中对这个词的来源有过考证 (在中文版的162页),将其替换为计算出来的动态值,经过这样的处理,说thunk是knuth的倒拼字,knuth就是大名鼎鼎的计算机经 典名著《

Thunk技术,一般认为是在程序中直接构造出可执行代码的技术(在正常情况 下,这是编译器的任务)。《深度探索C++对象模型》中对这个词的来源有过考证 (在中文版的162页),说thunk是knuth的倒拼字。knuth就是大名鼎鼎的计算机经 典名著《The Art of Computer Programming》的作者,该书被程序员们称为 “编程圣经”,与牛顿的“自然哲学的数学原理”等一起 ,被评为“世界历史上最伟大的十种科学著作”之一(也不知是谁评的 ,我没查到,不过反正这本书很牛就是了)。

一般情况下,使用thunk技术 都是事先查好指令的机器码,然后将数组或结构体赋值为这些机器码的二进制值 ,最后再跳转到数组或结构体的首地址。比如在参考文献[1]中的代码:

void foo(int a)
{ printf ("In foo, a = %d
", a); }
unsigned char code[9];
* ((DWORD *) &code[0]) = 0x042444FF; /* inc dword ptr [esp+4] */
        code[4] = 0xe9;    /* JMP */
* ((DWORD *) &code[5]) = (DWORD) &foo - (DWORD) &code[0] - 9; /* 跳转偏移量 */
void (*pf)(int/* a*/) = (void (*)(int)) &code[0];
pf (6);

这是一段典型的thunk代码,其执行结果是“In foo, a = 7”。

可以看到,它定义了一个数组code[9],然后将事先查好的各汇编指令的 机器码直接赋值给数组。然后定义一个函数指针等于数组的首地址,最后通过该 函数指针调用thunk代码。这里使用了函数指针完成调用,好处是代码比较清晰易 读。也可以使用汇编代码jmp或call来完成,这样就不必额外定义一个函数指针。

网络上的thunk代码,基本上都是这个思路。如果你实际写一段这样的代 码,一定会发现很麻烦。对着教科书查找每一个汇编指令的机器码,相信不会是 一件愉快的事情。其实我们回过头来想想,这件事计算机来做不是最合适吗,编 译器不就是做这个事情的吗?

以上面的代码为例,让我们重新考虑一下整 个过程。我们的目的是在调用函数foo之前将参数增加1。一般而言,这样做肯定 是没有foo函数的源代码或者不允许修改源代码,否则直接改foo函数的代码就好 了,何必这么麻烦。为了调用时候的简单化,定义一个函数指针是比较合适的, 否则每次调用都写汇编代码jmp或call太麻烦。这样一来,函数指针必须指向一个 代码段的地址。但是这个代码段必须用机器码来构造吗,直接写汇编代码也同样 可以做到。

当然,这里有一个问题。我们写汇编指令的时候,必须是一条 指令一条指令的写,不能说指令写一半,然后让汇编程序去处理。上面的代码中 ,第一条指令inc直接写汇编语句当然没问题。但下面的jmp语句,就不能直接写 。因为我们写汇编语句的时候,jmp跳转偏移量是未知的,必须编译后才知道。并 且我们不能只写jmp而不写偏移量,那是通不过编译的。

这个问题可以这 样解决,写jmp语句的时候,我们写一个占位的DWORD,其值设为一个特殊的值, 比如0xffff(原理是这样,实际处理还要迂回一下,后面有说明)。只要在这段 thunk代码中不出现这个值就好。然后执行的时候,在第一次调用之前,在thunk 代码中查找该值,将其替换为计算出来的动态值。经过这样的处理,就可以彻底 在thunk代码中消除机器码的直接操作。

1 2 3 4  下一页

Tags:Thunk 技术 一个

编辑录入:爽爽 [复制链接] [打 印]
[]
  • 好
  • 好的评价 如果觉得好,就请您
      0%(0)
  • 差
  • 差的评价 如果觉得差,就请您
      0%(0)
赞助商链接