1.gdb和gdbserver調試原理 通過linux虛擬機里的gdb,來向開發板里的gdbserver發送命令,比如設置斷點,運行setp等,然後開發板上的gdbserver收到命令後,便會執行應用程式做相應的動作,來實現調試的功能 和之前學的裸板GDB調試 一樣,只不過之前學的是在win下的,本 ...
1.gdb和gdbserver調試原理
通過linux虛擬機里的gdb,來向開發板里的gdbserver發送命令,比如設置斷點,運行setp等,然後開發板上的gdbserver收到命令後,便會執行應用程式做相應的動作,來實現調試的功能
和之前學的裸板GDB調試 一樣,只不過之前學的是在win下的,本次是在linux里的gdb
1.1同樣,它們都會需要一個帶調試信息的編譯文件.
通過Makefile里的arm-linux-gcc -g 來的, -g:表示編譯文件里包含gdb調試信息
1.2為什麼需要調試信息的編譯文件?
比如讀開發板的應用程式里的變數a:
首先gdb通過應用程式的帶調試信息的編譯文件,來找出變數a存的地址位置
然後將地址發送給開發板里的gdbserver,來讀出a地址的值
2.安裝gdb和gdbserver
首先進入官網下載gdb-7.4: http://ftp.gnu.org/gnu/gdb/
2.1在虛擬機上安裝GDB:
# tar xjf gdb-7.4.tar.bz2 //解壓
# cd gdb-7.4/ //進入gdb-7.4目錄
#./configure --target=arm-linux
//GDB需要在pc本機里運行,並調試開發板里的應用程式,所以--target設為arm-linux
#make //編譯
#mkdir tmp
#make install prefix=$PWD/tmp //安裝到./tmp目錄下
sudo cp tmp/bin/arm-linux-gdb /bin/ //複製到/bin目錄下
/bin/arm-linux-gdb -v //-v: 確定一下gdb的版本VID,是否是7.4
2.2 在開發板上安裝GDBServer:
cd gdb/gdbserver/ //在gdb-7.4目錄下輸入
./configure --target=arm-linux --host=arm-linux //設GDBServer的工作環境
make //編譯
出現以下錯誤:
指在linux-arm-low.c里,沒有找到PTRACE_GETSIGINFO 定義
2.3 解決:
1)
#echo $PATH //來查看PATH環境變數
找到編譯器gcc位於/work/tools/gcc-3.4.5-glibc-2.3.6/bin
2)
#cd /work/tools/gcc-3.4.5-glibc-2.3.6/
# grep "PTRACE_GETSIGINFO" * -nR
在gcc根目錄下,搜索到在linux/ptrace.h中定義:
3)
#vi linux-arm-low.c
添加: #define PTRACE_GETSIGINFO 0x4202
4)最後重新make,生成gdbserver命令文件
然後將gdbserver命令文件,放入我們開發板的根目錄/bin中,便能使用了
cp gdbserver /nfs_root/bin/ //nfs_root:開發板的nfs系統根目錄
3.測試程式如下(test_debug.c)
#include <stdio.h>
void C(int *p)
{
*p = 0x12;
}
void B(int *p)
{
C(p);
}
void A(int *p)
{
B(p);
}
void A2(int *p)
{
C(p);
}
int main(int argc, char **argv)
{
int a;
int *p = NULL;
A2(&a); // A2 > C
printf("a = 0x%x\n", a);
A(p); // A > B > C
return 0;
}
其中A2(&a)會調用A2()->C(),然後將a賦值為0x12.
A(p)會調用A()->B()->C(),由於p是個空指針,這裡將會出錯.
接下來,我們便以這個應用程式為例.
4.編譯
#arm-linux-gcc -g -o test_debug test_debug.c //-g:附帶調試信息
5.調試test_debug.c
在開發板上:
首先,需要讓gdbserver建立本地伺服器,以及要測試的哪個文件:
#gdbserver 192.168.2.107:2345 ./test_debug
//192.168.2.107:本地IP地址
//2345:埠號,用來讓gdb來連接用的
//./test_debug:要測試的哪個文件
在虛擬機上:
#/bin/arm-linux-gdb ./test_debug // 啟動gdb,指定調試文件為test_debug
#target remote 192.168.2.107:2345 //與gdbserver建立連接
5.1連接成功,便使用gdb命令來調試
常用命令如下所示(參考http://blog.sciencenet.cn/blog-619295-813770.html):
l
列出所有源代碼
break [file]:[row]
打斷點,比如:
break test_debug.c:21 //在test_debug.c文件的第21行處打斷點
info br
查看斷點
info file
列出當前的文件,共用庫。
delete <num>
刪除第幾個斷點,如下圖所示:
c
啟動程式運行
step
單步執行
next
單步執行,和step不同的是,比如:當前行里有函數調用時,next直接執行下一句,step會進入函數
print a
列印a變數的值
quit
退出gdb
6.也可以通過gdb+coredump來調試test_debug.c
當程式運行出錯時,便會生成core文件,並將程式里的運行狀況存到core中,也就是coredump,供給gdb來調試
6.1首先,通過ulimit來查看coredump的資源大小
ulimit命令(user limit),主要用來限制用戶的各個進程資源.
在開發板里,輸入
如上圖所示,可以看到coredump的資源大小為0,也就是說,當程式運行出錯時,不會生成core文件
6.2設置core文件
設置core文件的資源大小為無限制,輸入:
ulimit -c unlimited //-c:對應coredump
6.3生成core文件
執行:
#./test_debug
出現段錯誤,並生成core文件,如下圖所示:
6.4 進入虛擬機
將core拷貝過來,然後執行:
#/bin/arm-linux-gdb ./test_debug ./core
然後輸入bt,便可查看調用關係: