在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部分,但它會產生預期的結果?