Linux應用調試 :使用gdb和gdbserver進行遠程調試


一.引言

  在日常程序開發中不免遇到類似空指針操作導致程序崩潰的問題,所以需要一定的手段去定位bug,而斷點調試是普遍使用的技巧,比如Windows中用VC++的debug模式進單步運行、斷點調試等,而且是圖形化操作界面很友好,但在Linux系統中使用的是沒有圖形界面的調試工具-GDB(聽說eclipse支持GUI調試,暫未嘗試),所以需要通過指令進行操作,下面逐步介紹gdb調試環境的搭建和使用方法。

 

二.gdb調試環境搭建

(1)下載gdb工具源碼:http://www.gnu.org/software/gdb/download/

選擇下載最新版本:

注:由於個人本地arm-linux-gcc版本較低(4.4.3)不支持 C++11,后面下載編譯的是 gdb-7.12

(2)解壓

   解壓tar.gz文件:tar -zxvf xxx.tar.gz

   解壓tar.xz文件:先 xz -d xxx.tar.xz 將 xxx.tar.xz解壓成 xxx.tar 然后,再用 tar xvf xxx.tar來解包。

(3)編譯安裝

--------①編譯gdb(在Linux主機上運行的工具)

    ./configure --target=arm-linux   //配置要調試的目標為arm-Linux開發板(前提已經配置了arm-linux-gcc交叉編譯環境)
    make
    make install //默認安裝路徑可以在Makefile中看到:prefix = /usr/local

  也可以指定安裝目錄,比如 : make install prefix=$PWD/tmp 

  環境變量添加該路徑 或 復制arm-linux-gdb到/bin目錄下后便可作為系統工具使用。

 

錯誤1:

location.c:527:19: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
       || *argp == '\0'

解決方法:  || *argp == '\0'  修改為  || *argp == NULL

 

錯誤2:

make[5]: 進入目錄“/home/sheldon/work/linux_project/gdb-8.2/gdb/doc”
/home/sheldon/work/linux_project/gdb-8.2/missing makeinfo --split-size=5000000 --split-size=5000000   -I ./../../readline/doc -I ./../mi -I . \
    -o gdb.info ./gdb.texinfo
/home/sheldon/work/linux_project/gdb-8.2/missing: 81: /home/sheldon/work/linux_project/gdb-8.2/missing: makeinfo: not found
WARNING: 'makeinfo' is missing on your system.
         You should only need it if you modified a '.texi' file, or
         any other file indirectly affecting the aspect of the manual.
         You might want to install the Texinfo package:
         <http://www.gnu.org/software/texinfo/>
         The spurious makeinfo call might also be the consequence of
         using a buggy 'make' (AIX, DU, IRIX), in which case you might
         want to install GNU make:
         <http://www.gnu.org/software/make/>
make[5]: *** [gdb.info] 錯誤 127
make[5]: 離開目錄“/home/sheldon/work/linux_project/gdb-8.2/gdb/doc”
make[4]: *** [subdir_do] 錯誤 1
make[4]: 離開目錄“/home/sheldon/work/linux_project/gdb-8.2/gdb”
make[3]: *** [install-only] 錯誤 2
make[3]: 離開目錄“/home/sheldon/work/linux_project/gdb-8.2/gdb”
make[2]: *** [install] 錯誤 2
make[2]: 離開目錄“/home/sheldon/work/linux_project/gdb-8.2/gdb”
make[1]: *** [install-gdb] 錯誤 2
make[1]: 離開目錄“/home/sheldon/work/linux_project/gdb-8.2”
make: *** [install] 錯誤 2
sheldon@sheldon-vm:~/work/linux_pro

解決方法:sudo apt-get install texinfo (或者從GNU下載源碼自行編譯安裝:http://ftp.gnu.org/gnu/texinfo/

 


--------②編譯gdbserver(在Linux開發板上作為父進程運行,啟動加了gdb調試信息的應用程序)

    cd gdb/gdbserver/   //繼續進入到gdbserver目錄
    ./configure --host=arm-linux  //配置要運行的平台為arm-Linux開發板
    make
    make install prefix=../../tmp/gdbserver //指定安裝到之前的tmp目錄下

  將編譯生成的gdbserver通過nfs或usb復制到開發板上,后面就可以開始遠程gdb調試了!

 

三.調試方法

(1)編寫測試程序:

#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;
}

  編譯生成可執行文件(-g選項增加gdb調試信息):

arm-linux-gcc test_debug.c -g -o test_debug

(2)發現在ARM板上運行test_debug后產生段錯誤,接下來就啟動gdbserver來定位問題:

gdbserver 192.168.1.17:2345 ./test_debug    //開發板通過gdbserver執行test_debug,並開啟網絡端口監聽

(3)在PC上執行

/bin/arm-linux-gdb ./test_debug  //讀取應用程序
target remote 192.168.1.17:2345  //通過開發板監聽的網絡端口傳輸控制指令

然后便可使用gdb命令來遠程控制程序運行進行調試:


示例①:main函數入口打個斷點,然后繼續運行:

  示例②:在代碼的31行處打斷點,然后繼續運行:

  示例③:進入函數A2執行C(p),然后繼續進入函數C到*p = 0x12(此時該語句還未執行),打印*p的隨機值為33620,再繼續執行賦值操作后打印值為賦值的0x12即十進制18:

 

  更詳細的使用方法可參考如下指令自行調試:

命令

命令縮寫

命令說明

list

l

顯示多行源代碼

break

b

設置斷點,程序運行到斷點的位置會停下來

info

i

描述程序的狀態

run

r

開始運行程序

display

disp

跟蹤查看某個變量,每次停下來都顯示它的值

step

s

執行下一條語句,如果該語句為函數調用,則進入函數執行其中的第一條語句

next

n

執行下一條語句,如果該語句為函數調用,不會進入函數內部執行(即不會一步步地調試函數內部語句)

print

p

打印內部變量值

continue

c

繼續程序的運行,直到遇到下一個斷點

set var name=v

 

設置變量的值

start

st

開始執行程序,main函數的第一條語句前面停下來

file

 

裝入需要調試的程序

kill

k

終止正在調試的程序

watch

 

監視變量值的變化

backtrace

bt

產看函數調用信息(堆棧)

frame

f

查看棧幀

quit

q

退出GDB環境

  

  后面運行到操縱空指針處便打印了相關異常信息,這樣就能大致定位出具體哪條語句處出現問題:

  

 

四.另一種調試方法(非單步調試):

  讓程序在開發板上直接運行,當它發生錯誤時,令它產生core dump文件,然后使用gdb根據core dump文件找到發生錯誤的地方,具體步驟如下:
  (1)在ARM板上進行如下操縱:

ulimit -c unlimited  //一般Linux系統不會產生core dump文件(默認大小0),所以需要對core文件重新設置大小
./test_debug      //程序出錯時會在當前目錄下生成名為core的文件

  如下就是產生了core文件:

 

  (2)將core文件復制到PC上進行如下操縱:

/bin/arm-linux-gdb ./test_debug ./core 

   執行后便可看到程序終止的信息並提示了具體出錯位置:

  另外也可以通過 bt 指令打印函數調用信息(堆棧) main->A->B->C,然后到第6行異常終止:

   

 

以上便是gdb調試的一般方法,更靈活的操作技巧需要多參考相關資料加以實踐~

 

-end-

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM