文章目錄
- GDB常用命令
- 1 信息顯示
- 1.1 顯示版本信息:`show version`
- 1.2 啓動時不顯示信息:`gdb -q`
- 1.3 退出時不顯示提示信息:`set confirm off`
- 1.4 輸出信息是不暫停:`set pagination off` 或者` set height 0`
- 2 變量
- 3 字符串
- 4 函數
- 4.1 開始執行程序:`start`
- 4.2 列出可執行文件的所有函數名稱:`info functions`
- 4.3 單步調試(不進入函數內部):`next(n)`
- 4.4 單步調試(進入函數):`step(s)`
- 4.5 退出正在調試的函數:`finish`
- 4.6 直接調用函數執行:`call function_name` 或者 `print function_name`
- 4.7 選擇函數棧幀:`frame n(f n)`
- 4.8 打印函數堆棧幀信息:`info frame(i frame)`
- 5 斷點
- 5.1 在程序地址上打斷點:`b *address`
- 5.2 在程序入口處打斷點
- 5.3 在文件行號上打斷點:`b linenum`
- 5.4 查看已經創建的斷點:`info breakpoints(i b)`
- 5.5 保存已經設置的斷點:`save breakpoints file-name-to-save`
- 5.6 設置臨時斷點(生效一次):`tbreak(tb)`
- 5.7 設置條件斷點:`break … if cond`
- 6 觀察點
GDB常用命令
1 信息顯示
1.1 顯示版本信息:show version
1.2 啓動時不顯示信息:gdb -q
1.3 退出時不顯示提示信息:set confirm off
1.4 輸出信息是不暫停:set pagination off
或者set height 0
2 變量
2.1 設置變量的值:set var variable=expr
3 字符串
3.1 打印ASCII字符串:x/s str_name
例如:
# char str1[] = "abcd";
(gdb) x/s str1
3.2 設置字符串的值
例如,針對如下C代碼:
#include <stdio.h>
int main(void)
{
char p1[] = "Sam";
char *p2 = "Bob";
printf("p1 is %s, p2 is %s\n", p1, p2);
return 0;
}
可以使用如下命令,設置字符串的值:
(gdb) set main::p1="Jil"
(gdb) set main::p2="Bill"
4 函數
4.1 開始執行程序:start
4.2 列出可執行文件的所有函數名稱:info functions
4.3 單步調試(不進入函數內部):next(n)
4.4 單步調試(進入函數):step(s)
4.5 退出正在調試的函數:finish
4.6 直接調用函數執行:call function_name
或者 print function_name
例如,如下C函數:
int func(int a)
{
int i = a * 2;
return i;
}
可以使用如下方法直接調用:
(gdb) call func(2)
$1 = 4
(gdb) print func(3)
$2 = 6
4.7 選擇函數棧幀:frame n(f n)
(gdb) bt
#0 func1 (a=10) at test.c:5
#1 0x0000000000400560 in func2 (a=10) at test.c:11
#2 0x0000000000400586 in func3 (a=10) at test.c:18
#3 0x000000000040059e in main () at test.c:24
(gdb) f 2
4.8 打印函數堆棧幀信息:info frame(i frame)
- 例如
Breakpoint 1, func (a=1, b=2) at a.c:5
5 printf("c is %d\n", c);
(gdb) i frame
Stack level 0, frame at 0x7fffffffe590:
rip = 0x40054e in func (a.c:5); saved rip = 0x400577
called by frame at 0x7fffffffe5a0
source language c.
Arglist at 0x7fffffffe580, args: a=1, b=2
Locals at 0x7fffffffe580, Previous frame's sp is 0x7fffffffe590
Saved registers:
rbp at 0x7fffffffe580, rip at 0x7fffffffe588
5 斷點
5.1 在程序地址上打斷點:b *address
當調試彙編程序,或者沒有調試信息的程序時,經常需要在程序地址上打斷點,方法:b *address
。例如:
0000000000400522 <main>:
400522: 55 push %rbp
400523: 48 89 e5 mov %rsp,%rbp
400526: 8b 05 00 1b 00 00 mov 0x1b00(%rip),%eax # 40202c <he+0xc>
40052c: 85 c0 test %eax,%eax
40052e: 75 07 jne 400537 <main+0x15>
400530: b8 7c 06 40 00 mov $0x40067c,%eax
400535: eb 05 jmp 40053c <main+0x1a>
(gdb) b *0x400522
5.2 在程序入口處打斷點
當調試沒有調試信息的程序時,直接運行 start
命令是沒有效果的。如果不知道main在何處,那麼可以在程序入口處打斷點。先通過 readelf 獲得入口地址,然後使用如下方法在程序的地址上打斷點。
$ strip a.out
$ readelf -h a.out
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400440
Start of program headers: 64 (bytes into file)
Start of section headers: 4496 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 28
(gdb) start
Function "main" not defined.
(gdb) b *0x400440
(gdb) r
5.3 在文件行號上打斷點:b linenum
如果要在當前文件中的某一行打斷點,直接b linenum
即可,例如:
(gdb) b 7
可以通過指定(部分)路徑,來區分相同的文件名:
(gdb) b a/file.c:6
注意:通過行號進行設置斷點的一個弊端是,如果你更改了源程序,那麼之前設置的斷點就可能不是你想要的了。
5.4 查看已經創建的斷點:info breakpoints(i b)
5.5 保存已經設置的斷點:save breakpoints file-name-to-save
在gdb中,可以使用如下命令將設置的斷點保存下來:
(gdb) save breakpoints file-name-to-save
下此調試時,可以使用如下命令批量設置保存的斷點:
(gdb) source file-name-to-save
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000005a7af0 in gdb_main at /home/xmj/project/binutils-trunk/g
2 breakpoint keep y 0x00000000005a6bd0 in captured_main at /home/xmj/project/binutils-tr
3 breakpoint keep y 0x00000000005a68b0 in captured_command_loop at /home/xmj
5.6 設置臨時斷點(生效一次):tbreak(tb)
在使用gdb時,如果想讓斷點只生效一次,可以使用“tbreak”命令(縮寫爲:tb)。例如:
(gdb) tb a.c:15
Temporary breakpoint 1 at 0x400500: file a.c, line 15.
5.7 設置條件斷點:break … if cond
gdb可以設置條件斷點,也就是隻有在條件滿足時,斷點纔會被觸發,命令是“ break … if cond ”。
#include <stdio.h>
int main(void)
{
int i = 0;
int sum = 0;
for (i = 1; i <= 200; i++)
{
sum += i;
}
printf("%d\n", sum);
return 0;
}
以上面程序爲例:
(gdb) start
Temporary breakpoint 1 at 0x4004cc: file a.c, line 5.
Starting program: /data2/home/nanxiao/a
Temporary breakpoint 1, main () at a.c:5
5 int i = 0;
(gdb) b 10 if i==101
Breakpoint 2 at 0x4004e3: file a.c, line 10.
(gdb) r
Starting program: /data2/home/nanxiao/a
Breakpoint 2, main () at a.c:10
10 sum += i;
(gdb) p sum
$1 = 5050
6 觀察點
6.1 設置觀察點:watch(wa)
gdb可以使用“ watch ”命令設置觀察點,也就是當一個變量值發生變化時,程序會停下來。
6.2 設置觀察點只針對特定線程生效:watch expr thread threadnum
gdb可以使用“ watch expr thread threadnum ”命令設置觀察點只針對特定線程生效,也就是隻有編號爲 threadnum 的線程改變了變量的值,程序纔會停下來,其它編號線程改變變量的值不會讓程序停住。例如:
(gdb) watch a thread 2 # a is a variable
Hardware watchpoint 2: a
6.3 設置讀觀察點:rwatch(rw)
gdb可以使用“ rwatch ”命令設置讀觀察點,也就是當發生讀取變量行爲時,程序就會暫停住。例如:
(gdb) rw a # a is a variable
Hardware read watchpoint 2: a
6.4 設置讀寫觀察點:awatch(aw)
gdb可以使用“ awatch ”命令設置讀寫觀察點,也就是當發生讀取變量或改變變量值的行爲時,程序就會暫停住。需要注意的是 awatch 命令只對硬件觀察點才生效。例如:
(gdb) aw a
Hardware access (read/write) watchpoint 1: a