Linux kernel 双机调试

准备

  • VMWare 16 (15也行)

  • Windows 宿主机

  • Ubuntu 20.04 虚拟机 (用作起 gdb 调试)

  • Debian 10 虚拟机 (用作被调试)

  • 一台性能好点的服务器 (用作编译内核)

编译内核

  1. https://www.kernel.org/pub/linux/kernel/ 中下载想要的内核版本并解压

  2. 将 debian 自带的 config 文件复制到解压后的内核源码目录下

    cp /boot/config-`uname -r` ./.config

  3. 配置编译环境

    我选择在 docker 中编译,好处是可以使用特定版本的 gcc 又不会污染公共服务器环境

    可以在 Debian 的 config 文件中看到编译时用的 gcc 版本,保证版本号一样就不会出错了

    docker pull gcc:8.3.0

    docker run -dit -v `pwd`:/root/linux-4.20.7 gcc:8.3.0

    docker exec -it <container hash> bash

    步骤 4 在 docker 内操作

  4. 编译为 deb 包

    apt update && apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev bc kmod cpio fakeroot -y

    make menuconfig

    勾选

    1
    2
    3
    Kernel hacking --->

    ---> <*> Export kernel pagetable layout to userspace via debugfs

    save exit 即可,作用是配置.config中没有配置的东西 (内核版本不同 配置内容不完全相同)

    make -j `getconf _NPROCESSORS_ONLN` deb-pkg LOCALVERSION=-custom

    注: 需要先把 CONFIG_SYSTEM_TRUSTED_KEYS 注释掉

安装内核

sudo dpkg -i linux-image*

sudo update-grub

旧内核卸载与否都可以,我选择留着以备不时之需

配置双机调试

在 Debian 的虚拟机目录下的 .vmx 文件末尾添加

1
2
3
4
5
6
7
debugStub.listen.guest64 = "TRUE"                 
debugStub.listen.guest64.remote = "TRUE"
debugStub.port.guest64 = "8864"
debugStub.listen.guest32 = "TRUE"
debugStub.listen.guest32.remote = "TRUE"
debugStub.port.guest32 = "8832"
debugStub.hideBreakpoints= "TRUE"

最后的 hideBreakpoints 是配置硬件断点, “TRUE”为硬件断点, “FALSE”为软件断点

一定要有 debugStub.listen.guest64.remote,否则只能在宿主机(windows)上调试

如果需要虚拟机在开机时等待 gdb attach,则加入

monitor.debugOnStartGuest64 = "TRUE"

配置宿主机 (windows) 防火墙

进入 控制面板->系统和安全->Windows Defender 防火墙->高级设置

在入站规则中添加一个8864端口的TCP规则(如果要调试32位内核的话也开个8832的端口)

关闭 KASLR

编辑被调试机 /etc/default/grub

quiet加入 nokaslr

update-grub

愉快调试

gdb ./vmlinux

gdb> target remote <宿主机ip>:8864