¿Cómo pasar argumentos y redirigir stdin desde un archivo al programa ejecutado en gdb?

210

Normalmente ejecuto un programa como:

./a.out arg1 arg2 <file

Me gustaría depurarlo usando gdb.

Soy consciente de la set argsfuncionalidad, pero eso solo funciona desde el indicador gdb.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente

Respuestas:

136

Pase los argumentos al runcomando desde dentro de gdb.

$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t
moinudin
fuente
3
res la abreviatura de runy puedes seguirlo con cualquier argumento. Como en esta pregunta, sería: r arg1 arg2 <fileo podría serrun arg1 arg2 <file
phyatt
Para mi no funciona. Luego intenté $ gdb ./a.out, (gdb) r < t arg1 arg2que me funciona bien. En mi caso a.out = nft arg1 = import arg2 = json yt = file containing json rules
mystictot
410

Puedes hacerlo:

gdb --args path/to/executable -every -arg you can=think < of

El ser mágico --args.

Simplemente escriba runla consola de comandos de gdb para iniciar la depuración.

rubenvb
fuente
24
Al principio pensé que estaba leyendo esto mal; extraño que --args va antes que el ejecutable. Pero así es!
Kaolin Fire
8
@Kaolin --args debe aparecer antes del ejecutable porque es un conmutador para gdb. Si vino después, ¿cómo lo distinguiría gdb de un argumento que desea pasar al ejecutable que está depurando?
codehippo
9
@codehippo: Bueno, si no especificó, --argsentonces no hay ningún argumento pasado al ejecutable, por lo que no es ambiguo.
ligereza corre en órbita el
14
Supongo que es porque convencionalmente argv[0]es el nombre del ejecutable
Claudiu
3
esto va a redirigir la entrada de la gdbmisma en el ofarchivo y dar lugar a GDB intentar ejecutar comandos de ella
Unkulunkulu
4

Si desea tener un runcomando simple gdbpara ejecutar su programa con redirecciones y argumentos, puede usar set args:

% gdb ./a.out
(gdb) set args arg1 arg2 <file
(gdb) run

No pude lograr el mismo comportamiento con el --argsparámetro, gdbescapa ferozmente de las redirecciones, es decir

% gdb --args echo 1 2 "<file"
(gdb) show args
Argument list to give program being debugged when it is started is "1 2 \<file".
(gdb) run
...
1 2 <file
...

Este realmente redirige la entrada de gdb en sí, no lo que realmente queremos aquí

% gdb --args echo 1 2 <file
zsh: no such file or directory: file
unkulunkulu
fuente
1

Inicie GDB en su proyecto.

  1. Vaya al directorio del proyecto, donde ya compiló el ejecutable del proyecto. Emita el comando gdb y el nombre del ejecutable como se muestra a continuación:

    gdb projectExecutablename

Esto inicia gdb, imprime lo siguiente: GNU gdb (Ubuntu 7.11.1-0ubuntu1 ~ 16.04) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. ............... .................................. Escriba "apropos word" para buscar comandos relacionados con "word" .. Lectura de símbolos del nombre del proyecto ejecutable ... hecho. (gdb)

  1. Antes de comenzar a ejecutar su programa, desea configurar sus puntos de interrupción. El comando break te permite hacerlo. Para establecer un punto de interrupción al comienzo de la función denominada main:

    (gdb) b principal

  2. Una vez que tenga el indicador (gdb), el comando ejecutar inicia la ejecución del ejecutable. Si el programa que está depurando requiere argumentos de línea de comandos, especifíquelos en el comando de ejecución. Si desea ejecutar mi programa en el archivo "xfiles" (que se encuentra en una carpeta "mulder" en el directorio del proyecto), haría lo siguiente:

    (gdb) r mulder / xfiles

Espero que esto ayude.

Descargo de responsabilidad: esta solución no es mía, está adaptada de https://web.stanford.edu/class/cs107/guide_gdb.html Esta breve guía de gdb fue, muy probablemente, desarrollada en la Universidad de Stanford.

Ehsan
fuente
0

¿No sería bueno simplemente escribir debugdelante de cualquier comando para poder depurarlo congdb a nivel de shell?

Debajo de esta función. Incluso funciona con lo siguiente:

"$program" "$@" < <(in) 1> >(out) 2> >(two) 3> >(three)

Esta es una llamada en la que no puede controlar nada, todo es variable, puede contener espacios, avances de línea y metacaracteres de shell. En este ejemplo, in, out, two, ythree son arbitrarias otros comandos que consumen o producen datos que no deben ser perjudicados.

La siguiente bashfunción invoca gdbcasi limpiamente en un entorno de este tipo [ Gist ]:

debug()
{
  1000<&0 1001>&1 1002>&2 \
  0</dev/tty 1>/dev/tty 2>&0 \
  /usr/bin/gdb -q -nx -nw \
  -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" exec' \
  -ex r \
  --args "$@";
}

Ejemplo sobre cómo aplicar esto: simplemente escriba debug en frente:

Antes de:

p=($'\n' $'I\'am\'evil' "  yay  ")
"b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)

Después:

p=($'\n' $'I\'am\'evil' "  yay  ")
debug "b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)

Eso es. Ahora es absolutamente obvio para depurar gdb. Excepto por algunos detalles o más:

  • gdbno se cierra automáticamente y, por lo tanto, mantiene abierta la redirección de E / S hasta que salga gdb. Pero yo llamo a esto una característica.

  • No puede pasar fácilmente argv0al programa como con exec -a arg0 command args. Lo siguiente debería hacer este truco: Después de exec-wrappercambiar "execa "exec -a \"\${DEBUG_ARG0:-\$1}\".

  • Hay FDs superiores a 1000 abiertos, que normalmente están cerrados. Si esto es un problema, cambie 0<&1000 1>&1001 2>&1002a leer0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-

  • No puede ejecutar dos depuradores en paralelo. También puede haber problemas, si algún otro comando consume /dev/tty(o STDIN). Para arreglar eso, reemplace /dev/ttycon "${DEBUGTTY:-/dev/tty}". En otro tipo de TTY tty; sleep infy luego use el TTY impreso (i. E. /dev/pts/60) para la depuración, como en DEBUGTTY=/dev/pts/60 debug command arg... Ese es el poder de Shell, ¡acostúmbrate!

Función explicada:

  • 1000<&0 1001>&1 1002>&2 aleja los primeros 3 FD
    • Esto supone que los DF 1000, 1001 y 1002 son gratuitos.
  • 0</dev/tty 1>/dev/tty 2>&0restaura los primeros 3 FD para apuntar a su TTY actual. Para que puedas controlar gdb.
  • /usr/bin/gdb -q -nx -nwejecuta gdbinvocaciones gdben shell
  • -ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" crea un contenedor de inicio, que restaura los primeros 3 FD que se guardaron en 1000 y superiores
  • -ex r inicia el programa usando el exec-wrapper
  • --args "$@" pasa los argumentos como dados

¿No fue fácil?

Tino
fuente