Translation(s): Русский - English
Contents
Как получить осмысленный бэктрейс
Эта страница попытается объяснить, как получить осмысленный бэктрейс отладки из воспроизводимой ошибки в программе. В этом примере, мы установим пакет "hello" с отладочными символами или в случае если пакет не доступен, пересоберем и установим его с сохранением отладочной информации.
Для справки, знак "#" в начале строки означает, что следующая команда будет выполнена от имени суперпользователя root (или с помощью sudo). "$" в начале строки означает, что следующая команда будет выполнена от имени обычного пользователя. "(gdb)" означает, что вы должны придерживаться набора текста в командной строке приглашения gdb (GNU Debugger).
Установка отладочных символов
Чтобы узнать, имеется ли у отлаживаемого вами пакета зависимость в виде пакета -dbg (например, пакет с исходным кодом hello и пакет hello-dbg) найдите его с помощью пакетного менеджера. Выполните следующую команду в командной строке.
$ apt-cache search hello | grep dbg p hello-dbg - hello debug symbols
Если ничего не нашлось, вам придется пересобрать пакет, согласно описанию в следующем разделе (или особенно если вы сопровождающий пакета, модифицируйте пакет таким образом, чтобы пакет всегда собирался с отладочными символами). Если вы нашли соответствующий пакет, просто установите соответствующую зависимость -dbg, например с помощью
# apt-get install hello-dbg
и пропустите процесс пересборки в следующей инструкции и перейдите к запуску gdb.
Пересборка пакета, необходимого для отладки
Вы можете пропустить этот раздел, если имеется возможность установить необходимые пакеты(ы) -dbg с предыдущего раздела.
Установите основные пакеты разработки и сборочные зависимости для пакета, который нам необходимо собрать. Заметьте, что вы можете пропустить часть про пересборку, и перейти прямо к gdb, однако в таком случае, маловероятно, что вы сможете получить полезный бэктрейс. (Если build-dep выдает ошибку, проверьте наличие строки deb-src в /etc/apt/sources.list.)
# apt-get install build-essential fakeroot gdb # apt-get build-dep hello
- Загрузите и пересоберите пакет из исходного кода, с сохранением отладочных символов
$ DEB_BUILD_OPTIONS="nostrip noopt" fakeroot apt-get -b source hello
* Установите свежесобранные пакеты. Здесь могут быть несколько собранных пакетов, поэтому удостоверьтесь, что вы устанавливаете только то, что вам нужно. В данном примере созданный пакет называется hello_2.1.1-4_i386.deb.
# dpkg -i hello_2.1.1-4_i386.deb
Вы можете удостовериться, что двоичные файлы, установленные из вашего пакета, имеют отладочные символы, используя команду 'file' или с помощью самого gdb (см. ниже).
$ file /usr/bin/hello # вывод должен быть "not stripped"
Запуск gdb
Теперь вы можете запустить вашу программу, заменив "[--args]" на любой необходимый вам аргумент:
$ gdb hello ... gdb loads ... (gdb) set pagination 0 (gdb) run [--args] ... hello loads...
- Далее попробуйте воспроизвести ошибку. Если все пройдет удачно, произойдет ошибка в программе, и вы вернетесь к окну с приглашением gdb.
- Если вам не удалось вызвать ошибку и вместо этого произошло зависание, вы все еще можете получить доступ к приглашению gdb, нажав CTRL+C в окне терминала с запущенным gdb.
На этом этапе можно выполнить:
(gdb) bt
- Вы сможете получить большой вывод, который может быть скопирован в письмо с сообщением об ошибке или в другую программу для отправки сообщений об ошибках.
Для завершения работы с gdb, выполните:
(gdb) quit
Если проблема была обнаружена в системной библиотеке, такой как libc6, xlibs, или libgtk2.0-0, вам необходимо установить соответствующий пакет -dbg (т.е. libc6-dbg в случае с libc6), затем снова запустить проблемную программу из под gdb.
Чаще всего, вы можете получить бэктрейс, где первые несколько строк находятся в malloc() или g_malloc(). Это означает, что ваш бэктрейс не совсем полезен. Наилегкий путь состоит в том, чтобы найти какую-либо полезную информацию, изменив значение переменной MALLOC_CHECK_ на 2. Вы можете выполнить это во время запуска gdb с помощью:
$ MALLOC_CHECK_=2 gdb hello
Дополнительные команды gdb
Если программа, с который вы собираетесь работать, является многопоточной, вам необходимо получить бэктрейс всех потоков:
(gdb) thread apply all bt
Кое-что еще может здорово помочь в выявлении того, какие переменные были установлены локально на каждом этапе стека:
(gdb) bt full
Вы можете вывести вывод комбинаций предыдущих параметров:
(gdb) thread apply all bt full
Если данный вывод совсем не относится к ошибке, вы можете солхранить только несколько вызовов, к примеру первые 10:
(gdb) thread apply all bt full 10
Если у вас большой бэктрейс, вы можете сохранить вывод gdb в файл (по умолчанию gdb.txt):
(gdb) set logging on
Для проверки на наличие отладочных символов в двоичном файле:
$ gdb (gdb) symbol-file /usr/bin/hello # вы можете увидеть что-то вроде этого: Reading symbols from /usr/bin/hello ... done Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1". (gdb) # А вот это крайне нежелательно: Reading symbols from /usr/bin/hello...(no debugging symbols found)...done
Отладка ошибок X (Xorg)
Если программа, написанная на GTK выдала ошибку; т. е. Вы увидели ошибку вида:
The program 'preview1' received an X Window System error.
в этом случае, вы можете попробовать запустить программу с аргументом --sync, и сломать функцию gdk_x_error для того, чтобы получить бэктрейс, вот так:
(gdb) break gdk_x_error (gdb) run --sync
Прочие полезные ссылки
Авторы: Ari Pollak и Loic Minier