wandres.dev
LABORATORIO (QEMU) · VM segura y gdb

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.

⏱ 12 min

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.

🎯 Al terminar esta lección sabrás
  • 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
Ver el kernel ejecutarse es entenderlo de verdad

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.

💡
Símbolos: sin ellos, gdb está ciego

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.

⚔️ Depura el kernel en vivo
  1. Compila un kernel con CONFIG_DEBUG_INFO y arráncalo en QEMU con -s -S.
  2. Conecta gdb vmlinux, pon un breakpoint en start_kernel y haz continue.
  3. Avanza con next/step e inspecciona una variable con print.
  4. Pon un breakpoint en una syscall (p. ej. __x64_sys_write) y observa cuándo se dispara.