GNU Debugger o GDB: un potente strumento di debug del codice sorgente per programmi Linux

A debugger plays a vital role in any software development system. Nobody can write a bug-free code all at once. During the course of development, bugs are being raised and needs to be solved for further enhancement. A development system is incomplete without a debugger. Considering the open source developers community, GNU Debugger is their best choice. It is also used for commercial software development on UNIX type platforms.

Debugging source code with GNU Debugger

Il GNU Debugger, conosciuto anche come gdb, ci consente di esaminare il codice mentre viene eseguito o cosa stava tentando di fare un programma nel momento prima di bloccarsi. GDB in sostanza ci aiuta a fare quattro cose principali per individuare difetti nel codice sorgente.

  1. Avviare il programma, specificando gli argomenti che potrebbero influenzare il comportamento generale.
  2. Fermare il programma in determinate condizioni.
  3. Esaminare il crash o il momento in cui il programma è stato interrotto.
  4. Modificare il codice ed eseguire esperimenti con il codice modificato istantaneamente.

Possiamo utilizzare gdb per eseguire il debug di programmi scritti in C e C++ senza troppa fatica. Al momento il supporto ad altri linguaggi di programmazione come D, Modula-2, Fortran è parziale.

Iniziare con GNU Debugger o GDB

GDB viene invocato utilizzando il comando gdb. Emettendo il comando gdb, vengono visualizzate alcune informazioni sulla piattaforma e si viene inseriti nel prompt (gdb) come mostrato di seguito.

[root@fedora20 ~]# gdb
Output di Esempio
GNU gdb (GDB) Fedora 7.6.50.20130731-19.fc20 
Copyright (C) 2013 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-redhat-linux-gnu". 
Type "show configuration" for configuration details. 
For bug reporting instructions, please see: 
<http://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". 
(gdb)

Digitare aiuto per elencare le diverse classi di comandi disponibili all’interno di gdb. Digitare help seguito da un nome di classe per ottenere un elenco dei comandi in quella classe. Digitare help all per l’elenco di tutti i comandi. Le abbreviazioni dei nomi dei comandi sono ammesse se sono non ambigue. Ad esempio, è possibile digitare n invece di digitare next o c per continua e così via.

Comandi GDB più comunemente usati

I comandi gdb più comunemente usati sono elencati nella seguente tabella. Questi comandi devono essere utilizzati dal prompt dei comandi di gdb (gdb).

Command
Description
run
Start a program execution
quit
Quit gdb
print expr
Print expression where expr may be a variable name too
next
Go to next line
step
Step into next line
continue
Continue from the current line till the end of program or next break point

Nota la differenza tra i due comandi step e next. Il comando next non entra all’interno di una funzione se la linea successiva è una chiamata di funzione. Mentre il comando step può entrare all’interno della funzione e vedere cosa succede lì.

A sample session with GDB

Considera il seguente codice sorgente.

// sum.c
#include <stdio.h> 

int sum (int a, int b) { 
	int c; 
	c = a + b; 
	return c; 
} 

int main() { 
	int x, y, z; 
	printf("\nEnter the first number: "); 
	scanf("%d", &x); 
	printf("Enter the second number: "); 
	scanf("%d", &y); 
	z = sum (x, y); 
	printf("The sum is %d\n\n", z); 
	return 0; 
}

Per poter eseguire il debug del file di output dobbiamo compilarlo con l’opzione -g al gcc come segue.

$ gcc -g sum.c -o sum

Il file di output sum può essere associato a gdb tramite uno dei seguenti 2 modi:

1. Specificando il file di output come argomento per gdb.

$ gdb sum

2. Eseguendo il file di output all’interno di gdb utilizzando il comando file.

$ gdb
(gdb) file sum

Il comando list elenca le linee nel file del codice sorgente e sposta il puntatore. Quindi prima list mostrerà le prime 10 linee e poi list mostrerà le successive 10 e così via.

