Debian调试

2024-02-06 64

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 及其相关程序。

# 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-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) 反编译二进制代码。

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

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

  • 广告合作

  • QQ群号:707632017

温馨提示:
1、本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。邮箱:2942802716#qq.com(#改为@)。 2、本站原创内容未经允许不得转裁,转载请注明出处“站长百科”和原文地址。