Le débogage en assembleur est une compétence essentielle pour les développeurs bas niveau travaillant avec l’architecture x86, ARM ou RISC-V. L’outil le plus utilisé pour cette tâche est GDB (GNU Debugger), qui permet d’analyser l’exécution d’un programme, d’examiner les registres, la mémoire et le code machine.
Dans cet article, nous verrons :
✅ Comment compiler un programme en assembleur pour le débogage
✅ Les commandes essentielles de GDB
✅ L’analyse des registres et de la mémoire
✅ Des cas pratiques de débogage
1. Préparer un programme en assembleur pour GDB
Avant d’utiliser GDB, il faut compiler le programme en assembleur avec les options adaptées.
🔹 Exemple de programme en assembleur x86 (NASM, Linux 64 bits)
assemblyCopierModifiersection .data
message db "Hello, GDB!", 0 ; Chaîne de caractères avec un terminateur NULL
section .bss
buffer resb 10 ; Réserve un buffer de 10 octets
section .text
global _start
_start:
mov rax, 1 ; syscall write (sys_write)
mov rdi, 1 ; stdout
mov rsi, message ; Adresse du message
mov rdx, 13 ; Longueur du message
syscall ; Appel système
mov rax, 60 ; syscall exit (sys_exit)
xor rdi, rdi ; Code de retour 0
syscall ; Quitte le programme
🔹 Compilation avec NASM et GCC
shCopierModifiernasm -f elf64 -g -F dwarf program.asm -o program.o
gcc -no-pie program.o -o program
✅ Options utilisées :
-g -F dwarf: Ajoute les informations de débogage au format DWARF.-no-pie: Désactive l’ASLR (Address Space Layout Randomization) pour simplifier le débogage.
2. Lancer GDB et charger le programme
🔹 Démarrer GDB sur le programme compilé
shCopierModifiergdb program
Une fois dans GDB, vous verrez un prompt similaire à :
scssCopierModifierGNU gdb (Ubuntu 12.1) 12.1
Reading symbols from program...
(gdb)
🔹 Lancer l’exécution pas à pas
Vous pouvez exécuter immédiatement le programme avec :
shCopierModifier(gdb) run
Mais pour analyser l’exécution en détail, il est préférable de définir des points d’arrêt (breakpoints).
3. Commandes essentielles pour le débogage
📌 1️⃣ Définir des points d’arrêt (breakpoints)
Un point d’arrêt permet de stopper l’exécution du programme à une ligne précise.
- Arrêter à l’entrée du programme :
shCopierModifier(gdb) break _start
- Arrêter à une adresse mémoire précise :
shCopierModifier(gdb) break *0x401000
- Lister tous les breakpoints :
shCopierModifier(gdb) info breakpoints
📌 2️⃣ Exécuter pas à pas
- Exécuter une seule instruction en assembleur (y compris les appels système) :
shCopierModifier(gdb) stepi
- Exécuter une seule instruction en ignorant les appels système :
shCopierModifier(gdb) nexti
- Continuer jusqu’au prochain breakpoint :
shCopierModifier(gdb) continue
📌 3️⃣ Examiner le code assembleur
- Afficher le désassemblage du programme :
shCopierModifier(gdb) disassemble _start
- Désassembler les instructions autour de l’exécution actuelle :
shCopierModifier(gdb) disassemble $pc
- Afficher les instructions suivantes :
shCopierModifier(gdb) x/10i $pc
💡 $pc représente le compteur de programme (registre qui stocke l’adresse de l’instruction actuelle).
4. Analyser les registres et la mémoire
📌 1️⃣ Lire les registres
- Afficher tous les registres :
shCopierModifier(gdb) info registers
- Afficher un registre spécifique :
shCopierModifier(gdb) print $rax
📌 2️⃣ Examiner la mémoire
- Lire 10 octets en hexadécimal à l’adresse du message :
shCopierModifier(gdb) x/10xb &message
- Lire une valeur à une adresse donnée :
shCopierModifier(gdb) x/gx 0x601000
5. Cas pratiques de débogage
🔹 Détecter une erreur de segmentation (segfault)
Si le programme crashe avec une erreur de segmentation, lancez-le dans GDB :
shCopierModifiergdb program
(gdb) run
Si une segfault se produit, GDB affiche un message du type :
javaCopierModifierProgram received signal SIGSEGV, Segmentation fault.
0x0000000000401000 in _start ()
🔍 Étapes pour analyser l’erreur :
1️⃣ Vérifier l’adresse où le crash a eu lieu :
shCopierModifier(gdb) bt
2️⃣ Désassembler pour voir l’instruction qui a causé le crash :
shCopierModifier(gdb) disassemble _start
3️⃣ Vérifier les valeurs des registres :
shCopierModifier(gdb) info registers
🔹 Déboguer une boucle infinie
Si le programme tourne sans fin, utilisez CTRL+C pour l’interrompre dans GDB :
shCopierModifier(gdb) interrupt
Ensuite, vérifiez l’instruction en cours d’exécution avec :
shCopierModifier(gdb) x/10i $pc
Si une boucle tourne indéfiniment, vous pouvez modifier la valeur d’un registre pour la forcer à sortir :
shCopierModifier(gdb) set $rcx=0
🔹 Modifier des valeurs à l’exécution
Si vous voulez modifier une variable ou un registre sans modifier le code source, vous pouvez utiliser set :
- Modifier un registre :
shCopierModifier(gdb) set $rax = 100
- Modifier une adresse mémoire :
shCopierModifier(gdb) set {int}0x601000 = 42
Cela permet de tester des correctifs en direct sans recompiler le programme.
6. Conclusion et bonnes pratiques
✔️ Toujours compiler avec -g pour inclure les symboles de débogage.
✔️ Utiliser breakpoints pour examiner le programme progressivement.
✔️ Surveiller les registres et la mémoire pour comprendre l’état du programme.
✔️ Désactiver ASLR (set disable-randomization on) pour des adresses fixes.
✔️ Si une segfault se produit, utiliser bt, info registers et disassemble pour analyser.
Le débogage en assembleur avec GDB est une compétence précieuse pour les développeurs systèmes, embarqués et reverse-engineers. Maîtriser ces techniques permet de mieux comprendre le fonctionnement des processeurs et d’écrire du code plus robuste. 🚀

















