GNU Debugger ou GDB: uma poderosa ferramenta de depuração de código-fonte para programas Linux
Um depurador desempenha um papel vital em qualquer sistema de desenvolvimento de software. Ninguém pode escrever um código livre de bugs de uma só vez. Durante o desenvolvimento, bugs estão sendo levantados e precisam ser resolvidos para melhorias adicionais. Um sistema de desenvolvimento está incompleto sem um depurador. Considerando a comunidade de desenvolvedores de código aberto, o GNU Debugger é a melhor escolha. Também é usado para desenvolvimento de software comercial em plataformas do tipo UNIX.
O GNU Debugger, também conhecido como gdb, nos permite percorrer o 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 detectar falhas no código-fonte.
- Inicie o programa especificando argumentos que podem afetar o comportamento geral.
- Pare o programa em condições especificadas.
- Examine a falha ou quando o programa foi interrompido.
- Altere o código e experimente o código modificado instantaneamente.
Podemos usar o gdb para depurar programas escritos em C e C++ sem muito esforço. A partir de agora o suporte para outras linguagens de programação como D, Modula-2, Fortran é parcial.
Introdução ao GNU Debugger ou GDB
GDB é invocado usando o comando gdb. Ao emitir gdb, ele exibe algumas informações sobre a plataforma e leva você ao prompt (gdb) conforme mostrado abaixo .
[root@fedora20 ~]# gdb
Saída de amostra
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 list para ver as diferentes classes de comandos disponíveis dentro do gdb. Digite help seguido de um nome de classe para obter 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 não forem ambíguas. Por exemplo, você pode digitar n em vez de digitar próximo ou c para continuar e assim por diante.
Comandos GDB mais comumente usados
Os comandos gdb comumente usados estão listados na tabela a seguir. Esses comandos devem ser usados no prompt de comando do gdb (gdb).
-
Command
- Descrição
-
run
- Iniciar a execução de um programa
-
quit
- Sair do gdb
-
print expr
- Imprimir expressão onde expr também pode ser um nome de variável
-
next
- Ir para a próxima linha
-
step
- Passar para a próxima linha
-
continue
- Continue da linha atual até o final do programa ou próximo ponto de interrupção
Observe a diferença entre os dois comandos step e next. O comando next não entra na função se a próxima linha for uma chamada de função. Considerando que o comando step pode entrar na função e ver o que acontece lá.
Um exemplo de sessão com 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 gcc como segue.
gcc -g sum.c -o sum
O arquivo de saída sum pode ser anexado ao gdb de uma das duas maneiras a seguir:
1. Especificando o arquivo de saída como argumento para 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. Portanto, a primeira lista exibirá as primeiras 10 linhas e a próxima lista 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 breakpoints no código fonte para depuração, certo? Esses pontos de interrupção podem ser especificados para funções ou em linhas específicas.
(gdb) b main
Nota: usei uma abreviatura b para quebra.
Depois de definir o ponto de interrupção na função principal, a nova execução do programa irá parar na linha 11. A mesma coisa pode ocorrer se o número da linha for conhecido antes.
(gdb) b sum.c:11
Agora percorra as linhas de código usando o comando next ou n. É importante observar que o comando next não entra no código da função, a menos que um ponto de interrupção seja definido na função. Vamos testar o comando print agora. Defina o ponto de interrupção na soma da função conforme 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 que está sendo executado exigir parâmetros de linha de comando, forneça os mesmos junto com o comando run como.
(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
O GDB também é capaz de modificar variáveis durante a execução do programa. Vamos tentar isso. Conforme mencionado acima, defina o 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 alteramos o resultado final para z=4 na função principal. Desta 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 é To. habilitado desabilitar os pontos de interrupção especifique o número do ponto de interrupção junto com o comando disable. Para habilitar posteriormente use o 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
Você também pode excluir os pontos de interrupção com o comando delete.
Depurando processos em execução
Vários processos estão sendo executados em segundo plano em um sistema GNU/Linux. Para depurar um processo em execução, primeiro precisamos encontrar o ID do processo desse processo específico. O comando pidof fornece o pid de um processo.
pidof <process_name>
Agora precisamos anexar este pid ao gdb. Existem 2 maneiras.
1. Especificando pid junto com gdb.
gdb -p <pid>
2. Usando o comando attach do gdb.
(gdb) attach <pid>
É tudo por agora. Estes são apenas os princípios básicos do gdb para começar bem a depuração do código-fonte e é muito mais do que o explicado acima. Por exemplo, podemos depurar usando informações de pilha, variáveis de ambiente e muito mais. Tente brincar com todas essas coisas…