ld忽略了nobits输入部分

时间:2016-08-02 21:17:10

标签: linker ld elf linker-scripts

当处理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部分,但它会产生预期的结果?

1 个答案:

答案 0 :(得分:1)

好的,我明白了。

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

所以

section .bootstrap_stack, nobits

应该是

section .bootstrap_stack nobits