使用GDB+QEMU调试Linux内核环境搭建


        一直想搭建一个debug kernel的环境,这样的话就可以对kernel启动的各个部分,运行过程中的特定部分进行定位,跟踪,调试,尤其是启动阶段。如果没有debug kernel的环境,那么我们只有使用其他方式来进行调试,例如printk。当然还有kgdb,不过此次不讨论此方式。
        下面我们来进行详细的环境搭建。

1 busybox软件

1.1 busybox下载

        可以从busybox官网地址下载最新版本,或者直接使用wget下载我使用的版本
        [root@localhost ~]# wget https://www.busybox.net/downloads/busybox-1.29.0.tar.bz2
        命令执行效果如下:
在这里插入图片描述

1.2 busybox编译安装

        在编译busybox之前,我们需要对其进行设置,如下所示
首先对压缩包进行解压,之后执行make menuconfig,如下

[root@localhost temp]# tar jxvf busybox-1.29.0.tar.bz2
............
[root@localhost busybox-1.29.0]# make menuconfig

在这里插入图片描述

在这里插入图片描述
        之后选择Exit退出,到这里我们就可以编译busybox了,执行下面的命令

[root@localhost busybox-1.29.0]# make -j 4
..............
[root@localhost busybox-1.29.0]# make install
  ./_install//bin/arch -> busybox
  ./_install//bin/ash -> busybox
  ./_install//bin/base64 -> busybox

  ....................
  ....................

  ./_install//usr/sbin/ubirsvol -> ../../bin/busybox
  ./_install//usr/sbin/ubiupdatevol -> ../../bin/busybox
  ./_install//usr/sbin/udhcpd -> ../../bin/busybox


--------------------------------------------------
You will probably need to make your busybox binary
setuid root to ensure all configured applets will
work properly.

--------------------------------------------------

[root@localhost busybox-1.29.0]# ls -l _install/
total 8
drwxr-xr-x 2 root root 4096 Jan 26 20:02 bin
lrwxrwxrwx 1 root root   11 Jan 26 20:02 linuxrc -> bin/busybox
drwxr-xr-x 2 root root 4096 Jan 26 20:02 sbin
drwxr-xr-x 4 root root   27 Jan 26 20:02 usr

 

2 构建initramfs根文件系统

        创建initramfs,其中包含BusyBox可执行程序、必要的设备文件、启动脚本init。这里没有内核模块,如果需要调试内核模块,可将需要的内核模块包含进来。init脚本只挂载了虚拟文件系统procfs和sysfs,没有挂载磁盘根文件系统,所有调试操作都在内存中进行,不会落磁盘。

[root@localhost temp]# ls
busybox-1.29.0  busybox-1.29.0.tar.bz2
[root@localhost temp]# mkdir initramfs
[root@localhost temp]# cd initramfs
[root@localhost initramfs]# cp ../busybox-1.29.0/_install/* -rf ./
[root@localhost initramfs]# mkdir dev proc sys
[root@localhost initramfs]# sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/
[root@localhost initramfs]# rm -f linuxrc
[root@localhost initramfs]# vim init
[root@localhost initramfs]# chmod a+x init
[root@localhost initramfs]# ls
bin  dev  init  proc  sbin  sys  usr

        其中init的内容如下

#!/bin/busybox sh
mount -t proc none /proc
mount -t sysfs none /sys

exec /sbin/init

        打包initramfs:

[root@localhost initramfs]# find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
.
./bin
./bin/busybox
./bin/arch
............
............
./dev/tty3
./dev/tty4
./proc
./sys
./init
5285 blocks

[root@localhost initramfs]# ls ../
busybox-1.29.0  busybox-1.29.0.tar.bz2  initramfs  initramfs.cpio.gz

 

3 kernel代码下载及编译

3.1 kernel代码下载

        可以从kernel官网下载需要的kernel版本,我这里使用的是linux-4.14.95版本。执行下面的命令下载即可

[root@localhost temp]# wget https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.14.95.tar.gz

--2021-01-26 20:21:12--  https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.14.95.tar.gz
Resolving mirrors.edge.kernel.org (mirrors.edge.kernel.org)... 147.75.95.133, 2604:1380:3000:1500::1
Connecting to mirrors.edge.kernel.org (mirrors.edge.kernel.org)|147.75.95.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 156176622 (149M) [application/x-gzip]
Saving to: ‘linux-4.14.95.tar.gz’

100%[====================================================================================================================>] 156,176,622 12.2MB/s   in 16s

2021-01-26 20:21:29 (9.30 MB/s) - ‘linux-4.14.95.tar.gz’ saved [156176622/156176622]

3.2 kernel生成需要的.config文件

        之后就是tar包的解压,完成后进入目录执行make menuconfig,如下

