建立ARM平臺上的交叉調試器gdb和gdbserver

 

建立ARM平臺上的交叉調試器gdb和gdbserver(轉)  

注:這是安裝gdb6.6 的,gdb的交叉調試和命令可以借鑑下。

gdb-6.6使用了autoconf/automake,因此通過設置configure腳本的--target,--host,--prefix參數就可以方便的移植到別的平臺。--target指定編譯後的文件針對的是什麼目標

板,一般設置爲交叉編譯器的前綴,比如--target=arm-linux, --target=mips-linux,--target=armv5-linux-uclibc, --target的缺省值爲i386-linux, 也就是PC機。 --host指

定編譯後的文件的運行環境,取值可以是i386-linux或者交叉編譯器的前綴,缺省爲i386-linux,--prefix指定要安裝的目錄。

1.到http://www.gnu.org/software/gdb下載gdb-6.6.tar.gz到/tmp解壓到/opt下
   #cd /opt
   #tar xzvf /tmp/gdb-6.6.tar.gz
  
2、建立配置文件、編譯
   gdb允許把編譯配置和編譯結果放到任意的目錄,因此可以在gdb目錄之外建立一個專門放編譯文件的目錄。
   #cd /opt
   #mkdir -p arm-gdb/build
   #cd arm-gdb/build

   #/opt/gdb-6.6/configure --host=i386-linux --target=armv5-linux-uclibc --prefix=/opt/arm-gdb
   #make
   #make install
其中:host指定了運行環境爲i386機器,target指定了需要調試的目標機環境(我使用的ARM toolchain是armv5-linux-uclibc-gcc,因此這樣指定,如果是用arm-linux-gcc,則

--target=arm-linux),prefix指定了編譯後的結果存放的位置,也就是安裝目錄。
   如果在編譯arm-linux-low.c這個文件時提示找不到“sys/reg.h”, 則修改arm-linux-low.c,註釋掉#include "sys/reg.h"。

    可以在/opt/arm-gdb/bin下找到可執行的armv5-linux-uclibc-gdb, armv5-linux-uclibc-gdbtui, armv5-linux-uclibc-run。

3、gdbserver的移植
   gdbserver要用到gdb源碼目錄下的一些頭文件,因此無法在gdb源碼目錄之外建立編譯文件。

   #cd /opt/gdb-6.6/gdb/gdbserver
   #vi build.arm        
   內容如下:
      ./configure --target=armv5-linux-uclibc --host=armv5-linux-uclibc --prefix=/opt/arm-gdb/gdbserver
      make
      make install
   #chmod +x build.arm
   #./build.arm

   注意:此處target參數和host參數都要設置爲armv5-linux-uclibc,因爲gdbserver是放在目標板上運行的。
   編譯後,可以在/opt/arm-gdb/gdbserver/bin下找到armv5-linux-uclibc-gdbserver,下載該文件到目標板並重命名爲gdbserver,
   同時要下載gdbserver需要的庫文件libthread_db-x.x.x.so,再建立兩個符號鏈接libthread_db.so和libthread_db.so.1。
  
  
4、使用gdbserver
   在目標板上運行gdbserver
   #./gdbserver 192.168.0.2:2345 hello

   其中192.168.0.2爲目標板的IP,可以寫localhost,也可以不寫。2345爲gdbserver打開的端口,可以自己設置。
   #./gdbserver :2345 hello

   在宿主機上運行
   #armv5-linux-uclibc-gdb hello
   (gdb)target remote 192.168.0.2:2345
   (gdb)b main
   (gdb)continue

   使用X-Windows下的DDD
   #ddd --debugger armv5-linux-uclibc-gdb

   在DDD的GDB終端控制窗口中健入:
   (gdb) target 192.168.0.2:2345

6、問題
   移植的gdbserver可以和Host上的mips-linux-gdb連接上,但是run的時候gdbserver出現
   Killing inferior錯誤
   解決方法:因爲執行完target命令後,目標板程序已經在運行,所有應該用continue命令而不是run命令。


