GDB的極致運用

0. 前言
GDB(GNU Debugger)是UNIX及UNIX-like下的強大除錯工具,可以除錯ada, c, c++, asm, minimal, d, fortran, objective-c, go, java,pascal等語言。本文以C程式為例,介紹GDB啟動除錯的多種方式。
1.哪類程式可被除錯
對於C程式來說,需要在編譯時加上-g引數,保留除錯資訊,否則不能使用GDB進行除錯。
但如果不是自己編譯的程式,並不知道是否帶有-g引數,如何判斷一個檔案是否帶有除錯資訊呢?
1.1gdb 檔案
例如:
$ gdb helloworld Reading symbols from helloWorld...(no debugging symbols found)...done.
如果沒有除錯資訊,會提示: no debugging symbols found。
如果是下面的提示:
Reading symbols from helloWorld...done.
則可以進行除錯。
1.2readelf檢視段資訊
例如:
$ readelf -S helloWorld|grep debug [28] .debug_arangesPROGBITS00000000000000000000106d [29] .debug_infoPROGBITS00000000000000000000109d [30] .debug_abbrevPROGBITS00000000000000000000115b [31] .debug_linePROGBITS0000000000000000000011b9 [32] .debug_strPROGBITS0000000000000000000011fc
helloWorld為檔名,如果沒有任何debug資訊,則不能被除錯。
1.3file檢視strip狀況
下面的情況也是不可除錯的:
file helloWorld helloWorld: (省略前面內容) stripped
如果最後是stripped,則說明該檔案的符號表資訊和除錯資訊已被去除,不能使用gdb除錯。但是not stripped的情況並不能說明能夠被除錯。
2.除錯未執行程式
程式還未啟動時,可有多種方式啟動除錯。
2.1除錯啟動無參程式
例如:
$ gdb helloWorld (gdb)
輸入run命令,即可執行程式
2.2除錯啟動帶參程式
假設有以下程式,啟動時需要帶引數:
#include<stdio.h> int main(int argc,char *argv[]) { if(1 >= argc){ printf("usage:hello name\n"); return 0; } printf("Hello World %s!\n",argv[1]); return 0 ; }
編譯:
gcc -g -o hello hello.c
這種情況如何啟動除錯呢?需要設定引數:
$ gdb hello (gdb)run 程式設計珠璣 Starting program: /home/shouwang/workspaces/c/hello 程式設計珠璣 Hello World 程式設計珠璣! [Inferior 1 (process 20084) exited normally] (gdb)
只需要run的時候帶上引數即可。
或者使用set args,然後在用run啟動:
gdb hello (gdb) set args 程式設計珠璣 (gdb) run Starting program: /home/hyb/workspaces/c/hello 程式設計珠璣 Hello World 程式設計珠璣! [Inferior 1 (process 20201) exited normally] (gdb)
2.3除錯core檔案
當程式core dump時,可能會產生core檔案,它能夠很大程式幫助我們定位問題。但前提是系統沒有限制core檔案的產生。可以使用命令limit -c檢視:
$ ulimit -c 0
如果結果是0,那麼恭喜你,即便程式core dump了也不會有core檔案留下。我們需要讓core檔案能夠產生:
ulimit -c unlimied#表示不限制core檔案大小 ulimit -c 10#設定最大大小,單位為塊,一塊預設為512位元組
上面兩種方式可選其一。第一種無限制,第二種指定最大產生的大小。
除錯core檔案也很簡單:
gdb 程式檔名 core檔名
具體可參看《linux常用命令-開發除錯篇》gdb部分。
3.除錯已執行程式
如果程式已經運行了怎麼辦呢?
首先使用ps命令找到程序id:
ps -ef|grep 程序名
3.1attach方式
假設獲取到程序id為20829,則可用下面的方式除錯程序:
$ gdb (gdb) attach 20829
接下來就可以繼續你的除錯啦。
可能會有下面的錯誤提示:
Could not attach to process.If your uid matches the uid of the target process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try again as the root user.For more details, see /etc/sysctl.d/10-ptrace.conf ptrace: Operation not permitted.
解決方法,切換到root使用者:
將/etc/sysctl.d/10-ptrace.conf中的
kernel.yama.ptrace_scope = 1
修改為
kernel.yama.ptrace_scope = 0
3.2直接除錯相關id程序
還可以是用這樣的方式gdb program pid,例如:
gdb hello 20829
或者:
gdb hello --pid 20829
3.3已執行程式沒有除錯資訊
為了節省磁碟空間,已經執行的程式通常沒有除錯資訊。但如果又不能停止當前程式重新啟動除錯,那怎麼辦呢?還有辦法,那就是同樣的程式碼,再編譯出一個帶除錯資訊的版本。然後使用和前面提到的方式操作。對於attach方式,在attach之前,使用file命令即可:
$ gdb (gdb) file hello Reading symbols from hello...done. (gdb)attach 20829
總結
本文主要介紹了兩種型別的GDB啟動除錯方式,分別是除錯未執行的程式和已經執行的程式。對於什麼樣的程式能夠進行除錯也進行了簡單說明。
===========我是華麗的分割線===========
更多知識:
點選關注專題: 嵌入式Linux & ARM
或瀏覽器開啟: https://www.jianshu.com/c/42d33cadb1c1
或掃描二維碼:
