生成正确的.DEF文件以导出非静态函数和GLOBALS

时间:2014-02-06 03:15:17

标签: c windows linker dllexport dumpbin

a question about detecting bad linkage to globals across dll boudaries开始,我发现我需要修改PostgreSQL项目使用的.DEF文件生成器工具,以便正确地为全局变量的.DEF条目发出DATA标记。

问题

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

想法?

当前破碎的方法

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

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

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

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

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文件,该文件省略了未初始化的全局变量,并将其他所有内容声明为代码(未指定CONSTANT或{{1在.DEF中)。对于那些破碎的东西,它的效果非常好。

修复它

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

我查看了使用DATA的{​​{1}}选项,但它只是链接器的cl.exe选项的直通,当您只是生成目标文件时没有做任何事情,而不是链接它。

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

此时,我无法使用/MAP(项目使用的nm.exe / PGDLLIMPORT宏)简单地注释每个导出的函数,并停止使用DEF文件。

即使我可以找到一种方法,当在公开变量上省略__declspec(dllimport)时,会导致明显的链接器错误。

因此。 Windows链接器/编译器专家。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

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

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

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

PE/COFF specification,p。 46-47。

您可以在()的输出中搜索符号类型(在您的情况下为notype)后dumpbin的存在/绝对值,以查找它是code还是{ {1}}。

2)。此外,datacl个文件中为链接器生成特殊部分,其中包括obj切换每个export符号表格__declspec(dllexport)

3)。最后,你可以指定'C ++'外部链接并获取符号的类型,因为它会被修改。

答案 1 :(得分:1)

我只是添加到other post中。
dumpbin有一个特定的选项,即/headers,它明确指出 Type 代码数据以及其他属性列表。