【发布时间】:2016-07-30 02:59:15
【问题描述】:
这会分配一些 BSS 变量:
.lcomm page_table_l2, 4096
.lcomm page_table_l3, 4096
.lcomm page_table_l4, 4096
我正在构建的二进制文件最终为 4792 字节,因此您可以看到没有直接包含 BSS 变量(或者二进制文件将 >12 KiB)。
但是,这三个需要 4 KiB 对齐,所以我将部分更改为:
.section .bss
.align 4096
.lcomm page_table_l2, 4096
.lcomm page_table_l3, 4096
.lcomm page_table_l4, 4096
...二进制文件增长到 8760!鉴于 BSS 应该只是 ELF 二进制文件中的一个注释,对链接器说,嘿,分配 n 个字节的归零存储,为什么对齐 BSS 变量会导致二进制?
您也可以在 C 中看到这一点:
char x[4096] __attribute__ ((aligned (8192))) = {0};
如果您改变对齐方式,输出对象文件的大小也会随之变化。 (尽管在我最初的示例中,我正在查看最终二进制文件的大小。)
请注意,此输出二进制文件是操作系统内核;我正在关注教程here。我正在使用以下链接器脚本:
ENTRY(start)
SECTIONS {
. = 1M;
.boot ALIGN(8) : AT(ADDR(.boot))
{
/* ensure that the multiboot header is at the beginning */
KEEP( *(.multiboot_header) )
}
.text :
{
*(.text)
}
}
根据objdump,看起来整个程序在精灵本身中对齐了4 KiB,这有点奇怪。
没有.align:
Sections:
Idx Name Size VMA LMA File off Algn
0 .boot 00000018 0000000000100000 0000000000100000 00000078 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
.align:
Sections:
Idx Name Size VMA LMA File off Algn
0 .boot 00000018 0000000000100000 0000000000100000 00001000 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
注意File off,或文件中节的偏移量。为什么会改变?
【问题讨论】:
-
你用什么命令构建?
gcc -nostdlib?制作一个普通的 ELF 二进制文件?另外,我不知道多重引导内核有 text/data/bss 段;这很漂亮。您正在学习的教程使用的是 NASM,因此不难想象 gas 的工作方式略有不同。对齐 BSS 中的内容。无论如何,将其设为minimal reproducible example 只需要多几行命令和注释,说明哪个代码块放在哪个文件名中,对吧?这很有趣,让我想尝试一下,但还不足以猜测你到底做了什么:P -
@MichaelPetch:是的,我同意很明显这是一个 ELF 二进制文件。我只是不太了解制作多重引导内核映像,不知道您为此做的任何特别的事情是否相关,或者您在创建
.o或普通 Linux 可执行文件时是否期望相同的行为。我并不怀疑 GRUB 的多重引导加载程序会将 BSS 归零,我只是说直到我刚刚读到它才知道它受支持。 :P
标签: assembly linker elf memory-alignment