Как сделать небольшие двоичные файлы с использованием сборки? - PullRequest
4 голосов
/ 09 июля 2019

Я писал какой-то ассемблерный код для моего проекта и увидел кое-что интересное.размер бинарного файла при связывании очень большой.поэтому я тестировал и тестировал, и даже с наименьшими возможными строками кода выходной двоичный файл Elf очень большой.например:

.section .text
.global _start
_start:
    movl $1,%eax
    movl $0,%ebx
    int $0x80

после сборки и компоновки вышеуказанного кода двоичный результат будет больше, чем 4 КБ !Самое смешное, что большая часть двоичных файлов заполнена нулями.Я пробовал так много вещей, чтобы выяснить, в чем причина успеха.Может кто-нибудь, пожалуйста, объясните мне, в чем здесь проблема?

Я просто собираю и связываю файл:

as -o <OBJ_NAME> <SOURCE NAME>
ld -o <ELF_NAME> <OBJ_NAME>

рекомендую любую форму ресурса для дальнейшего чтения.

, как вы уже догадались, я использую 64-битную GNU / Linux

спасибо.

1 Ответ

4 голосов
/ 09 июля 2019

Это связано с выравниванием. Смотри readelf -eW <ELF_NAME>. Интересный бит

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        0000000000401000 001000 00000c 00  AX  0   0  1

Обратите внимание на столбец Off. Это смещение в файле, и раздел .text начинается с 0x1000, то есть 4K.

То же самое изображение, если вы посмотрите на заголовки программы . Пространство, заполненное нулями, находится между концом заголовка ELF и 0x1000.

Почему это?

Во-первых, потому что стандарт ELF диктует, что

Загружаемые сегменты процесса должны иметь совпадающие значения для p_vaddr и p_offset, по модулю размера страницы.

(см. man elf). Размер страницы в вашей системе (моя тоже) составляет 4K. Это значение, которое вы видите в p_align.

Во-вторых, виртуальный адрес, который компоновщик назначил началу «текстового» сегмента - так же, как и для раздела .text здесь, потому что это все, что содержит этот сегмент - это 0x0000000000401000. Поэтому шестнадцатеричное представление смещения сегмента «текст» в файле должно заканчиваться 000. Но 0 уже занято сегментом только для чтения, содержащим заголовок ELF (самое начало файла). Второй выбор 0x1000.

Почему компоновщик выбрал 0x401000 в качестве виртуального адреса для текстового раздела? Я не знаю. Я думаю, что если вы немного доработаете скрипт компоновщика, вы сможете получить исполняемый файл меньшего размера.


Как указал Питер и другой парень, выравнивание по размеру страницы можно отключить с помощью опции компоновщика -n:

'-n'
'--nmagic'
    Turn off page alignment of sections, and disable linking against
    shared libraries[…]

Таким образом, я получаю

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 1] .text             PROGBITS        0000000000400078 000078 00000c 00  AX  0   0  1

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  LOAD           0x000078 0x0000000000400078 0x0000000000400078 0x00000c 0x00000c R E 0x1

и размер исполняемого файла уменьшен до 664 байт (344 после strip ping).


В GNU ld вы можете использовать сценарии компоновщика для точной настройки макета выходных файлов компоновщика. ld.bfd (обычно также известный как просто ld) интерпретирует скрипт компоновщика по умолчанию, если пользователь не указывает его. Его можно получить с ld --verbose. Затем вы можете отредактировать его и указать вместо версии по умолчанию -T <your-script>.

Я отредактировал первое вхождение

. = ALIGN(CONSTANT (MAXPAGESIZE));

(до .text) и получил 720 (400 при strip ped) байтов. Это отличается от результата использования опции -n. Вы по-прежнему получаете 2 загружаемых сегмента, а их p_align по-прежнему 0x1000.

Существуют последствия для эффективности использования p_align <<code>MAX_PAGE_SIZE, которые я не до конца понимаю. (Страницы не будут загружаться так быстро из-за более сложных вычислений адресов? Я думаю, что должно быть лучшее объяснение.) Не стесняйтесь редактировать ответ, если вы знаете больше об этом или где он объяснен.

...