当前位置:首页 > 站长知识 > 正文内容

Debian调试教程

2024-08-27站长知识25

在Debian系统上,程序调试是开发和维护过程中不可或缺的一环。本篇教程主要介绍基本的 gdb 使用命令、调试 Debian 软件包、获得栈帧、高级 gdb 命令、检查库依赖性、动态调用跟踪工具、调试与 X 相关的错误、内存泄漏检测工具和反汇编二进制程序。

调试软件包列表:

软件包流行度大小文档
gdbV:14, I:9611637由 gdb-doc 包提供的“info gdb
dddV:0, I:74105由 ddd-doc 包提供的“info ddd

一、gdb命令

Debian 上原始的调试器是 gdb(1), 它能让在程序执行的时候检查程序。

通过如下所示的命令来安装 gdb 及其相关程序。

# apt-get install gdb gdb-doc build-essential devscripts

下面例子用 gdb(1) 在”程序”带有 “-g” 选项编译的时候来产生调试信息。

$ gdb program
(gdb) b 1 # set break point at line 1
(gdb) run args # run program with args
(gdb) next # next line
...
(gdb) step # step forward
...
(gdb) p parm # print parm
...
(gdb) p parm=12 # set value to 12
...
(gdb) quit

二、调试Debian软件包

在Debian系统中,为了节省空间并提高安全性,默认情况下安装的二进制程序会经过strip处理,这意味着大部分调试符号(debugging symbols)在常规的软件包中是被移除的。若要使用gdb(1)对Debian软件包进行调试,需要安装相应的*-dbgsym软件包。例如,要调试coreutils程序,就需要安装coreutils-dbgsym软件包。这些源代码软件包与普通的二进制软件包是同时生成的,并且会自动创建*-dbgsym软件包。这些专门的调试软件包被单独存放在debian-debug存档库中。

如果一个需要被调试的软件包没有提供其 *-dbgsym 软件包,需要按如下所示的从源代码中重构并且安装它:

$ mkdir /path/new ; cd /path/new
$ sudo apt-get update
$ sudo apt-get dist-upgrade
$ sudo apt-get install fakeroot devscripts build-essential
$ apt-get source package_name
$ cd package_name*
$ sudo apt-get build-dep ./

按需修改bug即可。

软件包调试版本跟它的官方 Debian 版本不冲突,例如当重新编译已存在的软件包版本产生的 “+debug1” 后缀,如下所示是编译未发行的软件包版本产生的 “~pre1” 后缀。

$ dch -i

如下所示编译并安装带有调试符号的软件包:

$ export DEB_BUILD_OPTIONS="nostrip noopt"
$ debuild
$ cd ..
$ sudo debi package_name*.changes

需要检查软件包的构建脚本并确保编译二进制的时候使用了 “CFLAGS=-g -Wall” 选项。

三、获得栈帧

当碰到程序崩溃的时候,报告 bug 时附上栈帧信息是个不错的注意。

使用如下方案之一,可以通过 gdb(1) 取得栈帧信息:

1、在 GDB 中崩溃的方案:

  • 从 GDB 运行程序;

  • 崩溃程序;

  • 在 GDB 提示符输入 “bt”。

2、奔溃的方案:

  • 更新“/etc/security/limits.conf”文件,包括下面内容:

* soft core unlimited
  • shell 提示符下输入 “ulimit -c unlimited”;

  • 从这个 shell 提示符运行程序;

  • 崩溃的程序产生一个 core dump 文件;

  • 加载 core dump 文件到 GDB,用 “gdb gdb ./program_binary core” ;

  • 在 GDB 提示符输入 “bt”。

注意:如果看到堆栈顶部有一行或者多行有 “malloc()” 或 “g_malloc()”.当这个出现的时候,堆栈不是非常有用的。找到一些有用信息的一个简单方法是设置环境变量 “$MALLOC_CHECK_” 的值为 2 (malloc(3)).可以通过下面的方式在运行 gdb 时设置。

$ MALLOC_CHECK_=2 gdb hello

四、高级gdb命令

高级 gdb 命令列表:

命令命令用途的描述
(gdb) thread apply all bt得到多线程程序的所有线程栈帧
(gdb) bt full查看函数调用栈中的参数信息
(gdb) thread apply all bt full和前面的选项一起得到堆栈和参数
(gdb) thread apply all bt full 10得到前10个调用的栈帧和参数信息,以此来去除不相关的输出
(gdb) set logging on把 gdb 的日志输出到文件 (默认的是 “gdb.txt“)

五、检查库依赖性

按如下所示使用 ldd(1) 来找出程序的库依赖性:

$ ldd /usr/bin/ls
librt.so.1 => /lib/librt.so.1 (0x4001e000)
libc.so.6 => /lib/libc.so.6 (0x40030000)
libpthread.so.0 => /lib/libpthread.so.0 (0x40153000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

因为 ls(1) 运行在 `chroot`ed 环境,以上的库在 `chroot`ed 环境也必须是可用的。

六、调试X相关错误

如果一个 GNOME 程序 preview1 收到了一个 X 错误,您应当看见一条下面这样的信息。

The program 'preview1' received an X Window System error.

如果就是这种情况,可以尝试在运行程序的时候加上 “–sync” 选项,并且在 “gdk_x_error” 函数处设置中断来获得栈帧信息。

七、内存泄漏检测工具

Debian 上有一些可用的内存泄漏检测工具。

内存泄漏检测工具的列表:

软件包流行度大小说明
libc6-devV:259, I:56912051mtrace(1):调试 glibc 中的 malloc
valgrindV:5, I:3678191内存调试器和分析器
electric-fenceV:0, I:373malloc(e) 调试器
libdmalloc5V:0, I:2390内存分配库调试
dumaV:0, I:0296在 C 和 C++ 程序中检测缓存溢出和缓存欠载( buffer under-runs )的库
leaktracerV:0, I:156C++ 程序内存泄露跟踪器

八、反汇编二进制程序

可以使用下面的方式通过 objdump(1) 反编译二进制代码。

$ objdump -m i386 -b binary -D /usr/lib/grub/x86_64-pc/stage1

注意:gdb(1) 可以用来交互式反汇编代码。