(gdb) list
1	#include <stdio.h>   
2	 
3	int sum (int a, int b) { 
4		int c; 
5		c = a + b; 
6		return c; 
7	} 
8	 
9	int main() { 
10		int x, y, z;

Per avviare l’esecuzione, emetti il comando run . Ora il programma viene eseguito normalmente. Ma ci siamo dimenticati di impostare dei punti di interruzione nel codice sorgente per il debug, giusto? Questi punti di interruzione possono essere specificati per funzioni o a linee specifiche.

(gdb) b main

Nota: Ho utilizzato l’abbreviazione b per break.

Dopo aver impostato un punto di interruzione nella funzione principale, il riprocessamento del programma si fermerà alla riga 11. La stessa cosa può essere ottenuta se si conosce il numero di linea in precedenza.

(gdb) b sum.c:11

Ora passa attraverso le righe di codice utilizzando il comando next o n. È importante notare che il comando next non entra nel codice della funzione a meno che non venga impostato un punto di interruzione sulla funzione. Proviamo ora il comando print. Imposta un punto di interruzione sulla funzione “sum” come segue.

(gdb) b sum 
Breakpoint 1 at 0x4005aa: file sum.c, line 5. 
(gdb) r 
Starting program: /root/sum 

Enter the first number: 2 
Enter the second number: 3 

Breakpoint 1, sum (a=2, b=3) at sum.c:5 
5		c = a + b; 
(gdb) p a 
$1 = 2 
(gdb) p b 
$2 = 3
(gdb) c 
Continuing. 
The sum is 5 

[Inferior 1 (process 3444) exited normally]

Se il programma in esecuzione richiede parametri da riga di comando, forniscili insieme al comando run come segue.

(gdb) run   . . .

I file di libreria condivisa associati al programma in esecuzione possono essere elencati come segue.

(gdb) info share 
From                To                  Syms Read   Shared Object Library 
0x00000035a6000b10  0x00000035a6019c70  Yes         /lib64/ld-linux-x86-64.so.2 
0x00000035a641f560  0x00000035a6560bb4  Yes         /lib64/libc.so.6

Modifica delle variabili

GDB è anche in grado di modificare le variabili durante l’esecuzione del programma. Proviamo questo. Come accennato in precedenza, impostare un punto di interruzione alla riga 16 e avviare il programma.

(gdb) r 
Starting program: /root/sum 

Enter the first number: 1 
Enter the second number: 2 

Breakpoint 1, main ( ) at sum.c:16 
16		printf("The sum is %d\n\n", z); 
(gdb) set z=4 
(gdb) c 
Continuing. 
The sum is 4

Ora a = 1, b = 2 e il risultato dovrebbe essere z = 3. Ma qui abbiamo cambiato il risultato finale in z = 4 nella funzione principale. In questo modo il debug può essere reso più facile utilizzando gdb.

Abilita/Disabilita i punti di interruzione

Per ottenere l’elenco di tutti i punti di interruzione, digitare info breakpoints.

(gdb) info breakpoints 
Num     Type           Disp Enb Address            What 
1       breakpoint     keep y   0x00000000004005c2 in main at sum.c:11

Qui c’è solo un punto di interruzione ed è abilitato. Per disabilitare i punti di interruzione, specificare il numero del punto di interruzione insieme al comando disable. Per abilitarli successivamente, utilizzare il comando enable.

(gdb) disable 1 
(gdb) info breakpoints 
Num     Type           Disp Enb Address            What 
1       breakpoint     keep n   0x00000000004005c2 in main at sum.c:11

Puoi anche eliminare i punti di interruzione con il comando delete.

Debug dei processi in esecuzione

In un sistema GNU/Linux sono in esecuzione numerosi processi in background. Per eseguire il debug di un processo in esecuzione, prima di tutto dobbiamo trovare l’ID del processo in questione. Il comandopidof ti fornisce l’ID del processo.

$ pidof <process_name>

Ora dobbiamo collegare questo PID a gdb. Ci sono 2 modi.

1. Specificando il PID insieme a gdb.

$ gdb -p <pid>

2. Utilizzando il comando attach da gdb.

(gdb) attach <pid>

E questo è tutto per ora. Questi sono solo concetti di base di gdb per iniziare bene nel debug del codice sorgente ed è molto di più rispetto alle cose spiegate sopra. Ad esempio, possiamo eseguire il debug utilizzando le informazioni dello stack, le variabili d’ambiente e molto altro. Prova a sperimentare con tutte queste cose…

Source:
https://www.tecmint.com/debug-source-code-in-linux-using-gdb/