15

在编写内核时,我正在尝试调试我遇到的链接器问题。

问题是我有一个SCAN_CODE_MAPPING无法使用的变量——它似乎是空的或什么的。我可以通过更改链接程序的方式来解决此问题,但我不知道为什么。

当我使用 来查看生成的二进制文件objdump时,变量的数据肯定在那里,所以只是对它的引用有问题。

这是链接器脚本和两个文件之间不同的符号表部分的要点。

让我感到困惑的是,两个符号表都具有相同的符号,它们的长度都相同,而且它们似乎包含正确的数据。我能看到的唯一区别是它们的顺序不同。

到目前为止我已经尝试过

  • 检查SCAN_CODE_MAPPING内存位置以确保它具有我期望的数据并且没有被归零
  • 检查所有符号是否相同
  • 检查所有符号内容的长度是否相同
  • 查看.data.rel.ro.local以确保它具有数据的地址

一个可能的线索是这个警告:

warning: uninitialized space declared in non-BSS section `.text': zeroing

我在损坏的情况下和正确的情况下都得到了。

接下来我应该尝试什么?

4

2 回答 2

5

这里的问题原来是我正在编写一个操作系统,并且只有 12k 被加载而不是全部。所以链接器脚本实际上工作正常。

我用来理解二进制文件的主要工具是:

  • 纳米
  • 对象转储
  • 自述
于 2013-12-23T17:28:16.687 回答
4

您可以使用“readelf”获得更多信息。

特别是,看看程序头:

readelf -l 程序

您的 BSS 部分与标准部分完全不同,这可能会导致警告。这是我系统上的默认设置:

  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   /* Align here to ensure that the .bss section occupies space up to
      _end.  Align after .bss to ensure correct alignment even if the
      .bss section disappears because there are no input sections.
      FIXME: Why do we need it? When there is no .bss section, we don't
      pad the .data section.  */
   . = ALIGN(. != 0 ? 64 / 8 : 1);
  }

如果输入部分与链接器脚本中的任何内容都不匹配,则链接器仍必须将其放置在某处。确保你覆盖了所有的输入部分。

请注意,部分和段之间存在差异。链接器使用段,但程序加载器查看的唯一内容是段。文本段包括文本部分,但也包括其他部分。进入同一段的部分必须相邻。所以顺序很重要。

rodata 部分通常在文本部分之后。它们在执行期间都是只读的,并且将在您的程序头中显示一次,作为具有读取和执行权限的 LOAD 条目。该 LOAD 条目是文本段。

bss 部分通常在数据部分之后。它们在执行期间都是可写的,并且会在您的程序头中显示一次,作为具有读写权限的 LOAD 条目。该 LOAD 条目是数据段。

如果更改顺序,它会影响链接器生成程序头的方式。在执行程序之前加载程序时使用程序头而不是节头。确保在使用自定义链接描述文件时检查程序头。

如果您可以详细说明您的实际症状是什么,那么帮助会更容易。

于 2013-12-23T16:11:00.750 回答