如何使用QEMU和KGDB调试Linux内核?

Hig*_*eat 6 linux embedded qemu powerpc linux-kernel

我已经能够使用以下方法来启动基于PowerPC的系统(具体来说为MPC8544DS)来调用qemu(v1.7.0)

qemu-system-ppc -M mpc8544ds -m 512 -kernel zImage -s -nographic -initrd busyboxfs.img -append "root=/dev/ram rdinit=/bin/sh kgdboc=ttyS0,115200 kgdbwait"
Run Code Online (Sandbox Code Playgroud)

其中zImage是一个自定义的交叉编译Linux内核(v2.6.32),已启用并编译了KGDB(用于启动代码调试),并且busyboxfs.img是基于busybox的rootfs。

由于我正在使用-sQemu 的标志,因此可以使用跨gdb闯入内核,如下所示:

(gdb) target remote localhost:1234
Remote debugging using localhost:1234
mem_serial_in (p=<value optimized out>, offset=5) at drivers/serial/8250.c:405
405  }
Run Code Online (Sandbox Code Playgroud)

但是,如果我删除该-s标志并尝试闯入内核,/dev/ttyS0则会给我一个权限被拒绝的错误:

(gdb) set remotebaud 115200
(gdb) target remote /dev/ttyS0
permission denied 
Run Code Online (Sandbox Code Playgroud)

是因为它被Qemu保留了吗?另外,在互联网上的示例中ttyAMA0,我已经了解了kgdboc ,该AMBA总线代表特定于基于ARM的系统的总线。我们对PowerPC有类似的东西吗?我在这里做错什么了吗?

Chr*_*ton 5

您似乎混淆了客户机的主机串行设备 /dev/ttyS0 和客户机内核中用于 KGDB 的 QEMU 自己的 gdbserver。

QEMU 通常没有理由接触主机的串行端口。真正这样做的唯一原因是,如果您想让一台物理机托管 QEMU,并有效地将其物理串行端口提供给来宾,以便您可以使用通过实际串行电缆连接的不同物理机来调试客人。

当您使用 -s 标志时,您告诉 QEMU 运行它自己的 GDB 服务器(默认情况下侦听主机环回 TCP 端口 1234)允许您闯入来宾上运行的任何程序,无论是内核还是引导加载程序或其他东西. 这与让来宾内核本身通过 KGDB 与调试合作不同。

如果您想使用 KGDB,您将需要在内核构建中配置 KGDB 以使用模拟串行端口的来宾端,然后告诉主机上的 GDB 使用该模拟端口的主机端。该QEMU命令行documenation覆盖了本详细:

调试/专家选项:

'-serial dev' 将虚拟串口重定向到主机字符设备 dev。默认设备在图形模式下是 vc,在非图形模式下是 stdio。

此选项可多次使用以模拟最多 4 个串行端口。

一些更有趣的选项的缩写列表:

'pty' [仅限 Linux] 伪 TTY(自动分配新的 PTY)

'/dev/XXX' [仅限 Linux] 使用主机 tty,例如 '/dev/ttyS0'。主机串口参数根据仿真设置。

这是您不想要的 - 除非您想使用串行电缆连接到将运行 GDB 的不同物理机器。

'tcp:[host]:port[,server][,nowait][,nodelay]' TCP 网络控制台有两种操作模式。它可以将串行 I/O 发送到某个位置或等待来自某个位置的连接。默认情况下,TCP 网络控制台发送到端口的主机。如果您使用服务器选项 QEMU 将在继续之前等待客户端套接字应用程序连接到端口,除非指定了 nowait 选项。nodelay 选项禁用 Nagle 缓冲算法。如果省略主机,则假定为 0.0.0.0。一次只接受一个 TCP 连接。您可以使用 telnet 连接到相应的字符设备。

示例将 tcp 控制台发送到 192.168.0.2 端口 4444 -serial tcp:192.168.0.2:4444

在端口 4444 上侦听和等待连接的示例 -serial tcp::4444,server

不等待和侦听 ip 192.168.0.100 端口 4444 -serial tcp:192.168.0.100:4444,server,nowait 的示例

这是一个很好且常见的选择。您可以使用基本相同的 GDB 语法,例如,如果您指定环回接口地址 127.0.0.1 和端口 1234,您可以使用与以前完全相同的 GDB 命令。

'unix:path[,server][,nowait]' 使用 unix 域套接字而不是 tcp 套接字。该选项的工作方式与您已指定 -serial tcp 相同,但 unix 域套接字路径用于连接。

这也是一个不错的选择,假设您的 GDB 支持它。

您可能需要首先配置这些选项之一,在没有 KGDB 的情况下运行并启动 shell 并找出模拟设备的来宾端被调用的内容,然后在配置为使用它的 KGDB 的情况下重新启动。


Cir*_*四事件 5

KGDB + QEMU逐步

首先,QEMU的-gdb选项严格比KGDB更强大,因此您可能要使用它:如何使用GDB和QEMU调试Linux内核?但是,QEMU是与KGDB一起为实际硬件做准备的一种简便方法。我在以下位置发布了一些Raspberry Pi KGDB指针:Linux内核实时调试,如何完成调试以及使用了哪些工具?

如果您想从头开始快速入门,我在以下网址提供了一个最小的全自动Buildroot示例:https : //github.com/cirosantilli/linux-kernel-module-cheat/tree/d424380fe62351358d21406280bc7588d795209c#kgdb

主要步骤是:

  1. 使用以下命令编译内核:

    CONFIG_DEBUG_KERNEL=y
    CONFIG_DEBUG_INFO=y
    
    CONFIG_CONSOLE_POLL=y
    CONFIG_KDB_CONTINUE_CATASTROPHIC=0
    CONFIG_KDB_DEFAULT_ENABLE=0x1
    CONFIG_KDB_KEYBOARD=y
    CONFIG_KGDB=y
    CONFIG_KGDB_KDB=y
    CONFIG_KGDB_LOW_LEVEL_TRAP=y
    CONFIG_KGDB_SERIAL_CONSOLE=y
    CONFIG_KGDB_TESTS=y
    CONFIG_KGDB_TESTS_ON_BOOT=n
    CONFIG_MAGIC_SYSRQ=y
    CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
    CONFIG_SERIAL_KGDB_NMI=n
    
    Run Code Online (Sandbox Code Playgroud)

    其中大多数不是强制性的,但这是我测试过的。

  2. 添加到您的QEMU命令:

    -append 'kgdbwait kgdboc=ttyS0,115200' \
    -serial tcp::1234,server,nowait
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用以下命令从Linux内核源树的根目录运行GDB:

    gdb -ex 'file vmlinux' -ex 'target remote localhost:1234'
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在GDB中:

    (gdb) c
    
    Run Code Online (Sandbox Code Playgroud)

    并且启动应该完成。

  5. 在QEMU中:

    echo g > /proc/sysrq-trigger
    
    Run Code Online (Sandbox Code Playgroud)

    GDB应该崩溃了。

  6. 现在我们完成了,您可以照常使用GDB:

    b sys_write
    c
    
    Run Code Online (Sandbox Code Playgroud)

在Ubuntu 14.04中测试。

无法正常工作。可能与以下内容有关:如何在ARM上使用kgdb?