GNU Debugger ou GDB: Uma poderosa ferramenta de depuração de código-fonte para programas 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

GNU Debugger, também conhecido como gdb, nos permite navegar pelo código enquanto ele é executado ou o que um programa estava tentando fazer no momento antes de travar. O GDB basicamente nos ajuda a fazer quatro coisas principais para identificar falhas no código-fonte.

  1. Iniciar o programa, especificando argumentos que podem afetar o comportamento geral.
  2. Parar o programa em condições especificadas.
  3. Examinar a falha ou quando o programa foi parado.
  4. Alterar o código e experimentar com o código modificado instantaneamente.

Podemos usar o gdb para depurar programas escritos em C e C++ sem muito esforço. Até o momento, o suporte para outras linguagens de programação como D, Modula-2 e Fortran é parcial.

Começando com o GNU Debugger ou GDB

GDB é invocado usando o comando gdb. Ao emitir o comando gdb, ele exibe algumas informações sobre a plataforma e o direciona para o prompt do (gdb) conforme mostrado abaixo.

[root@fedora20 ~]# gdb
Saída de exemplo
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)

Digite help para listar as diferentes classes de comandos disponíveis dentro do gdb. Digite help seguido por um nome de classe para uma lista de comandos nessa classe. Digite help all para obter a lista de todos os comandos. Abreviações de nomes de comandos são permitidas se forem inequívocas. Por exemplo, você pode digitar n em vez de digitar next ou c para continue e assim por diante.

Comandos GDB Mais Comuns

Os comandos gdb mais comuns estão listados na tabela a seguir. Esses comandos devem ser usados a partir do prompt de comando do 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

Observe a diferença entre os dois comandos step e next. O comando next não entra em uma função se a próxima linha for uma chamada de função. Enquanto o comando step pode entrar na função e ver o que acontece lá dentro.

A sample session with GDB

Considere o seguinte código-fonte.

// 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; 
}

Para depurar o arquivo de saída, precisamos compilá-lo com a opção -g para o gcc da seguinte forma.

$ gcc -g sum.c -o sum

O arquivo de saída sum pode ser anexado ao gdb de duas maneiras diferentes:

1. Especificando o arquivo de saída como argumento para o gdb.

$ gdb sum

2. Executando o arquivo de saída dentro do gdb usando o comando file.

$ gdb
(gdb) file sum

O comando list lista as linhas no arquivo de código fonte e move o ponteiro. Então, primeiro list irá exibir as primeiras 10 linhas e o próximo list exibirá as próximas 10 e assim por diante.

(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;

Para iniciar a execução, emita o comando run . Agora o programa é executado normalmente. Mas esquecemos de colocar alguns pontos de interrupção no código-fonte para depuração, certo? Esses pontos de interrupção podem ser especificados para funções ou em linhas especificadas.

(gdb) b main

Nota: Eu usei a abreviação b para break.

Depois de definir um ponto de interrupção na função principal, ao executar novamente o programa irá parar na linha 11. A mesma coisa pode ser feita se o número da linha for conhecido antes.

(gdb) b sum.c:11

Agora, avance pelas linhas de código usando o comando próximo ou n. É importante notar que o comando próximo não entra no código da função, a menos que um ponto de interrupção seja definido na função. Vamos experimentar o comando imprimir agora. Defina um ponto de interrupção na função soma como abaixo.

(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 o programa em execução exigir parâmetros da linha de comando, forneça o mesmo juntamente com o comando executar.

(gdb) run   . . .

Os arquivos de biblioteca compartilhada associados ao programa em execução atual podem ser listados como.

(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

Modificando Variáveis

GDB também é capaz de modificar variáveis durante a execução do programa. Vamos tentar isso. Como mencionado acima, defina um ponto de interrupção na linha 16 e execute o programa.

(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

Agora a = 1, b = 2 e o resultado deve ser z = 3. Mas aqui mudamos o resultado final para z = 4 na função principal. Dessa forma, a depuração pode ser facilitada usando o gdb.

Ativar/Desativar Pontos de Interrupção

Para obter a lista de todos os pontos de interrupção, digite info breakpoints.

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

Aqui há apenas um ponto de interrupção e está ligado. Para desativar os pontos de interrupção, especifique o número do ponto de interrupção junto com o comando desativar. Para ativar posteriormente, use o comando ativar.

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

Também pode excluir os pontos de interrupção com o comando delete.

Depurar Processos em Execução

Inúmeros processos estão em execução em segundo plano em um sistema GNU/Linux. Para depurar um processo em execução, primeiro precisamos encontrar o id do processo específico. O comando pidof fornece o pid de um processo.

$ pidof <process_name>

Agora precisamos anexar esse pid ao gdb. Existem 2 maneiras.

1. Especificando o pid juntamente com o gdb.

$ gdb -p <pid>

2. Usando o comando attach do gdb.

(gdb) attach <pid>

Por enquanto é isso. Estes são apenas conceitos básicos do gdb para começar bem na depuração de código fonte e vai além do que foi explicado acima. Por exemplo, podemos depurar usando informações da pilha, variáveis de ambiente e muito mais. Experimente brincar com todas essas coisas…

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