【问题标题】:Detecting missing __declspec(dllimport) in access to exported globals across dll boundaries在跨 dll 边界访问导出的全局变量时检测丢失的 __declspec(dllimport)
【发布时间】:2014-03-01 08:43:26
【问题描述】:

我正在为 PostgreSQL 项目的 Windows 支持中的一个有趣的新问题寻找解决方案。

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

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

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

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

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

想法?当在另一个模块中定义 extern 全局并且 extern 未正确注释 __declspec(dllimport) 时,有什么方法可以让链接器引发运行时错误?

如果项目停止生成 .def 文件,而是使用 PGDLLIMPORT 注释,在编译 .exe 时扩展为 __declspec(dllexport),在编译使用 exe 的 API 的插件时使用 __declspec(dllimport),当符号注释不正确?有没有其他选择?

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

【问题讨论】:

  • 你想让某人更容易导出全局变量???让他们受苦!并禁止将这种做法作为项目指南。替代方案过于简单和优越。
  • @HansPassant 我完全同意,但不幸的是,我目前无法改变这种做法,只能修复任何由此产生的错误。
  • 在此处发布后续问题:stackoverflow.com/questions/21593281/…
  • 另外,有用的文章(针对特定于 Windows 的位):lurklurk.org/linkers/linkers.html
  • @CraigRinger 那么,这会是三部曲吗?还是可以认为您的问题已完全解决?

标签: c windows winapi dll linker


【解决方案1】:

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

EXPORTS
   i1 DATA
   i2 DATA

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

让我们看看当您将插件链接到这种格式错误的.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
   call addr   ; E8 xx xx xx xx

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

【讨论】:

  • 谢谢。我将查看生成的 def 文件以验证它们是否正确标记了导出。这是对观察到的行为的合理解释。我个人更喜欢“根本不使用 .def 文件”的方法,但不幸的是,目前由于非技术原因,这不是一种选择。我会跟进(这需要我一段时间)确认defs是否包含DATA注释或nt。
  • @gwm 看起来 .def 生成器(循环 dumpbin 输出)没有用 DATA 注释导出的全局变量。所以这至少需要修复。我会看看所涉及的内容并评论它是如何进行的。
  • @CraigRinger 有什么进展吗?
  • @qvm 在澳大利亚,忙着睡觉 ;-) 。今天应该有时间测试修补 def 生成器。
  • Didn't find any reference to confirm the DEF file overrides __declspec annotations though - 您可以尝试通过在玩具项目上进行测试来确认它。我没有阅读任何文章说明,只是解析了编译器/链接器输出
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-30
  • 2011-09-30
相关资源
最近更新 更多