Debugging (Русский)/Getting traces (Русский)

From ArchWiki
Состояние перевода: На этой странице представлен перевод статьи Debugging/Getting traces. Дата последней синхронизации: 19 мая 2023. Вы можете помочь синхронизировать перевод, если в английской версии произошли изменения.

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

Введение

Обычно исполняемые файлы очищаются (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) показывают, что необходимая отладочная информация, такая, как названия функций, файлов, библиотек, отсутствует в отлаживаемом файле.

Есть несколько способов получения отладочной информации, каждый из которых описан в соответствующем разделе: #Debuginfod, #Установка отладочных пакетов, #Пересборка пакетов.

Debuginfod

Для пакетов из официальных репозиториев, которые это поддерживают (смотрите https://debuginfod.archlinux.org/packages), можно скачать отладочную информацию с помощью debuginfod.

gdb автоматически скачивает её, если задана переменная окружения DEBUGINFOD_URLS. Она задаётся автоматически с помощью файла в /etc/profile.d/.

$ gdb приложение
This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.archlinux.org>
Enable debuginfod for this session? (y or [n]) y
Debuginfod has been enabled.
To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit.
Downloading separate debug info for /usr/bin/приложение
Reading symbols from /home/user/.cache/debuginfod_client/fbaee841e2ed2c11ecbbda26f39eeec1da23d6c3/debuginfo...

После включения поддержки debuginfo можно сразу переходить к разделу #Получение трассировки.

Скачивание вручную

Например, чтобы скачать отладочные символы для пакета 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

Получение отладочной информации вручную

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

[...]
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)
[...]

Проверить, какому пакету принадлежат упомянутые в тексте исполняемые файлы или библиотеки, можно, например, с помощью pacman:

$ pacman -Qo /lib/libthread_db.so.1
/lib/libthread_db.so.1 принадлежит glibc 2.5-8

Пакет glibc версии 2.5-8. Повторите это для каждого упомянутого файла, чтобы собрать список пакетов, которым нужна отладочная информация.

Установка отладочных пакетов

Примечание: Arch Linux Archive не хранит отладочные пакеты.

В настоящее время несколько зеркал распространяют отладочные пакеты в доступных репозиториях. Это спонсируемые зеркала, контролируемые Arch Linux, которым предоставляется доступ к отладочным репозиториям.

Можно установить пакет напрямую из репозитория. Например:

# pacman -U https://geo.mirror.pkgbuild.com/core-debug/os/x86_64/zstd-debug-1.5.2-2-x86_64.pkg.tar.zst
Важно: Отладочные пакеты с одного зеркала несовместимы с обычными пакетами с другого зеркала, если оба зеркала не синхронизированы и оттого имеют несовпадающие сборки. В этом случае избегайте смешивания пакетов с разных зеркал (что приведёт к частичному обновлению), а перенастройте все репозитории на одно debug-зеркало.

Другой вариант — добавить репозитории в конфигурацию pacman.

/etc/pacman.conf
# Testing Repositories

[core-testing-debug]
Include = /etc/pacman.d/mirrorlist

[extra-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

[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. Это может пригодиться, если пакет содержит очень большие бинарные файлы (например, больше гигабайта с включенными отладочными символами), так как они могут привести к зависаниям и другому странному поведению.

Примечание: Недостаточно просто установить новый собранный отладочный пакет, поскольку отладчик проверит, что отладочные файлы относятся к той же сборке, что и связанные с ним библиотека и исполняемый файл. Нужно установить оба собранных пакета. В Arch отладочные файлы устанавливаются в /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[ссылка недействительна: package not found]).

Добавьте следующее в начало функции build() нужного пакета:

build() {
  CFLAGS=${CFLAGS/-fvar-tracking-assignments}
  CXXFLAGS=${CXXFLAGS/-fvar-tracking-assignments}
[...]
LTO

При использовании link-time optimization (LTO) как во время компиляции, так и в отладчике будет использоваться больше памяти[1][2]. Если приложение большое, такое как Firefox или Qt, памяти может не хватить. В этом случае собирайте приложение без LTO.

Все пакеты в официальных репозиториях обычно собираются с LTO.

Сборка и установка пакета

Соберите пакет командой makepkg, находясь в одном каталоге с файлом PKGBUILD. Это может занять некоторое время:

$ makepkg

Установка собранного пакета:

# pacman -U glibc-2.26-1-x86_64.pkg.tar.gz

Получение трассировки

Теперь можно получить backtrace (трассировку стека), например, с помощью gdb (GNU Debugger). Запуск осуществляется так:

# gdb /путь/к/файлу
Совет: gdb использует переменную окружения $PATH, так что указывать полный путь к исполняемому файлу обычно не требуется.

Затем в gdb введите run и аргументы для передачи запускаемому файлу:

(gdb) run аргументы

После запуска выполните действия, приводящие к возникновению бага. Когда приложение упадёт, gdb автоматически прекратит его выполнение и отобразит приглашение для ввода команд. Если программа зависает, можно нажать Ctrl+c для перехода к вводу команд.

Можно включить логирование происходящего командой:

(gdb) set logging enabled on
Совет: По умолчанию лог пишется в файл с именем gdb.txt. Задать другое имя можно командой:
(gdb) set logging file trace.log

и, наконец, записать трассировку в файл trace.log в текущем рабочем каталоге:

(gdb) thread apply all backtrace full
Совет: Для отладки Python-приложения:
# gdb /usr/bin/python
(gdb) run python-приложение

Также отладчик может подключиться к уже запущенному приложению:

# gdb --pid=$(pidof firefox)
(gdb) continue

Для отладки уже упавшего приложения запустите gdb на соответствующем дампе памяти.

Смотрите также