题
我正在网上阅读一些有关 Vtable thunk 的文章,并且在某处读到 thunk 可用于挂钩/链过程调用。
可以实现吗?
有谁知道这是如何工作的,我也无法找到很好的资源来解释重击。对此有何建议?
解决方案
以 v-table thunk 的风格实现原始 thunk 是最后的手段。无论您需要完成什么,很可能都可以通过包装函数来实现,而且会轻松得多。
一般来说,thunk 会执行以下操作:
- 修复输入参数(例如,转换为不同的格式)
- 调用真正的实现
- 清理步骤 1/修复输出参数
要查看其工作原理的示例,让我们看看我们的好朋友 Raymond Chen 和他对调节器 thunk 的讨论:
http://blogs.msdn.com/oldnewthing/archive/2004/02/06/68695.aspx
他使用的 thunk 如下:
[thunk]:CSample::QueryInterface`adjustor{4}':
sub DWORD PTR [esp+4], 4 ; this -= sizeof(lpVtbl)
jmp CSample::QueryInterface
正如他所描述的,您有一个类通过多个接口实现相同的方法,因此它有多个 v 表。(如果您不了解 COM,您只需要知道它直接与 v-table 一起工作,因此指向特定接口的指针必须包含指向该接口的所有方法的函数指针 为了.)
如果在特定槽中使用不同方法实现两个接口,则需要多个 v-table。但是,您只需编写一次重叠方法,因此该方法需要能够使用两个“this”指针。为此,编译器会生成一个方法来进行必要的修复并调用原始实现。
因此,这个 thunk 执行以下步骤:
- 修复第一行的输入参数,即隐藏的“this”指针。
- 在第二行调用真正的实现。
- 清理:不需要(见下文)
这就是 jmp
指令进来了。通常,如果您要使用以下方式调用该函数 call
, ,它会返回给你,而你必须 ret
返回给您的来电者。由于不需要进行清理,编译器会进行优化,将执行直接移至实际实现,并让实际实现的 return 语句返回到 你的 呼叫者。这只是一种优化,而不是 thunking 的基本部分。例如,16/32位thunk会根据需要在16位和32位之间转换输入/输出参数,因此它无法跳过清理步骤;它必须 call
, , 不是 jmp
.
这个故事的寓意是:如果您需要做某事,例如 jmp
优化,您不能直接用 C++ 或您选择的其他高级语言编写,请继续编写汇编语言 thunk。否则,只需编写一个包装器即可完成。
老实说,这听起来像是您要求性能优化,并且大多数时候(1)编译器的优化比我们想象的要好,(2)它不会给您带来您想象的那么大的改进。
其他提示
好了,你看的是的thunk的解决方案,而现在你正在寻找一个问题的解决?
的thunk,通常是短的“转发”,其提供次要功能 - 通常硬编码 - 调整
的VTable块在时刻维基百科解释很好。他们使用的共用图案:产生一个小的功能,以避免在运行时计算/额外的工作
。我见过的其它地方/使用的thunk:
关联有窗口对象窗口句柄:用于向被继承每个窗口,对调用与对象参考窗口过程实时生成的小形实转换,在thunk然后用作窗口过程
延迟加载DLL:在thunk可以确保DLL被加载在第一时间任意函数被调用
。俘获COM接口调用:所述的thunk用于诊断提供一种注射点,并跳转到的实际方法。