TGViewer
.NET Kings .NET Kings @netskings · 7.38K subscribers
Post #733 484
👁‍🗨Hello world~

Разбор ELF: Формат объектных файлов под микроскопом

Секции


• В первом посте мы разобрали общую структуру ELF-файла, а сегодня заглянем внутрь объектного файла и посмотрим, из каких секций он состоит.

• Секция (section) — это участок файла с данными одного вида, код, инициализированные переменные, таблица символов и так далее. Все секции перечислены в таблице заголовков секций, где у каждой записаны имя, тип, размер и другие свойства.

• Посмотрим на практике. Возьмём программу с тремя глобальными переменными:

#include <stdio.h>

int counter = 5;
int buffer[1000];
const char msg[] = "hello";

int main(void) {
printf("%s %d\n", msg, counter);
return 0;
}


• Соберём объектный файл (gcc -c hello.c -o hello.o) и спросим у nm, что в какую секцию попало:

0000000000000000 B buffer
0000000000000000 D counter
0000000000000000 T main
0000000000000000 R msg
U printf


• Код функции лежит в .text (T), переменная с начальным значением в .data (D), константа в .rodata (R), а переменная без начального значения в .bss (B). Только printf нигде не лежит (U): его найдёт компоновщик.

• Теперь загадка: массив buffer занимает 4000 байт, а весь hello.o весит всего около 1,7 КБ. Куда делись данные? Смотрим таблицу секций командой readelf -SW hello.o (оставил две нужные строки и три столбца):

Name   Type      Size
.data PROGBITS 000004
.bss NOBITS 000fa0


• Размер .bss равен 0xfa0, то есть те самые 4000 байт, но тип у неё NOBITS, содержимого в файле нет. Хранить 4000 нулей незачем, достаточно записать "нужно столько-то памяти", а загрузчик выделит её и заполнит нулями при запуске. У .data тип PROGBITS: её байты лежат прямо в файле, objdump -s -j .data hello.o покажет 05 00 00 00, то есть число 5 из counter.

• Проверим экспериментом. Увеличим массив до миллиона элементов, то есть до 4 МБ. Файл останется маленьким, но стоит добавить начальное значение, и он раздуется:

int buffer[1000000];        ≈ 1,7 КБ
int buffer[1000000] = {1}; ≈ 4 МБ


• Во втором случае nm покажет D вместо B: массив переехал из .bss в .data, и все 4 МБ пришлось хранить в файле.

• Секции это взгляд компоновщика на файл, он собирает однотипные секции из разных объектных файлов и склеивает их вместе. А загрузчику секции не нужны, ему важны сегменты. Про них поговорим позже, а в следующем посте разберём таблицу символов. Удачи!

• Поддержать автора монеткой: @v_meshke
  • ❤ 7
  • 🔥 4
  • ❤‍🔥 3
More from @netskings
  1. Oct 5, 2026Освой сети и командную строку с лучшими обучающими каналами 🤩 Network Admin - обучающий к…
  2. Oct 5, 2026👁‍🗨Hello world~ Компилятор: Путь от исходника до исполняемого файла. Обзор и практика на…
  3. Oct 4, 2026👁‍🗨Hello world~ Когда проблема не в коде, а в замысле. OWASP A06: Insecure Design • Inse…
  4. Oct 3, 2026👁‍🗨Hello world~ Изучаем сеть: Как коммутатор запоминает устройства • Коммутатор передаёт…
  5. Oct 2, 2026👁‍🗨Hello world~ Парадокс дней рождения: почему коллизии хешей находить проще, чем кажетс…
  6. Oct 1, 2026👁‍🗨Hello world~ Как работает антивирус: Hell’s Gate • В прошлом посте мы разобрали Direc…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →