gdb 调试断点

1. 在匿名空间设置断点

1
2
3
4
5
6
namespace Foo {
void foo() {}
}
namespace {
void bar() {}
}

在 gdb 中,如果要对 namespace Foo 中的 foo 函数设置断点,可以:(gdb) b Foo::foo

如果要对匿名空间中的 bar 函数设置断点,可以:(gdb) b (anonymous namespace)::bar

2. 在程序地址上打断点

调试汇编程序时,或者没有调试信息的程序时,可以在程序地址上打断点。方法

1
2
(gdb) b *address
(gdb) b *0x400500

3. 在程序入口处打断点

当调试没有调试信息的程序,直接运行 start 命令是没有效果的。如果不知道 main 在哪里。可以通过 readelf 获取入口地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# readelf -h main       
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: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x540
Start of program headers: 64 (bytes into file)
Start of section headers: 8776 (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: 34
Section header string table index: 33

可以看到 Entry point address: 0x540 ,因此可以在这个地址打断点

4. 在文件行号上打断点

可以显式指定文件,比如:(gdb) b file:linenum。同时也可以设置文件的路径。

5. 保存已经设置的断点

保存已设置的断点:(gdb) save breakpoints file-name-to-save。当前目录下会生成一个文件:file-name-to-save

在新的调试中,使用命令恢复保存的断点:(gdb) source file-name-to-save

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# gdb -q ./main
Reading symbols from ./main...done.
(gdb) b 6
Breakpoint 1 at 0x64e: file main_01.cpp, line 6.
(gdb) b 10
Breakpoint 2 at 0x669: file main_01.cpp, line 10.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000000064e in func() at main_01.cpp:6
2 breakpoint keep y 0x0000000000000669 in main() at main_01.cpp:10
(gdb) save breakpoints file-name-to-save # 当前目录下会生成一个文件:file-name-to-save
Saved to file 'file-name-to-save'.

# 重新调试
(gdb) source file-name-to-save
Breakpoint 1 at 0x64e: file main_01.cpp, line 6.
Breakpoint 2 at 0x669: file main_01.cpp, line 10.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000000064e in func() at main_01.cpp:6
2 breakpoint keep y 0x0000000000000669 in main() at main_01.cpp:10

6. 设置临时断点

如果想让断点只生效一次,可以使用 tbreak 命令(缩写:tb)。断点命中一次后,就被删除掉了

7. 设置条件断点

只有在条件满足时,断点才会被触发。命令:break ... if cond

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// code
int main(void) {
int i = 0;
int sum = 0;
for (i = 1; i <= 200; i++) {
sum += i;
}
printf("%d\n", sum);
return 0;
}

// gdb 调试
(gdb) b 7 if i = 100 # 只有在 i 的值为 100 时会触发
Breakpoint 1 at 0x670: file main_01.cpp, line 7.
(gdb) r
Starting program: /data/code/cpp/test/gdb_test/main

Breakpoint 1, main () at main_01.cpp:7
7 sum += i;
(gdb) p i
$1 = 100

8. 忽略断点

忽略断点,命令:ignore bnum count。意思是接下来 count 次编号为 bnum 的断点触发都不会让程序中断。只有 count+1 次断点触发才会让程序中断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// code
int main(void) {
int i = 0;
int sum = 0;
for (i = 1; i <= 200; i++) {
sum += i;
}
printf("%d\n", sum);
return 0;
}

// gdb 调试
(gdb) b 7
Breakpoint 1 at 0x670: file main_01.cpp, line 7.
(gdb) ignore 1 5 # 接下来 5 次编号为 1 的断点都不会让程序中断,只有第 6 次断点触发才会让程序中断
Will ignore next 5 crossings of breakpoint 1.
(gdb) r
Starting program: /data/code/cpp/test/gdb_test/main

Breakpoint 1, main () at main_01.cpp:7
7 sum += i;
(gdb) p i
$1 = 6