gdb实现原理
参考链接。
在 vim / emacs 中启动 gdb
为什么在 Emacs/vim 中运行 GDB?
- 统一环境:你可以在 Emacs 中同时查看源代码和调试信息
- 快捷键支持:使用 Emacs 的快捷键控制 GDB(如设置断点、单步执行)
- 图形化布局:支持多窗口显示,如断点列表、堆栈信息、变量值等
- 增强效率:无需离开编辑器即可完成调试任务
Vim 从 8.1 版本开始内置了一个叫做 Termdebug 的插件,它可以直接在 Vim 中运行 GDB,并显示调试信息。
✅ 步骤:
确保 Vim 版本 ≥ 8.1
编译你的程序(加上 -g 选项):
1 | gcc -g my_program.c -o my_program |
在 Vim 中加载插件:
1 | :packadd termdebug |
Vim 会打开一个新的窗口,显示 GDB 控制台,你可以在里面输入 GDB 命令。
📖 教程参考:Baeldung 的 Vim-GDB 集成指南
gdb命令
thread apply [threadno] [all] args
- 将命令传递给一个或多个线程,参见链接。
比如,thread apply all continue
表示将continue
命令传递给所有线程,也就是让所有线程都继续运行。rbreak
- Set a breakpoint for all functions matching REGEXP. 参考链接。e.g.
rbreak file.C:.*
- 给file.C的所有函数加上断点。info
常用寄存器:
寄存器 | 用途说明 |
---|---|
rax | 函数返回值,乘除法运算 |
rbx | 通用寄存器,常用于基址 |
rcx | 循环计数器 |
rdx | I/O 指针或中间数据 |
rdi | 函数第一个参数 |
rsi | 函数第二个参数 |
rsp | 栈顶指针 |
rbp | 栈底指针,栈帧基址 |
rip | 当前执行指令地址 |
eflags | 运算状态标志,如 ZF(零标志)、CF(进位标志)等 |
gdb 的寄存器变量
x86(32 位)
$eax, $ebx, $ecx, $edx | 通用寄存器 |
---|---|
$esi, $edi | 源/目标索引寄存器 |
$esp | 栈顶指针(Stack Pointer) |
$ebp | 栈底指针(Base Pointer) |
$eip | 指令指针(下一条执行的指令地址) |
$eflags | 标志寄存器(保存条件标志) |
x86_64(64 位)
寄存器 | 说明 |
---|---|
$rax, $rbx, $rcx, $rdx | 通用寄存器(64 位) |
$rsi, $rdi | 参数寄存器 |
$rsp | 栈顶指针 |
$rbp | 栈底指针 |
$rip | 指令指针 |
$r8~$r15 | 扩展通用寄存器 |
$eflags | 标志寄存器 |
show
show environment
查看全局变量set environment <var>=<value>
设置环境变量
attach
- 连接到正在运行的进程。与gdb -p
效果相同。detach
- 取消连接的进程。handle <signal> print pass nostop
- 捕获信号(比如SIGSEGV
)并且忽略它。handle <signal nostop
。pass
表示 gdb 会将捕获到的信号发回给被调试的进程。
set
- 修改变量的值,比如set x=10
(或set var x=10
)将变量x
的值改为10
。参考博客。show directories
print
- gdb默认设置打印字符串的长度为200;更改打印最大长度:set print elements <number-of-elements>
,0
表示unlimited.
- 打印数组:print arr[0]@3
,其中@3
表示打印 3 个元素。
- 以十六进制打印:p/x <var>
ptype <variable name>
- 打印变量类型。finish
- 从函数中返回,并打印函数返回值(即使函数的return语句很复杂,也可以获取返回值)。frame <n>
- 跳转到某个栈帧。up
跳转到上一个栈帧x/FMT
:x
表示examine
,查看内存。/i
表示instruction
,即查看汇编指令。/g
表示giant word
,即每次查看 8 字节。x/g 0x400000
查看地址 0x400000 处的 8 字节内容(以十六进制显示)x/4g $rsp
查看当前栈指针$rsp
指向的连续 4 个 8 字节值(共 32 字节)
命令 | 说明 |
---|---|
x/g | 默认十六进制显示 8 字节内容 |
x/dg | 十进制显示 8 字节内容 |
x/ug | 无符号十进制显示 8 字节内容 |
x/tg | 二进制显示 8 字节内容 |
x/fg | 浮点数格式显示 8 字节内容(double) |
环境变量
见链接
断点
添加断点:
1 | break file:line_no |
查看断点:
1 | info break |
删除第2个断点:
1 | delete 2 |
条件断点
break ... if cond
观察断点
捕捉断点
1 | try...catch |
打印长度的限制
- Value sizes - 参考:文档
1 | set max-value-size bytes |
打印字符长度限制
gdb默认设置打印字符串的长度为200;更改打印最大长度:
set print elements
coredump
gdb命令:gcore
。
WSL无法使用gdb
WSL指Windows虚拟机。
解决方法:
1 | sudo add-apt-repository ppa:ubuntu-support-team/gdb |
gdb attach 权限报错
This is due to kernel hardening in Linux; you can disable this behavior by echo 0 > /proc/sys/kernel/yama/ptrace_scope
or by modifying it in /etc/sysctl.d/10-ptrace.conf
.
How to solve “ptrace operation not permitted” when trying to attach GDB to a process?
gdb debug forks
By default, when a program forks, gdb will continue to debug the parent process and the child process will run unimpeded.
If you want to follow the child process instead of the parent process, use the command set follow-fork-mode
.
set follow-fork-mode mode
Set the debugger response to a program call of fork
or vfork
. A call to fork or vfork creates a new process. The mode argument can be:parent
The original process is debugged after a fork. The child process runs unimpeded. This is the default.child
The new process is debugged after a fork. The parent process runs unimpeded.ask
gdb 会提示让你选择 parent
还是 child
。
show follow-fork-mode
Display the current debugger response to a fork or vfork call.
On Linux, if you want to debug both the parent and child processes, use the command set detach-on-fork.
set detach-on-fork mode
Tells gdb whether to detach one of the processes after a fork, or retain debugger control over them both.on
The child process (or parent process, depending on the value of follow-fork-mode) will be detached and allowed to run independently. This is the default.off
Both processes will be held under the control of gdb. One process (child or parent, depending on the value of follow-fork-mode) is debugged as usual, while the other is held suspended.
show detach-on-fork
Show whether detach-on-fork mode is on/off.
If you issue a run command to gdb after an exec call executes, the new target restarts. To restart the parent process, use the file command with the parent executable name as its argument. By default, after an exec call executes, gdb discards the symbols of the previous executable image. You can change this behaviour with the set follow-exec-mode command.
set follow-exec-mode mode
Set debugger response to a program call of exec. An exec call replaces the program image of a process.
follow-exec-mode can be:
new
gdb creates a new inferior and rebinds the process to this new inferior. The program the process was running before the exec call can be restarted afterwards by restarting the original inferior.
For example:
1 | (gdb) info inferiors |
same
gdb keeps the process bound to the same inferior. The new executable image replaces the previous executable loaded in the inferior. Restarting the inferior after the exec call, with e.g., the run command, restarts the executable the process was running after the exec call. This is the default mode.
For example:
1 | (gdb) info inferiors |
Setting Catchpoints
gdb redirect to a log file
You need to enable logging:
1 | (gdb) set logging on |
更新:新版本 gdb 采用 set logging enabled on
。
记录输入的命令:
1 | (gdb) set trace-commands on |