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

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

Ссылки по теме

- Устранение часто встречающихся неполадок
- Указания по созданию отчета об ошибке
- Debuginfod (Русский)
- Дамп памяти

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

## Введение

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

- 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

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

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

- Debian:HowToGetABacktrace
- Gentoo:Project:Quality Assurance/Backtraces
- Fedora:StackTraces
- GNOME - Getting Stack Traces
- gdb mini intro

Category:

- Package development (Русский)

Hidden category:

- Pages with broken package links