在嵌入式linux平臺使用gdb除錯進行遠端除錯需要安裝gdbserver,gdbserver工作在目標板上,通過串列埠或者網線與主機上的gdb互聯實現遠端除錯。
Gdbserver需要根據不同的嵌入式平臺來編譯生成,首先到http://ftp.gnu.org/gnu/gdb/下載合適的版本。然後在本地進行編譯。在Unbuntu下編譯gdb需要安裝ncurses 庫,在redhat上通過yum install “Development tools” 安裝依賴就可以了。
首先編譯主機端gdb,編譯過程如下:
解壓原始碼包:
$> tar xzvf gdb 7.3.1.tar.gz
進入目錄:
$>cd gdb-7.3.1
生成makefile檔案:
$>./configure --target=arm-linux --prefix=/mygdb7.3.1
或者,如果是mips平臺
$>./configure --target=mips-linux --prefix=/mygdb7.3.1
$> make
$> make install
執行結束之後你就會在mygdb7.3.1資料夾下bin目錄找到arm-linux-gdb 或者 mips-linux-gdb 可執行檔案。
注意:執行 configure 步驟的時候目錄一定要選對,否則編譯會失敗,各種找到不到依賴!
此外,由於這是生成在Linux主機上除錯的可執行檔案,因此不必使用交叉編譯環境,換句話說在編譯生成gdbserver的時候需要使用交叉編譯器。
接下來編譯執行在目標板上的gdbserver。
首先進入gdbserver目錄(在gdb7.3.1目錄中):
$>cd gdb gdbserver
生成makefile檔案,這一步需要指定交叉編譯器的位置,假設你交叉編譯的位置在xx/yy目錄下:
$>CC=xx/yy/arm-linux-gcc ./configure --target=arm-linux --host=arm-linux
生成gdbserver
$> make
這裡沒有指定—prefix引數,因此生成的gdbserver就位於 gdb7.3.1/gdb/gdbserver目錄下。
現在可以將gdbserver移植到目標板中了,方法有很多,就看你的環境了,可以使用nfs,可以使用tftp等工具。
進行除錯:
假設我們使用交叉編譯器產生了一個helloworld可執行程式,在目標板上執行:
$> gdbserver 192.168.1.100:2345 helloworld
其中 192.168.1.100 是除錯主機的地址,2345是除錯埠,helloword是需要除錯的可執行程式。
隨後在主機上執行:
$> gdb helloworld
$> target remote 192.168.1.10:2345
其中 192.168.1.10 是目標板的地址,2345是gdbserver開啟的用於建立除錯連線的埠。
可能遇到的問題:
- 在除錯實際模組的時候,設定了斷點一執行就表現出各種找不到動態連線庫(.so)
可以這樣設定:set solib-search-path PATH
通過上面設定告訴gdb所以來的動態庫在那裡,其中PATH是被除錯可執行程式所需的動態庫的位置,多個不同路徑可以使用“:”來隔開,這些路徑一般都是你價差編譯工具鏈的位置。
2. 在除錯多執行緒程式的時候目標板出現“gdb: error initializing thread_db library”“Child terminated with signal 5”
出現這個問題的原因有很多,有可能是你目標板上沒有thread_db 庫,但是也有可能是你使用的gdb版本過低不支援多執行緒除錯(注意gdb7.0以下就不支援! 我當時一味的追求生成的檔案小就使用gdb6.3 這個問題一直沒有找到原因,折騰了一陣,最好也不要使用strip裁剪生成的可執行檔案)。
3. 編譯gdb失敗:提示在linux-low.c中“siginfo isn’t known”
進入到linux-low.c 中,找到相應函式(大概有兩個函式),將 struct siginfo 全部換成為 siginfo_t。
4. 多執行緒除錯可以設定 set follow-fork-mode child/parent
表示在多執行緒中產生新執行緒的時候gdb進入到子執行緒還是父執行緒。
Gdb多執行緒除錯常用命令:
http://coolshell.cn/articles/3643.html
多執行緒除錯可能是問得最多的。其實,重要就是下面幾個命令:
- info thread 檢視當前程式的執行緒。
- thread <ID> 切換除錯的執行緒為指定ID的執行緒。
- break file.c:100 thread all 在file.c檔案第100行處為所有經過這裡的執行緒設定斷點。
- set scheduler-locking off|on|step,這個是問得最多的。在使用step或者continue命令除錯當前被除錯執行緒的時候,其他執行緒也是同時執行的,怎麼只讓被除錯程式執行呢?通過這個命令就可以實現這個需求。
- off 不鎖定任何執行緒,也就是所有執行緒都執行,這是預設值。
- on 只有當前被除錯程式會執行。
- step 在單步的時候,除了next過一個函式的情況(熟悉情況的人可能知道,這其實是一個設定斷點然後continue的行為)以外,只有當前執行緒會執行。