到目前为止,使用gdb + qemu,我可以单步进入/越过linux内核源代码。是否可以同时调试用户空间程序?例如,单步执行一个从用户空间到内核空间的程序,这样我就可以通过发出info registers命令来观察qemu监视器上寄存器的变化。
info registers
t5fffqht1#
最小的分步设置
Mahouk is right,但这里有一个fully automated QEMU + Buildroot example,它假定你已经知道如何使用QEMU + gdb调试内核,以及更详细的解释:
readelf -h myexecutable | grep Entry
提供:
Entry point address: 0x4003a0
所以在GDB内部我们需要做的是:
add-symbol-file myexecutable 0x4003a0 b main
然后才在QEMU中启动可执行文件:
myexecutable
更可靠的方法是将myexecutable设置为init进程(如果可以的话)。add-symbol-file也被提到:How to load multiple symbol files in gdb
init
add-symbol-file
为什么你要这样做而不是gdbserver?
gdbserver
到目前为止,我只能看到一个用例:调试init:Debug init on Qemu using gdb否则,为什么不使用以下更可靠的方法,例如:进入系统调用:
qemu-system-* -s
gdbserver myexecutable
b sys_read
continue
我提出这一点是因为:
sharedlibrary
(gdb) sharedlibrary ../../staging/lib/libc.so.0 No loaded shared libraries match the pattern `../../staging/lib/libc.so.0'.
因此,由于大多数内核交互都通过stdib,因此您需要执行大量智能汇编步进来查找内核条目,这可能是不切实际的。直到,也就是说,有人写了一个更聪明的GDB脚本,每个步骤的指令,直到上下文切换发生或直到源变得可用。我想知道这样的脚本是否会太慢,因为朴素的方法对于每条指令都有与GDB通信的开销。这可能会让你开始:告诉gdb跳过标准文件
解析Linux内核数据结构
为了正确地进行用户态进程调试,这是我们最终必须做的:thread-aware gdb for the Linux kernel
3zwjbxry2#
我通过使用gdb命令add-symbol-file来添加用户空间程序调试信息来实现它。但是你必须知道这些程序的加载地址。因此,准确地说,您必须像往常一样通过将gdb连接到gdbserver来启动内核调试;然后,你可以添加那些程序调试信息。你也可以使用.gdbinit脚本。读取this
kkbh8khc3#
在麻省理工学院xv6操作系统实验室,我们可以使用file命令在不同的可执行文件之间切换符号表,包括xv6内核或运行在用户模式的程序。因此,我检查它是否工作或不对Linux内核和它的用户程序。结果是它也可以工作,但我们需要保证内核和用户程序是静态链接的。总之,您可以使用以下步骤调试用户程序:1.当gdb和QEMU连接时,通常需要加载vmlinux符号表。按ctrl+c停止QEMU,gdb正在等待以下命令。1.使用file [your user programs]命令切换符号表。1.尝试在用户程序上设置断点,continue gdb并在QEMU上运行用户程序。确保所有程序都是用-g编译的,以构建调试信息并静态链接。
file
vmlinux
file [your user programs]
-g
3条答案
按热度按时间t5fffqht1#
最小的分步设置
Mahouk is right,但这里有一个fully automated QEMU + Buildroot example,它假定你已经知道如何使用QEMU + gdb调试内核,以及更详细的解释:
提供:
所以在GDB内部我们需要做的是:
然后才在QEMU中启动可执行文件:
更可靠的方法是将
myexecutable
设置为init
进程(如果可以的话)。add-symbol-file
也被提到:How to load multiple symbol files in gdb为什么你要这样做而不是
gdbserver
?到目前为止,我只能看到一个用例:调试
init
:Debug init on Qemu using gdb否则,为什么不使用以下更可靠的方法,例如:进入系统调用:
qemu-system-* -s
gdbserver myexecutable
,如以下所述:https://reverseengineering.stackexchange.com/questions/8829/cross-debugging-for-mips-elf-with-qemu-toolchain/16214#16214gdbserver
的GDB中,尽可能靠近系统调用,这通常意味着进入libcb sys_read
用于读取系统调用gdbserver
,执行continue
我提出这一点是因为:
gdbserver
的情况下正确加载共享库:直接尝试sharedlibrary
得到:因此,由于大多数内核交互都通过stdib,因此您需要执行大量智能汇编步进来查找内核条目,这可能是不切实际的。
直到,也就是说,有人写了一个更聪明的GDB脚本,每个步骤的指令,直到上下文切换发生或直到源变得可用。我想知道这样的脚本是否会太慢,因为朴素的方法对于每条指令都有与GDB通信的开销。
这可能会让你开始:告诉gdb跳过标准文件
解析Linux内核数据结构
为了正确地进行用户态进程调试,这是我们最终必须做的:thread-aware gdb for the Linux kernel
3zwjbxry2#
我通过使用gdb命令add-symbol-file来添加用户空间程序调试信息来实现它。但是你必须知道这些程序的加载地址。因此,准确地说,您必须像往常一样通过将gdb连接到gdbserver来启动内核调试;然后,你可以添加那些程序调试信息。你也可以使用.gdbinit脚本。读取this
kkbh8khc3#
在麻省理工学院xv6操作系统实验室,我们可以使用
file
命令在不同的可执行文件之间切换符号表,包括xv6内核或运行在用户模式的程序。因此,我检查它是否工作或不对Linux内核和它的用户程序。结果是它也可以工作,但我们需要保证内核和用户程序是静态链接的。
总之,您可以使用以下步骤调试用户程序:
1.当gdb和QEMU连接时,通常需要加载
vmlinux
符号表。按ctrl+c停止QEMU,gdb正在等待以下命令。1.使用
file [your user programs]
命令切换符号表。1.尝试在用户程序上设置断点,
continue
gdb并在QEMU上运行用户程序。确保所有程序都是用
-g
编译的,以构建调试信息并静态链接。