調試/獲取跟蹤數據
通常,為了讓可執行文件儘可能小,會在編譯和連結時移除和運行無關的調試信息。這種可執行文件的棧回溯信息非常少,所以在調試軟體或者報告 Bug 的時候,需要安裝帶調試信息的版本,或者使用相關服務補充調試信息。這樣在報告軟體 bug 時就可以提供完整的棧回溯信息,對開發者的幫助更大。
確認軟體包[編輯 | 編輯原始碼]
首先是確認需要調試信息的軟體包名稱。
[...]
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[編輯 | 編輯原始碼]
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.
- https://geo.mirror.pkgbuild.com (GeoDNS mirror)
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
mirror.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_CFLAGS
和 DEBUG_CXXFLAGS
編譯標誌。要使用它們,請開啟debug
makepkg選項並禁用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.
/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
# gdb /usr/bin/python (gdb) run <python application>
你也可以調試一個已經運行的程序,例如:
# gdb --pid=$(pidof firefox) (gdb) continue
要調試已經崩潰的程序,請用 gdb
分析 core dump.