COFF目标文件中大于64K的未初始化数组的意外符号值

时间:2019-01-16 13:07:49

标签: c

编辑:使用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库可以读取的任何目标文件格式实现了相同的任务。我已经构建了该程序,但是由于目标文件中的数据与预期不符,因此无法正常工作。

1 个答案:

答案 0 :(得分:0)

COFF不保留数组大小。与数组符号关联的值是其起始地址。要推断数组dumpbin的大小,必须使用某种启发式方法,例如通过查看相邻的符号,节的末尾等。显然,启发式方法失败。只有编译器知道为什么BSS比预期的要大。