調試前準備
獲取進程的內核轉儲(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未定義
二、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