2016-07-30 11 views
0

Это выделяет некоторые BSS переменные:Почему выравнивание переменной .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, или смещение раздела в файле. Почему это меняется?

+1

С какими командами вы строите? 'gcc -nostdlib'? Создание простой ELF-бинарной? Кроме того, я не знал, что многозадачные ядра получили сегменты text/data/bss; это довольно причудливо. Учебник, который вы используете, использует NASM, поэтому нетрудно представить, что газ работает немного по-другому. выравнивание вещей в BSS. Во всяком случае, для этого [mcve] потребуется всего несколько строк команд и заметок о том, какой блок кода входит в какое имя файла, не так ли? Это интересно и заставляет меня попробовать, но не настолько, чтобы догадаться, что именно вы сделали: P –

+0

@MichaelPetch: Да, я согласен, ясно, что это ELF-бинарный файл. Я просто не знаю достаточно о том, чтобы сделать многозадачные изображения ядра, чтобы узнать, будет ли что-то особенное, что вы сделали бы для этого, было бы уместным или если вы ожидаете такого же поведения при создании исполняемого файла .o или обычного Linux. Я не сомневался, что многозагрузочный загрузчик GRUB будет нулевым BSS для вас, я просто сказал, что не знаю, что было поддержано, пока я не прочитал его сейчас. :П –

ответ

0

Я проверил это некоторые (с только этот код и _start, составляющем exit_group системный вызов), построенный с gcc -c или gcc -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 (неотделенный).