GDB Breakpoint

Table of Contents

1. GDB Breakpoint

1.1. software breakpoint

插入 software breakpoint 时, gdb 会把断点处的指令替换为会触发 trap 的指令, 例如 x86 上的 INT3 (0xcc), 以及 riscv 上的 ebreak. 同时记下原来的旧指令.

gdb 会用 ptrace catch 住 INT3 触发的 SIGTRAP, 从而实现断点的功能.

1.1.1. example

#include <stdio.h>

void foo() {}
int main(int argc, char** argv) {
    printf("%p\n", &foo);
    printf("%x\n", *((int*)foo));
    foo();
    printf("%p\n", &foo);
    printf("%x\n", *((int*)foo));
}

0x5648755ee149 fa1e0ff3 0x5648755ee149 fa1e0ff3

$> gdb ./a.out
(gdb) r
Starting program: /home/sunway/download/a.out
0x555555555149
fa1e0ff3
0x555555555149
fa1e0ff3
[Inferior 1 (process 234451) exited normally]

(gdb) b foo
Breakpoint 1 at 0x555555555149: file test.c, line 3.
(gdb) r
Starting program: /home/sunway/download/a.out
0x555555555149
fa1e0fcc

Breakpoint 1, foo () at test.c:3
3       void foo() {}

# 注意在 gdb 中用 x 显示的并非真实的内存数据, gdb 在显示时把 0xcc 替换成为原始的
# 0xf3

(gdb) x foo
0x555555555149 <foo>:   0xfa1e0ff3

(gdb) delete 1
(gdb) r
Starting program: /home/sunway/download/a.out
0x555555555149
fa1e0ff3
0x555555555149
fa1e0ff3

gdb 需要 shadow 软件断点修改的内存, 参考 gdb 源码中的 `breakpoint shadow`

ps. 新版本的 gdb 使用 `b foo` 时会跳过函数的 prolog, 导致断点并没有设置在 &foo, 通过 `b *foo` 可以禁止 gdb 的这个行为

1.2. hardware breakpoint

参考 riscv trigger

1.3. misc

https://github.com/scottt/debugbreak

利用这个库在代码中直接插入 INT3, 从而不需要从 gdb 中设断点

Backlinks

GDB (GDB > GDB Breakpoint): GDB Breakpoint

GDB Target Arch (GDB Target Arch > backtrace > insert breakpoint): 可以看到 native debug 时 breakpoint 是通过写内存实现 (xfer_partial) 的 (参考 breakpoint)

ebreak (RISC-V Debug Module > debug with debug module > breakpoint > ebreak): 另外, gdb native debug 时 ebreak 需要触发 trap 而不是进入 debug mode (类似于 x86 的 int3, 参考 GDB Breakpoint), 这个通过 dcsr 可以配置

Author: [email protected]
Date: 2020-11-18 Wed 00:00
Last updated: 2024-03-24 Sun 12:16

知识共享许可协议