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
在为 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