Kernel Debugging with QEMU: Difference between revisions

Axka (talk | contribs)
m Add link for more info about patching and configuring the kernel
DHCP (talk | contribs)
m style fixes
 
Line 62: Line 62:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
  users.motd =
users.motd =
    let
  let
      gdbScript = pkgs.writeScript "attach-gdb.sh" ''
    gdbScript = pkgs.writeScript "attach-gdb.sh" ''
        mkdir -p /tmp/gdb
      mkdir -p /tmp/gdb
        cd /tmp/gdb
      cd /tmp/gdb
        rm -rf *
      rm -rf *


        ls ${pkgs.srcOnly config.boot.kernelPackages.kernel} | while read line ; do ln -s ${pkgs.srcOnly config.boot.kernelPackages.kernel}/$line $line ; done
      ls ${pkgs.srcOnly config.boot.kernelPackages.kernel} | while read line ; do ln -s ${pkgs.srcOnly config.boot.kernelPackages.kernel}/$line $line ; done


        mkdir kos
      mkdir kos
        cd kos
      cd kos


        cp ${config.boot.kernelPackages.kernel}/lib/modules/*/kernel/fs/netfs/* .
      cp ${config.boot.kernelPackages.kernel}/lib/modules/*/kernel/fs/netfs/* .
        cp ${config.boot.kernelPackages.kernel}/lib/modules/*/kernel/fs/9p/* .
      cp ${config.boot.kernelPackages.kernel}/lib/modules/*/kernel/fs/9p/* .
        cp ${config.boot.kernelPackages.kernel}/lib/modules/*/kernel/net/9p/* .
      cp ${config.boot.kernelPackages.kernel}/lib/modules/*/kernel/net/9p/* .
        xz -d *
      xz -d *
        GDB_SCRIPT_DIR=$(echo ${config.boot.kernelPackages.kernel.dev}/lib/modules/*/build/scripts/gdb)
      GDB_SCRIPT_DIR=$(echo ${config.boot.kernelPackages.kernel.dev}/lib/modules/*/build/scripts/gdb)


        gdb \
      gdb \
          -ex "python import sys; sys.path.insert(0, '$GDB_SCRIPT_DIR')" \
        -ex "python import sys; sys.path.insert(0, '$GDB_SCRIPT_DIR')" \
          -ex "target remote :1234" \
        -ex "target remote :1234" \
          -ex "source $GDB_SCRIPT_DIR/vmlinux-gdb.py" \
        -ex "source $GDB_SCRIPT_DIR/vmlinux-gdb.py" \
          -ex "lx-symbols" \
        -ex "lx-symbols" \
          ${config.boot.kernelPackages.kernel.dev}/vmlinux
        ${config.boot.kernelPackages.kernel.dev}/vmlinux
      '';
    '';
    in ''
  in ''
      look at /repro/default.json
    look at /repro/default.json


      kernel at ${config.boot.kernelPackages.kernel}
    kernel at ${config.boot.kernelPackages.kernel}
      kernel dev at ${config.boot.kernelPackages.kernel.dev}
    kernel dev at ${config.boot.kernelPackages.kernel.dev}


      attach gdb with ${gdbScript} on the host
    attach gdb with ${gdbScript} on the host
    '';
  '';
</syntaxhighlight>
</syntaxhighlight>


Line 166: Line 166:
$ scripts/config --set-val GDB_SCRIPTS y
$ scripts/config --set-val GDB_SCRIPTS y
$ scripts/config --set-val DEBUG_DRIVER y # Enable printk messages in drivers
$ scripts/config --set-val DEBUG_DRIVER y # Enable printk messages in drivers
# everything as one command for copy'n'paste
$ # everything as one command for copy'n'paste
$ scripts/config --set-val DEBUG_INFO y --set-val DEBUG y  --set-val GDB_SCRIPTS y --set-val DEBUG_DRIVER y
$ scripts/config --set-val DEBUG_INFO y --set-val DEBUG y  --set-val GDB_SCRIPTS y --set-val DEBUG_DRIVER y
# this might ask for further options, just press enter for every question
$ # this might ask for further options, just press enter for every question
$ make -j$(nproc)
$ make -j$(nproc)
</syntaxhighlight>
</syntaxhighlight>
Line 231: Line 231:
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
$ nix-build
$ nix-build
# copy out
$ # copy out
$ install -m644 result/nixos.qcow2 qemu-image.img
$ install -m644 result/nixos.qcow2 qemu-image.img
</syntaxhighlight>
</syntaxhighlight>
Line 241: Line 241:


<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
$ nix-shell -p debootstrap qemu
$ nix-shell -p debootstrap qemu
$ qemu-img create qemu-image.img 5G
$ qemu-img create qemu-image.img 5G
$ mkfs.ext2 qemu-image.img
$ mkfs.ext2 qemu-image.img
$ mkdir mount-point.dir
$ mkdir mount-point.dir
$ sudo mount -o loop qemu-image.img mount-point.dir
$ sudo mount -o loop qemu-image.img mount-point.dir
$ sudo debootstrap --arch amd64 buster mount-point.dir
$ sudo debootstrap --arch amd64 buster mount-point.dir
$ sudo chroot mount-point.dir /bin/bash -i
$ sudo chroot mount-point.dir /bin/bash -i
$ export PATH=$PATH:/bin
$ export PATH=$PATH:/bin
$ passwd # Set root password
$ passwd # Set root password
$ exit
$ exit
$ sudo umount mount-point.dir
$ sudo umount mount-point.dir
</syntaxhighlight>
</syntaxhighlight>


Line 257: Line 257:
The filesystem is mounted read only so to add tools like lspci. Mount and chroot then use apt to install the needed binaries.
The filesystem is mounted read only so to add tools like lspci. Mount and chroot then use apt to install the needed binaries.
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
$ sudo  mount -o loop qemu-image.img mount-point.dir
$ sudo  mount -o loop qemu-image.img mount-point.dir
$ sudo chroot mount-point.dir /bin/bash -i
$ sudo chroot mount-point.dir /bin/bash -i
$ export PATH=$PATH:/bin
$ export PATH=$PATH:/bin
$ apt install pciutils tree
$ apt install pciutils tree
$ sudo umount mount-point.dir  
$ sudo umount mount-point.dir  
</syntaxhighlight>
</syntaxhighlight>


Line 270: Line 270:


<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
$ qemu-system-x86_64 -s -S \
$ qemu-system-x86_64 -s -S \
    -kernel arch/x86/boot/bzImage \
  -kernel arch/x86/boot/bzImage \
    -hda qemu-image.img \
  -hda qemu-image.img \
    -append "root=/dev/sda console=ttyS0 nokaslr" \
  -append "root=/dev/sda console=ttyS0 nokaslr" \
    -enable-kvm \
  -enable-kvm \
    -nographic
  -nographic
</syntaxhighlight>
</syntaxhighlight>


==== Connect with gdb ====
==== Connect with gdb ====
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
$ echo "add-auto-load-safe-path `pwd`/scripts/gdb/vmlinux-gdb.py" >> ~/.gdbinit
$ echo "add-auto-load-safe-path `pwd`/scripts/gdb/vmlinux-gdb.py" >> ~/.gdbinit
$ gdb -ex "target remote :1234" ./vmlinux
$ gdb -ex "target remote :1234" ./vmlinux
(gdb) continue
(gdb) continue
</syntaxhighlight>
</syntaxhighlight>


Line 300: Line 300:
Make sure the driver you want to inspect is not compiled into the kernel, look for the option to enable compilation of your driver, to do this execute:
Make sure the driver you want to inspect is not compiled into the kernel, look for the option to enable compilation of your driver, to do this execute:
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
$ make nconfig
$ make nconfig
</syntaxhighlight>
</syntaxhighlight>
press <code>F8</code> and search for your driver, and check if it is set to "Module" with <code><M></code>. After compilation copy the driver.ko into the mounted <code>qemu-image.img</code>. Unmount start the kernel and break at the <code>load_module</code> function and <code>insmod driver.ko</code>. Happy hacking!
press <code>F8</code> and search for your driver, and check if it is set to "Module" with <code><M></code>. After compilation copy the driver.ko into the mounted <code>qemu-image.img</code>. Unmount start the kernel and break at the <code>load_module</code> function and <code>insmod driver.ko</code>. Happy hacking!