Qué es un depurador como gdb
gdb es un depurador: ejecuta un programa, lo detiene donde tú dices y te deja leer sus registros y su memoria. Con él ves qué dos textos compara un programa justo antes de decidir.
Un desensamblador solo lee el archivo. Un depurador mira el programa mientras corre, y por eso encuentra datos que el archivo no muestra.
Al final de esta lección
Nota
Puedo parar un programa en gdb y leer los textos que compara.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Depurador | una herramienta que ejecuta un programa y lo detiene donde quieras | gdb |
| Punto de interrupción | un lugar donde el depurador detiene el programa | break strcmp |
| Dirección | el número que dice dónde está un dato en la memoria | |
| Argumento | un valor que se entrega a una función al llamarla | |
| Memoria | el espacio donde el programa guarda sus datos mientras corre |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un punto de interrupción detiene el programa
break strcmp detiene el programa cada vez que llega a strcmp. En x86-64, los dos primeros argumentos de una llamada están en rdi y rsi, y aquí son direcciones de textos.
x/s $rsi examina la memoria en esa dirección y la muestra como texto. La x es de examinar, la s de string. El primer Run crea tienda, el programa de ejemplo, y no es uno de los de la práctica del laboratorio.
Crea el programa de ejemplo tienda
printf '#include <stdio.h>\n#include <string.h>\nint main(int argc, char **argv) {\n if (argc == 2 && strcmp(argv[1], "REBAJAS26") == 0) { puts("Descuento aplicado"); return 0; }\n puts("Codigo incorrecto");\n return 1;\n}\n' | gcc -O0 -no-pie -x c -o /tmp/tienda -Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Por qué el punto va después de main
Antes de main, el cargador de bibliotecas también usa strcmp para sus cosas. Un punto de interrupción puesto demasiado pronto se detiene ahí, y lees un texto que no es de tu programa.
Los Runs ponen LD_BIND_NOW=1, que hace que el cargador resuelva las llamadas al arrancar, y detienen primero el programa en main. Solo la última pareja de textos entrecomillados es la que buscas.
Lee lo que compara con el texto hola
gdb -batch -ex 'set environment LD_BIND_NOW=1' -ex 'break main' -ex run -ex 'break strcmp' -ex continue -ex 'x/s $rsi' -ex 'x/s $rdi' --args /tmp/tienda hola 2>&1 | grep -o '"[^"]*"' | tail -n 2Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Lee lo que compara con otro texto
gdb -batch -ex 'set environment LD_BIND_NOW=1' -ex 'break main' -ex run -ex 'break strcmp' -ex continue -ex 'x/s $rsi' -ex 'x/s $rdi' --args /tmp/tienda PRUEBA 2>&1 | grep -o '"[^"]*"' | tail -n 2Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Una sesión interactiva de gdb, escrita
gdb --args /tmp/tienda hola
(gdb) break main
(gdb) run
(gdb) break strcmp
(gdb) continue
(gdb) x/s $rsi
(gdb) x/s $rdi
(gdb) info registers rdi rsi
(gdb) quitUn error frecuente
Advertencia
Mucha gente cree que la primera parada en strcmp es siempre la comparación de su programa. No siempre: el cargador de bibliotecas u otra función pueden llamarla antes. Mira los argumentos. Si no son tuyos, pulsa continue o pon el punto después de main.
Para ir más lejos
En una sesión interactiva, después de la parada en strcmp, escribe bt. Es la pila de llamadas: quién llamó a quién hasta llegar ahí.
Explica con tus palabras cómo bt te habría avisado de que la parada era del cargador y no de tu programa.