从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链接器/编译器专家。有什么想法吗?
答案 0 :(得分:2)
好吧,我必须说我错误地说微软工具根本不使用符号类型字段。
1)。 cl
不会用它来区分实际的类型信息,但它会存储您需要的信息:
0x20
表示功能0x00
表示不是函数PE/COFF specification,p。 46-47。
您可以在()
的输出中搜索符号类型(在您的情况下为notype
)后dumpbin
的存在/绝对值,以查找它是code
还是{ {1}}。
2)。此外,data
在cl
个文件中为链接器生成特殊部分,其中包括obj
切换每个export
符号表格__declspec(dllexport)
。
3)。最后,你可以指定'C ++'外部链接并获取符号的类型,因为它会被修改。
答案 1 :(得分:1)
我只是添加到other post中。
dumpbin
有一个特定的选项,即/headers
,它明确指出 Type 为代码或数据以及其他属性列表。