GDB 使用入门与进阶:用户态与内核态调试

GNU Debugger(GDB)是 Linux 下最常用的调试器。它既能调试 用户态程序,也能通过特殊接口调试 内核态代码。本文将分为两个部分:

用户态调试 —— 以一个完整的 main.c 示例演示所有常用命令

内核态调试 —— 介绍 KGDB、QEMU gdbstub、crash/kdump 等方式


一、用户态调试

1. 示例源码

我们先准备一个带多线程、递归、循环、崩溃点的 C 程序,用于覆盖各种 GDB 用例。

main.c

编译:

gcc -g -O0 -pthread main.c -o main

  • -g:生成调试符号表(必须有,否则只能看汇编)

  • -O0:关闭优化,避免变量被优化掉

  • -pthread:启用线程库


2. 启动 GDB 的几种方式

启动方式 用途
gdb ./main 调试程序
gdb ./main core 调试 core dump
gdb ./main PID 调试指定进程
gdb -p PID 直接附加进程
gdb --args ./main arg1 arg2 带参数调试
gdb -q ./main 安静模式(无 banner)

3. 常用调试命令

(1)运行与参数

run arg1 arg2 # 运行程序并传递参数

start # 停在 main 函数第一行

quit # 退出

(2)断点与条件

break main # 在 main 函数入口设置断点

break main.c:25 # 在第 25 行设置断点

break factorial if n==3 # 条件断点

info breakpoints # 查看断点

delete 1 # 删除编号为 1 的断点

(3)单步与继续

next # 单步执行(跳过函数)

step # 单步进入函数

finish # 运行到当前函数返回

continue # 继续运行

(4)变量与内存

print n # 打印变量

set var n=100 # 修改变量

display global_var # 每次停下自动显示

watch global_var # 观察点,变量变化时停下

x/16xw &global_var # 查看内存

(5)栈与函数

backtrace # 查看调用栈 frame 2 # 切换到栈帧 2 info locals # 查看局部变量

(6)多线程

info threads # 显示所有线程 thread 2 # 切换到线程 2 break thread_func # 给线程函数打断点

(7)进程调试

ps -aux | grep systemd gdb -p <pid>

在 gdb 内可用 detach 退出调试。

(8)core dump 调试

生成 core 文件:

ulimit -c unlimited ./main crash

调试:

gdb ./main core

常用命令:

bt info locals list


二、内核态调试

用户态程序可以直接用 gdb 调试,但内核态需要特殊支持。主要有三种方式:


1. KGDB + 串口调试

KGDB 是 Linux 内核内置的 gdb 调试接口。

  • 编译内核时启用:

  • CONFIG_KGDB=y CONFIG_KGDB_SERIAL_CONSOLE=y CONFIG_KDB=y

  • 内核启动参数:

  • kgdboc=ttyS0,115200 kgdbwait

  • 表示使用串口 ttyS0 连接 gdb,并在启动时等待。

  • 主机端 gdb 连接:

  • gdb vmlinux (gdb) target remote /dev/ttyS0


2. QEMU + GDB Stub

虚拟机调试更常用 gdbstub。

启动 QEMU:

qemu-system-x86_64 -kernel bzImage -append "console=ttyS0" \ -nographic -S -s

参数说明:

  • -S:启动时暂停 CPU

  • -s:等价于 -gdb tcp::1234

连接 gdb:

gdb vmlinux (gdb) target remote :1234

示例:

break start_kernel continue


3. crash/kdump 事后分析

当内核崩溃(oops/panic)时,可以用 kdump 保存转储,然后用 crash 工具分析。

安装工具:

sudo apt install kexec-tools crash

  1. 配置 kdump,崩溃后生成 vmcore 文件。

  2. 使用 crash 调试:

crash vmlinux vmcore

常用命令:


bt # 栈回溯 ps # 进程信息 files # 打开文件表 kmem # 内存信息


三、总结

  • 用户态调试main.c 示例涵盖了断点、条件断点、观察点、栈回溯、多线程、core dump 等典型用法。

  • 内核态调试:需要额外机制(KGDB 串口、QEMU gdbstub、crash/kdump)。

  • 符号表 + 源文件 是调试的关键,用户态依赖 -g 编译,内核态依赖 vmlinux

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