Comment passer des arguments et rediriger stdin d'un fichier vers le programme exécuté dans gdb?
J'exécute habituellement un programme comme:
./a.out arg1 arg2 <file
Je voudrais le déboguer en utilisant gdb.
Je suis conscient de la fonctionnalité set args
, mais cela ne fonctionne qu'à partir de l'invite gdb.
5 réponses
Passez les arguments à la commande run
depuis gdb.
$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t
, Vous pouvez faire ceci:
gdb --args path/to/executable -every -arg you can=think < of
Le bit magique étant --args
.
Tapez simplement run
dans la console de commande gdb pour commencer le débogage.
Si vous voulez avoir la commande bare run
dans gdb
pour exécuter votre programme avec des redirections et des arguments, vous pouvez utiliser set args
:
% gdb ./a.out
(gdb) set args arg1 arg2 <file
(gdb) run
J'ai été incapable d'obtenir le même comportement avec --args
paramètre gdb
farouchement échappe à l'redirections, c'est à dire
% 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
...
Celui-ci redirige en fait l'entrée de gdb elle-même, pas ce que nous voulons vraiment ici
% gdb --args echo 1 2 <file
zsh: no such file or directory: file
Démarrez GDB sur votre projet.
-
Allez dans le répertoire du projet, où vous avez déjà compilé l'exécutable du projet. Émettez la commande gdb et le nom de l'exécutable comme ci-dessous:
Gdb projectExecutablename
Cela démarre gdb, imprime ce qui suit: GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. ................................................. Tapez "apropos word" pour rechercher des commandes liées "word"... Lecture des symboles de projectExecutablename...faire. (gdb)
-
Avant de commencer votre programme en cours d'exécution, vous souhaitez configurer vos points d'arrêt. La commande break vous permet de le faire. Pour définir un point d'arrêt au début de la fonction nommée main:
(gdb) B principal
-
Une fois que vous avez l'invite (gdb), la commande run démarre l'exécution de l'exécutable. Si le programme que vous déboguez nécessite des arguments de ligne de commande, vous les spécifiez à l'exécution commande. Si vous vouliez exécuter mon programme sur le fichier" xfiles " (qui se trouve dans un dossier "mulder" dans le répertoire du projet), vous feriez ce qui suit:
(gdb) R mulder/xfiles
J'espère que cela aide.
Avertissement: Cette solution n'est pas la mienne, elle est adaptée de https://web.stanford.edu/class/cs107/guide_gdb.html Ce petit guide de gdb a été, très probablement, développé à L'Université de Stanford.
Ne serait-il pas agréable de taper debug
devant n'importe quelle commande pour pouvoir le déboguer avec gdb
au niveau du shell?
Ci-dessous cette fonction. Il fonctionne même avec ce qui suit:
"$program" "$@" < <(in) 1> >(out) 2> >(two) 3> >(three)
C'est un appel où vous ne pouvez rien contrôler, tout est variable, peut contenir des espaces, des flux de lignes et des méta-caractères shell. Dans cet exemple, in
, out
, two
, et three
sont arbitraires d'autres commandes qui consomment ou produisent des données qui ne doivent pas être lésés.
Suivant bash
fonction appelle gdb
près proprement dans un tel environnement [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 "$@";
}
Exemple sur la façon d'appliquer ceci: tapez simplement debug
devant:
Avant:
p=($'\n' $'I\'am\'evil' " yay ")
"b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)
Après:
p=($'\n' $'I\'am\'evil' " yay ")
debug "b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)
, c'est ça. Maintenant, c'est une évidence absolue de déboguer avec gdb
. Sauf pour quelques détails ou plus:
gdb
ne quitte pas automatiquement et maintient donc la redirection D'E / S ouverte jusqu'à ce que vous quittiezgdb
. Mais j'appelle cela un caractéristique.Vous ne pouvez pas facilement passer
argv0
pour le programme comme avecexec -a arg0 command args
. Suivant devrait faire cette astuce: aprèsexec-wrapper
changer"exec
à"exec -a \"\${DEBUG_ARG0:-\$1}\"
.Il y a des FDs au-dessus de 1000 ouverts, qui sont normalement fermés. Si c'est un problème, modifiez
0<&1000 1>&1001 2>&1002
lire0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-
Vous ne pouvez pas exécuter deux débogueurs en parallèle. Il peut également y avoir des problèmes, si une autre commande consomme
/dev/tty
(ou STDIN). Pour résoudre ce problème, remplacez/dev/tty
par"${DEBUGTTY:-/dev/tty}"
. Certaines autre type de TTYtty; sleep inf
, puis utilisez le TTY imprimé (par exemple/dev/pts/60
) pour le débogage, comme dansDEBUGTTY=/dev/pts/60 debug command arg..
. C'est le pouvoir de Shell, s'y habituer!
Fonction expliquée:
-
1000<&0 1001>&1 1002>&2
éloigne les 3 premiers FDs- cela suppose que les FDs 1000, 1001 et 1002 sont libres
-
0</dev/tty 1>/dev/tty 2>&0
restaure les 3 premiers FDs pour pointer vers votre TTY actuel. Vous pouvez donc contrôlergdb
. -
/usr/bin/gdb -q -nx -nw
exécutegdb
appellegdb
sur le shell -
-ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\""
crée un wrapper de démarrage, qui restaure les 3 premiers FD qui ont été enregistrés à 1000 et au-dessus -
-ex r
démarre le programme en utilisantexec-wrapper
-
--args "$@"
transmet les arguments comme indiqué
N'était-ce pas facile?