🐞 PrĂ©sentation de gdb

Il permet de comprendre ce que fait exactement un programme Ă  l’exĂ©cution, Ă©tape par Ă©tape.

gdb signifie GNU Debugger.
C’est l’outil de dĂ©bogage en ligne de commande pour les programmes compilĂ©s avec GCC.

Commandes de gdb Ă  connaitre

CommandeDescription
run ou rExécute le programme
break main ou b mainMet un point d’arrĂȘt au dĂ©but du main
next ou nExécute la ligne suivante (sans entrer dans les fonctions)
step ou sExécute la ligne suivante, en entrant dans les fonctions
print x ou p xAffiche la valeur de la variable x
continue ou cReprend l’exĂ©cution jusqu’au prochain point d’arrĂȘt
quit ou qQuitte gdb

exemple d’utilisation

fichier: code.c

/********************************
 * Projet :Newbie code
 * Auteur :Leprof
 * Date   :04/06/2025
 ********************************/
#include <stdlib.h>
#include <stdio.h>

int main (int argc, char **argv)
{
	printf("Bonjour le monde \n");
	printf("Au revoir newbie ! Ă  bientot \n");
	return EXIT_SUCCESS;
}

on va compiler le code (code.c) avec l’option -g

puis on entre dans gdb , qui va nous permettre de piloter notre code !

gdb code

bruno@elliott:~/Works/langage_C/projet$ gcc code.c -o code -g
bruno@elliott:~/Works/langage_C/projet$ ls
code  code.c
bruno@elliott:~/Works/langage_C/projet$ gdb code
GNU gdb (Debian 13.1-3) 13.1
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from projet...
(gdb) l
1       /********************************
2        * Projet :Newbie code
3        * Auteur :Leprof
4        * Date   :04/06/2025
5        ********************************/
6       #include <stdlib.h>
7       #include <stdio.h>
8
9       int main (int argc, char **argv)
10      {
11              printf("Bonjour le monde \n");
12              printf("Au revoir newbie ! Ă  bientot \n");
13              return EXIT_SUCCESS;
14      }
(gdb) _

ici l pour list , nous liste le code .. avec des numéros de lignes et on voit ici une fonction main.

(gdb) run
Starting program: /home/bruno/Works/langage_C/projet/projet 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Bonjour le monde 
Au revoir newbie ! Ă  bientot 
[Inferior 1 (process 15054) exited normally]
(gdb) 

run , lancer notre code

et on constate :

Bonjour le monde 
Au revoir newbie ! Ă  bientot 

🔍 DĂ©cryptage

  • Inferior 1 : c’est le processus que tu dĂ©bogues (le programme que tu as lancĂ© avec gdb)
  • process 15054 : c’est son identifiant de processus (PID) dans le systĂšme
  • exited normally : cela signifie que le programme s’est terminĂ© sans erreur
    → il n’y a pas eu de crash, ni d’exception, ni de signal fatal

bien comprendre ici que int devant main() !et le code retour 0 car EXIT_SUCCESS , terminé normalement .

On va mettre un point d’arrĂȘt !

(gdb) br 11
Breakpoint 1 at 0x1148: file projet.c, line 11.
(gdb) run  
Starting program: /home/bruno/Works/langage_C/projet/projet  
[Thread debugging using libthread_db enabled]
Using host libthread_db library « /lib/x86_64-linux-gnu/libthread_db.so.1 ».

Breakpoint 1, main (argc=1, argv=0x7fffffffdab8) at projet.c:11
11              printf(« Bonjour le monde \n »);
(gdb)_

br pour break , contraction de break point (point d’arrĂȘt ligne 11)

on appel point d’arrĂȘt un endroit ou on va demander Ă  gdb de nous attendre , ici on va attendre avant d’afficher Bonjour le monde

et gdb attends une commande

run ou r va lancer l’exĂ©cution

(gdb) n
Bonjour le monde  
12              printf(« Au revoir newbie ! Ă  bientot \n »);
(gdb)

next ou n pour exécuter la ligne

on est en attente de rĂ©aliser la ligne 12 , on a plus qu’a faire next ..

Gdb est un outil incontournable pour le développeur c

pour aller plus loin, et plus proche de la machine

đŸ§Ÿ Autres formats utiles avec x/ :

FormatTailleDescriptionExemple
b1 octetbytex/10xb : 10 octets en hex
h2 octetshalfword (16 bits)x/4xh : 4 entiers 16 bits
w4 octetsword (32 bits)x/4xw : 4 int/pointeurs 32b
g8 octetsgiant word (64 bits)x/5gx : 5 pointeurs 64 bits

Exemples :

(gdb) x/10xb 0x7fffffffe5b4                                                                                                       
0x7fffffffe5b4: 0x75    0x6e    0x00    0x64    0x65    0x75    0x78    0x00                                                      
0x7fffffffe5bc: 0x74    0x72
(gdb) print argv
$16 = (char **) 0x7fffffffe2f8
(gdb)  x/5gx 0x7fffffffe2f8
0x7fffffffe2f8: 0x00007fffffffe58b      0x00007fffffffe5b4
0x7fffffffe308: 0x00007fffffffe5b7      0x00007fffffffe5bc
0x7fffffffe318: 0x0000000000000000

