Depuración Simple en Rust utilizando rust-gdb en Linux
Holas, el día de hoy como último post del año 2020 quiero comentarles sobre rust-gdb y cómo utilizarlo para depurar nuestros programas escritos en Rust.
rust-gdb no es mas que un script que añade ciertos parámetros al poderoso depurador GDB, de esta manera la depuración en Rust se hace más amigable que utilizando unicamente GDB, si están interesados en lo que contiene el script de rust-gdb es lo siguiente:
#!/bin/sh
# Exit if anything fails
set -e
# Prefer rustc in the same directory as this script
DIR="$(dirname "$0")"
if [ -x "$DIR/rustc" ]; then
RUSTC="$DIR/rustc"
else
RUSTC="rustc"
fi
# Find out where the pretty printer Python module is
RUSTC_SYSROOT="$("$RUSTC" --print=sysroot)"
GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
# Run GDB with the additional arguments that load the pretty printers
# Set the environment variable RUST_GDB
to overwrite the call to a
# different/specific command (defaults to gdb
).
RUST_GDB="${RUST_GDB:-gdb}"
PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" exec ${RUST_GDB} \
--directory="$GDB_PYTHON_MODULE_DIRECTORY" \
-iex "add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY" \
"$@"
Para nuestro ejemplo de depuración vamos a escribir un programa super sencillo que agregue valores a un Vector, luego imprima todo el vector y al final los valores que posee.
Nuestro ejemplo tiene como nombre vectors.rs
fn main() {
// Instanciamos un nuevo Vector
let mut vector = Vec::new();
// Añadimos valores al vector
vector.push(1);
vector.push(2);
vector.push(3);
vector.push(4);
vector.push(5);
// Imprimimos todo el vector
println!("Vector is: {:?}", vector);
// Imprimimos cada valor del vector
println!("\nVector Values:");
for x in &vector {
println!("{}", x);
}
}
Para compilarlo y que pueda ser depurable, vamos a hacerlo de la siguiente manera:
rustc -g src/vectors.rs
Esto creará un archivo ejectuable llamado vectors
en el directorio donde hemos ejecutado el comando rustc
.
La variable -g nos permite crear el ejecutable en modo depuración para luego poder enlazarlo con el codigo fuente del mismo dentro de GDB
Si ejecutamos vectors
la respuesta va a ser la siguiente:
Vector is: [1, 2, 3, 4, 5]
Vector Values:
1
2
3
4
5
Ahora vamos a lo que nos concierne, la depuración. Para ello hacemos lo siguiente:
rust-gdb vectors
Esto nos abre un prompt similar al siguiente:
Debemos añadir un punto de depuración lo hacemos de la siguiente manera:
Si queremos ver donde están nuestros puntos de depuración ejecutamos el comando i b
en el prompt de gdb
Esto tambien se puede hacer como
info break
La respuesta será algo como:
Por último el ejecutamos el comando run
, el cual iniciará el programa y se detendrá en el punto de depuración que añadimos previamente.
En este punto de la ejecución ya tenemos la variable vector
instanciada y con valores, por lo cual podemos ver que tiene dicha variable, esto se hace mediante el comando p {nombre_variable}
.
Si quieremos ver un backtrace es decir la pila de llamadas que se hicieron hasta llegar al punto de depuración que añadimos lo podemos realizar mediante el comando backtrace
En este caso no tenemos más llamadas que
main
por que el ejemplo es muy pequeño
Para continuar hasta el siguiente punto de depuración o hasta que finalice la ejecución del programa presionamos la letra c
Existe una manera un poco más dinámica de hacer la depuración con rust-gdb mediante el uso de su interfaz TUI, para esto ejecutamos en el prompt de gdb el comando tui enable
Al depurar con TUI habilitado podemos ver algo similar a lo siguiente:
El código de este ejemplo se encuentra en:
https://github.com/nano-bytes/rust-samples
Eso es todo por hoy.
Happy Hacking!!!
Felices fiestas y un excelente año nuevo.