在跨dll边界访问导出的全局变量时检测缺少的__declspec(dllimport)

时间:2014-02-05 04:05:23

标签: c windows winapi dll linker

我正在寻找Windows支持PostgreSQL项目中有趣的新皱纹的解决方案。

当插件DLL通过LoadLibrary调用加载到主可执行文件中时,他们希望动态链接器解析对postgres.exe公开的函数和全局变量的引用。

很容易忘记在通过DLL访问的__declspec(dllimport)上放置PGDLLIMPORT注释,或者更确切地说是扩展到它的extern宏,因为几乎所有的PostgreSQL开发都是如此并且测试发生在Linux和OS X上,这些都不适用。

该项目依赖于自动化测试来检测函数上何时缺少__declspec(dllimport),因为这会导致链接器错误。直到昨天,假设全局变量也是如此,但事实并非如此;事实证明,动态链接以静默方式成功,产生垃圾结果

所以 - 我正在寻找有关如何检测阻止此类非法访问的建议,其中全局不是__declspec(dllimport)

这很复杂,因为在Windows上,PostgreSQL的构建系统会生成只导出所有内容的.def个文件。 (不是我做的,但我不能改变它,是的,我知道)。这意味着即使在构建主可执行文件期间没有PGDLLIMPORT标记网站__declspec(dllexport),该符号仍会被导出。

想法?有没有办法让链接器在另一个模块中定义extern全局并且extern未正确__declspec(dllimport)注释时抛出运行时错误?

如果项目停止生成.def文件,而是在编译.exe时使用扩展到PGDLLIMPORT的{​​{1}}注释,而在编译使用exe的API的插件时使用__declspec(dllexport),当符号没有正确注释时会产生链接器错误?还有其他选择吗?

我正在寻找更多信息,我将编写一些测试程序来尝试测试想法,但我远不是Windows开发方面的专家,我正在寻找权威的“正确的方法“如果可能的话。

1 个答案:

答案 0 :(得分:1)

最好的方法是在.def文件中清楚地表明您导出数据的链接器,而不是代码:

EXPORTS
   i1 DATA
   i2 DATA

或根本不使用.def。它优先,默认导出符号为code

让我们看看当您将插件链接到这种格式错误的.lib文件时会发生什么。并假设您声明:

   int __declspec(dllimport) i1;
   extern int i2;

这意味着您的.obj文件将具有外部依赖关系__imp__i1_i2。而第一个将指向真正的导入符号,jmp - 存根

   jmp [addr]  ; FF 25 xx xx xx xx
将为第二个('因为它被认为是代码符号)生成

,这意味着修复两种呼叫之间的差异:

   call [addr] ; FF 15 xx xx xx xx
   call addr   ; E8 xx xx xx xx

因此,您的i2实际上将指向jmp-stub的代码段地址,因此其值将为0x????25ff