Debugging/Getting traces

出自 Arch Linux 中文维基

通常,為了讓可執行文件儘可能小,會在編譯和連結時移除和運行無關的調試信息。這種可執行文件的棧回溯信息非常少,所以在調試軟體或者報告 Bug 的時候,需要安裝帶調試信息的版本,或者使用相關服務補充調試信息。這樣在報告軟體 bug 時就可以提供完整的棧回溯信息,對開發者的幫助更大。

確認軟體包[編輯 | 編輯原始碼]

首先是確認需要調試信息的軟體包名稱。

使用 gdb 查看 core dump 中的調試信息 :

[...]

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[編輯 | 編輯原始碼]

For packages in the official repositories that support it [1], debug information can be retrieved directly over HTTP with debuginfod.

If one wants to retrieve the debug symbols for zstd, along with some source files, one can utilize debuginfod-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

Debuggers like gdb can download them automatically.

You can do for example:

# coredumpctl gdb

And then inside gdb

(gdb) bt full

and you will have the debug symbols of the last crashed application in your system.

Install debug packages[編輯 | 編輯原始碼]

這篇文章的某些內容需要擴充。

原因: Explain the different scenarios properly. Either you install a debug package or you let debuginfod fetch the things it needs? (在 Talk:Debugging/Getting traces 中討論)
注意: Debug packages are not archived by Arch Linux on Arch Linux Archive.

A few mirrors currently distribute debug packages in accessible repositories. These are sponsored mirrors controlled by Arch Linux and are given access to the debug repositories.

To install a package you can install it directly from the repository. For example:

# pacman -U https://geo.mirror.pkgbuild.com/core-debug/os/x86_64/zstd-debug-1.5.2-2-x86_64.pkg.tar.zst
警告: Debug packages from one mirror are not compatible with regular packages from another mirror, if both mirrors are not in sync, and thus have mismatching builds. In this case, avoid mixing packages from different mirrors (this would result in a partial upgrade), but point all repositories to the debug mirror.

本文或本章節可能需要合併到Official repositories

附註: Official repositories have a dedicated page.(在 Talk:Debugging/Getting traces 中討論)

Another option is to add the repositories to your pacman configuration.

/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

Place a mirror with debug packages as the first one in the mirrorlist file:

/etc/pacman.d/mirrorlist
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch
...

重新編譯軟體包[編輯 | 編輯原始碼]

如果軟體包沒有被 debuginfod 支持,比如 AUR 中的軟體包,可以通過源碼重新編譯獲取調試信息。官方軟體倉庫中的軟體包請參考ABS, AUR 中的軟體參考 AUR#Acquire build files

To set the required #Compilation options, you can modify the makepkg configuration if you will only use makepkg for debug purposes. In other cases, you should modify package's PKGBUILD file only for each package you would like to rebuild.

編譯設置[編輯 | 編輯原始碼]

Pacman 從 4.1 開始,會使用 etc/makepkg.conf 中的 DEBUG_CFLAGSDEBUG_CXXFLAGS 編譯標誌。要使用它們,請開啟debugmakepkg選項並禁用strip。這兩個選項會強制編譯調試信息並在連結成可執行文件時保留這些信息。

/etc/makepkg.conf
OPTIONS+=(debug !strip)

要修改單個軟體包設定, 修改 PKGBUILD:

PKGBUILD
options=(debug !strip)

Alternatively you can put the debug information in a separate package by enabling both debug and strip, debug symbols will then be stripped from the main package and placed, together with source files to aid in stepping through the debugger, in a separate pkgbase-debug package. This is advantageous if the package contains very large binaries (e.g. over a GB with debug symbols included) as it might cause freezing and other strange, unwanted behavior occurring.

注意: It is insufficient to simply install the newly compiled debug package, because the debugger will check that the file containing the debug symbols is from the same build as the associated library and executable. You must install both of the recompiled packages. In Arch, the debug symbol files are installed under /usr/lib/debug/, and source files are installed under /usr/src/debug. See the GDB documentation for more information about debug packages.

glibc[編輯 | 編輯原始碼]

Certain packages such as glibc are stripped regardless. Check the PKGBUILD for sections such as:

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

And remove them where appropriate.

Clang[編輯 | 編輯原始碼]

Packages using Clang as the compiler will not build with the debug option due to the debug flag -fvar-tracking-assignments' not being handled (e.g. js78).

Add the following at the top of the build() function to only remove the flag for the affected package:

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

構建和安裝軟體包[編輯 | 編輯原始碼]

當在PKGBUILD的文件夾中使用makepkg,這可能花費些時間:

$ makepkg

然後安裝這個軟體包:

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

獲得回溯[編輯 | 編輯原始碼]

真正的回溯 (或堆棧回溯)現在可以通過例如GNU調試器gdb來獲得。 通過以下任一命令運行它:

# gdb /path/to/file

或:

# gdb
(gdb) exec /path/to/file

如果已經在$PATH變量中設定過了,路徑可以省略

然後在gdb中,鍵入run連同以下任何你想要程序運行時的參數,例如:

(gdb) run --no-daemon --verbose

開始執行這個文件,復現要追蹤的 bug。對於實際日誌,鍵入以下行:

(gdb) set logging file trace.log
(gdb) set logging enabled on

然後:

(gdb) thread apply all bt full

然後輸出回溯到在gdb運行的目錄中trace.log。退出時,鍵入:

(gdb) set logging enabled off
(gdb) quit
提示: 調試python寫成的應用時:
# gdb /usr/bin/python
(gdb) run <python application>

你也可以調試一個已經運行的程序,例如:

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

要調試已經崩潰的程序,請用 gdb 分析 core dump.

參見[編輯 | 編輯原始碼]