Assumptions: Host machine is linux.
- Download virtualbox
- Install a linux flavour. Preference for Debian since distro-dependent commands in the following steps will be debian-dependent
- Run your VM.
- Inside VM, download last kernel code from kernel.org
- Extract linux src code
- Copy your configuration file from
/boot/config-$(uname -r)to.configin the extract linux src code folder. - Make sure
.confighas the following options: CONFIG_FRAME_POINTER=y , CONFIG_KGDB=y , CONFIG_KGDB_SERIAL_CONSOLE=y , CONFIG_KGDB_KDB=y , CONFIG_KDB_KEYBOARD=y. Change if necessary. Alternatively usemake xconfigto configure in UI. - Install compilation dependencies (debian:
sudo apt-get install build-essential libncurses-dev bison flex libssl-dev libelf-dev) - Compile the kernel:
make -j8 - Compile kernel modules:
sudo make modules_install - Install kernel to
/boot:sudo make install - Output will be in
/bootdirectory. GRUB needs to be updated. On debian, run:sudo update-initramfs -c -k <KERNEL VERSION>. Example:sudo update-initramfs -c -k 5.6.9 - After that, run
sudo update-grub. - For more info about the compilation part, here: https://www.cyberciti.biz/tips/compiling-linux-kernel-26.html
- Go back to linux src folder and find the compiled file
vmlinux. Send this file to your host machine, either usingscpor virtualbox shared folders. - Reboot the VM. Afterwards, run
uname -rms. You should see the new just-compiled version. - Run
sudo vim /etc/default/grub - Append to
GRUB_CMDLINE_LINUX_DEFAULTthe following parameters:kgdboc=ttyS0,115200 nokaslr. The first parameter tells the debugger to be active on serial port/dev/ttyS0. The second one tells to load the kernel without address space layout randomization, so the debugger can find the function addresses properly. Example:GRUB_CMDLINE_LINUX_DEFAULT=quiet splash kgdboc=ttyS0,115200 nokaslr. - Run
sudo update-grub. - Turn off the VM.
- On the host machine, open VM settings and go to Serial Ports. Go to tab
Port 1. MarkEnable serial port. ChoosePort Number=COM1,Port Mode=Host Pipeand Path/Address=/tmp/pipe. Don't markConnect to existing pipe/socket. - Run the VM again.
- Open a terminal in the VM and go to su mode by running
sudo su - Run
echo g > /proc/sysrq-triggerto make the kernel execution stop and wait for the debugger to be attached. Note that once you run this command, the VM will be frozen until you continue the execution using GDB later. - On the host machine, run
socat -d /tmp/pipe TCP4-LISTEN:65335. This will create a TCP connection from the/tmp/pipe. Even though GDB supports connecting directly to serial ports, the/tmp/pipeis a UNIX socket, so GDB does not recognize it as a serial port. Usingsocatwe can create a TCP connection and connect using GDB. - Now run GDB via
gdb ./vmlinuxwhere./vmlinuxis the path to the kernel binary file that you copied before. - In GDB run
target remote localhost:65335. - At this point the debugger should be attached. Put breakpoints using
breakand typecontinueto resume the kernel execution in the VM.
Wonderful! Thanks for sharing.