sábado, 19 de junio de 2010

Post-mortem debugging en linux


Que es el debugging post-mortem

El debugging post-mortem es una clasica tecnica de debugging que consiste en que el sistema operativo genera un volcado completo de los registros, los threads y la memoria de un proceso que termina de manera anomala (ya sea por SIGSEGV o por SIGABRT), en linux estos volcados se llaman "cores" y se pueden examinar con gdb para ver en que punto del codigo ocurrio el error, los threads con sus backtraces, los registros, e incluso el valor de las variables (si se tiene informacion de debug) en el momento en que termino el proceso.

Como activarlo

Por default, en la mayoria de los sistemas linux viene desactivado, pero activarlo es tan simple como ejecutar en la terminal:

ulimit -c 4000000000

Que determina que el limite maximo para el tamaño del core sera de aproximadamente 4Gb (valores mucho mayores pueden ser rechazados a no ser que se tenga privilegios de root).

Esto solo tiene validez en la shell en la que se activo, si se necesita que este siempre activo para cualquier sesion, se podria agregar la linea "ulimit -c 4000000000" al final del archivo ~/.bashrc

echo ulimit -c 4000000000 >> ~/.bashrc

Como verlo funcionando

Se crea un programa de purebas, "mytest.c" que genera un error abort()

#include "stdlib.h"

int main() {
abort();
}


Se compila generando informacion de debug y se ejecuta:

gcc -ggdb mytest.c -o mytest
./mytest

El programa falla y seguramente anunciara que se genero el core (en mi caso solamente el archivo generado se llama "core", en algunos sistemas pone el pid o cosas asi)

Se puede usar gdb para analizar el core, tambien hay que pasarle como parametro el ejecutable que genero el core para poder ver la informacion de debug:

gdb -c core mytest


A partir de entonces se puede examinar el estado que tenia el programa en el momento de finalizar como si se tratara de un debug normal:

(gdb) bt
#0 0x00007f55e7ef3a75 in raise () from /lib/libc.so.6
#1 0x00007f55e7ef75c0 in abort () from /lib/libc.so.6
#2 0x000000000040052d in main () at mytest.c:4
(gdb) info threads
* 1 Thread 4352 0x00007f55e7ef3a75 in raise () from /lib/libc.so.6
(gdb) disass main
Dump of assembler code for function main:
0x0000000000400524 <+0>: push %rbp
0x0000000000400525 <+1>: mov %rsp,%rbp
0x0000000000400528 <+4>: callq 0x400418
End of assembler dump.
(gdb) print/x $rcx
$4 = 0xffffffffffffffff
(gdb)

No hay comentarios: