我正在网上阅读一些关于Vtable thunk的文章,我在某处读到了thunk可用于挂钩/链接程序调用。
可以实现吗?
有谁知道它是如何工作的,我也无法找到解释thunk的好资源。 有什么建议吗?
答案 0 :(得分:3)
以v-table thunks的方式实现原始thunk是最后的选择。无论你需要完成什么,最有可能通过包装函数来实现,而且不会那么痛苦。
一般情况下,thunk执行以下操作:
为了看一个如何运作的例子,让我们转向我们的好朋友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-table。 (如果您不了解COM,您需要知道的是它直接与v表一起使用,因此指向特定接口的指针必须包含指向该接口的所有方法的函数指针。)
如果在特定插槽中使用不同方法实现两个接口,则需要多个v表。但是,您只需编写一次重叠方法,因此该方法需要能够同时使用“this”指针。为此,编译器会生成一个方法来执行必要的修复并调用原始实现。
所以,这个thunk执行以下步骤:
这是jmp
指令的来源。通常情况下,如果您使用call
调用该函数,它将返回给您,您必须返回ret
给你的来电者。由于没有要做的清理,编译器会进行优化,将执行直接移动到实际实现,让实际实现的return语句返回您的调用者。这只是一种优化,而不是thunking的基本部分。例如,16/32位thunk会根据需要将输入/输出参数转换为16位和32位,因此不能跳过清理步骤;它必须call
,而不是jmp
。
故事的寓意是:如果你需要做某些事情,例如jmp
优化,你不能直接用C ++或你选择的其他高级语言写作,那就去写一个汇编语言thunk。否则,只需编写一个包装器并完成它。
老实说,这听起来像是在要求性能优化,而且大部分时间(1)编译器在优化方面比我们想象的更好;(2)它不会给你带来如此大的改进你想。
答案 1 :(得分:0)
嗯,你读到thunks是一个解决方案,现在你正在寻找一个需要解决的问题?
通常,Thunk是一种简短的“转发”功能,提供次要的 - 通常是硬编码的 - 调整。
目前在wikipedia中很好地解释了VTable块。它们使用通用模式:生成一个小函数,以避免在运行时计算/额外工作。
我见过/使用过thunk的其他地方:
将窗口句柄与窗口对象相关联:对于要进行子类化的每个窗口,动态生成一个小的thunk,使用对象引用调用窗口过程,然后将thunk用作窗口过程。
延迟加载DLL:thunk确保在第一次调用任何函数时加载DLL。
捕获COM接口调用:thunk为诊断提供注入点,并跳转到实际方法。