Как отладить отказ сегментации, в то время как gdb отслеживание стека полно'??'?

Мой исполняемый файл содержит таблицу символов. Но кажется, что отслеживание стека является overwrited.

Как получить больше информации из того ядра? Например, есть ли способ осмотреть "кучу"? Посмотрите, что экземпляры объектов заполняют "кучу" для получения некоторых подсказок. Безотносительно, любая идея ценится.

13
задан yves Baumes 10 March 2010 в 18:03
поделиться

7 ответов

Я зарабатываю на жизнь программистом на C ++ и сталкивался с этой проблемой больше раз, чем мне хотелось бы признать. Ваше приложение разбивает ОГРОМНУЮ часть стека. Скорее всего, функция, которая повреждает стек, также дает сбой при возврате. Причина в том, что адрес возврата был перезаписан, и поэтому трассировка стека GDB испорчена.

Вот как я отлаживаю эту проблему:

1) Обходите приложение, пока оно не выйдет из строя. (Ищите функцию, которая дает сбой при возврате).

2) После того, как вы определили функцию, объявите переменную в ОЧЕНЬ ПЕРВОЙ СТРОКЕ функции:

int canary=0;

(Причина, по которой она должна быть первой строкой, состоит в том, что это значение должно находиться на самом верху стека. . Эта "канарейка" будет перезаписана перед адресом возврата функции.)

3) Поставьте переменную watch на canary, пройдитесь через функцию, и когда canary! = 0, то вы обнаружили переполнение буфера! Другая возможность - установить точку останова для переменной, когда canary! = 0 и просто запустить программу в обычном режиме, это немного проще, но не все точки останова для переменных, поддерживаемых IDE.

РЕДАКТИРОВАТЬ: Я разговаривал со старшим программистом в моем офисе, и для понимания дампа ядра вам необходимо разрешить адреса памяти, которые в нем есть. Один из способов выяснить эти адреса - посмотреть файл MAP для двоичного файла, который читается человеком. Вот пример создания файла MAP с помощью gcc:

gcc -o foo -Wl,-Map,foo.map foo.c

Это часть головоломки, но все равно будет очень сложно получить адрес функции, которая дает сбой.Если вы запускаете это приложение на современной платформе, то ASLR, вероятно, сделает адреса в дампе ядра бесполезными. Некоторая реализация ASLR будет рандомизировать адреса функций вашего двоичного файла, что делает дамп ядра абсолютно бесполезным.

14
ответ дан 1 December 2019 в 22:06
поделиться

Не совсем. Конечно, вы можете покопаться в памяти и посмотреть на вещи. Но без трассировки стека вы не знаете, как вы попали туда, где находитесь, и каковы были значения параметров.

Однако сам факт того, что ваш стек поврежден, говорит вам о том, что вам нужно искать код, который записывается в стек.

  • Перезапись массива стека. Это можно сделать очевидным способом или путем вызова функции или системного вызова с аргументами плохого размера или указателями неправильного типа.
  • Использование указателя или ссылки на локальные переменные стека функции после ее возврата.
  • Приведение указателя на значение стека к указателю неправильного размера и его использование.

Если у вас система Unix, valgrind - хороший инструмент для поиска некоторых из этих проблем.

1
ответ дан 1 December 2019 в 22:06
поделиться

Я предполагаю, что, поскольку вы говорите «Мой исполняемый файл содержит таблицу символов», которую вы скомпилировали и связан с -g, и что ваш двоичный файл не был удален.

Мы можем просто подтвердить это: strings -a | grep function_name_you_know_should_exist

Также попробуйте использовать pstack на ядре и посмотрите, лучше ли он справляется с получением стека вызовов. В этом случае похоже, что ваш gdb устарел по сравнению с вашей версией gcc / g ++.

0
ответ дан 1 December 2019 в 22:06
поделиться

Попробуйте запустить отладчик памяти Valgrind.

1
ответ дан 1 December 2019 в 22:06
поделиться

Чтобы подтвердить, был ли ваш исполняемый файл скомпилирован в режиме выпуска, то есть без символов отладки .... это могло бы объяснить, почему там ?? Попробуйте перекомпилировать с помощью переключателя -g , который «включает отладочную информацию и встраивает ее в исполняемый файл» .. Кроме этого, у меня нет идей относительно того, почему у вас есть «??» ...

1
ответ дан 1 December 2019 в 22:06
поделиться
  1. Вы должны использовать какой-нибудь отладчик для обнаружения, valgrind подходит
  2. во время компиляции кода убедитесь, что вы добавили опцию -Wall, это заставит компилятор сказать вам, есть ли какие-то ошибки или нет (убедитесь, что у вас нет никаких предупреждений в коде).

например: gcc -Wall -g -c -o oke.o oke.c
3. Убедитесь, что у вас также есть опция -g для получения отладочной информации. Вызвать отладочную информацию можно с помощью некоторых макросов. Для меня очень полезны следующие макросы:

__LINE__ : сообщает вам строку

__FILE__ : сообщает вам исходный файл

__func__ : сообщает вам функцию

  1. Использование отладчика недостаточно, я думаю, вы должны привыкнуть к максимальному использованию возможностей компилятора.

Надеюсь, это поможет

4
ответ дан 1 December 2019 в 22:06
поделиться

Похоже, вы не используете на своей машине ту же версию glibc, которая была у corefile, когда он разбился при производстве. Получите файлы, выводимые с помощью "ldd ./appname", и загрузите их на свой компьютер, затем скажите gdb, где искать;

set solib-absolute-prefix /path/to/libs
0
ответ дан 1 December 2019 в 22:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: