1. 程式人生 > >使用GDB在ARM上進行開發除錯

使用GDB在ARM上進行開發除錯

一、安裝GDB及GDB server 

1.1 GDB簡介 

GDB除錯環境由宿主機GDB和目標開發板的GDB server共同構成,兩者通過串列埠或TCP連線。使用GDB標準序列協議協同工作,實現對目標機的系統核心和上層應用的監控和除錯功能。 
GdbServer是GDB的一個元件,但通常不隨發行版本的GDB一同釋出,需要使用者自行編譯GDB的原始碼包得到相應的GDB和GDBServer,可以從下載地址:http://ftp.gnu.org/gnu/gdb/,或者百度獲取下載地址。 

1.2 安裝GDB 

本例中目標板為Hi3520D,使用的GDB是GDB 7.2,宿主機為ubuntu10.4(vmware),本機開發環境為win7 x64。在獲取原始碼gdb-7.2a.tar.gz(24MB)後,將其解壓: 

1.tar zxvf gdb-7.2.tar.gz 
2.配置GDB,./configure –target=arm-Linux –enable-sim –prefix=/opt/arm-gdb(其中prefix為設定您所需要的安裝目錄) 
3.編譯及安裝,執行make,然後執行make install 
4.執行結束後,在/opt/arm-gdb/bin目錄下可看到生成的應用程式。 
這裡寫圖片描述 
5.將三個應用程式拷貝到/usr/local/bin。 

1.3 安裝GDB server 

在編譯安裝GDB後,進入到目錄gdbserver下,我的目錄為/home/arm/gdb/gdb-7.2/gdb/gdbserver,在該目錄下進行配置。在命令列裡輸入:./configure –target=arm-
linux –host=arm-linux。接著,配置所採用的交叉編譯器。我用的是Hi3520D,所用的交叉編譯器為arm-hisiv100nptl-linux-gcc,因此我在命令列裡輸入 : 
make CC=/opt/hisi-linux-nptl/arm-hisiv100-linux/target/bin/arm-hisiv100nptl-linux-gcc 
注意,一定要寫交叉編譯器的絕對路徑!在make的過程中可能會出錯,提示: 
“linux-x86-low.c error: sys/reg.h: No such file or directory”。 
這時候,在#ifdef HAVE_SYS_REG_H這句前面加上一句: 

#undef HAVE_SYS_REG_H 
然後重新編譯即可。編譯完成後,在gdbserver目錄下就會生成gdbserver和gdbreplay。,這兩個檔案就可以放在目標板上和開發編譯的程式一起進行除錯。而主機上可以採用編譯出來的arm-linux-gdb作為主機端執行的除錯。 
這裡寫圖片描述

二、測試程式碼及應用程式生成 

為簡單起見,我們就用一個十餘行的C程式進行GDB除錯演示。以下是C程式碼:
<code class="hljs perl has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#include<stdio.h></span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> a,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> b) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> a+b; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc ,char* argv[]) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> num1=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,num2=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">time</span>; const <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> plusCount=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">time</span>=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">time</span>!=plusCount;++<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">time</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%dplus</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%d</span>=<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%d</span>.\r\n"</span>,num1,num2,num1+num2); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%dplus</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%d</span>=<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%d</span> byfunc.\r\n"</span>,num1,num2,add(num1,num2)); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

在命令列裡輸入:arm-hisiv100nptl-linux-gcc test.c -g -o test 即可生成應用程式test。注意,編譯時一定要加入-g引數,表示應用程式除錯。 
這裡寫圖片描述 

三、GDB+GDB server nfs除錯方法 

進行除錯前首先需要保證目標開發板與宿主機支援nfs。在宿主機上安裝samba教程可自行百度獲取,或者參考文章附錄。本例中宿主機IP為218.192.171.55,目標板IP為218.192.171.72,開發環境(win7 x64)IP為218.192.171.78,宿主機的共享目錄為/mnt/nfs。 
1.將gdbserver和test拷貝到/mnt/nfs,更改應用程式許可權:chmod 777 gdbserver test。 
2.通過telnet或者minicom遠端到目標板,掛載nfs: 
mount -t nfs -o nolock -o tcp 218.192.171.55:/mnt/nfs /nfsroot 
這裡寫圖片描述 
3.進入/nfsroot目錄,輸入指令: 
./gdbserver 218.192.171.55:5000 test 
其中,218.192.171.55為宿主機IP,5000表示目標開發板的除錯埠(一般任意大於1024的埠號均可)。 
這裡寫圖片描述 
4.在宿主機命令列輸入:arm-linux-gdb test,接著輸入: 
target remote 218.192.171.72:5000 
連線成功後,出現如下提示: 
這裡寫圖片描述 
5.在宿主機命令列輸入:b add 設定斷點為函式add,然後再輸入’c’,執行程式。效果如下: 
這裡寫圖片描述 
目標板端輸出提示如下: 
這裡寫圖片描述 
6.輸入’c’,繼續執行程式,直到結束。然後輸入’q’退出gdb。效果圖如下: 
這裡寫圖片描述 
這裡寫圖片描述 
注,本例僅進行簡單測試,其它除錯命令可參考附錄。 

四、GDB+GDB server串列埠除錯 

由於本人開發板未配有串列埠除錯,故以下內容為搬運過來的。除錯步驟如下: 
1.如果你用串列埠1除錯test的話,你就要現在板子上執行命令:gdbserver hello /dev/ttyS0 (詳情可以參考gdbserver目錄下的readme檔案)。 
2.在宿主機命令列輸入: 
arm-linux-gdb test 
3.然後配置到串列埠,在宿主機命令列輸入: 
set remotedevice /dev/ttyS0(這裡設定串列埠1) 
set remote baud 9600 (這裡設定串列埠波特率) 
set debug remote 1(可選) 
target remote /dev/ttyS0 
4.操作到這兒,gdb就應該和gdbserver聯絡上了。接下來的操作和nfs中的操作保持一致,就不再贅述。 

五、附錄 

本博文參考了多家之言,並且肯定存在許多不足。如果哪裡表述有問題,還煩請指正。另外,推薦以下網頁,可進一步學習相關內容。

1.GDB在ARM上的除錯實戰 

http://blog.chinaunix.net/uid-2630593-id-2138581.html 

2.CentOS 6.3下Samba伺服器的安裝與配置 

http://www.cnblogs.com/mchina/archive/2012/12/18/2816717.html 

3.GDB下載地址: 

http://ftp.gnu.org/gnu/gdb/ 

4.GDB十分鐘教程 

http://blog.csdn.net/liigo/article/details/582231

出處:http://blog.csdn.NET/kxc0720/article/details/45953563