Quantcast
Channel: efsystems - GNU/Linux
Viewing all articles
Browse latest Browse all 2

Depuración remota con gdbserver

$
0
0
La manera de hacer ésto es utilizando gdbserver, un depurador remoto que permite a gdb conectarse remotamente con él y depurar de forma remota.

gdbserver

gdbserver Es una aplicación que permite depurar remotamente, a través de gdb, cualquier software que queramos. Para ello, gdbserver debe de estar corriendo en la máquina local sobre la que se ejecuta el software a depurar, mientras que gdb puede estar corriendo en otra máquina. La conexión puede realizarse bien mediante un enlace serie o mediante una conexión TCP.

De esta manera, podemos utilizar gdbserver en nuestra máquina target ejecutando el código que deseamos depurar, mientras que desde nuestra máquina host podemos conectar con gdbserver vía TCP y depurar cómodamente nuestra aplicación, aunque ésta esté corriendo en un entorno GNU/Linux embebido.

El proceso es muy parecido a cuando depuramos con un depurador JTAG (como por ejemplo OpenOCD) utilizando gdb también. En este caso, OpenOCD actúa de la misma manera que lo haría gdbserver: se encarga de leer el contenido de variables y registros de la aplicación, se encarga de controlar la ejecución, permite modificar variables, establecer puntos de ruptura y envía la información a gdb para que éste la pueda representar. OpenOCD actúa sobre un hardware externo en el que se está ejecutando la aplicación a depurar mientras que gdbserver se ejecuta en la misma máquina en la que la aplicación a depurar.

El ejemplo

En este post voy a mostrar cómo depurar una aplicación que correrá en la misma máquina host. No depuraré una aplicación cruzada mas que nada por facilidad. El proceso para depurar una aplicación cruzada es exactamente el mismo, salvo que en éste caso deberemos de ejecutar gdbserver en la máquina target y ésta deberá estar conectada a la misma red local que la máquina host en la que ejecutemos gdb. Además, deberemos utilizar la versión de gdb distribuida con la toolchain cruzada con la que hayamos compilado nuestra aplicación. Por lo demás, el proceso es exactamente el mismo que el que describiré aquí.

Aplicación de ejemplo

Ésta es la aplicación de ejemplo que voy a utilizar para mostrar como depurar con gdbserver:

#include <stdio.h> 
int main(int argc,char** argv){int counter =0;for(counter =0; counter <10; counter++){printf("counter = %i\n", counter);} 
    return0;}

Podemos ver que el código es muy simple: un bucle que se ejecuta 10 veces e imprime el valor de la variable. Ésto será suficiente para lo que queremos demostrar.

Para compilarlo:

javieralso@bender:~/tmp/test$ gcc -g foo.c -o foo

El flag -g incluirá información de depuración dentro de nuestro ejecutable que podrá ser utilizada por gdb. Hay que mencionar, que en el caso de depurar una aplicación mas o menos compleja, es muy recomendable no utilizar flags de optimización para la compilación.

Si quisiésemos depurar una aplicación cruzada, ahora sería el momento de llevar el binario generado (foo en este caso), junto con todas las posibles dependencias de éste a la máquina target sobre la que queremos depurar. También es importante conservar el binario en la máquina host, pues será necesario para que gdb cargue todos los símbolos de depuración.

Depurando

Ahora ya estamos listos para depurar. Lo primero que tenemos que hacer es lanzar gdbserver:

javieralso@bender:~/tmp/test$ gdbserver localhost:3333 foo
Process foo created; pid = 23928
Listening on port 3333

En el ejemplo se ha invocado gdbserver, pasándole el binario a depurar (foo) y se le ha hecho quedar a la escucha en el puerto TCP 3333. En este momento, gdbserver está listo para funcionar. Si estamos depurando una aplicación en un entorno GNU/Linux embebido, el procedimiento aquí es exactamente el mismo, salvo que en este caso, invocaremos gdbserver desde el target.

Ahora ya podemos ejecutar gdb para depurar:

javieralso@bender:~/tmp/test$ gdb foo
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /home/javieralso/tmp/test/foo...done.
(gdb) 

Este comando lo ejecutaremos desde la máquina Host. Invocamos a gdb pasándole el binario que pretendemos depurar.

(gdb) target remote localhost:3333
Remote debugging using :3333
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007ffff7dddaf0 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) 

El comando target remote localhost:3333 nos permite conectar gdb con gdbserver. En nuestro caso, como gdbserver y gdb están en la misma máquina, usamos localhost que deberá ser sustituido por la IP del target si estamos trabajando de forma remota.

Veremos que gdbserver ha aceptado la conexión (en este caso desde 127.0.0.1):

Remote debugging from host 127.0.0.1

Ahora podemos establecer un punto de ruptura, por ejemplo:

(gdb) list
1	#include 
2	
3	int main(int argc, char** argv)
4	{
5	
6	    int counter = 0;
7	    for(counter = 0; counter < 10; counter++)
8	    {
9		printf("counter = %i\n", counter);
10	    }	    
(gdb) break 9
Breakpoint 1 at 0x40052b: file foo.c, line 9.
(gdb) 

y empezar la depuración:

(gdb) c
Continuing.

Breakpoint 1, main (argc=1, argv=0x7fffffffe148) at foo.c:9
9		printf("counter = %i\n", counter);
(gdb) 

Si ejecutamos un paso mas ('s') imprimiremos en la salida estándard:

(gdb) s
7	    for(counter = 0; counter < 10; counter++)
(gdb) 

y en la salida de gdbserver veremos el resultado:

Remote debugging from host 127.0.0.1
counter = 0

con lo que podemos ver que, efectivamente, la aplicación se está ejecutando a través de gdbserver controlada por gdb.


Viewing all articles
Browse latest Browse all 2

Latest Images

Trending Articles





Latest Images