[root@localhost temp]# tar -zxf linux-4.14.95.tar.gz
[root@localhost temp]# cd linux-4.14.95/
[root@localhost linux-4.14.95]# ls
arch   certs    CREDITS  Documentation  firmware  include  ipc     Kconfig  lib          Makefile  net     samples  security  tools  virt
block  COPYING  crypto   drivers        fs        init     Kbuild  kernel   MAINTAINERS  mm        README  scripts  sound     usr

[root@localhost linux-4.14.95]# make menuconfig

        我们需要选择开启两个选项:Compile the kernel with debug info 和 Provide GDB scripts for kernel debugging。
        Compile the kernel with debug info设置路径:在这里插入图片描述在这里插入图片描述

在这里插入图片描述

        Provide GDB scripts for kernel debugging设置路径:
在这里插入图片描述

在这里插入图片描述

3.3 编译kernel代码

[root@localhost linux-4.14.95]# make -j4
[root@localhost linux-4.14.95]# make modules
[root@localhost linux-4.14.95]# make modules_install
[root@localhost linux-4.14.95]# make install

4 调试

4.1QEMU程序的命令行

#!/bin/bash
KERNEL_MIRROR=kernel_source/linux-4.14.95/arch/x86_64/boot/bzImage
/usr/local/bin/qemu-system-x86_64  \
    -s \
    -smp 2 \
    -kernel  $KERNEL_MIRROR \
    -initrd initramfs.cpio.gz \
    -nographic \
    -append "console=ttyS0 nokaslr"

  • -s是-gdb tcp::1234缩写,监听1234端口,在GDB中可以通过target remote localhost:1234连接
  • -smp 设置多个CPU
  • -kernel指定编译好的调试版内核;
  • -initrd指定制作的initramfs;
  • -nographic取消图形输出窗口,使QEMU成简单的命令行程序;
  • -append "console=ttyS0"将输出重定向到console,将会显示在标准输出stdio。

4.2 启动gdb

        我们需要使用源码编译出来的vmlinux,此文件在kernel源代码的root目录,我们需要到此目录执行gdb vmlinux命令

[root@localhost kernel_source]# cd linux-4.14.95/
[root@localhost linux-4.14.95]# ls
arch        certs    crypto         firmware   include  Kbuild   lib          mm               Module.symvers  samples   sound       usr      vmlinux-gdb.py
block       COPYING  Documentation  fs         init     Kconfig  MAINTAINERS  modules.builtin  net             scripts   System.map  virt     vmlinux.o
built-in.o  CREDITS  drivers        gdb.debug  ipc      kernel   Makefile     modules.order    README          security  tools       vmlinux

[root@localhost linux-4.14.95]# gdb vmlinux

 
        启动gdb后可以使用下面的命令来连接之前的qemu vm,成功后执行bt,如下

(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0xffffffff81734122 in native_safe_halt () at ./arch/x86/include/asm/irqflags.h:57
57              asm volatile("sti; hlt": : :"memory");
(gdb) bt
#0  0xffffffff81734122 in native_safe_halt () at ./arch/x86/include/asm/irqflags.h:57
#1  0xffffffff81733df8 in arch_safe_halt () at ./arch/x86/include/asm/paravirt.h:94
#2  default_idle () at arch/x86/kernel/process.c:564
#3  0xffffffff810ce286 in cpuidle_idle_call () at kernel/sched/idle.c:156
#4  do_idle () at kernel/sched/idle.c:246
#5  0xffffffff810ce4ef in cpu_startup_entry (state=CPUHP_ONLINE) at kernel/sched/idle.c:351
#6  0xffffffff81726d56 in rest_init () at init/main.c:435
#7  0xffffffff8252711b in start_kernel () at init/main.c:710
#8  0xffffffff810000d5 in secondary_startup_64 () at arch/x86/kernel/head_64.S:240
#9  0x0000000000000000 in ?? ()
(gdb) b do_IRQ
Breakpoint 1 at 0xffffffff81802620: file arch/x86/kernel/irq.c, line 217.
(gdb) c
Continuing.

Breakpoint 1, do_IRQ (regs=0xffffffff82003de8 <init_thread_union+15848>) at arch/x86/kernel/irq.c:217
217     {
(gdb) bt
#0  do_IRQ (regs=0xffffffff82003de8 <init_thread_union+15848>) at arch/x86/kernel/irq.c:217
#1  0xffffffff81800947 in common_interrupt () at arch/x86/entry/entry_64.S:571
#2  0xffffffff82003de8 in init_thread_union ()
#3  0x0000000000000000 in ?? ()

        至此环境搭建完毕。

参考文档

1 使用QEMU和GDB调试Linux内核
2 Linux内核调试 之 qemu+gdb
3 2020-02-27-Linux内核0-使用QEMU和GDB调试Linux内核

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值