检测在dll边界访问导出的全局变量时缺少__declspec(dllimport) [英] Detecting missing __declspec(dllimport) in access to exported globals across dll boundaries

查看:161
本文介绍了检测在dll边界访问导出的全局变量时缺少__declspec(dllimport)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



当插件DLL被加载到主要的可执行文件中时,我们正在寻找一个有趣的新皱纹的解决方案,支持PostgreSQL项目。 c $ c> LoadLibrary 调用他们期望动态链接器解析引用由 postgres.exe 和全局变量 >。



很容易忘记放一个 __ declspec(dllimport)注释,或者说, extern 的PGDLLIMPORT 这个东西不适用。



该项目依赖于自动测试来检测何时一个 __ declspec(dllimport)在函数中缺少,因为这会导致链接器错误。直到昨天,假设全球变量也是如此,但不是;事实证明,动态链接静默成功,产生垃圾结果。



所以 - 我正在寻找关于如何检测防止这样的非法访问,其中全局不是 __ declspec(dllimport)'ed。



这是复杂的事实,在Windows上,PostgreSQL的构建系统生成 .def 只导出所有内容的文件。 (不是我的,但我不能改变,是的,我知道)。这意味着即使在构建主可执行文件期间没有 PGDLLIMPORT 标记站点 __ declspec(dllexport),则符号仍然导出。



想法?在另一个模块中定义 extern global时,是否有任何方法可以使链接器发生运行时错误,而 extern 不正确 __ declspec(dllimport)注释?



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



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

解决方案

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

  EXPORTS 
i1 DATA
i2 DATA

或不使用 .def 。它的优先级和默认值导出的符号为代码



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

  int __declspec(dllimport)i1; 
extern int i2;

这意味着您的 .obj 文件将外部依赖关系 __ imp__i1 _i2 。而第一个将指向真实的进口符号, jmp -stub

  jmp [addr];将为第二个生成FF 25 xx xx xx xx 

(因为它被认为是代码符号),用于修复两种调用之间的差异:

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

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


I'm looking for solutions to a fun new wrinkle in Windows support for the PostgreSQL project.

When plugin DLLs are loaded into the main executable with a LoadLibrary call they expect the dynamic linker to resolve references to functions and global variables exposed by postgres.exe.

It's easy to forget to put a __declspec(dllimport) annotation, or rather, the PGDLLIMPORT macro that expands to it, on an extern that's accessed via a DLL, since almost all PostgreSQL development and testing happens on Linux and OS X, where none of this stuff applies.

The project relies on automated testing to detect when a __declspec(dllimport) is missing on a function, as this causes linker errors. Until yesterday the assumption was that the same was true for global variables, but it isn't; it turns out that dynamic linkage succeeds silently, producing a garbage result.

So - I'm looking for advice on how to detect and prevent such illegal accesses, where a global is not __declspec(dllimport)'ed.

This is complicated by the fact that on Windows, PostgreSQL's build system generates .def files that just export everything. (Not my doing, but I can't change it, yes, I know). This means that even if there's no PGDLLIMPORT marking the site __declspec(dllexport) during building of the main executable, the symbol is still exported.

Ideas? Is there any way to get the linker to throw a runtime error when an extern global is defined in another module and the extern isn't properly __declspec(dllimport) annotated?

If the project stopped generating .def files and instead used PGDLLIMPORT annotations that expand to __declspec(dllexport) when compiling the .exe, and __declspec(dllimport) when compiling plugins that use the exe's API, would that produce linker errors when a symbol isn't annotated properly? Is there any alternative to that?

I'm currently looking for more info and I'm going to be writing a few test programs to try to test ideas, but I'm far from an expert on Windows development and I'm looking for an authoritative "the right way to do it" if possible.

解决方案

The best way is to make it clear in .def file to linker that you export data, not code:

EXPORTS
   i1 DATA
   i2 DATA

or not use .def at all. It takes precedence and defaults exported symbol to code.

Let's look what happens when you link your plugin to such malformed .lib file. And assume you declare:

   int __declspec(dllimport) i1;
   extern int i2;

This means your .obj file will have external dependencies __imp__i1 and _i2. And while the first one will point to the real imported symbol, jmp-stub

   jmp [addr]  ; FF 25 xx xx xx xx

will be generated for the second one ('cause it considered to be the code symbol) which is meant to fix difference between two kinds of call:

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

Thus, your i2 will actually point to code section address of jmp-stub, so its value gonna be0x????25ff.

这篇关于检测在dll边界访问导出的全局变量时缺少__declspec(dllimport)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