在x86架构的小型32位内核上工作时,我发现ld
处理nobits节时有些奇怪。ld忽略nobits输入节的大小
在我的内核中,我定义了一个.bootstrap_stack
部分,该部分包含系统初始化部分的临时堆栈。我也持有堆栈开始和结束的符号。该输入部分重定向到.bss
输出部分。我的内核的每个输出部分都有一个符号,用于该部分的开头和结尾。
问题是,在最终的可执行文件中,堆栈结束的符号是,在后面的.bss
节结束。在下面的例子中,符号stack_top
和_kernel_ebss
(和_kernel_end
)具有相同的值,这不是我想要的。我希望_kernel_ebss
等于stack_bottom
。
但是,一旦我将.bootstrap_stack
重命名为.bss
,这种情况不会发生。删除nobits
也可以,但生成的二进制文件要大得多。
下面是重现我的问题剥离文件:
boot.s
section .bootstrap_stack, nobits ; this does not work
;section .bootstrap_stack ; this works
;section .bss ; this also works
stack_top:
resb 8096
stack_bottom:
section .text
global _start
_start:
hlt
jmp _start
linker.ld
ENTRY(_start)
SECTIONS
{
. = 0xC0100000;
_kernel_start = .;
.text ALIGN(4K) : AT(ADDR(.text) - 0xC0000000)
{
_kernel_text = .;
*(.multiboot)
*(.text)
_kernel_etext = .;
}
.bss ALIGN(4K) : AT(ADDR(.bss) - 0xC0000000)
{
_kernel_bss = .;
*(COMMON)
*(.bss)
*(.bootstrap_stack)
_kernel_ebss = .;
}
_kernel_end = .;
}
这里的符号:
$ objdump -t kernel | sort
00000000 l df *ABS* 00000000 boot.s
c0100000 g .text 00000000 _kernel_start
c0100000 g .text 00000000 _kernel_text
c0100000 g .text 00000000 _start
c0100000 l d .text 00000000 .text
c0100003 g .text 00000000 _kernel_etext
c0101000 g .text 00000000 _kernel_bss
c0101000 g .text 00000000 _kernel_ebss
c0101000 g .text 00000000 _kernel_end
c0101000 l .bootstrap_stack, 00000000 stack_top
c0101000 l d .bootstrap_stack, 00000000 .bootstrap_stack,
c0102fa0 l .bootstrap_stack, 00000000 stack_bottom
通过重命名.bootstrap_stack
到.bss
我得到了我的预期。
00000000 l df *ABS* 00000000 boot.s
c0100000 g .text 00000000 _kernel_start
c0100000 g .text 00000000 _kernel_text
c0100000 g .text 00000000 _start
c0100000 l d .text 00000000 .text
c0100003 g .text 00000000 _kernel_etext
c0101000 g .bss 00000000 _kernel_bss
c0101000 l .bss 00000000 stack_top
c0101000 l d .bss 00000000 .bss
c0102fa0 g .bss 00000000 _kernel_ebss
c0102fa0 g .bss 00000000 _kernel_end
c0102fa0 l .bss 00000000 stack_bottom
我的问题是这是否是预期的ld行为。如果是的话,我的例子有什么问题,因为据我了解.bss
也是一个nobits部分,但它会产生预期的结果?