Debugging 是否可以使用gdb和qemu同时调试linux用户空间程序和内核空间?

Debugging 是否可以使用gdb和qemu同时调试linux用户空间程序和内核空间?,debugging,linux-kernel,gdb,qemu,Debugging,Linux Kernel,Gdb,Qemu,到目前为止,有了gdb+qemu,我可以跨入/跨过linux内核源代码。是否可以同时调试用户空间程序?例如,通过发出info registers?我可以通过使用gdb命令add symbol file添加用户空间程序调试信息来实现从用户空间到内核空间的一步程序,这样我就可以观察qemu监视器上寄存器的变化。但是你必须知道这些程序的加载地址。因此,准确地说,您必须像往常一样通过将gdb连接到gdbserver来启动内核调试;然后,您可以添加这些程序调试信息。不过,您也可以使用.gdbinit脚本。

到目前为止,有了gdb+qemu,我可以跨入/跨过linux内核源代码。是否可以同时调试用户空间程序?例如,通过发出
info registers

我可以通过使用gdb命令add symbol file添加用户空间程序调试信息来实现从用户空间到内核空间的一步程序,这样我就可以观察qemu监视器上寄存器的变化。但是你必须知道这些程序的加载地址。因此,准确地说,您必须像往常一样通过将gdb连接到gdbserver来启动内核调试;然后,您可以添加这些程序调试信息。不过,您也可以使用.gdbinit脚本。阅读“最小步进setep设置”

,但这里有一个假设,假设您和一个更详细的调查:

readelf -h myexecutable | grep Entry
给出:

  Entry point address:               0x4003a0
因此,在GDB内部,我们需要做:

add-symbol-file myexecutable 0x4003a0
b main
然后才在QEMU中启动可执行文件:

myexecutable
更可靠的方法是将
myexecutable
设置为
init
进程(如果可以的话)

添加符号文件
还提到:

您为什么要这样做而不是
gdbserver

到目前为止,我只能看到一个用例:调试
init

否则,为什么不使用以下更可靠的方法,例如单步执行系统调用:

  • 启动两个远程GDB:
    • 一个带有
      qemu系统-*-s
    • 另一个
      gdbserver myexecutable
      ,解释如下:
  • gdbserver
    的GDB中尽可能靠近系统调用,这通常意味着进入libc
  • 在QEMU的GDB上,对read系统调用执行例如
    b sys\u read
  • 回到
    gdbserver
    ,继续
我提出这项建议是因为:

  • 当内核上下文切换到另一个使用相同虚拟地址的进程时,将QEMU GDB用于userland可能会导致随机跳转

  • 没有
    gdbserver
    ,我无法正确加载共享库:尝试
    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内核数据结构


要正确地进行userland进程调试,我们最终必须这样做:

为什么不呢?要查看任务切换,请尝试单步执行,尤其是在它“返回”到新任务时。否则,请尝试在各种系统调用上设置断点,以查看进程调用断点时会发生什么。谢谢Jonathon,但是当程序仍在用户空间中运行时,我可以中断吗?实际上,当进程在用户空间中运行时,我更感兴趣的是观察寄存器。@JeffLi您在qemu中调试过用户空间程序吗?我也在尝试同样的方法,但无法确定如何识别程序加载地址?objdump-h您可以查找.text部分的VMA(链接地址)和LMA(加载地址)。这些地址为您提供了所需的信息