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