编辑:使用clang编译器测试时,我犯了一个错误。这与clang一样有效。 Visual Studio 2015产生了意想不到的结果。我的结论是Visual Studio 2015有点令人毛骨悚然。
我已经观察到我无法解释关于表示Visual Studio 2015生成的COFF对象文件中未初始化的C数组的对象文件符号的值。该值应该表示以字节为单位的数组大小,但这是不是我观察到的。我希望有人能解释这里发生的事情。
考虑源文件testdata_works.c
char testb[0x10002];
考虑源文件testdata_fails.c:
char testa[0x10001];
char testb[0x10002];
现在编译:
cl -c testdata_works.c
cl -c testdata_fails.c
现在在两个目标文件上运行“ dumpbin / symbols”,并注意如何 两个目标文件之间的符号“ testb”的值不同(!) 有关血腥的细节。
dumpbin /symbols testdata_works.obj
006 00010002 UNDEF notype External | testb
现在为testdata_fails.obj
dumpbin /symbols testdata_fails.obj
006 00010001 UNDEF notype External | testa
007 00010041 UNDEF notype External | testb
我们注意到符号testb在以下位置具有预期值0x10002 testdata_works.obj,但在testdata_fails.obj中具有意外值0x10041。
我已经将真正奇怪的部分保存了下来,这可能会触发 精通COFF目标文件的人众所周知的“ a-ha” 格式:
将testdata_fails.c中数组的大小减小到下面 0x10000,例如:
char testa[0x0001];
char testb[0x0002];
并编译
cl -c testdata_fails.c
dumpbin命令现在产生符号testa和的预期结果。 testb:
006 00000001 UNDEF notype External | testa
007 00000002 UNDEF notype External | testb
关于这里发生的事情以及如何解决它的任何建议,以便对于大于64K的符号值产生预期结果?
最后的评论:
我使用clang / llvm-nm 7.0.1而不是Visual复制了此内容 Studio 2015 / dumpbin,所以它可能与COFF格式有关?
您可能会正确地问我如何处理此问题。我正在学习BSD 内核genassym.sh脚本,并决定编写一个小型C ++ STL程序 从LLVM库可以读取的任何目标文件格式实现了相同的任务。我已经构建了该程序,但是由于目标文件中的数据与预期不符,因此无法正常工作。
答案 0 :(得分:0)
COFF不保留数组大小。与数组符号关联的值是其起始地址。要推断数组dumpbin
的大小,必须使用某种启发式方法,例如通过查看相邻的符号,节的末尾等。显然,启发式方法失败。只有编译器知道为什么BSS比预期的要大。