【MenuOS】可gdb调试内核代码的MenuOS搭建

可gdb调试内核代码的MenuOS搭建

实验环境:Ubuntu18.04.1, qemu

1. 尝试升级当前系统内核

1.1 查看当前系统内核

当前内核为5.0.0-23-generic

$ uname -a
Linux ubuntu 5.0.0-23-generic #24~18.04.1-Ubuntu SMP Mon Jul 29 16:12:28 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

1.2 下载Linux内核源代码

# 创建目录,下载最新内核
~$ mkdir ~/LinuxKernel
~$ cd ~/LinuxKernel/
~/LinuxKernel$ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.2.tar.xz

1.3 下载过程如下

linux-5.4.2.tar.xz 100%[============================================>] 104.37M 275KB/s 用时 3m 9s   
2019-12-10 19:37:51 (566 KB/s) - 已保存 “linux-5.4.2.tar.xz” [109441848/109441848])

1.4 解压并编译内核

# 解压xz压缩文件
~/LinuxKernel$ xz -d linux-5.4.2.tar.xz 
# 提取tar归档文件
~/LinuxKernel$ tar -xvf linux-5.4.2.tar
# 安装编译依赖
~/LinuxKernel$ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev

# 编译内核
~/LinuxKernel$ cd linux-5.4.2/
~/LinuxKernel/linux-5.4.2$ make i386_defconfig # 按照默认值生成32位x86配置文件
~/LinuxKernel/linux-5.4.2$ make

编译完成

1.5 尝试升级当前系统内核

最后失败了,不想对系统内核尝试升级的/或者不是在虚拟机上进行的,这部分可以跳过。

1.5.1 系统快照

防止升级当前系统内核后无法启动,创建系统快照

1.5.2 升级内核

~/LinuxKernel/linux-5.4.2$ sudo make modules install

~/LinuxKernel/linux-5.4.2$ sudo make install

~/LinuxKernel/linux-5.4.2$ sudo update-grub
# 接着重启系统
~/LinuxKernel/linux-5.4.2$ reboot

重启后发现,系统起不来了,还好进行了快照备份。。。

快照恢复,算了不折腾当前系统内核了

2. QEMU虚拟机

2.1 下载安装QEMU

~/LinuxKernel$ sudo apt install qemu
# 使用qemu加载linux内核,参数kernel需要调整为对应版本号的镜像
~/LinuxKernel$ qemu-system-i386 -kernel linux-5.4.2/arch/x86/boot/bzImage

2.2 构造menuOS

~/LinuxKernel$ git clone https://github.com/mengning/menu.git
~/LinuxKernel/menu$ cd menu
~/LinuxKernel/menu$ sudo apt-get install libc6-dev-i386  # 32位编译所需要的库
~/LinuxKernel/menu$ nvim Makefile

两处地方需要修改,第一个是修改为对应启动命令,第二个是修改内核版本号为之前编译的内核文件夹名

~/LinuxKernel/menu$ make rootfs

接着就会启动MenuOS,同时Linux目录下会生成一个rootfs.img,下次启动就不用make

比如关了qemu后,下次可以在LinuxKernel文件夹下直接通过qemu-system-i386 -kernel linux-5.4.2/arch/x86/boot/bzImage -initrd rootfs.img来启动虚拟机

2.3 集成TCP服务端测试网络功能

在MenuOS中集成我们的TCP服务端程序

~/LinuxKernel$ git clone https://github.com/mengning/linuxnet.git
~/LinuxKernel$ cd linuxnet/lab2
~/LinuxKernel/linuxnet/lab2$ make
~/LinuxKernel/linuxnet/lab2$ cd ~/LinuxKernel/menu/

会发现menuos中多个一个replyhi的命令

此时只是集成了TCP服务端程序

检查lab3的Makefile,修改内核路径部分,并构建

~/LinuxKernel/linuxnet/lab3$ nvim Makefile
~/LinuxKernel/linuxnet/lab3$ make rootfs

运行服务并测试TCP功能

2.4 重新编译内核

为了能进行调试,对内核进行重新编译

~/LinuxKernel/menu$ make menuconfig
# kernel hacking—>Compile-time checks and compiler options—> 
# [*] compile the kernel with debug info

依次进入kernel hackingCompile-time checks and compiler options,选中compile the kernel with debug info,然后save

save的时候检查下是否有该信息,接着就可以Esc退出了

~/LinuxKernel/menu$ make

make重新编译(时间较长)

2.5 启动带gdbserver的MenuOS

~/LinuxKernel$ qemu-system-i386 -kernel linux-5.4.2/arch/x86/boot/bzImage -initrd rootfs.img -append "root=/dev/sda init=/init nokaslr" -s -S
  • -S freeze CPU at startup(use c to start execution)
  • -s shorthand for -gdb tcp::1234(可以使用-gbd tcp::xxxx来更换端口)
  • nokaslr KASLR是kernel address space layout randomization的缩写

运行命令后,qemu虚拟机会等待gdb连接,所以是一个黑屏的界面

2.6 启动gdb连接gdbserver

2.6.1 新打开一个窗口

~/LinuxKernel$ gdb
(gdb) file ~/LinuxKernel/linux-5.4.2/vmlinux
(gdb) target remote:1234  # 设置gdbserver端口
(gdb) break start_kernel  # 设置启动断点
(gdb) break sys_socketcall  # 套接字调用断点

2.6.2 输入c让系统继续启动

(gdb) c
(gdb) list  # 停下来后通过list查看断点上下文命令

可以看到

gdb中继续输入c,让系统继续启动,发现进入了socketcall断点

在qemu中可以看到是在启动本地环回端口

接着c继续,加上环回地址总共进入了三次socketcall断点,在qemu上分别是lo,eth0,list all interfaes,然后进入了系统

2.6.3 使用tcp服务端和客户端通信

这里要重新集成测试用的TCP服务端和客户端

(gdb) replyhi
(gdb) hello

在这期间,可以看到多次进入socketcall断点

到此通过gdb可以跟踪到内核代码,比如start_kernelsys_socketcall等内核函数的MenuOS已搭建完成。


作者:SA19225176,万有引力丶

参考资料来源:USTC Socket网络编程-编译构建调试Linux系统

posted @ 2019-12-11 13:31  万有引力丶  阅读(776)  评论(0编辑  收藏  举报