Секция .debug — это раздел в исполняемом файле или бинарнике, который хранит отладочную информацию: имена функций, номера строк исходного кода, типы переменных, имена файлов. Если вы столкнулись с крашем программы и видите в стеке вызовов только адреса вроде 0x00007ff6a3b11234, а не нормальные имена функций — скорее всего, секция .debug отсутствует или была удалена. Разберёмся, зачем она нужна, как проверить её наличие и что делать, когда её нет.
- Что вообще такое секция .debug
- Зачем разработчику знать о .debug
- Как проверить наличие секции .debug
- Способ 1: команда readelf (Linux)
- Способ 2: команда objdump
- Способ 3: команда file
- Способ 4: GDB
- Способ 5: для Windows (PE-файлы)
- Сравнение способов проверки
- Что делать, если секции .debug нет
- Если вы собираете проект сами
- Если бинарник собран в конвейере CI/CD
- Если вы аналилируете чужой бинарник
- Частые ошибки при работе с .debug
- Как лучше организовать работу с отладочной информацией
- Итог
Что вообще такое секция .debug
Когда компилятор превращает исходный код в машинный код, он может добавить туда дополнительные данные — отладочную информацию. В формате ELF (Linux, большинство Unix-систем) эта информация живёт в именованных секциях, и .debug — это общее название для целой группы таких секций. В PE-файлах (Windows) отладочная информация хранится по-другому, но суть та же.
Конкретно в формате ELF вы встретите не одну секцию .debug, а несколько:
.debug_info— основная информация: имена функций, переменных, типы, номера строк..debug_line— таблица соответствия между машинными адресами и строками исходного кода..debug_abbrev— таблица сокращений, которая описывает структуру записей в.debug_info..debug_str— строковые данные (имена файлов, имена переменных)..debug_ranges— диапазоны адресов для функций, разбитых на несколько частей.
Все эти секции вместе образуют то, что называется DWARF — формат отладочной информации. GDB, LLDB и другие отладчики читают именно эти данные, чтобы показывать вам осмысленные имена вместо голых адресов.
Зачем разработчику знать о .debug
Практических сценариев несколько, и они все реальные:
- Анализ крашей. Программа упала, вы открываете core dump в GDB, а стек вызовов состоит из адресов. Без
.debugвы не поймёте, в какой функции произошла ошибка, не увидите значения локальных переменных. - Профилирование и трассировка. Инструменты вроде
perf,valgrind,bpftrace показывают адресовый профиль. Чтобы сопоставить его с исходным кодом, нужна отладочная информация. - Проверка сборки. Вы собрали проект и хотите убедиться, что отладочная информация действительно попала в бинарник. Особенно актуально в CI/CD, где могут быть нюансы с флагами компилятора.
- Оптимизация размера. Отладочная информация может занимать значительный объём. Иногда её нужно оставить, иногда — удалить. Но для этого сначала нужно проверить, есть ли она.
- Reverse engineering. Если вы анализируете чужой бинарник, наличие
.debug— подарок. Имена функций и перварные типы сильно упрощают понимание кода.
Как проверить наличие секции .debug
Способ 1: команда readelf (Linux)
Это самый прямой и информативный способ. Утилита readelf входит в состав binutils и есть практически в любом Linux-дистрибутиве.
Чтобы посмотреть все секции файла:
readelf -S /path/to/your/binary
В выводе найдите строки, начинающиеся с .debug:
[26] .debug_info PROGBITS 0000000000000000 001a4c 0000000000000000 0 0 1
[27] .debug_abbrev PROGBITS 0000000000000000 001b2a 0000000000000000 0 0 1
[28] .debug_line PROGBITS 0000000000000000 001c89 0000000000000000 0 0 1
[29] .debug_str PROGBITS 0000000000000000 001d10 0000000000000000 0 0 1
Если таких строк нет — отладочная информация отсутствует. Если есть, но размер (Size) равен нулю — секция пустая, что тоже говорит о проблеме.
Способ 2: команда objdump
Более короткий вариант проверки — искать секции по имени:
objdump -h /path/to/your/binary | grep debug
Если вывод пуст — секций .debug нет. Если есть — вы увидите имена, размеры и виртуальные адреса каждой секции.
Способ 3: команда file
Команда file не показывает конкретные секции, но может подсказать, есть ли отладочная информация в файле:
file /path/to/your/binary
Ищите строку with debug_info, not stripped — это значит, что отладочная информация присутствует. Если написано просто not stripped — символы есть, но DWARF-секций может не быть. Если stripped — всё вырезано.
Способ 4: GDB
Загрузите файл в отладчик и посмотрите, что он скажет:
gdb /path/to/your/binary
GDB при загрузке выведет что-то вроде:
Reading symbols from /path/to/your/binary...
(No debugging symbols found in /path/to/your/binary)
Или, если символы есть:
Reading symbols from /path/to/your/binary...
Без предупреждения — значит, отладочная информация загружена успешно.
Способ 5: для Windows (PE-файлы)
В Windows отладочная информация хранится в секции .debug PE-файла или в отдельном PDB-файле. Для проверки можно использовать dumpbin:
dumpbin /headers /path/to/your/binary.exe | findstr debug
Или PowerShell:
[System.IO.File]::ReadAllBytes("binary.exe")[...] # анализ PE-заголовков вручную
Проще всего использовать утилиту dbghelp или посмотреть в CFF Explorer — это GUI-инструмент, который наглядно показывает все секции PE-файла.
Сравнение способов проверки
| Способ | Что показывает | Удобство | Где работает |
|---|---|---|---|
readelf -S |
Полный список секций с размерами | Высокое — максимум информации | Linux, любые ELF-системы |
objdump -h | grep |
Только секции .debug (отфильтрованно) | Среднее — быстрый чек | Linux, кросс-компиляция |
file |
Общий признак наличия debug info | Низкое — только факт, без деталей | Linux, macOS (для Mach-O) |
gdb |
Загрузка символов и диагностика | Среднее — если уже работаете с GDB | Linux, частично Windows |
dumpbin |
Секции PE, включая .debug | Среднее — нужно знать формат | Windows |
Что делать, если секции .debug нет
Здесь всё зависит от вашей ситуации.
Если вы собираете проект сами
Проверьте флаги компилятора. Для GCC и Clang нужен флаг -g:
gcc -g -O0 main.c -o myprogram
Важные нюансы:
-gбез указания уровня — генерирует DWARF последней поддерживаемой версии.-g1— минимальная информация: имена функций и номера строк, но без локальных переменных. Полезно, когда нужно экономить место.-g3— максимум информации, включая макросы препроцессора.- Флаги оптимизации (
-O2,-O3) не удаляют отладочную информацию, но могут сделать отладку неудобной — переменные оптимизируются, строки переставляются. - Если в вашем Makefile или CMakeLists.txt есть
stripна этапе установки — он удаляет все символы и секции.debug. Проверьте этапы сборки.
Если бинарник собран в конвейере CI/CD
Частая ситуация: разработчик собирает с -g, а перед публикой запускает strip --strip-debug или strip --strip-all. Первый удаляет только DWARF-секции, второй — всё, включая таблицу символов.
Если вам нужны символы для анализа крашей, не удаляйте их. Вместо этого сохраняйте debug info отдельно:
objcopy --only-keep-debug myprogram myprogram.debug
strip --strip-debug myprogram
objcopy --add-gnu-debuglink=myprogram.debug myprogram
После этого в GDB можно загрузить myprogram.debug отдельно, и отладчик подхватит его автоматически.
Если вы аналилируете чужой бинарник
Если отладочной информации нет и взять её неоткуда — остаётся работать с тем, что есть. Инструменты вроде Ghidra, IDA Pro, Binary Ninja могут восстановить часть информации: имена импортируемых функций, строки, структуры по шаблонам использования. Но это уже совсем другой уровень работы.
Частые ошибки при работе с .debug
Путаница между символами и отладочной информацией. Таблица символов (
.symtab) и отладочные секции (.debug_info) — разные вещи.strip --strip-symbolsудаляет таблицу символов, но не DWARF.strip --strip-debugудаляет DWARF, но оставляет символы. Если вы видите имена функций вnm, но GDB не показывает номера строк — значит, удалена именно.debug_info.
Сборка с -g, но линковка без неё. Если вы компилируете объектные файлы с
-g, а линковщик запускается с флагом-Sили-s, отладочная информация потеряется на этапе линковки. Проверяйте все этапы сборки.
Использование -g в продакшн-сборке без разделения. Не отправляйте бинарники с полной отладочной информацией в продакшн. Размер файла может быть в 5–10 раз больше. Используйте
objcopyдля разделения: рабочий бинарник — без debug, файл с отладочной информацией — отдельно, в защищённом хранилище.
Несовместимость версий DWARF. Если компилятор генерирует DWARF 5, а отладчик поддерживает только DWARF 4, вы получите сообщение об ошибке при загрузке. Это редкость в свежих дистрибутивах, но встречается в корпоративных средах со старым инструментарием.
Как лучше организовать работу с отладочной информацией
Здесь зависит от масба проекта, но есть общие рекомендации:
- Для разработки и тестирования: собирайте с
-g -O0. Никакой оптимизации, полная отладочная информация. Это ваша рабочая среда. - Для бета-сборок и стейджинга:
-g -O2. Отладочная информация есть, но код уже с оптимизацией — ближе к боевому поведению. - Для продакшна: собирайте с
-g, затем сохраняйте debug info черезobjcopy, а в продакшн отправляйте ужеstrip --strip-debugверсию. - Хранение debug info: храните файлы
.debugили debug packages в артефактории (Nexus, Artifactory, S3). При получении core dump вы сможете подтянуть нужную версию и получить читаемый стек.
Итог
Проверить наличие секции .debug — дело одной команды: readelf -S или objdump -h | grep debug. Если секций нет — пересоберите с флагом -g и проверьте, что линковщик и strip не удалили отладочную информацию. Если есть — решите, что с ней делать: оставить в бинарнике, вынести в отдельный файл или удалить для уменьшения размера.
Главное правило: отладочная информация — это не мусор, а ценный ресурс для диагностики проблем. Не удаляйте её бездумно и не тащите в продакшн целиком. Разделяйте — и будете получать читаемые стектрейсы вместо наборов адресов.
