GDB調試

調試前準備

獲取進程的內核轉儲(core dump)

why:最大好處是,其保存了問題發(fā)生時的狀態(tài)。記錄進程當前狀態(tài)。

步入正題:

啟動內核轉儲,查看當前內核轉儲功能是否有效,結果為0表示內核轉儲無效

$ ulimit -c

那么,則需要開啟內核轉儲,該命令不限制轉儲文件大小。亦可設置為有限上限1G,ulimit -c 1073741842。

$ ulimit -c? unlimited

$ ./a.out??? 生成轉儲文件

查看生成的轉儲文件

$ file core*

GDB啟動,使用轉儲文件

$ gdb -c core.xxx?? ./a.out

?

一、GDB調試前問題匯總

1.編譯出現undefined reference to 'pthread_create'

編譯加上參數?? -lpthread

2.apue.h找不到

導入src.3e.tar.gz 中apue/include/apue.h? 到 /usr/include

3.err_sys未定義

關于err_sys未定義錯誤解決方法

二、GDB例子(切入)

一個調試示例

——————

源程序:tst.c

#include <stdio.h>

int func(int n){

int sum = 0,i;

for(i=0; i<7;i++){

sum += i; } return sum;}

main(){

int i;

long result = 0;

for(i=1;i<=100;i++){

result += i;}

printf("result[1-100]= %d/n",result);

printf("result[1-250]= %d/n",func(250));

}

編譯生成執(zhí)行文件:(Linux下)

hchen/test> cc -g tst.c -o tst

使用GDB調試:

hchen/test> gdb tst? <---------- 啟動GDB

GNU gdb 5.1.1

Copyright 2002 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.? Type "show warranty" for details.

This GDB was configured as "i386-suse-linux"...

(gdb) l???? <-------------------- l命令相當于list,從第一行開始例出原碼。

1??????? #include

2

3??????? int func(int n)

4??????? {

5??????????????? int sum=0,i;

6??????????????? for(i=0; i

7??????????????? {

8??????????????????????? sum+=i;

9??????????????? }

10?????????????? return sum;

(gdb)?????? <-------------------- 直接回車表示,重復上一次命令

11?????? }

12

13

14?????? main()

15?????? {

16?????????????? int i;

17?????????????? long result = 0;

18?????????????? for(i=1; i<=100; i++)

19?????????????? {

20?????????????????????? result += i;

(gdb) break 16??? <-------------------- 設置斷點,在源程序第16行處。

Breakpoint 1 at 0x8048496: file tst.c, line 16.

(gdb) break func? <-------------------- 設置斷點,在函數func()入口處。

Breakpoint 2 at 0x8048456: file tst.c, line 5.

(gdb) info break? <-------------------- 查看斷點信息。

Num Type?????????? Disp Enb Address??? What

1?? breakpoint???? keep y?? 0x08048496 in main at tst.c:16

2?? breakpoint???? keep y?? 0x08048456 in func at tst.c:5

(gdb) r?????????? <--------------------- 運行程序,run命令簡寫

Starting program: /home/hchen/test/tst

Breakpoint 1, main () at tst.c:17??? <---------- 在斷點處停住。

17?????????????? long result = 0;

(gdb) n????????? <--------------------- 單條語句執(zhí)行,next命令簡寫。

18?????????????? for(i=1; i<=100; i++)

(gdb) n

20?????????????????????? result += i;

(gdb) n

18?????????????? for(i=1; i<=100; i++)

(gdb) n

20?????????????????????? result += i;

(gdb) c????????? <--------------------- 繼續(xù)運行程序,continue命令簡寫。

Continuing.

result[1-100] = 5050?????? <----------程序輸出。

Breakpoint 2, func (n=250) at tst.c:5

5??????????????? int sum=0,i;

(gdb) n

6??????????????? for(i=1; i<=n; i++)

(gdb) p i??????? <--------------------- 打印變量i的值,print命令簡寫。

$1 = 134513808

(gdb) n

8??????????????????????? sum+=i;

(gdb) n

6??????????????? for(i=1; i<=n; i++)

(gdb) p sum

$2 = 1

(gdb) n

8??????????????????????? sum+=i;

(gdb) p i

$3 = 2

(gdb) n

6??????????????? for(i=1; i<=n; i++)

(gdb) p sum

$4 = 3

(gdb) bt??????? <--------------------- 查看函數堆棧。

#0? func (n=250) at tst.c:5

#1? 0x080484e4 in main () at tst.c:24

#2? 0x400409ed in __libc_start_main () from /lib/libc.so.6

(gdb) finish??? <--------------------- 退出函數。

Run till exit from #0? func (n=250) at tst.c:5

0x080484e4 in main () at tst.c:24

24????????????? printf("result[1-250] = %d /n", func(250) );

Value returned is $6 = 31375

(gdb) c???? <--------------------- 繼續(xù)運行。

Continuing.

result[1-250] = 31375??? <----------程序輸出。

Program exited with code 027. <--------程序退出,調試結束。

(gdb) q???? <--------------------- 退出gdb。

hchen/test>

好了,有了以上的感性認識,還是讓我們來系統(tǒng)地認識一下gdb吧。

三、adb + GDB用法

3.1 靜態(tài)調試

(1)通過命令ulimit -c unlimited設置系統(tǒng)生成Core

?Dump文件

gdb+ 帶符號表的可執(zhí)行文件+Core Dump文件

該方式可以直接定位到錯誤發(fā)生的地方。

(2)直接gdb+ 帶符號表的可執(zhí)行文件

該方式需要啟動之后運行run命令才能執(zhí)行調試。

3.2 動態(tài)調試

就是用attach的方式連接到正在運行中的進程上面去,進行調試,下面是利用PC機動態(tài)調試手機上面的進程的操作步驟。

編譯小程序:

arm-none-linux-gnueabi-gcc -static HelloWorld.c -o HelloWorld

在android運行軟件-小程序

<1>adb shell ps -elf????????????????????????????????????????????????? 查看所需要調試程序的進程號

<2>adb shell gdbserver :5039 --attach PID????????? attach到對應進程號上面

<3>打開另一個終端,adb forward tcp:5039 tcp:5039

<4>運行arm-eabi-gdb

路徑:

/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-gdb

<5>set solib-absolute-prefix + 符號表文件路徑

<6>set? solib-search-path + 帶符號表可執(zhí)行文件路徑:動態(tài)共享庫文件路徑:....

<7>鏈接遠端程序target? remote:5039? 進行調試?

四、GDB 命令(一)

gcc -g main.c? -o? xxxxx?? //在目標文件加入源代碼的信息

gdb a.out? ? ?

(gdb) start? ? ? ? ? ? ? ? ? ? ? ? //開始調試

(gdb) n? ? ? ? ? ? ? ? ? ? ? ? ? ? //一條一條執(zhí)行

(gdb) step/s? ? ? ? ? ? ? ? ? ? ? ? //執(zhí)行下一條,如果函數進入函數

(gdb) backtrace/bt? ? ? ? ? ? ? ? ? //查看函數調用棧幀

(gdb) info/i locals? ? ? ? ? ? ? ? //查看當前棧幀局部變量

(gdb) frame/f? ? ? ? ? ? ? ? ? ? ? //選擇棧幀,再查看局部變量

(gdb) print/p? ? ? ? ? ? ? ? ? ? ? //打印變量的值

(gdb) finish? ? ? ? ? ? ? ? ? ? ? ? //運行到當前函數返回

(gdb) set var sum=0? ? ? ? ? ? ? ? //修改變量值

(gdb) list/l 行號或函數名? ? ? ? ? ? //列出源碼

(gdb) display/undisplay sum? ? ? ? //每次停下顯示變量的值/取消跟蹤

(gdb) break/b? 行號或函數名? ? ? ? ? //設置斷點

(gdb) continue/c? ? ? ? ? ? ? ? ? ? //連續(xù)運行

(gdb) info/i breakpoints? ? ? ? ? ? //查看已經設置的斷點

(gdb) delete breakpoints 2? ? ? ? ? //刪除某個斷點

(gdb) disable/enable breakpoints 3? //禁用/啟用某個斷點

(gdb) break 9 if sum != 0? ? ? ? ? //滿足條件才激活斷點

(gdb) run/r? ? ? ? ? ? ? ? ? ? ? ? //重新從程序開頭連續(xù)執(zhí)行

(gdb) watch input[4]? ? ? ? ? ? ? ? //設置觀察點

(gdb) info/i watchpoints? ? ? ? ? ? //查看設置的觀察點

(gdb) x/7b input? ? ? ? ? ? ? ? ? ? //打印存儲器內容,b--每個字節(jié)一組,7--7組

(gdb) disassemble? ? ? ? ? ? ? ? ? //反匯編當前函數或指定函數

(gdb) si? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 一條指令一條指令調試 而 s 是一行一行代碼

(gdb) info registers? ? ? ? ? ? ? ? // 顯示所有寄存器的當前值

(gdb) x/20 $esp? ? ? ? ? ? ? ? ? ? //查看內存中開始的20個數

(gdb) i ? threads? ? ? ? ? ? ? ? ? ? ? //查看threads

(gdb) t ?? x? ? ? ? ? ? ? ? ? ?????????? //切換至x線程下調試

(gdb) i ? ? r ? ? ? ? ? ? ? ? ? ? ? ? ? ?? //查看寄存器狀態(tài)

(gdb) i proc m????????????????????? //(info proc mappings 的簡寫)核查Mapped address

(gdb) i? signals??????????????????? //查看所有信號量的設置情況。

(gdb)?p $eax?????????????????????? ?//查看eax寄存器的內容。

(gdb)?generate-core-file?????? ?//生成轉儲文件

(gdb)?i? p?????????????????????????????? ?//info proc? 查看進程信息

(未完待續(xù))

四、GDB 命令(二)

attach 到進程

調試守護進程等已經啟動的進程,或是調試陷入死循環(huán)而無法返回的進程時使用。

attach pid

以sleep命令為舉例:

ps aux| grep sleep? 查看sleep進程ID? 若為17606

(gdb) attach 17606



五、GDB原理及調試實例參考

GDB原理及調試實例(推薦)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 程序調試的基本思想是“分析現象->假設錯誤原因->產生新的現象去驗證假設”這樣一個循環(huán)過程,根據現象如何假設錯誤原...
    Manfred_Zone閱讀 16,754評論 0 26
  • 版權聲明:本文為 cdeveloper 原創(chuàng)文章,可以隨意轉載,但必須在明確位置注明出處! gdb 簡介 gdb ...
    登龍zZ閱讀 7,689評論 1 15
  • 在花開的日子,曾從百花叢中走過,看盡繽紛花朵嬌艷盛開;葉落的時候,曾踩著紅黃斑駁的記憶,找尋逝去的時光。 君子蘭 ...
    第8日蟬閱讀 1,109評論 0 0
  • 生存還是死亡?這是多年以來一直籠罩在地方網站頭頂上的巨大陰影。 滅亡說這樣認為,隨著BAT的觸角越來越深,隨著垂直...
    李光春閱讀 236評論 0 1
  • 好久沒來這里了,今天是小雪節(jié)氣,心里也是一陣陣寒意,見過太多失敗的婚姻都源自于根本的不欣賞不理解,我和他現在大概就...
    此處有危險請遠離閱讀 276評論 0 0

友情鏈接更多精彩內容