在嵌入式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的行為)以外,只有當前線程會執行。