Debugging/Getting traces

来自 Arch Linux 中文维基
(重定向自Debug - Getting Traces

通常,为了让可执行文件尽可能小,会在编译和链接时移除和运行无关的调试信息。这种可执行文件的栈回溯信息非常少,所以在调试软件或者报告 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.

参见[编辑 | 编辑源代码]