Exemple pour voir comment est codé un entier et un entier signé

#include <stdlib.h>
#include <stdio.h>

int main() {
    int a = -10;
    unsigned int b = 10;
    return EXIT_SUCCESS;
}
bruno@elliott:~/Works/langage_C/int_gdb$ gcc main.c -o main -Wall -ansi -pedantic -g
main.c: In function ‘main’:
main.c:6:18: warning: unused variable ‘b’ [-Wunused-variable]
    6 |     unsigned int b = 10;
      |                  ^
main.c:5:9: warning: unused variable ‘a’ [-Wunused-variable]
    5 |     int a = -10;
      |         ^
bruno@elliott:~/Works/langage_C/int_gdb$ 

Juste des warnings , rien de grave et il est clair ici que notre code ne sert Ă  rien que voir les 2 types ! et pour le compilateur (gcc) a et b ne servent Ă  rien ! mais pas pour nous.

bruno@elliott:~/Works/langage_C/int_gdb$ gdb ./main 
GNU gdb (Debian 13.1-3) 13.1
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./main...
(gdb) l
1	#include <stdlib.h>
2	#include <stdio.h>
3	
4	int main() {
5	    int a = -10;
6	    unsigned int b = 10;
7	    return EXIT_SUCCESS;
8	}
(gdb) 

l pour list (on voit notre code ! )

on va faire br main puis, run et next (n) 2 fois ! (pour définir nos 2 variables)

Breakpoint 1, main () at main.c:5
5	    int a = -10;
(gdb) n
6	    unsigned int b = 10;
(gdb) n
7	    return EXIT_SUCCESS;
(gdb) p a
$1 = -10
(gdb) p b
$2 = 10
(gdb) p/x a
$3 = 0xfffffff6
(gdb) p/x b
$4 = 0xa
(gdb) 

Le cas de a , entier signé

on en dĂ©duit ici que un entier signĂ© est codĂ© sur 4 octets sur notre machine (4×8) = 32 Bits

si on prend l’exemple de -10 en dĂ©cimal , sur 32 bits 0xfffffff6 est son complĂ©ment Ă  2.

0xfffffff6 sur 32 bits

en binaire naturel  : 1111 1111 1111 1111 1111 1111 1111 0110 
le complément à 1   : 0000 0000 0000 0000 0000 0000 0000 1001 => 0x00000009

le complément à 2: cpl 1 +1

                    : 0000 0000 0000 0000 0000 0000 0000 1010 => 0x00000000A (10 en décimal)

on en déduit que 0xfffffff6 est un nombre négatif (bit de poids fort à 1) et on a sa valeur avec un complément à 2 , ici 10 (donc -10)

pour la variable b qui est juste en entier signé : 0x0000000A

Le rangement des octets en mémoire sont ici en Little Endian (opposé au big Endian) 
(gdb) x/4x &a
0x7fffffffdaec:	0xf6	0xff	0xff	0xff
(gdb) x 0x7fffffffdaec
0x7fffffffdaec:	0xf6
(gdb) x 0x7fffffffdaed
0x7fffffffdaed:	0xff
(gdb) x 0x7fffffffdaee
0x7fffffffdaee:	0xff
(gdb) x 0x7fffffffdaef
0x7fffffffdaef:	0xff
(gdb) 

x pour gdb la contraction de eXamine

(gdb) x/10xb chaine
0x7fffffffdb47:	0x42	0x6f	0x6e	0x6a	0x6f	0x75	0x72	0x21
0x7fffffffdb4f:	0x00	0x01
(gdb) p chaine
$2 = "Bonjour!"
(gdb) 
x    /   x    b    chaine
│       │    │      │
└─ commande  │      │
    "examine"│      │
             └─ format │
                hexa   │
                       └─ adresse/variable
Les parties :
x (premier)
Commande "examine memory" - pour examiner la mémoire.
/ (slash)
Sépare les options de la commande.

x (aprĂšs le slash)
Format d'affichage : hexadecimal

Autres formats possibles :
d : décimal signé
u : décimal non signé
o : octal
t : binaire
f : float
a : adresse
i : instruction assembleur
c : caractĂšre
s : chaĂźne

b
Taille de l'unité : byte (octet)

Autres tailles :
h : halfword (2 octets)
w : word (4 octets)
g : giant (8 octets)

Pour aller plus loin dans le debug (layout)

mise en page , disposition.

la commande layout

(gdb) layout
asm next prev regs split src
layout src

La commande focus ( pour mettre le focus sur la layout)

focus src / asm / cmd / next /prev

Raccourcis Clavier  Ctrl+X :

  • Ctrl+X O : passe Ă  la fenĂȘtre suivante (source → commandes → etc.)
  • Ctrl+X A : active/dĂ©sactive complĂštement le mode TUI
  • Ctrl+X 1 : passe en mode fenĂȘtre unique (utile pour agrandir)
  • Ctrl+X 2 : revient au mode fenĂȘtres multiples
Ctrl + X + O    # = focus next (tourne entre fenĂȘtres)
Ctrl + X + S    # Focus fenĂȘtre source
Ctrl + X + R    # Focus fenĂȘtre registres
Ctrl + X + A    # Focus fenĂȘtre assembleur
Ctrl + X + C    # Focus ligne de commande