我正在尝试在编写内核时调试我所拥有的链接器问题。
问题是我有一个我无法使用的变量SCAN_CODE_MAPPING
- 它似乎是空的或其他东西。我可以通过改变链接程序的方式来解决这个问题,但我不知道为什么。
当我使用objdump
查看生成的二进制文件时,变量的数据肯定存在,所以只有一些内容被引用。
Here's a gist和两个文件之间不同的符号表部分。
令我困惑的是,两个符号表都具有相同的符号,它们的长度都相同,并且它们似乎包含正确的数据。我能看到的唯一区别是它们的顺序不一样。
到目前为止,我已经尝试了
SCAN_CODE_MAPPING
内存位置以确保它具有我期望的数据并且未被清零.data.rel.ro.local
以确保其具有数据地址一个可能的线索就是这个警告:
warning: uninitialized space declared in non-BSS section `.text': zeroing
我在破碎和正确的案件中都得到了。
我接下来应该尝试什么?
答案 0 :(得分:5)
这里的问题原来是我正在编写一个操作系统,只有12k的操作系统被加载而不是整个操作系统。所以链接器脚本实际上工作正常。
我用来理解二进制文件的主要工具是:
答案 1 :(得分:4)
使用“readelf”可以获得更多信息。
特别是,请看一下程序标题:
readelf -l program
您的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条目是数据段。
如果更改顺序,则会影响链接器生成程序头的方式。在执行程序之前加载程序时,将使用程序头而不是节头。使用自定义链接描述文件时,请务必检查程序头。
如果你能详细说明你的实际症状,那么它会更容易帮助。