我正在寻找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开发方面的专家,我正在寻找权威的“正确的方法“如果可能的话。
答案 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
。