GDB實用命令

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章