Debugging (Русский)/Getting traces (Русский)
Эта статья описывает создание отладочного пакета и получение с его помощью отладочной информации, которую можно будет отправить разработчикам в сообщении об ошибке.
Обычно исполняемые файлы очищаются (strip) от человекочитаемого контекста, чтобы уменьшить их размер. Кроме того, расширенная отладочная информация обычно не добавляется в исполняемый файл, что сильно снижает качество трассировки. Поэтому перед получением трассировки нужно пересобрать пакет без выполнения strip и с отладочной информацией.
Используйте полную трассировку стека, чтобы сообщить разработчикам о найденной вами ошибке — это сильно поможет в решении проблемы.
Имена пакетов
Для начала нужно выяснить имена пакетов, которые требуется пересобрать.
Во время отладки, например, при просмотре дампа памяти в gdb, вы увидите что-то подобное:
[...] Backtrace was generated from '/usr/bin/epiphany' (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (no debugging symbols found) [Thread debugging using libthread_db enabled] [New Thread -1241265952 (LWP 12630)] (no debugging symbols found) 0xb7f25410 in __kernel_vsyscall () #0 0xb7f25410 in __kernel_vsyscall () #1 0xb741b45b in ?? () from /lib/libpthread.so.0 [...]
строки вида ??
и (no debugging symbols found)
показывают, что необходимая отладочная информация, такая, как названия функций, файлов, библиотек, отсутствует в отлаживаемом файле. Проверить, какому пакету принадлежит исполняемый файл или библиотека можно, например, с помощью pacman:
$ pacman -Qo /lib/libthread_db.so.1
/lib/libthread_db.so.1 is owned by glibc 2.5-8
Пакет glibc версии 2.5-8. Следует составить список пакетов, которые необходимо заменить для отладки.
Есть несколько способов получения отладочной информации, каждый из которых описан в соответствующем разделе: #Debuginfod, #Установка отладочных пакетов, #Пересборка пакетов.
Debuginfod
Для некоторых пакетов [1] из официальных репозиториев можно скачать отладочную информацию с помощью debuginfod.
Например, чтобы скачать отладочные символы для пакета zstd вместе с исходным кодом, можно использовать debuginfo-find:
$ debuginfod-find debuginfo /usr/bin/zstd
/home/user/.cache/debuginfod_client/70e1b456c5813658df6436a3deb71812e75a0267/debuginfo
$ debuginfod-find source /usr/bin/zstd /usr/src/debug/zstd-1.5.2/programs/fileio.c
/home/user/.cache/debuginfod_client/70e1b456c5813658df6436a3deb71812e75a0267/source##usr##src##debug##zstd-1.5.2##programs##fileio.c
Некоторые отладчики, например gdb, умеют скачивать их автоматически.
Например, вы можете сделать:
# coredumpctl gdb
И затем в gdb
(gdb) bt full
и в вашей системе появятся отладочные символы для последнего упавшего приложения.
Установка отладочных пакетов
В настоящее время несколько зеркал распространяют отладочные пакеты в доступных репозиториях. Это спонсируемые зеркала, контролируемые Arch Linux, которым предоставляется доступ к отладочным репозиториям.
- https://america.mirror.pkgbuild.com
- https://asia.mirror.pkgbuild.com
- https://europe.mirror.pkgbuild.com
- https://geo.mirror.pkgbuild.com (зеркало GeoDNS)
Можно установить пакет напрямую из репозитория. Например:
# pacman -U https://geo.mirror.pkgbuild.com/core-debug/os/x86_64/zstd-debug-1.5.2-2-x86_64.pkg.tar.zst
Другой вариант — добавить репозитории в конфигурацию pacman.
/etc/pacman.conf
# Testing Repositories [testing-debug] Include = /etc/pacman.d/mirrorlist [community-testing-debug] Include = /etc/pacman.d/mirrorlist [multilib-testing-debug] Include = /etc/pacman.d/mirrorlist # Stable repositories [core-debug] Include = /etc/pacman.d/mirrorlist [extra-debug] Include = /etc/pacman.d/mirrorlist [community-debug] Include = /etc/pacman.d/mirrorlist [multilib-debug] Include = /etc/pacman.d/mirrorlist
Поместите зеркало с отладочными пакетами в качестве первого в файле mirrorlist:
/etc/pacman.d/mirrorlist
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch ...
Пересборка пакетов
Если отладочная информация недоступна через debuginfod (например, если пакет собран из AUR), то его можно пересобрать из исходников с включением отладки. Получение файлов PKGBUILD от пакетов из официальных репозиториев описано в статье Arch Build System (Русский); работа с пакетами из AUR описана в статье Arch User Repository (Русский)#Получение файлов.
Чтобы установить необходимые #Параметры компиляции, можно изменить настройки makepkg, если вы планируете использовать makepkg только для отладки. В других случаях меняйте файлы PKGBUILD
только тех пакетов, которые вы хотите пересобрать.
Параметры компиляции
С версии pacman 4.1 makepkg.conf(5) имеет отладочные флаги компиляции в DEBUG_CFLAGS
и DEBUG_CXXFLAGS
. Для их использования включите опцию debug
и отключите опцию strip
.
Эти настройки включат компиляцию с отладочными символами и отключат их удаление из исполняемых файлов.
/etc/makepkg.conf
OPTIONS+=(debug !strip)
Для изменения параметров отдельного пакета измените его PKGBUILD
:
PKGBUILD
options=(debug !strip)
В качестве альтернативы можно поместить информацию об отладке в отдельный пакет, включив обе опции debug
и strip
. Тогда отладочные символы будут удалены из основного пакета и помещены вместе с исходным кодом в отдельный пакет pkgbase-debug
. Это может пригодиться, если пакет содержит очень большие бинарные файлы (например, больше гигабайта с включенными отладочными символами), так как они могут привести к зависаниям и другому странному поведению.
/usr/lib/debug/
, а исходные коды — в /usr/src/debug
. Подробнее об отладочных пакетах можно почитать в документации GDB.glibc
Некоторые пакеты, к примеру glibc, всё равно удаляют отладочные символы. Проверьте PKGBUILD
на наличие подобных команд:
strip $STRIP_BINARIES usr/bin/{gencat,getconf,getent,iconv,iconvconfig} \ usr/bin/{ldconfig,locale,localedef,nscd,makedb} \ usr/bin/{pcprofiledump,pldd,rpcgen,sln,sprof} \ usr/lib/getconf/* strip $STRIP_STATIC usr/lib/*.a strip $STRIP_SHARED usr/lib/{libanl,libBrokenLocale,libcidn,libcrypt}-*.so \ usr/lib/libnss_{compat,db,dns,files,hesiod,nis,nisplus}-*.so \ usr/lib/{libdl,libm,libnsl,libresolv,librt,libutil}-*.so \ usr/lib/{libmemusage,libpcprofile,libSegFault}.so \ usr/lib/{audit,gconv}/*.so
И удалите их по необходимости.
Clang
Пакеты, использующие Clang в качестве компилятора, не будут собираться с опцией debug
из-за того, что флаг -fvar-tracking-assignments'
не обрабатывается (например, js78).
Добавьте следующее в начало функции build()
нужного пакета:
build() { CFLAGS=${CFLAGS/-fvar-tracking-assignments} CXXFLAGS=${CXXFLAGS/-fvar-tracking-assignments} [...]
Сборка и установка пакета
Соберите пакет командой makepkg
, находясь в одном каталоге с файлом PKGBUILD
. Это может занять некоторое время:
$ makepkg
Установка собранного пакета:
# pacman -U glibc-2.26-1-x86_64.pkg.tar.gz
Получение трассировки
Теперь можно получить backtrace (трассировку стека), например, с помощью gdb (GNU Debugger). Запуск осуществляется так:
# gdb /путь/к/файлу
или:
# gdb (gdb) exec /путь/к/файлу
Если путь присутствует в $PATH
, его можно не указывать.
Затем в gdb
введите run
и аргументы для передачи запускаемому файлу:
(gdb) run --no-daemon --verbose
После запуска выполните действия, приводящие к возникновению бага. Также можно включить логгирование происходящего командой:
(gdb) set logging file trace.log (gdb) set logging on
и затем:
(gdb) thread apply all bt full
для вывода трассировки в файл trace.log
в каталоге, в котором был запущен gdb
. Для выхода введите:
(gdb) set logging off (gdb) quit
# gdb /usr/bin/python (gdb) run <python application>
Также отладчик может подключиться к уже запущенному приложению, например:
# gdb --pid=$(pidof firefox) (gdb) continue
Для отладки уже упавшего приложения запустите gdb
на соответствующем дампе памяти.