Split QEMU run, automate GDB debugging

This commit is contained in:
Ciro Santilli
2017-05-20 11:17:37 +01:00
parent c886a85f58
commit 7f6b148dc4
6 changed files with 120 additions and 33 deletions

View File

@@ -1,9 +1,10 @@
# Linux Kernel Module Cheat
Run one command, get into QEMU Buildroot BusyBox with several minimal Linux kernel 4.9 module example tutorials. Tested in Ubuntu 14.04.
Run one command, get into QEMU Buildroot BusyBox with several minimal Linux kernel 4.9 module example tutorials. Tested in Ubuntu 14.04 host.
Usage:
sudo apt-get install qemu
./run
First build will take a while (GCC, Linux kernel).
@@ -22,19 +23,72 @@ Each module comes from a C file under `kernel_module/`. For module usage do:
grep BR2_LINUX_KERNEL_VERSION buildroot/.config
After the first build, you can also run just:
./runqemu
to save a few seconds. `./run` wouldn't rebuild everything, but checking timestamps takes a few moments.
We use `printk` a lot, and it shows on the QEMU terminal by default. If that annoys you (e.g. you want to see stdout separately), do:
dmesg -n 1
See also: <https://superuser.com/questions/351387/how-to-stop-kernel-messages-from-flooding-my-console>
When your kernel starts crashing, get the full trace with:
## Debugging
GDB the linux kernel:
./runqemu -d
If you want to break immediately at a symbol, e.g. `start_kernel` of the boot sequence, open another terminal and run for example:
./rungdb start_kernel
Now QEMU will stop there, and you can use the normal GDB commands:
l
n
c
To skip the boot, run just:
./rungdb
and when you want to break, do `Ctrl + C` from GDB.
To have some fun, you can first run inside QEMU:
/count.sh
which counts to infinity to stdout, and then:
Ctrl + C
break sys_write
And now you can control the counting from GDB:
continue
continue
continue
## Text mode
Show serial output of QEMU directly on the current terminal, without opening a QEMU window:
./run -n
To exit, just do a regular:
poweroff
This is particularly useful to get full panic traces when you start making the kernel crashing :-)
In case of a panic, you want your terminal back with `Ctrl + C, A` and type `quit`. See also: <http://stackoverflow.com/questions/14165158/how-to-switch-to-qemu-monitor-console-when-running-with-curses>
See also: <https://unix.stackexchange.com/questions/208260/how-to-scroll-up-after-a-kernel-panic>
Then if you want your terminal back, hit `Ctrl + C, A` and type `quit`. See also: <http://stackoverflow.com/questions/14165158/how-to-switch-to-qemu-monitor-console-when-running-with-curses>
## Table of contents
1. [Introduction](introduction.md)
1. [Build](build.md)

View File

@@ -1,4 +1,7 @@
# If you change this file, you need to run:
# rm -rf buildroot/output/build/linux-*.*.*/
# before ./run
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_INFO=y
CONFIG_GDB_SCRIPTS=y

8
rootfs_overlay/count.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
# Generate infinitely many system calls :-)
i=0
while true; do
echo "$i"
i=$(($i+1))
sleep 1
done

32
run
View File

@@ -1,36 +1,8 @@
#!/usr/bin/env bash
set -e
# CLI handling.
nographic=false
while getopts n OPT; do
case "$OPT" in
n)
nographic=true
;;
esac
done
if $nographic; then
extra_append='console=ttyS0'
extra_flags='-nographic'
else
extra_append=''
extra_flags=''
fi
# Work.
cd buildroot
make BR2_EXTERNAL="$(pwd)/../kernel_module" qemu_x86_64_defconfig
cat ../buildroot_config_fragment >> .config
env -u LD_LIBRARY_PATH make BR2_JLEVEL="$(($(nproc) - 2))" kernel_module-rebuild all
qemu-system-x86_64 \
-M pc \
-append "root=/dev/vda $extra_append" \
-drive file=output/images/rootfs.ext2,if=virtio,format=raw \
-kernel output/images/bzImage \
-m 128M \
-net nic,model=virtio \
-net user \
-smp 1 \
$extra_flags \
;
cd ..
./runqemu "$@"

20
rungdb Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
if [ "$#" -gt 0 ]; then
brk="-ex 'break $1'"
else
brk=""
fi
cd buildroot/output/build/linux-*.*.*/
cmd="gdb \
-ex 'add-auto-load-safe-path $(pwd)' \
-ex 'file vmlinux' \
-ex 'set arch i386:x86-64:intel' \
-ex 'target remote localhost:1234' \
$brk \
-ex 'continue' \
-ex 'disconnect' \
-ex 'set arch i386:x86-64' \
-ex 'target remote localhost:1234'
"
echo "$cmd"
eval "$cmd"

30
runqemu Executable file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -e
# CLI handling.
extra_append=''
extra_flags=''
while getopts dn OPT; do
case "$OPT" in
d)
extra_flags="$extra_flags -S -s"
;;
n)
extra_append="$extra_append console=ttyS0"
extra_flags="$extra_flags -nographic"
;;
esac
done
qemu-system-x86_64 \
-M pc \
-append "root=/dev/vda $extra_append" \
-drive file=buildroot/output/images/rootfs.ext2,if=virtio,format=raw \
-kernel buildroot/output/images/bzImage \
-m 128M \
-net nic,model=virtio \
-net user \
-smp 1 \
$extra_flags \
;