7、附1:GDB的基本指令:

   load:裝入一個程序
   symbol-file:裝入符號庫文件,可以是用-g參數編譯的可執行文件。
   f(ile):指定一個可執行文件進行調試,gdb將讀取些文件的調試訊息,如f a.exe
   l(ist):列程序出源文件
   r(un) :裝載完要調試的可執行文件後,可以用run命令運行可執行文件
   b(reak):設置斷點(break point),如b 25,則在源程序的第25行設置一個斷點,當程序執行到第25行時,就會產生中斷;也可以使用b funcname,funcname爲函數的名稱,

當程序調用些函數時,則產生中斷
   c(ontinue):c命令可以另中斷的程序繼續執行,直到下一個中斷點或程序結束
   p(rint):輸入某個變量的值,如程序定義了一個int aa的就是,p aa就會輸出aa的當前值
   n(ext):程序執行到斷點時中斷執行,可以用n指令進行單步執行
   s(tep):程序執行到斷點時中斷執行,可以用s指令進行單步執行進某一函數
   q(uit):退出GDB

8、附2:調試驅動程序和共享庫

(1)調試LKM(Loadable Kernel Module)
.在目標板上插入模塊並輸出map信息,查看.text入口地址:
   #insmod -m hello.ko > map
   #grep .text map
             比如爲0xc68c0060
.在gdb中轉入LKM的調試信息:
   (gdb) add-symbol-file hello.ko 0xc68c0060 /*注意必須是LKM .text的入口地址)
.正常調試

(2)調試共享庫
    .樣例程序:
    test.c:
    #include <stdio.h>
    int test(int a, int b)
    {
    int s = a b;
    printf("%d\n", s);
    return s;
    }

    main.c:
    #include <stdio.h>
    extern int test(int a, int b);
    int main(int argc, char* argv[])
    {
    int s = test(10, 20);
    return s;
    }

    Makefile:
    all: so main
    so:
    armv5-linux-uclibc-gcc -g test.c -shared -o libtest.so
    main:
    armv5-linux-uclibc-gcc -g main.c -L./ -ltest -o test.exe
    clean:
    rm -f *.exe *.so
   
    .編譯並設置環境變量
#make

        在目標板上:
#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
#gdbserver localhost:2345 ./test.exe

    .運行gdb客戶端
#armv5-linux-uclibc-gdb
(gdb)symbol-file test.exe
(gdb)target remote 192.168.0.2:2345
(gdb)b main
(gdb)c

    .查看libtest.so的代碼在內存中的位置。
     (從gdbserver的輸出或者用ps可以得到test.exe的進程ID,這裏假設PID是11547)
     在目標板上:
     #cat /proc/11547/maps
輸出:

.........
0076a000-0076c000 rwxp 0076a000 00:00 0
00bbe000-00bbf000 r-xp 00bbe000 00:00 0
00fcc000-00fcd000 r-xp 00000000 03:01 1238761 /root/test/gdbservertest/libtest.so
00fcd000-00fce000 rwxp 00000000 03:01 1238761 /root/test/gdbservertest/libtest.so
08048000-08049000 r-xp 00000000 03:01 1238765 /root/test/gdbservertest/test.exe
08049000-0804a000 rw-p 00000000 03:01 1238765 /root/test/gdbservertest/test.exe
........

由此可以知道:libtest.so的代碼在00fcc000-00fcd000之間。

    .查看libtest.so的.text段在內存中的偏移位置:
        armv5-linux-uclibc-objdump -h libtest.so |grep .text
輸出:
   .text 00000130 00000450 00000450 00000450 2**4
        即偏移位置爲0x00000450

    .回到板子上的gdb窗口,加載libtest.so的符號表。
(gdb)add-symbol-file libtest.so 0x00fcc450
   (這裏0x00fcc450 = 0x00fcc000 0x00000450)

    .在共享庫的函數中設置斷點
(gdb)b test

    .繼續調試共享庫

發佈了1 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章