Зачем GDB нужен как исполняемый файл, так и дамп ядра?


11

Я отлаживаю с помощью дампов ядра, и обратите внимание, что gdb требует, чтобы вы предоставили как исполняемый файл, так и дамп ядра. Почему это? Если дамп ядра содержит всю память, используемую процессом, разве исполняемый файл не содержится в дампе ядра? Возможно, нет никакой гарантии, что весь exe загружен в память (хотя отдельные исполняемые файлы обычно не такие большие), или, может быть, дамп ядра не содержит всей необходимой памяти? Это для символов (возможно, они не загружаются в память нормально)?


1
Исполняемый файл содержит информацию о
Томас Дики

1
Удивительно, но ни в одном ответе (кроме того, который я только что добавил) не упоминается формат DWARF
Старынкевич,

Ответы:


15

Дамп ядра - это просто дамп памяти вашей программы, если вы знаете, где все было, вы можете просто использовать это.

Вы используете исполняемый файл, потому что он объясняет, где (в терминах логических адресов) вещи находятся в памяти, то есть в файле ядра.

Если вы используете команду, objdumpона выдаст метаданные об исполняемом объекте, который вы исследуете. Используя в качестве примера исполняемый объект с именем a.out.

objdump -h a.outвыводит только информацию заголовка, вы увидите разделы с именем например. .data или .bss или .text (их намного больше). Они информируют загрузчик ядра о том, где в объекте можно найти различные разделы и где в адресном пространстве процесса следует загрузить раздел, а для некоторых разделов (например, .data .text), что следует загрузить. (Раздел .bss не содержит никаких данных в файле, но относится к объему памяти, который резервируется в процессе для неинициализированных данных, он заполнен нулями).

Компоновка исполняемого объектного файла соответствует стандарту ELF.

objdump -x a.out - сбрасывает все

Если исполняемый объект все еще содержит свои таблицы символов (он не был удален - man stripи вы использовали -gгенерацию отладки для gcc предположения компиляции источника переменного тока), то вы можете проверить содержимое ядра по именам символов, например, если у вас была переменная / буфер с именем inputLine в вашем исходном коде, вы можете использовать это имя gdbдля просмотра его содержимого. то есть gdbбудет знать смещение от начала сегмента данных, инициализированных вашими программами, где начинается inputLine, и длину этой переменной.

Дальнейшее чтение Article1 , статья 2 , и вшивый песчаный Исполняемые и Linking Format (ELF) спецификации .


Обновление после комментария @mirabilos ниже.

Но если использовать таблицу символов, как в

$ gdb --batch -s a.out -c core -q -ex "x buf1"

Производит

 0x601060 <buf1>:    0x72617453

а затем не использовать таблицу символов и исследовать адрес непосредственно в,

$ gdb --batch -c core -q -ex "x 0x601060"

Производит

0x601060:   0x72617453

Я проверил память напрямую, не используя таблицу символов во 2-й команде.


Я также вижу, что ответ @ user580082 дополняет объяснение и будет способствовать голосованию.


6
Никогда не слышал об "основной секции стека". .bss (исторически) является «блоком, начинающимся с символа» и практически «унифицированными данными», а .data - «инициализированными данными», а текст (не .code) используется для хранения машинного кода. В двоичном файле нет стекового раздела, так как стеки создаются во время выполнения.
jlliagre

«Если вы знаете, где все было, тогда вы могли бы просто использовать это», что также неверно, потому что не все в программе обязательно включено в след.
Мирабилось

1
@jlliagre вы правы, я по ошибке назвал .text .code (потому что я придумывал объяснение, пока составлял ответ) - обновил. Я ошибочно думал о bss неправильно по имени и обновил свой ответ, но избегал * Блок, начатый символом, так как я не думаю, что это действительно добавляет к уравнению, и объяснил, что он используется как неинициализированные данные, которые были нашими общее понимание Спасибо - я оценил ваш комментарий, чтобы исправить это сообщение.
X Тянь

4

Основной файл представляет собой снимок образа стека, отображений памяти и регистров во время завершения процесса. Содержанием которого можно манипулировать, как указано на основной странице man . По умолчанию частные сопоставления, общие сопоставления и информация заголовка ELF выгружаются в основной файл.

Что касается вашего вопроса , то причина, по которой gdb требуется исполняемый файл, заключается в том, что он не имитирует выполнение, читая и интерпретируя двоичные инструкции, как это делает valgrind, вместо этого он становится родителем процесса, чтобы контролировать поведение процесса во время выполнения. время. Он использует файл ядра для определения отображений памяти и состояния процессора во время сбоя.

В Linux родительские процессы могут получать дополнительную информацию о своих дочерних элементах, в частности возможность отслеживать их, что позволяет отладчику получать доступ к низкоуровневой информации процесса, такой как чтение / запись в его памяти, регистры, изменение отображений сигналов, остановка его выполнения и т. Д.

Вы поймете требование к исполняемому файлу, несмотря на наличие файла core еще раз, прочитав, как работает любой отладчик.


1

(в дополнение к другим хорошим ответам)

В современных системах Linux (и многих Unix-подобных) информация об отладке (включая метаданные о типах символов, расположении исходного кода, типе переменных и т. Д. И т. Д.) Находится в формате DWARF и находится внутри исполняемого файла ELF ( или ELF разделяемые библиотеки), когда он компилируется с какой-либо -gопцией. Я рекомендую отлаживать компиляцию программ -g3 -O0и, возможно, -fno-inlineпри использовании недавнего GCC ; однако, с GCC вы можете даже скомпилировать как информацию об оптимизации, так и информацию отладки, например, с помощью -O2 -g1, хотя информация отладки в этом случае может быть немного «нечеткой» (это может немного помочь поймать некоторых непослушных гейзенбагов ).

Разумно избегать помещения этой информации в основные файлы, поскольку у вас может быть много разных основных файлов (представьте себе широко используемое программное обеспечение, в котором многие пользователи создают отчеты об ошибках, большинство из которых имеют coreдамп) для одного и того же исполняемого файла. Также файлы core (5) выгружаются ядром, которому не нужно заботиться о существовании разделов DWARF в исполняемых файлах elf (5) (поскольку эти разделы не отображаются в виртуальное адресное пространство ошибочного процесса, который выгружал ядро ​​по некоторому сигналу ( 7) ). Существует даже возможность размещения отладочной информации в отдельных файлах (вне исполняемого файла).

Кстати, GDB может быть болезненно используются для отладки ядра свалки для исполняемых файлов без какой - либо информации отладки. Но затем вы практически отлаживаете на уровне машинного кода (не на символическом уровне, обеспечиваемом языками программирования и их компиляторами).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.