为什么对齐.bss变量导致二进制大小大幅增加?

时间:2016-07-30 02:59:15

标签: assembly linker elf memory-alignment

这会分配一些BSS变量:

.lcomm page_table_l2, 4096
.lcomm page_table_l3, 4096
.lcomm page_table_l4, 4096

二进制I建筑物最终为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};

如果改变对齐方式,输出对象文件的大小会随之变化。 (虽然在我最初的例子中,我正在查看最终的二进制文件大小。)

请注意,此输出二进制文件是OS内核;我按照教程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,或文件中该部分的偏移量。为什么会改变?

1 个答案:

答案 0 :(得分:0)

我测试了一些(使用此代码和_start构成一个exit_group系统调用),使用gcc -cgcc -nostdlib构建。

似乎.o大小与.S中使用的最大对齐关系缩放。 ELF文件中有零字节。 (例如,查看hexdump)。

但是,链接的二进制文件似乎没有任何额外的填充。所以链接后不是问题,只是为了在构建期间占用临时文件的空间。

我使用.space将归零字节组装到.bss中得到了相同的结果,就像我使用.lcomm在.bss中分配空间而不切换到它一样。

.section .bss
    .balign 4096                # .balign or .p2align are preferable, to avoid ambiguity between power-of-2 or exponent

page_table_l2:  .space 4096
.balign 1024
page_table_l3:  .space 4096
page_table_l4:  .space 4096
foo:     .space 17
    .balign 4096              # This doesn't make the .o any bigger if a .align 4096 is already present
bar:    .space 1

#   .lcomm page_table_l2, 4096
#   .lcomm page_table_l3, 4096
#   .lcomm page_table_l4, 4096


    .text
.global _start
_start:
    xor %edi, %edi

    mov $231, %eax  #  exit_group(0)
    syscall

# the .o is big
$ gcc -c align-bss.S  && ll align-bss.o && objdump -haf align-bss.o
-rw-rw-r-- 1 peter peter 4.8K Jul 30 11:05 align-bss.o
...
Idx Name          Size      VMA               LMA               File off  Algn
...
  2 .bss          00004001  0000000000000000  0000000000000000  00001000  2**12

# the binary doesn't care
$ gcc -nostdlib align-bss.S -o align-bss  && ll align-bss && objdump -haf align-bss
-rwxrwxr-x 1 peter peter 1.2K Jul 30 11:08 align-bss
  ...
Idx Name          Size      VMA               LMA               File off  Algn
 ...
  2 .bss          00004008  0000000000601000  0000000000601000  00001000  2**12

注释.balign指令后,.o为872B,链接的静态二进制文件仍为1.2k(未提取)。