在Debian系統(tǒng)上,程序調試是開發(fā)和維護過程中不可或缺的一環(huán)。本篇教程主要介紹基本的 gdb 使用命令、調試 Debian 軟件包、獲得棧幀、高級 gdb 命令、檢查庫依賴性、動態(tài)調用跟蹤工具、調試與 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), 它能讓在程序執(zhí)行的時候檢查程序。
通過如下所示的命令來安裝 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系統(tǒng)中,為了節(jié)省空間并提高安全性,默認情況下安裝的二進制程序會經過strip處理,這意味著大部分調試符號(debugging symbols)在常規(guī)的軟件包中是被移除的。若要使用gdb(1)對Debian軟件包進行調試,需要安裝相應的*-dbgsym軟件包。例如,要調試coreutils程序,就需要安裝coreutils-dbgsym軟件包。這些源代碼軟件包與普通的二進制軟件包是同時生成的,并且會自動創(chuàng)建*-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” 后綴,如下所示是編譯未發(fā)行的軟件包版本產生的 “~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()”.當這個出現(xiàn)的時候,堆棧不是非常有用的。找到一些有用信息的一個簡單方法是設置環(huán)境變量 “$MALLOC_CHECK_” 的值為 2 (malloc(3)).可以通過下面的方式在運行 gdb 時設置。
$ MALLOC_CHECK_=2 gdb hello
四、高級gdb命令
高級 gdb 命令列表:
命令 | 命令用途的描述 |
---|---|
(gdb) thread apply all bt |
得到多線程程序的所有線程棧幀 |
(gdb) bt full |
查看函數(shù)調用棧中的參數(shù)信息 |
(gdb) thread apply all bt full |
和前面的選項一起得到堆棧和參數(shù) |
(gdb) thread apply all bt full 10 |
得到前10個調用的棧幀和參數(shù)信息,以此來去除不相關的輸出 |
(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 環(huán)境,以上的庫在 `chroot`ed 環(huán)境也必須是可用的。
六、調試X相關錯誤
如果一個 GNOME 程序 preview1 收到了一個 X 錯誤,您應當看見一條下面這樣的信息。
The program 'preview1' received an X Window System error.
如果就是這種情況,可以嘗試在運行程序的時候加上 “–sync” 選項,并且在 “gdk_x_error” 函數(shù)處設置中斷來獲得棧幀信息。
七、內存泄漏檢測工具
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) 可以用來交互式反匯編代碼。