Skip to content

Instantly share code, notes, and snippets.

@ben-cohen
Created February 19, 2025 17:41
Show Gist options
  • Save ben-cohen/f3b550b75b12f8bdf76ca60b43e1186f to your computer and use it in GitHub Desktop.
Save ben-cohen/f3b550b75b12f8bdf76ca60b43e1186f to your computer and use it in GitHub Desktop.
How to set up QEMU to debug the kernel using gdb

How to set up QEMU to debug the kernel using gdb

  1. Install packages that we need. For Ubuntu this includes:

     apt-install git build-essential ncurses-dev xz-utils libssl-dev \
                 bc flex libelf-dev bison qemu-system-x86 gdb
    
  2. Get the Linux source. (Or use your Linux distribution's package manager to fetch it.)

     mkdir ~/src
     cd ~/src
     # Choose the tag for the version you want...
     git clone --depth 1 --branch v6.8 \
         git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
     cd linux
    
  3. Choose debugging parameters for the kernel. (You can use your Linux distribution's config from /boot but it probably has a lot of features enabled and therefore take a long time to compile.)

     make defconfig
     ./scripts/config -d DEBUG_INFO_NONE \
                      -e DEBUG_INFO \
                      -e DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
     make oldconfig
    
  4. Compile the kernel.

     # Choose a number of parallel processes based on the number of
     # processors in your CPU.
     make -j $(nproc)
    
  5. Make initramfs. In this example we'll use ~/src/linux/my_test_binary as the "init" process. If you want to boot a full system then it will be more complicated!

     cat << EOF > initramfs
     dir /dev 755 0 0
     nod /dev/console 644 0 0 c 5 1
     nod /dev/loop0 644 0 0 b 7 0
     dir /bin 755 1000 1000
     dir /proc 755 0 0
     dir /sys 755 0 0
     dir /mnt 755 0 0
     file /init my_test_binary 755 0 0
     EOF
     ./usr/gen_initramfs.sh initramfs | gzip -9 > cpio 
    
  6. Start QEMU. This will wait for you to attach GDB in the next step. qemu-system-x86_64 -kernel ~/src/linux/arch/x86_64/boot/bzImage
    -initrd /boot/initrd.img-6.8.0-51-generic
    -append "console=ttyS0 nokaslr"
    -s -S -nographic

  7. In another terminal, start GDB.

     cd ~/src/linux
     gdb ./vmlinux
    
  8. In GDB, attach to the kernel. Happy debugging!

     target remote :1234
    
     # You can set breakpoints
     hb load_elf_binary
     continue
    

References

https://kernelnewbies.org/KernelBuild https://www.youtube.com/watch?v=2VcA5Wj7IvU https://nickdesaulniers.github.io/blog/2018/10/24/booting-a-custom-linux-kernel-in-qemu-and-debugging-it-with-gdb/ https://bmeneg.com/post/kernel-debugging-with-qemu/ https://trac.gateworks.com/wiki/linux/initramfs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment