Vamos a ver de una forma sencilla y rápida como podemos analizar el fichero core generado por una aplicación en nuestro sistema. No vamos a utilizar ningún tipo de herramienta, sino únicamente las que disponemos en un sistema normalmente, esto es así por que quiero enseñar lo sencillo que es intentar descubrir la causa de un core simplemente con mdb.
Lo primero que tenemos que hacer, antes de enfrentarnos a un core desconocido es analizar el core que genere una aplicación que nosotros conozcamos, nada mejor para esto, que crear nuestra propia aplicación, la cual generará un fichero core de una forma controlada.
Creamos el siguiente fichero gen_core.c:
#include < stdio.h >
void funcion(int *a);
main()
{
int *p;
printf(" main(): Entrada n");
funcion(p);
printf(" main(): Salida n");
return 0;
}
void funcion(int *a)
{
printf("funcion(): Entrada0 n");
a=NULL;
printf("funcion(): Entrada1 n");
*a=1;
printf("funcion(): Salida n");
}
El programa tiene una función la cual es la encargada de generar el coredump, la razón de que el core lo genere una función es poder identificar en la pila los distintos anidamientos en las llamadas.
Compilamos nuestro programa C.
(root@huelva)# gcc gen_core.c -o gen_core (root@huelva)#
Una vez terminada la compilación podemos ejecutar el binario para generar el fichero core que necesitamos, pero antes de hacer esto debemos comprobar cual es el límite del tamaño de los fichero core, para ello utilizamos el comando ulimit.
(root@huelva)# ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited file size (blocks, -f) unlimited open files (-n) 256 pipe size (512 bytes, -p) 10 stack size (kbytes, -s) 8480 cpu time (seconds, -t) unlimited max user processes (-u) 7957 virtual memory (kbytes, -v) unlimited
Podemos ver en la salida del comando que la línea core file size está a 0, esto signifca que no se generará ficheros core, para cambiar este valor ejecutamos el siguiente comando.
(root@huelva)# ulimit -c unlimited
Ahora podemos ejecutar nuestro binario para que se genere un fichero core.
(root@huelva)# ./gen_core main(): Entrada funcion(): Entrada0 funcion(): Entrada1 Segmentation Fault (root@huelva)# (root@huelva)# ls -lrt total 4598 -rw------- 1 root root 287 Apr 3 13:37 gen_core.c -rwx------ 1 root root 7044 Apr 3 13:37 gen_core -rw------- 1 root root 2324149 Apr 3 13:50 core
Podemos ver en la salida que se ha producido un Segmentation Fault y que se ha generado un fichero core. Para analizar el fichero core vamos a utilizar la herramienta mdb, como primer parámetro utilizaremos el fichero binario que hemos compilado y como segundo parámetro el fichero core que se ha generado.
(root@huelva)# mdb ./gen_core ./core Loading modules: [ libc.so.1 ld.so.1 ] > > ::status debugging core file of gen_core (32-bit) from huelva file: gen_core initial argv: ./gen_core threading model: native threads status: process terminated by SIGSEGV (Segmentation Fault) >
Con el comando de mdb ::status podemos ver el estatus del fichero core.
El primer paso es analizar el contenido de la pila justo cuando se produjo el core, para ello utilizaremos el comando de mdb ::stack.
>::stack funcion+0x30(0, 80508b9, 8060bb0, 8060bc0) main+0x37(1, 8047958, 8047960) _start+0x80(1, 8047a80, 0, 8047a8b, 8047ae2, 8047b10) >
La pila se lee de abajo hacia arriba, con lo cual, lo último que se ejecutó antes del core está en la dirección de memoria funcion y el desplazamiento 0×30. MDB dispone de un comando que nos permite desensamblar las intrucciones, vamos a ejecutar el siguiente comando en mdb para ver el contenido de la función funcion().
>> funcion::dis funcion: pushl %ebp funcion+1: movl %esp,%ebp funcion+3: subl $0x8,%esp funcion+6: subl $0xc,%esp funcion+9: pushl $0x8050a1f funcion+0xe: call -0x260 < plt ="libc.so.1`printf" > funcion+0x13: addl $0x10,%esp funcion+0x16: movl $0x0,0x8(%ebp) funcion+0x1d: subl $0xc,%esp funcion+0x20: pushl $0x8050a35 funcion+0x25: call -0x277 < plt ="libc.so.1`printf" > funcion+0x2a: addl $0x10,%esp funcion+0x2d: movl 0x8(%ebp),%eax funcion+0x30: movl $0x1,(%eax) funcion+0x36: subl $0xc,%esp funcion+0x39: pushl $0x8050a4b funcion+0x3e: call -0x290 < plt ="libc.so.1`printf" > funcion+0x43: addl $0x10,%esp funcion+0x46: leave funcion+0x47: ret
Podemos comparar la salida desemsamblada de la función y con el código fuente de nuestro programa en C, podemos ver las tres llamadas a printf, sabemos que el core se debe generar entre la segunda y la tercera llamada a printf. Antes, cuando ejecutamos el comando ::stack apareció la dirección de la llamada a funcion() con un desplazamiento, podemos decirle a mdb que nos desensamble esta parte y nos daría algo parecido a:
> ::stack funcion+0x30(0, 80508b9, 8060bb0, 8060bc0) main+0x37(1, 8047958, 8047960) _start+0x80(1, 8047a80, 0, 8047a8b, 8047ae2, 8047b10) > funcion+0x30::dis funcion: pushl %ebp funcion+1: movl %esp,%ebp funcion+3: subl $0x8,%esp funcion+6: subl $0xc,%esp funcion+9: pushl $0x8050a1f funcion+0xe: call -0x260 < plt ="libc.so.1`printf" > funcion+0x13: addl $0x10,%esp funcion+0x16: movl $0x0,0x8(%ebp) funcion+0x1d: subl $0xc,%esp funcion+0x20: pushl $0x8050a35 funcion+0x25: call -0x277 < plt ="libc.so.1`printf" > funcion+0x2a: addl $0x10,%esp funcion+0x2d: movl 0x8(%ebp),%eax funcion+0x30: movl $0x1,(%eax) funcion+0x36: subl $0xc,%esp funcion+0x39: pushl $0x8050a4b funcion+0x3e: call -0x290 < plt ="libc.so.1`printf" > funcion+0x43: addl $0x10,%esp funcion+0x46: leave funcion+0x47: ret
Donde podemos ver en negrita cual es la línea que ha generado el core y que coincide con la asignación que haciamos en el programa en C, asignando al puntero *a el valor 1.
# Representación desensamblada funcion+0x30: movl $0x1,(%eax) # Parte del código de la función funcion(). *a=1;
De esta forma sencilla podemos intentar identificar, analizando el fichero core y el binario de la aplicación, donde se ha producido el problema que ha generado el fichero core.
Technorati Tag(s) : Solaris OpenSolaris MDB
Algunos derechos reservados. Licencia Creative Commons
Comentarios Recientes
Sobre
Esta plantilla a sido creada con la validacion de CSS y XHTML, por N.Design Studio.Los iconos usados son de Web 2 Mini pack.