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

时间:2014-02-25 04:30:05

标签: linux linux-kernel embedded qemu powerpc

我已经能够使用以下方式启动基于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"

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

由于我在Qemu中使用了-s标志,因此我可以使用交叉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  }

但是,如果我删除-s标志并尝试通过/dev/ttyS0进入内核,则会向我提供权限被拒绝错误:

(gdb) set remotebaud 115200
(gdb) target remote /dev/ttyS0
permission denied 

是不是因为它被Qemu控制了?另外在互联网上的示例中,kgdboc已设置为ttyAMA0,我已理解为AMBA总线,这是基于ARM的系统特有的。我们有类似PowerPC的东西吗?我在这里做错了吗?

2 个答案:

答案 0 :(得分:3)

您似乎混淆了guest虚拟机的主机串行设备/ dev / ttyS0,以及来宾内核中QEMU自己的KGDB gdbserver。

QEMU通常没有理由触摸主机的串口。这样做的唯一原因是,如果您想拥有一台物理机主机QEMU,并有效地将其物理串口提供给客户机,那么您就可以使用通过实际串行电缆连接的不同物理机来调试客。

当您使用-s标志时,您告诉QEMU运行自己的GDB服务器(默认情况下侦听主机环回TCP端口1234),允许您进入正在运行的任何程序,是一个内核或引导程序或其他东西。这与guest虚拟机内核本身配合KGDB调试不同。

如果你想使用KGDB,你需要在内核版本中配置KGDB以使用仿真串口的客户端,然后告诉主机上的GDB使用它的主机端模拟端口。 QEMU command line documenation详细介绍了这一点:

  

调试/专家选项:

     

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

     

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

一些的缩略列表是您更有趣的选项:

  

“PTY”   [仅限Linux] Pseudo TTY(自动分配新的PTY)

     

“的/ dev / XXX”   [仅限Linux]使用主机tty,例如“的/ dev / ttyS0来”。主机串口参数根据模拟的参数设置。

这是您不想要的 - 除非您想将串行电缆用于运行GDB的其他物理机器。

  

“TCP:[主持人]:端口[,服务器] [,NOWAIT] [,NODELAY]”   TCP Net Console有两种操作模式。它可以将串行I / O发送到某个位置或等待来自某个位置的连接。默认情况下,TCP Net Console将发送到端口的主机。如果使用服务器选项,QEMU将在继续之前等待客户端套接字应用程序连接到端口,除非指定了nowait选项。 nodelay选项禁用Nagle缓冲算法。如果省略host,则假定为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:路径[,服务器] [,NOWAIT]”   使用unix域套接字而不是tcp套接字。除了使用unix域套接字路径进行连接之外,该选项的工作方式与> gt;指定了-serial tcp相同。

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

您可能需要首先配置其中一个选项,在没有KGDB的情况下运行并获取shell并确定调用模拟设备的客户端的内容,然后使用配置为使用它的KGDB重新启动。

答案 1 :(得分:3)

KGDB + QEMU一步一步

首先,QEMU的-gdb选项比KGDB强大得多,所以你可能想要使用它:How to debug the Linux kernel with GDB and QEMU? QEMU是一个简单的方法来准备KGDB准备对于真正的硬件。我在:Linux kernel live debugging, how it's done and what tools are used?

发布了一些Raspberry Pi KGDB指针

如果您想从头开始快速入门,我已经在https://github.com/cirosantilli/linux-kernel-module-cheat/tree/d424380fe62351358d21406280bc7588d795209c#kgdb

制作了一个最小化的全自动Buildroot示例

主要步骤是:

  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
    

    其中大部分都不是强制性的,但这是我测试过的。

  2. 添加到您的QEMU命令:

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

    gdb -ex 'file vmlinux' -ex 'target remote localhost:1234'
    
  4. 在GDB中:

    (gdb) c
    

    并且靴子应该完成。

  5. 在QEMU:

    echo g > /proc/sysrq-trigger
    

    GDB应该破解。

  6. 现在我们完成了,您可以像往常一样使用GDB:

    b sys_write
    c
    
  7. 在Ubuntu 14.04中测试。

    <强> ARM

    无法让它发挥作用。可能与:How to use kgdb on ARM??

    有关