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