1d5af79c0SRandy Dunlap.. highlight:: none 2d5af79c0SRandy Dunlap 3d5af79c0SRandy DunlapDebugging kernel and modules via gdb 4d5af79c0SRandy Dunlap==================================== 5d5af79c0SRandy Dunlap 6d5af79c0SRandy DunlapThe kernel debugger kgdb, hypervisors like QEMU or JTAG-based hardware 7d5af79c0SRandy Dunlapinterfaces allow to debug the Linux kernel and its modules during runtime 8d5af79c0SRandy Dunlapusing gdb. Gdb comes with a powerful scripting interface for python. The 9d5af79c0SRandy Dunlapkernel provides a collection of helper scripts that can simplify typical 10d5af79c0SRandy Dunlapkernel debugging steps. This is a short tutorial about how to enable and use 11d5af79c0SRandy Dunlapthem. It focuses on QEMU/KVM virtual machines as target, but the examples can 12d5af79c0SRandy Dunlapbe transferred to the other gdb stubs as well. 13d5af79c0SRandy Dunlap 14d5af79c0SRandy Dunlap 15d5af79c0SRandy DunlapRequirements 16d5af79c0SRandy Dunlap------------ 17d5af79c0SRandy Dunlap 18d5af79c0SRandy Dunlap- gdb 7.2+ (recommended: 7.4+) with python support enabled (typically true 19d5af79c0SRandy Dunlap for distributions) 20d5af79c0SRandy Dunlap 21d5af79c0SRandy Dunlap 22d5af79c0SRandy DunlapSetup 23d5af79c0SRandy Dunlap----- 24d5af79c0SRandy Dunlap 25d5af79c0SRandy Dunlap- Create a virtual Linux machine for QEMU/KVM (see www.linux-kvm.org and 26d5af79c0SRandy Dunlap www.qemu.org for more details). For cross-development, 27d5af79c0SRandy Dunlap https://landley.net/aboriginal/bin keeps a pool of machine images and 28d5af79c0SRandy Dunlap toolchains that can be helpful to start from. 29d5af79c0SRandy Dunlap 30d5af79c0SRandy Dunlap- Build the kernel with CONFIG_GDB_SCRIPTS enabled, but leave 31d5af79c0SRandy Dunlap CONFIG_DEBUG_INFO_REDUCED off. If your architecture supports 32d5af79c0SRandy Dunlap CONFIG_FRAME_POINTER, keep it enabled. 33d5af79c0SRandy Dunlap 34d5af79c0SRandy Dunlap- Install that kernel on the guest, turn off KASLR if necessary by adding 35d5af79c0SRandy Dunlap "nokaslr" to the kernel command line. 36d5af79c0SRandy Dunlap Alternatively, QEMU allows to boot the kernel directly using -kernel, 37d5af79c0SRandy Dunlap -append, -initrd command line switches. This is generally only useful if 38d5af79c0SRandy Dunlap you do not depend on modules. See QEMU documentation for more details on 39d5af79c0SRandy Dunlap this mode. In this case, you should build the kernel with 40d5af79c0SRandy Dunlap CONFIG_RANDOMIZE_BASE disabled if the architecture supports KASLR. 41d5af79c0SRandy Dunlap 42d5af79c0SRandy Dunlap- Build the gdb scripts (required on kernels v5.1 and above):: 43d5af79c0SRandy Dunlap 44d5af79c0SRandy Dunlap make scripts_gdb 45d5af79c0SRandy Dunlap 46d5af79c0SRandy Dunlap- Enable the gdb stub of QEMU/KVM, either 47d5af79c0SRandy Dunlap 48d5af79c0SRandy Dunlap - at VM startup time by appending "-s" to the QEMU command line 49d5af79c0SRandy Dunlap 50d5af79c0SRandy Dunlap or 51d5af79c0SRandy Dunlap 52d5af79c0SRandy Dunlap - during runtime by issuing "gdbserver" from the QEMU monitor 53d5af79c0SRandy Dunlap console 54d5af79c0SRandy Dunlap 55d5af79c0SRandy Dunlap- cd /path/to/linux-build 56d5af79c0SRandy Dunlap 57d5af79c0SRandy Dunlap- Start gdb: gdb vmlinux 58d5af79c0SRandy Dunlap 59d5af79c0SRandy Dunlap Note: Some distros may restrict auto-loading of gdb scripts to known safe 60d5af79c0SRandy Dunlap directories. In case gdb reports to refuse loading vmlinux-gdb.py, add:: 61d5af79c0SRandy Dunlap 62d5af79c0SRandy Dunlap add-auto-load-safe-path /path/to/linux-build 63d5af79c0SRandy Dunlap 64d5af79c0SRandy Dunlap to ~/.gdbinit. See gdb help for more details. 65d5af79c0SRandy Dunlap 66d5af79c0SRandy Dunlap- Attach to the booted guest:: 67d5af79c0SRandy Dunlap 68d5af79c0SRandy Dunlap (gdb) target remote :1234 69d5af79c0SRandy Dunlap 70d5af79c0SRandy Dunlap 71d5af79c0SRandy DunlapExamples of using the Linux-provided gdb helpers 72d5af79c0SRandy Dunlap------------------------------------------------ 73d5af79c0SRandy Dunlap 74d5af79c0SRandy Dunlap- Load module (and main kernel) symbols:: 75d5af79c0SRandy Dunlap 76d5af79c0SRandy Dunlap (gdb) lx-symbols 77d5af79c0SRandy Dunlap loading vmlinux 78d5af79c0SRandy Dunlap scanning for modules in /home/user/linux/build 79d5af79c0SRandy Dunlap loading @0xffffffffa0020000: /home/user/linux/build/net/netfilter/xt_tcpudp.ko 80d5af79c0SRandy Dunlap loading @0xffffffffa0016000: /home/user/linux/build/net/netfilter/xt_pkttype.ko 81d5af79c0SRandy Dunlap loading @0xffffffffa0002000: /home/user/linux/build/net/netfilter/xt_limit.ko 82d5af79c0SRandy Dunlap loading @0xffffffffa00ca000: /home/user/linux/build/net/packet/af_packet.ko 83d5af79c0SRandy Dunlap loading @0xffffffffa003c000: /home/user/linux/build/fs/fuse/fuse.ko 84d5af79c0SRandy Dunlap ... 85d5af79c0SRandy Dunlap loading @0xffffffffa0000000: /home/user/linux/build/drivers/ata/ata_generic.ko 86d5af79c0SRandy Dunlap 87d5af79c0SRandy Dunlap- Set a breakpoint on some not yet loaded module function, e.g.:: 88d5af79c0SRandy Dunlap 89d5af79c0SRandy Dunlap (gdb) b btrfs_init_sysfs 90d5af79c0SRandy Dunlap Function "btrfs_init_sysfs" not defined. 91d5af79c0SRandy Dunlap Make breakpoint pending on future shared library load? (y or [n]) y 92d5af79c0SRandy Dunlap Breakpoint 1 (btrfs_init_sysfs) pending. 93d5af79c0SRandy Dunlap 94d5af79c0SRandy Dunlap- Continue the target:: 95d5af79c0SRandy Dunlap 96d5af79c0SRandy Dunlap (gdb) c 97d5af79c0SRandy Dunlap 98d5af79c0SRandy Dunlap- Load the module on the target and watch the symbols being loaded as well as 99d5af79c0SRandy Dunlap the breakpoint hit:: 100d5af79c0SRandy Dunlap 101d5af79c0SRandy Dunlap loading @0xffffffffa0034000: /home/user/linux/build/lib/libcrc32c.ko 102d5af79c0SRandy Dunlap loading @0xffffffffa0050000: /home/user/linux/build/lib/lzo/lzo_compress.ko 103d5af79c0SRandy Dunlap loading @0xffffffffa006e000: /home/user/linux/build/lib/zlib_deflate/zlib_deflate.ko 104d5af79c0SRandy Dunlap loading @0xffffffffa01b1000: /home/user/linux/build/fs/btrfs/btrfs.ko 105d5af79c0SRandy Dunlap 106d5af79c0SRandy Dunlap Breakpoint 1, btrfs_init_sysfs () at /home/user/linux/fs/btrfs/sysfs.c:36 107d5af79c0SRandy Dunlap 36 btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); 108d5af79c0SRandy Dunlap 109d5af79c0SRandy Dunlap- Dump the log buffer of the target kernel:: 110d5af79c0SRandy Dunlap 111d5af79c0SRandy Dunlap (gdb) lx-dmesg 112d5af79c0SRandy Dunlap [ 0.000000] Initializing cgroup subsys cpuset 113d5af79c0SRandy Dunlap [ 0.000000] Initializing cgroup subsys cpu 114d5af79c0SRandy Dunlap [ 0.000000] Linux version 3.8.0-rc4-dbg+ (... 115d5af79c0SRandy Dunlap [ 0.000000] Command line: root=/dev/sda2 resume=/dev/sda1 vga=0x314 116d5af79c0SRandy Dunlap [ 0.000000] e820: BIOS-provided physical RAM map: 117d5af79c0SRandy Dunlap [ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable 118d5af79c0SRandy Dunlap [ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved 119d5af79c0SRandy Dunlap .... 120d5af79c0SRandy Dunlap 121d5af79c0SRandy Dunlap- Examine fields of the current task struct(supported by x86 and arm64 only):: 122d5af79c0SRandy Dunlap 123d5af79c0SRandy Dunlap (gdb) p $lx_current().pid 124d5af79c0SRandy Dunlap $1 = 4998 125d5af79c0SRandy Dunlap (gdb) p $lx_current().comm 126d5af79c0SRandy Dunlap $2 = "modprobe\000\000\000\000\000\000\000" 127d5af79c0SRandy Dunlap 128d5af79c0SRandy Dunlap- Make use of the per-cpu function for the current or a specified CPU:: 129d5af79c0SRandy Dunlap 130*09e1d93aSIllia Ostapyshyn (gdb) p $lx_per_cpu(runqueues).nr_running 131d5af79c0SRandy Dunlap $3 = 1 132*09e1d93aSIllia Ostapyshyn (gdb) p $lx_per_cpu(runqueues, 2).nr_running 133d5af79c0SRandy Dunlap $4 = 0 134d5af79c0SRandy Dunlap 135d5af79c0SRandy Dunlap- Dig into hrtimers using the container_of helper:: 136d5af79c0SRandy Dunlap 137*09e1d93aSIllia Ostapyshyn (gdb) set $leftmost = $lx_per_cpu(hrtimer_bases).clock_base[0].active.rb_root.rb_leftmost 138*09e1d93aSIllia Ostapyshyn (gdb) p *$container_of($leftmost, "struct hrtimer", "node") 139d5af79c0SRandy Dunlap $5 = { 140d5af79c0SRandy Dunlap node = { 141d5af79c0SRandy Dunlap node = { 142*09e1d93aSIllia Ostapyshyn __rb_parent_color = 18446612686384860673, 143*09e1d93aSIllia Ostapyshyn rb_right = 0xffff888231da8b00, 144*09e1d93aSIllia Ostapyshyn rb_left = 0x0 145d5af79c0SRandy Dunlap }, 146*09e1d93aSIllia Ostapyshyn expires = 1228461000000 147d5af79c0SRandy Dunlap }, 148*09e1d93aSIllia Ostapyshyn _softexpires = 1228461000000, 149*09e1d93aSIllia Ostapyshyn function = 0xffffffff8137ab20 <tick_nohz_handler>, 150*09e1d93aSIllia Ostapyshyn base = 0xffff888231d9b4c0, 151*09e1d93aSIllia Ostapyshyn state = 1 '\001', 152*09e1d93aSIllia Ostapyshyn is_rel = 0 '\000', 153*09e1d93aSIllia Ostapyshyn is_soft = 0 '\000', 154*09e1d93aSIllia Ostapyshyn is_hard = 1 '\001' 155d5af79c0SRandy Dunlap } 156d5af79c0SRandy Dunlap 157d5af79c0SRandy Dunlap 158d5af79c0SRandy DunlapList of commands and functions 159d5af79c0SRandy Dunlap------------------------------ 160d5af79c0SRandy Dunlap 161d5af79c0SRandy DunlapThe number of commands and convenience functions may evolve over the time, 162d5af79c0SRandy Dunlapthis is just a snapshot of the initial version:: 163d5af79c0SRandy Dunlap 164d5af79c0SRandy Dunlap (gdb) apropos lx 165d5af79c0SRandy Dunlap function lx_current -- Return current task 166d5af79c0SRandy Dunlap function lx_module -- Find module by name and return the module variable 167d5af79c0SRandy Dunlap function lx_per_cpu -- Return per-cpu variable 168d5af79c0SRandy Dunlap function lx_task_by_pid -- Find Linux task by PID and return the task_struct variable 169d5af79c0SRandy Dunlap function lx_thread_info -- Calculate Linux thread_info from task variable 170d5af79c0SRandy Dunlap lx-dmesg -- Print Linux kernel log buffer 171d5af79c0SRandy Dunlap lx-lsmod -- List currently loaded modules 172d5af79c0SRandy Dunlap lx-symbols -- (Re-)load symbols of Linux kernel and currently loaded modules 173d5af79c0SRandy Dunlap 174d5af79c0SRandy DunlapDetailed help can be obtained via "help <command-name>" for commands and "help 175d5af79c0SRandy Dunlapfunction <function-name>" for convenience functions. 176