Hola Steemiters,
Creo que la mayoría de la gente que sigue estas entradas entiende que funcionalidades tiene gdb y como se instala, para no decir lo que ya se sabe y ahórrarnos tiempo en la misma, meramente se hará referencia de algunos de los parámetros que se pueden utilizar en la depuración de un ejecutable con gdb. Este post sólo pretende ser únicamente una mini guía práctica con algunos ejemplos en código, observaremos algunos screenshot para mostrar la salida de comandos ejecutados una vez attacheado el proceso. El presente documento será utilizado como referencia para futuros post.
La principal motivación de este post es darle al lector un pequeño cheatsheet o una breve introducción de esta excelente herramienta.
Este documento podrá ser modificado a largo plazo, con el fin de añadirle mejoras complementando así ciertas secciones del mismo.
Todos estos test se han realizado bajo un sistema operativo de 64 bits.
(gdb) b main
Asigna un breakpoint en proceso attacheado en la función main
(gdb) disas main
Obtiene un dump en ensamblador de la función main
(gdb) s
Step over, ejecuta instrucción por instrucción después de un breakpoint
(gdb) p strEjmploVal
Print, hace un dump del valor de una variable en este caso strEjmploVal, es necesario que el ejecutable este corriendo suspendido por un breakpoint para observar los valores.
Otra modo de ver los datos en una forma aún mas útil es...
(gdb) x /1bt &int16var1
EXamine obtiene la dirección de memoria de la variable int16var1, nótese el &, sintaxis similar a la de C o C++ de igual modo obtiene el valor de dicha variable; este comando se puede descomponer de la siguiente forma.
/1bt Muestra 1 byte en memoria, en tal caso de necesitar mostrar una valor de 4 bytes se puede definir /4bt; en caso de querer mostrar un valor de 10 bytes entonces se establecerá /10bt
El comando eXemine tiene muchos parámetros y es bastante flexible a la hora de presentar valores y posiciones de memoria.
(gdb) bt
Backtrace, Muestra las funciones en el stack y sus argumentos
(gdb) x /4xw $sp
EXamine 4 palabras (w)
en notación hexadecimal (x)
del Stack Pointer ($sp)
.
(gdb) info registers
Como es de notar, muestra la información de algunos registros importantes; si le suministras un registro de uso específico (rdi, rsi, rdx) entonces devolverá el valor del mismo. Como por ejemplo:
(gdb) info registers rdi
(gdb) info registers rsi
Mejor lo vemos en código corto y sencillo en ASM x64.
global _start
section .text
_start:
mov rax, 9099
mov rbx, 555
; sycall_exit()
mov rbx, 0
mov rax, 1
int 0x80
Compilamos y luego en el gdb vemos algo como esto:
Con el gdb, breakponiamos, corremos y vamos ejecutando la aplicación con varios s
hasta llegar a la instrucción que nos interesa el mov rax, 9099
y vemos el dump de los registros que seteamos en el código en ensamblador, la primera columna nos muestra el nombre del registro rax
en la segunda columna el valor en memoria del registro en hexadecimal y finalmente la tercera columna nos muestra el valor en sistema decimal del registro rax
con valores 9099 y 555 para el registro rbx
Bien, creo que la idea se entiende cuando son variables con enteros, ¿pero que pasa con las variables strings? veamos otro ejemplo con cadenas de caracteres en ASM x64:
section .text
global _start
_start:
mov rbx, txt
; syscal_exit()
mov rbx, 0
mov rax, 1
int 0x80
section .data
txt db 'oPen syLar', 0
Compilamos y luego en el gdb vemos algo como esto:
Por lo anterior, se denota que el formato que presenta eXamine es el adecuado para explicar muchos temas que no se habían tratado con más detalle.
En primera instancia, vemos comandos b
r
s
que ya fueron tratados en este mismo post, luego observamos el comando x
pero éste nos muestra valores en binario que se pueden descomponer de diferentes formas:
Si no cuentas con suficiente tiempo, además te gusta simplificar las cosas, puedes tomar una calculadora, convertir valores binarios a decimales y decimales a valores ASCII.
Dirección en memoria | Binario | Decimal | ASCII |
---|---|---|---|
0x6000c8 | 01101111 | 111 | o |
0x6000c8 | 01010000 | 80 | P |
0x6000c8 | 01100101 | 101 | e |
0x6000c8 | 01101110 | 110 | n |
0x6000c8 | 00100000 | 32 | |
0x6000c8 | 01110011 | 115 | s |
0x6000c8 | 01111001 | 121 | y |
0x6000c8 | 01001100 | 76 | L |
0x6000d0 | 01100001 | 97 | a |
0x6000d0 | 01110010 | 114 | r |
0x6000d0 | 00000000 | 0 | NULL |
Creo que no hace falta explicar la tabla
Bonus track
Si tienes de tiempo libre, puedes usar la siguiente táctica para convertir decimales a binarios y comparar valores con una tabla ASCII.
Dicho procedimiento lo vi en un blog, es de mucha ayuda para quienes les apasiona hacer las cosas más interesantes; este método es solo uno de tantos que existen para convertir valores decimales a binarios, no es el mejor ni el peor, pero es el que me a servido.
Bien, tomemos el carácter y
de la cadena de ejemplo oPen syLar
Si al número le podemos restar 128, lo hacemos y escribimos un uno, si no se puede colocamos un cero
- Según la tabla ASCII el valor decimal es 121 por lo tanto no podemos restarle 128, entonces escribimos 0
Verificamos si al resultado anterior le podemos restar 64, si es así, lo hacemos y escribimos un uno, si no lo permite entonces colocamos un cero
- 121 si le podemos restar 64 por lo tanto escribimos 1
Verificamos si al resultado anterior le podemos restar 32, si es así, lo hacemos y escribimos un uno, si no lo permite entonces colocamos un cero.
- 57 si le podemos restar 32 por lo tanto escribimos 1
Verificamos si al resultado anterior le podemos restar 16, si es así, lo hacemos y escribimos un uno, si no lo permite entonces colocamos un cero.
- 25 si podemos restarle 16 por lo tanto escribimos 1
Verificamos si al resultado anterior le podemos restar 8, si es así, lo hacemos y escribimos un uno, si no lo permite entonces colocamos un cero.
- 9 si podemos restarle 8 por lo tanto escribimos 1
- 1 no podemos restarle 4 por lo tanto escribimos 0
Verificamos si al resultado anterior le podemos restar 2, si es así, lo hacemos y escribimos un uno, si no lo permite entonces colocamos un cero.
- 1 no podemos restarle 4 por lo tanto escribimos 0
Verificamos si al resultado anterior le podemos restar 1, si es así, lo hacemos y escribimos un uno, si no lo permite entonces colocamos un cero.
- 1 si le podemos restar 1 por lo tanto escribimos 1
Resultado: 01111001
Referencias |
---|
Dartmouth |
ASM86 Wordpress |
Sourceware |
SCSS |
Por si alguien le sirve en mi repo de Github están estos ejemplos y alguno que otro Makefile para no andar escribiendo lo mismo todo el tiempo.
Lo siento por si sus ojos sangraron al ver código en ASM sin un highlight decente pero es que no me adapto completamente al markdown del Steemit o tiene soporte parcial =(
Mejoras, criticas, errores o cualquier tipo de modificación por favor dejarlo en la zona de comentarios, es posible que esta publicación cambie a través del tiempo, añadiéndole información o modificando su estructura.
If you speak English you can also read it here it here
Excelente.
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit