Debian调试教程
在Debian系统上,程序调试是开发和维护过程中不可或缺的一环。本篇教程主要介绍基本的 gdb 使用命令、调试 Debian 软件包、获得栈帧、高级 gdb 命令、检查库依赖性、动态调用跟踪工具、调试与 X 相关的错误、内存泄漏检测工具和反汇编二进制程序。
调试软件包列表:
软件包 | 流行度 | 大小 | 文档 |
---|---|---|---|
gdb | V:14, I:96 | 11637 | 由 gdb-doc 包提供的“info gdb ” |
ddd | V:0, I:7 | 4105 | 由 ddd-doc 包提供的“info ddd ” |
一、gdb命令
Debian 上原始的调试器是 gdb(1), 它能让在程序执行的时候检查程序。
通过如下所示的命令来安装 gdb 及其相关程序。
下面例子用 gdb(1) 在”程序”带有 “-g” 选项编译的时候来产生调试信息。
二、调试Debian软件包
在Debian系统中,为了节省空间并提高安全性,默认情况下安装的二进制程序会经过strip处理,这意味着大部分调试符号(debugging symbols)在常规的软件包中是被移除的。若要使用gdb(1)对Debian软件包进行调试,需要安装相应的*-dbgsym软件包。例如,要调试coreutils程序,就需要安装coreutils-dbgsym软件包。这些源代码软件包与普通的二进制软件包是同时生成的,并且会自动创建*-dbgsym软件包。这些专门的调试软件包被单独存放在debian-debug存档库中。
如果一个需要被调试的软件包没有提供其 *-dbgsym 软件包,需要按如下所示的从源代码中重构并且安装它:
按需修改bug即可。
软件包调试版本跟它的官方 Debian 版本不冲突,例如当重新编译已存在的软件包版本产生的 “+debug1” 后缀,如下所示是编译未发行的软件包版本产生的 “~pre1” 后缀。
如下所示编译并安装带有调试符号的软件包:
需要检查软件包的构建脚本并确保编译二进制的时候使用了 “CFLAGS=-g -Wall” 选项。
三、获得栈帧
当碰到程序崩溃的时候,报告 bug 时附上栈帧信息是个不错的注意。
使用如下方案之一,可以通过 gdb(1) 取得栈帧信息:
1、在 GDB 中崩溃的方案:
从 GDB 运行程序;
崩溃程序;
在 GDB 提示符输入 “bt”。
2、奔溃的方案:
更新“/etc/security/limits.conf”文件,包括下面内容:
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 时设置。
四、高级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) 来找出程序的库依赖性:
因为 ls(1) 运行在 `chroot`ed 环境,以上的库在 `chroot`ed 环境也必须是可用的。
六、调试X相关错误
如果一个 GNOME 程序 preview1 收到了一个 X 错误,您应当看见一条下面这样的信息。
如果就是这种情况,可以尝试在运行程序的时候加上 “–sync” 选项,并且在 “gdk_x_error” 函数处设置中断来获得栈帧信息。
七、内存泄漏检测工具
Debian 上有一些可用的内存泄漏检测工具。
内存泄漏检测工具的列表:
软件包 | 流行度 | 大小 | 说明 |
libc6-dev | V:259, I:569 | 12051 | mtrace(1):调试 glibc 中的 malloc |
valgrind | V:5, I:36 | 78191 | 内存调试器和分析器 |
electric-fence | V:0, I:3 | 73 | malloc(e) 调试器 |
libdmalloc5 | V:0, I:2 | 390 | 内存分配库调试 |
duma | V:0, I:0 | 296 | 在 C 和 C++ 程序中检测缓存溢出和缓存欠载( buffer under-runs )的库 |
leaktracer | V:0, I:1 | 56 | C++ 程序内存泄露跟踪器 |
八、反汇编二进制程序
可以使用下面的方式通过 objdump(1) 反编译二进制代码。
注意:gdb(1) 可以用来交互式反汇编代码。