我在看这个Importing Function Calls Using __declspec(dllimport)和我不明白为什么真的需要__declspec(dllimport)?为什么链接器不能在链接阶段将调用func1补丁到调用DWORD PTR__imp_func1(IAT表地址),从而避免在源代码中单独声明的需要?
我在看这个Importing Function Calls Using __declspec(dllimport)和我不明白为什么真的需要__declspec(dllimport)?为什么链接器不能在链接阶段将调用func1补丁到调用DWORD PTR__imp_func1(IAT表地址),从而避免在源代码中单独声明的需要?
3条答案
按热度按时间jtw3ybtb1#
没有足够的空间来修补指令可能是一个原因,但不是主要原因。即使有足够的空间,链接器仍然不会为了更好的性能而修补它。原因是链接器不做或修改编译器后端生成的代码,它只是用重定位信息修补位置。下面的例子不是很好的编码风格,但是要清楚地解释这个问题。为
bar()
生成的指令是call dword[_imp__bar]
,它是6个字节长,即使链接器知道bar()
是在最终映像中定义的,它不会用call OffsetOfBar
打补丁,call OffsetOfBar
只需要5字节。(将/GL传递给cl.exe)可以解决此问题,因为链接器将在链接时调用编译器后端,并且后端将生成优化的call
指令,因为它知道call
目标在同一模块中。3npbholx2#
引用Raymond Chen的话:call func的长度是5个字节,但call dword ptr [_imp_func]的长度是6个字节。这个补丁不适合。它太大了一个字节。在每个call指令之后添加一个nop(以防它碰巧被导入)听起来相当过分。
vjrehmav3#
在VS 2022中(可能在很久很久以前),编译器(而不是链接器)确实能够在有或没有
__declspec(dllimport)
的情况下优化形实转换程序。今天它完全是多余的,希望有一天文档会反映出来。