ld 忽略 nobits 输入部分的大小

ld ignores size of nobits input section

在为 x86 架构开发小型 32 位内核时,我发现 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 部分,但它产生了预期的结果?

好的,我明白了。

显然,您不应该在部分名称后紧跟一个逗号。 objdump 在部分名称中包含逗号,以便清楚地表明这是错误的。

所以

section .bootstrap_stack, nobits

应该是

section .bootstrap_stack nobits