GDB调试Linux
本文主要根据文档:Debugging kernel and modules via gdb — The Linux Kernel documentation
下载内核代码,对Linux内核代码进行单步调试。
Linux内核下载:The Linux Kernel Archives
搭建开发环境:👾 Debugging the Linux Kernel with Qemu and GDB
内核代码下载与编译
参考文章:内核代码下载并编译
如果你使用的是Ubuntu20.04 ,config中有个地方需要修改。参考文章
CONFIG_SYSTEM_TRUSTED_KEYS=""
如果不修改这个地方,你将无法编译出bzImage
qemu启动
qemu更多的使用,可以参考官网:
正常启动,直接进入到命令行界面:
qemu-system-x86_64 -kernel /home/jewinh/linux-5.13/arch/x86_64/boot/bzImage -initrd /home/jewinh/ramdisk.img -m 512
进入到可以GDB调试捕获程序运行的第一句
qemu-system-x86_64 -kernel /home/jewinh/linux-5.13/arch/x86_64/boot/bzImage -initrd /home/jewinh/ramdisk.img -m 512 -s -S -append "console=ttyS0 nokaslr"
配置文件直接用这个: .config
GDB调试
-
# 当qemu已经进入到调试状态,也就是我们的系统准备运行时,停住了,这个时候,我们就可以用GDB工具连接到qemu,对内核代码进行调试。 gdb /home/jewinh/linux-5.13/vmlinux #调试内核 target remote :1234 # 远程连接到qemu hb start_kernel # 断点打到start_kernel c # 继续执行直到遇到断点 tui enable # 打开代码界面,看到调试内容。 s # 继续下一步。
使用vscode调试
启动内核
qemu-system-x86_64 -kernel /root/linux-5.13/arch/x86_64/boot/bzImage -initrd /root/ramdisk.img -m 512 -s -S -append "console=ttyS0 nokaslr"
vscode配置
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: Debugging in Visual Studio Code
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/vmlinux",
"miDebuggerServerAddress": "127.0.0.1:1234",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
GDB使用方法:
start #开始调试,停在第一行代码处,(gdb)start
l #list的缩写查看源代码,(gdb) l [number/function]
b <lines> #b: Breakpoint的简写,设置断点。(gdb) b 10
b <func> #b: Breakpoint的简写,设置断点。(gdb) b main
b filename:[line/function] #b:在文件filename的某行或某个函数处设置断点
i breakpoints #i:info 的简写。(gdb)i breakpoints
d [bpNO] #d: Delete breakpoint的简写,删除指定编号的某个断点,或删除所有断点。断点编号从1开始递增。 (gdb)d 1
s #s: step执行一行源程序代码,如果此行代码中有函数调用,则进入该函数;(gdb) s
n #n: next执行一行源程序代码,此行代码中的函数调用也一并执行。(gdb) n
r #Run的简写,运行被调试的程序。如果此前没有下过断点,则执行完整个程序;如果有断点,则程序暂停在第一个可用断点处。(gdb) r
c #Continue的简写,继续执行被调试程序,直至下一个断点或程序结束。(gdb) c
finish #函数结束
p [var] #Print的简写,显示指定变量(临时变量或全局变量 例如 int a)的值。(gdb) p a
display [var] #display,设置想要跟踪的变量(例如 int a)。(gdb) display a
undisplay [varnum] #undisplay取消对变量的跟踪,被跟踪变量用整型数标识。(gdb) undisplay 1
set args #可指定运行时参数。(gdb)set args 10 20
show args #查看运行时参数。
q #Quit的简写,退出GDB调试环境。(gdb) q
help [cmd] #GDB帮助命令,提供对GDB名种命令的解释说明。如果指定了“命令名称”参数,则显示该命令的详细说明;如果没有指定参数,则分类显示所有GDB命令,供用户进一步浏览和查询。(gdb)help
回车 #重复前面的命令,(gdb)回车
x/ <n/f/u> <addr> ,扫描内存地址中的值
n: 个数
f: 格式 : s→字符串,i→指令 , x→ 16进制 ,d → 10进制 ,u→ 16进制无符号 ,o→ 8进制 ,t→ 2进制 ,a → 16进制 ,c → 字符 ,f→ 浮点数格式,
u: 当前地址往后取多少个字节数,b ,h, w, g
x/3uh 0x54320 → 从地址0x54320开始读,2个字节一个单位,读3个单位,按16进制无符号整形数来表示。
调用栈 : GDB查看栈信息
frame
backtrace <n>
info frame
watch 变量名