在qemu中使用GDB调试Linux内核无法命中函数或给定地址

vin*_*yal 6 debugging gdb qemu linux-kernel embedded-linux

我试图在qemu环境中使用GDB逐步了解内核启动顺序.

以下是我的设置:

在一个终端即时运行

~/Qemu_arm/bin/qemu-system-arm -M vexpress-a9 -dtb ./arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel ./arch/arm/boot/zImage -append "root=/dev/mmcblk0 console=ttyAMA0" -sd ../Images/RootFS.ext3 -serial stdio -s -S
Run Code Online (Sandbox Code Playgroud)

在其他终端

arm-none-linux-gnueabi-gdb vmlinux
Reading symbols from vmlinux...done.
(gdb) target remote :1234
Remote debugging using :1234
0x60000000 in ?? ()
Run Code Online (Sandbox Code Playgroud)

我的问题是如何在/ arch/arm/boot/compressed/*文件中设置代码的断点.

例如,我试图为misc.c中定义的decompress_kernel设置断点.

情况1:

(gdb)  b decompress_kernel
Function "decompress_kernel" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (decompress_kernel) pending.
(gdb) c
Continuing.
Run Code Online (Sandbox Code Playgroud)

上面的一个是无法启动qemu启动的功能.

案例2:

(gdb) b *0x80008000
Breakpoint 1 at 0x80008000: file arch/arm/kernel/head.S, line 89.
(gdb) c
Continuing.
Run Code Online (Sandbox Code Playgroud)

在这种情况下它也无法击中qemu启动.

案例3:

(gdb) b start_kernel
Breakpoint 1 at 0x8064d8d8: file init/main.c, line 498.
(gdb) c
Continuing.

Breakpoint 1, start_kernel () at init/main.c:498
498 {
(gdb) 
Run Code Online (Sandbox Code Playgroud)

在这种情况下功能正在击中,我可以逐步调试.

注意:我已启用调试,早期printk并尝试了hbreak

所以我的查询是:

  1. 为什么有些功能无法达到突破点?
  2. 这是qemu限制还是我需要启用更多功能?
  3. 我需要附加任何额外的参数吗?
  4. 如何调试早期内核启动

小智 2

您无法在 start_kernel 之前的任何函数上放置断点,因为您没有为它们加载符号。事实上,您正在使用内核的 zImage 启动 qemu,但从 vmlinux 加载符号。它们并不相同:zImage 基本上是 vmlinux 压缩为数据有效负载,然后附加到存根,存根在内存中解压缩,然后跳转到 start_kernel。

start_kernel 是 vmlinux 的入口点,它之前的任何函数(包括 decompress_kernel)都是存根的一部分,并且不存在于 vmlinux 中。

我不知道执行“arm-none-linux-gnueabi-gdb zImage”是否允许您调试存根,我总是在真实硬件上使用JTAG调试器对ARM内核进行早期调试,并且从未使用过qemu,对不起