Lire le code attendu pendant la comparaison
Un débogueur est un outil qui lance un programme, l’arrête où vous le demandez et vous montre sa mémoire. Sous Linux, le plus répandu est gdb, le débogueur du projet GNU.
Un programme salle compare le code que l’on tape à celui qu’il attend. Plutôt que de deviner, on l’arrête au moment de la comparaison et on lit les deux textes. Rappel : seuls les programmes de votre labo se lisent ici.
À la fin de cette leçon
Remarque
Je peux arrêter un programme avec gdb et lire les textes qu’il compare.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Débogueur | un outil qui lance un programme et le contrôle pas à pas | gdb |
| Point d’arrêt | un endroit où le débogueur arrête le programme | break strcmp |
| Argument | une valeur donnée à une fonction quand on l’appelle | |
| rdi et rsi | les registres du premier et du second argument d’une fonction sur x86-64 | |
| Adresse | la place d’une donnée dans la mémoire | 0x402008 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un programme qui compare un texte
Les deux Runs suivants écrivent salle.c et le compilent avec les réglages du labo. Le programme prend un code sur la ligne de commande, le compare avec strcmp et répond « Salle ouverte. » ou « Salle fermee. ».
strcmp est une fonction de la bibliothèque : elle compare deux textes et rend 0 s’ils sont égaux.
Écrire le programme salle.c
printf '%s\n' '#include <stdio.h>' '#include <string.h>' 'int main(int argc, char **argv) {' ' if (argc != 2) { puts("usage: salle CODE"); return 2; }' ' if (strcmp(argv[1], "B12-nord") == 0) { puts("Salle ouverte."); return 0; }' ' puts("Salle fermee.");' ' return 1;' '}' > salle.cAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le compiler avec les réglages du labo
gcc -O0 -no-pie -fno-stack-protector -o salle salle.cAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Essayer un code au hasard
./salle essaiAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Un point d’arrêt stoppe le programme
Dans gdb, break strcmp pose un point d’arrêt sur strcmp, run lance le programme et continue le relance après un arrêt. Quand l’arrêt a lieu, le programme est suspendu juste à l’entrée de la fonction : ses arguments sont déjà prêts.
Le chargeur de bibliothèques peut aussi appeler strcmp avant main. On arrête donc le programme sur main d’abord, puis on pose le point d’arrêt sur strcmp.
x/s lit un texte à une adresse
Sur x86-64, le premier argument d’une fonction arrive dans le registre rdi et le second dans rsi. Ici, ce sont les adresses des deux textes comparés.
x/s $rdi veut dire : examine (x) comme un texte (s) l’adresse qui est dans rdi. Le Run lance tout cela d’un coup avec -batch, puis garde avec grep seulement les deux lignes lues en mémoire.
Lire les deux textes que strcmp compare
gdb -batch -ex 'set debuginfod enabled off' -ex 'set environment LD_BIND_NOW=1' -ex 'break main' -ex 'run' -ex 'break strcmp' -ex 'continue' -ex 'x/s $rdi' -ex 'x/s $rsi' --args ./salle essai 2>&1 | grep -E '^0x[0-9a-f]+:'Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Exemple travaillé : ce que fait chaque option -ex
| Option | Ce qu’elle fait | Pourquoi à cet endroit |
|---|---|---|
| set debuginfod enabled off | Refuse le téléchargement d’informations | Pas de question posée pendant le Run |
| set environment LD_BIND_NOW=1 | Résout tous les appels dès le départ | strcmp existe quand on pose l’arrêt |
| break main puis run | Lance et s’arrête à main | Après le chargeur, avant la comparaison |
| break strcmp puis continue | S’arrête à l’entrée de strcmp | Les deux textes sont prêts |
| x/s $rdi puis x/s $rsi | Lit le premier puis le second texte | Le texte tapé et le texte attendu |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
bt montre qui a appelé strcmp
Quand le programme est arrêté, bt 2 affiche les deux dernières fonctions en cours : la fonction où l’on est, puis celle qui l’a appelée. C’est une pile d’appels.
Le Run garde la ligne qui commence par #1. Elle doit finir par in main () : c’est main qui a appelé strcmp.
Voir qui a appelé strcmp
gdb -batch -ex 'set debuginfod enabled off' -ex 'set environment LD_BIND_NOW=1' -ex 'break main' -ex 'run' -ex 'break strcmp' -ex 'continue' -ex 'bt 2' --args ./salle essai 2>&1 | grep '^#1'Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Erreur fréquente
Attention
Beaucoup de gens pensent qu’un point d’arrêt sur strcmp s’arrête toujours dans leur programme. Il s’arrête à chaque appel de strcmp, même celui d’une autre partie du système. Posez-le après main, puis vérifiez avec bt que l’appelant est bien votre programme.
Pour aller plus loin
Relancez le Run avec ./salle B12-nord à la place de ./salle essai. Les deux textes lus sont-ils les mêmes ? Que répond le programme ?
Dites ensuite pourquoi l’arrêt sur strcmp donne la réponse quel que soit le texte tapé, alors que deviner à la main prend un temps énorme.