Depurar el kernel con gdb sobre QEMU
QEMU + gdb te dan lo que parecía imposible: poner breakpoints en el kernel, inspeccionar variables y ejecutar paso a paso el código que gobierna la máquina.
En una máquina real no puedes poner un breakpoint en el kernel: si lo paras, paras todo. Pero QEMU expone un servidor gdb que controla la CPU virtual desde fuera. Así depuras el kernel como si fuera un programa normal — una superpotencia que transforma cómo entiendes lo que ocurre dentro.
- Conectar gdb a QEMU.
- Breakpoints y ejecución paso a paso en el kernel.
- Inspeccionar el estado del kernel.
- kgdb, la alternativa integrada.
QEMU como servidor gdb
QEMU puede exponer la CPU virtual a un depurador externo con dos flags:
qemu-system-x86_64 -kernel bzImage -nographic \
-s \ # abre un servidor gdb en el puerto 1234
-S # congela la CPU al arrancar, esperando a gdb
-s es un atajo de -gdb tcp::1234; -S hace que arranque pausado, para que puedas poner breakpoints antes de que corra nada.
Conectar gdb
Desde otra terminal, lanza gdb sobre la imagen con símbolos (vmlinux, no la comprimida) y conéctate:
gdb vmlinux
(gdb) target remote :1234 # conecta con QEMU
(gdb) break start_kernel # breakpoint en el arranque del kernel
(gdb) continue # QEMU ejecuta hasta el breakpoint
(gdb) next # paso a paso
(gdb) print jiffies # inspeccionar variables globales del kernel
(gdb) backtrace # la pila de llamadas del kernel
Hay una diferencia enorme entre leer que “start_kernel inicializa los subsistemas” y verlo con gdb: parar en start_kernel, avanzar paso a paso, y observar cómo la memoria, el planificador y los timers cobran vida uno a uno. Poner un breakpoint en tu propio módulo, inspeccionar el valor de un puntero justo antes de un oops, o seguir una syscall desde que cruza la frontera (nivel 12) hasta que vuelve — eso convierte el kernel de una caja negra abstracta en un mecanismo transparente que puedes examinar. Esta técnica (QEMU -s -S + gdb vmlinux) es, junto con dmesg, tu herramienta de depuración más poderosa. Compila el kernel con símbolos (CONFIG_DEBUG_INFO) y ábrete este mundo.
kgdb: depuración integrada
Para depurar el kernel en hardware real (o entre dos máquinas), el propio kernel trae kgdb: un stub de gdb dentro del kernel al que te conectas por serie o red. Se activa con CONFIG_KGDB y parámetros de arranque. Es más complejo que QEMU pero imprescindible cuando el bug solo aparece en hardware concreto que no puedes emular.
Para que gdb te muestre nombres de función y líneas (no direcciones crudas), el kernel debe compilarse con información de depuración: activa CONFIG_DEBUG_INFO (y CONFIG_GDB_SCRIPTS para scripts de ayuda del kernel en gdb). Sin símbolos, ves 0xffffffff81a3... en vez de start_kernel. Con ellos, depuras el kernel casi como un programa de userspace.
- Compila un kernel con
CONFIG_DEBUG_INFOy arráncalo en QEMU con-s -S. - Conecta
gdb vmlinux, pon un breakpoint enstart_kernely hazcontinue. - Avanza con
next/stepe inspecciona una variable conprint. - Pon un breakpoint en una syscall (p. ej.
__x64_sys_write) y observa cuándo se dispara.