2

在关于跨 dll 边界检测到全局变量的错误链接的问题之后,事实证明我需要修改 PostgreSQL 项目使用的 .DEF 文件生成器工具,以便它正确地DATA为全局变量的 .DEF 条目发出标签。

问题

我似乎无法找到一种方法,使用 Microsoft 的工具来获取区分全局变量和函数的符号表列表,其中包括未在其定义站点初始化的全局变量。

想法?

断流方法

该工具循环dumpbin /symbols输出以生成 .DEF 文件。与nm我习惯的不同,dumpbin /symbols似乎不会为每个符号发出一个条目来指示符号类型 - 函数、初始化变量、未初始化变量。它只显示符号是否在本地定义。

每个dumpbin输出行后跟.c文件中的相应定义,我们首先有一个初始化的全局:

00B 00000000 SECT3  notype       External     | _DefaultXactIsoLevel
int         DefaultXactIsoLevel = XACT_READ_COMMITTED;

与具有非静态链接的函数:

022 00000030 SECT5  notype ()    External     | _IsAbortedTransactionBlockState
bool IsAbortedTransactionBlockState(void) {...}

...并且为了获得额外的乐趣,未初始化的全局变量似乎显示为UNDEF,就像对来自其他编译单元的符号的引用一样,例如:

007 00000004 UNDEF  notype       External     | _XactIsoLevel
int         XactIsoLevel;

即使这是在编译期间在标头中预先声明的(为了便于阅读而扩展了项目特定的宏):

extern __declspec(dllexport) int XactIsoLevel;

所以......看起来dumpbin输出不包含足够的信息来生成正确的.DEF文件。

现在gendefs.pl正在愉快地吐出一个.DEF文件,该文件省略了未初始化的全局变量,并将其他所有内容声明为代码(通过未能指定CONSTANTDATA在 .DEF 中)。对于如此破碎的东西,它工作得非常好。

修复它

为了生成正确的 .DEF 文件,我需要一种方法来确定哪些符号是变量。

我查看了 usingcl.exe/Fm选项,但它只是链接器选项的传递/MAP,当您只是生成一个目标文件而不是链接它时什么都不做。

我可以使用生成更多有用信息的符号转储工具,例如 gcc's nm.exe,但这会增加额外的工具依赖性并且看起来很脆弱。

在这一点上,我不能简单地用PGDLLIMPORT(项目使用的__declspec(dllimport)/__declspec(dllexport)宏)注释每个导出的函数并停止使用 DEF 文件。

即使我可以,我也需要找到一种PGDLLIMPORT在暴露变量上省略时会导致明显链接器错误的方法。

所以。Windows 链接器/编译器专家。有任何想法吗?

4

2 回答 2

2

好吧,我必须说我说微软工具根本不使用符号类型字段是错误的。

1)。 cl不使用它来区分实际类型信息,但它存储您需要的信息:

  • 0x20意味着功能
  • 0x00表示不是函数

PE/COFF 规范,p. 46-47。

您可以在's 的输出中搜索()after 符号类型(notype在您的情况下)的存在/不存在,以查找它是还是。dumpbincodedata

2)。此外,cl在文件中为链接器生成obj特殊部分,其中包括表单export中每个__declspec(dllexport)符号的开关/export:symbol[,type]

3)。最后,您可以指定“C++”外部链接并获取符号的类型,因为它是重整的。

于 2014-02-06T09:35:38.997 回答
2

我只是添加到另一个帖子
dumpbin有一个特定的选项,即/headers明确指出Typecodedata,以及其他属性的列表。

于 2018-07-02T09:42:30.353 回答