在通过QEMU进行调试时,为什么GDB无法找到Linux内核的源代码行?

时间:2017-06-18 07:47:40

标签: debugging linux-kernel gdb

我一直在尝试让内核在QEMU中使用GDB进行远程调试,但是我无法单步执行或设置断点。这是GDB会议:

linux (master *) $ gdb vmlinux
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
[LICENSE TEXT]
The target architecture is assumed to be i386:x86-64
Reading symbols from vmlinux...done.
(gdb) target remote localhost:1234
localhost:1234: Connection timed out.
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0xffffffffa13507ee in ?? ()
(gdb) c
Continuing.
^C
Thread 1 received signal SIGINT, Interrupt.
0xffffffffa13507ee in ?? ()
(gdb) b rcu_process_callbacks
Breakpoint 1 at 0xffffffff81101800: file kernel/rcu/tree.c, line 3037.
(gdb) c
Continuing.
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0xffffffff81101800

Command aborted.
(gdb) 

我已经使用内核文档中提到的调试符号编译了内核:

linux (master *) $ grep CONFIG_DEBUG .config | grep -v "^#" 
CONFIG_DEBUG_DEVRES=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_BOOT_PARAMS=y

我还检查了构建内核是否有调试符号。

linux (master *) $ nm --debug-syms vmlinux | grep "\.debug"
0000000000000000 N .debug_abbrev
0000000000000000 N .debug_aranges
0000000000000000 N .debug_frame
0000000000000000 N .debug_info
0000000000000000 N .debug_line
0000000000000000 N .debug_loc
0000000000000000 N .debug_ranges
0000000000000000 N .debug_str

我正在使用以下命令行运行QEMU:

linux (master *) $ qemu-system-x86_64 -smp 4 -cpu host \
-m 2048 -kernel arch/x86/boot/bzImage \
-initrd ../obj/initramfs-busybox-x86.cpio.gz -nographic \
-append "console=ttyS0" -enable-kvm \
-drive file=../disk.img,if=virtio,cache=none -s

我错过了什么可能导致GDB像这样失败?我也无法从内核GDB脚本执行GDB扩展命令,所以我猜这必须让GDB不知道它正在调试内核吗?我需要启用KGDB吗?

我正在使用Linux 4.12-rc5内核。

2 个答案:

答案 0 :(得分:3)

KASLR(内核地址空间布局随机化)。

因为$pc$rip程序不以0xffffffff81xxxxxx开头,而是0xffffffffa1xxxxxx

在gdb中,使用add-symbol-file添加内核符号文件而不是file(这样您就可以指定.text .data .bss的地址,或者在内核args中禁用kaslr。 (我更喜欢前者,kaslr太有趣了,无法被禁用。)

答案 1 :(得分:1)

<强> qemu-system-x86_64 -append nokaslr

nokasrl Linux命令行参数禁用KASRL。

自v4.12起,默认情况下打开KASLR时需要这样做。

以下是使用它的highly automated Buildroot example