Ferramentas do usuário

Ferramentas do site


dev:debug:gdb_debugger

Essa é uma revisão anterior do documento!


GDB - Debugger

Para quem programa em ambiente Linux existe uma ferramenta de debug muito importante o software gdb. Ele permite realizar certos debug em programas C. Vamos a um exemplo de um Ola Mundo e abri-lo no gdb.

#include <stdio.h>

int main()
{
   printf("Ola mundo\n");
   return 0;
}

Para compilar com suporte a simbolos que o gdb precisa para realizar o debug.

gcc -g -o olamundo olamundo.c

Para entrar no gdb e necessário somente passar como parametro o nome do programa no nosso caso de exemplo seria o nome olamundo.

ricardobarbosa@isadora:~/dev/c/pilha$ gdb olamundo 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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:
<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"...
Reading symbols from olamundo...done.
(gdb) 
(gdb) 
(gdb) 

Iremos cair no prompt de comando do gdb. O gdb funciona como um médico analisando um paciente, o paciente no nosso caso e o programa olamundo. Outro conceito importante do gdb é o breakpoint. O que seria um breakpoint seguindo a tradução seria um ponto de parada ou ponto de interrupção, ou seja, criaremos um ponto de parada onde nos executaremos o programa e quando ele chegar naquele ponto de parada irá parar e esperar interação do usuário, para verificar o conteúdo de uma variavel ou visualizar endereços de memória, etc.

Vamos criar um breakpoint na função main.

(gdb) break main
Breakpoint 1 at 0x400531: file olamundo.c, line 5.
(gdb) 

Agora iremos executar nosso programa e ver ele parar no breakpoint na função main.

(gdb) run
Starting program: /home/ricardobarbosa/dev/c/pilha/olamundo 

Breakpoint 1, main () at olamundo.c:5
5          printf("Ola mundo\n");
(gdb) 

podemos também visualizar o código do programa através do comando list.

(gdb) list
1       #include <stdio.h>
2
3       int main()
4       {
5          printf("Ola mundo\n");
6          return 0;
7       }
(gdb) 

Para executar passo-a-passo temos dois comandos

  • step: continua a execução, roda a próxima linha de código e pausa se a próxima instrução for uma função entra na mesma e excutará linha-a-linha.
  • next: continua a execução, roda a próxima linha de código e pausa se a próxima instrução for uma função ele executa a função inteira e retorna apenas o resultado se a função retornar.

Então executaremos a próxima instrução.

(gdb) next
Ola mundo
6          return 0;
(gdb) 

Repare que ele executou e exibiu a mensagem ola mundo e mostrou a próxima instruçao de return 0 o qual indica sucesso. Se continuarmos dando next executaremos todo o programa e o mesmo será finalizado.

(gdb) next
Ola mundo
6          return 0;
(gdb) next
7       }
(gdb) next
__libc_start_main (main=0x40052d <main>, argc=1, argv=0x7fffffffdcd8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdcc8) at libc-start.c:321
321     libc-start.c: No such file or directory.
(gdb) 

Além da execução de instruções passo-a-passo podemos ver o contéudo de variaveis. Vamos utilizar o seguinte código para exemplificar isto.

(gdb) break main
Breakpoint 1 at 0x4004f1: file olamundo2.c, line 5.
(gdb) run
Starting program: /home/ricardobarbosa/dev/c/pilha/olamundo2 

Breakpoint 1, main () at olamundo2.c:5
5               int a=10;
(gdb) n
6               int b=10;
(gdb) print a
$1 = 10
(gdb) print b
$2 = 0
(gdb) n
8               c=a+b;
(gdb) print b
$3 = 10
(gdb) n
9               return 0;
(gdb) print c
$4 = 20
(gdb) 

Existe alguns comandos para verificar variaveis.

O comando “info variables” para listar os nomes de todas as variaveis globais e estatica.

O comando “info locals” para listar as váriaveis locais que estão atualmente na pilha.

(gdb) info locals
a = 10
b = 10
c = 20
(gdb) 

O comando “info args” para listar os argumentos passados para o programa.

O comando “info frame” exibe informações sobre a pilha

(gdb) info frame
Stack level 0, frame at 0x7fffffffdc00:
 rip = 0x40050a in main (olamundo2.c:9); saved rip = 0x7ffff7a36f45
 source language c.
 Arglist at 0x7fffffffdbf0, args: 
 Locals at 0x7fffffffdbf0, Previous frame's sp is 0x7fffffffdc00
 Saved registers:
  rbp at 0x7fffffffdbf0, rip at 0x7fffffffdbf8
(gdb) 

O comando “backtrace” exibe um rastreio da pilha

(gdb) backtrace 
#0  foo (x=255, y=255) at exemplo01.c:14
#1  0x0000000000400778 in main () at exemplo01.c:50
(gdb) 

No comando acima mostra o frame da pilha para função main e função foo

Para navegar pela frame da pilha

gdb> frame 1

É possível também visualizar o conteúdo de uma posição de memória através do comando “x”. O comando “x” segue uma sintaxe bem simples

x/<contagem><formato><unidade tamanho> endereço

  • Contagem: número de elementos que será exibido.
  • Formato: formato que iremos utilizar
    • o - octal
    • x - hexadecimal
    • d - decimal
    • u - decimal sem sinal(unsigned)
    • t - binario
    • f - ponto flutuante
    • a - endereço
    • c - caracter(char)
    • s - string
    • i - instruction
  • Unidade de tamanho:
    • b - byte
    • h - halfword (16-bit)
    • w - word (32-bit)
    • g - giant word (64-bit)

Exemplo queremos visualizar o conteudo do registrador SP em hexadecimal, decimal e decimal sem sinal(unsigned).

(gdb) x/x $rsp 
0x7fffffffdb20: 0x00000001
(gdb) x/d $rsp 
0x7fffffffdb20: 1
(gdb) x/u $rsp 
0x7fffffffdb20: 1
(gdb) 

Para verificar a instrução armazenada no registrador RIP

(gdb) x/i $rip
=> 0x4005a1 <foo+180>:  movabs $0x406fe00000000000,%rax
(gdb) 

3. x/100x $sp - show stack memory

You need to use gdb's memory-display commands. The basic one is x, for examine. There's an example on the linked-to page that uses

gdb> x/4xw $sp

to print “four words (w ) of memory above the stack pointer (here, $sp) in hexadecimal (x)”. The quotation is slightly paraphrased.

############################

Try using ddd. ddd manual

Ok. Maybe I elaborate a little. I use it like this.

compile my program with debug symbols:

gcc -g program.c -o program

run ddd:

ddd program

In gui you can do all sorts of things, view machine code, view memory, etc. . Look around. In manual there is also a section of examining stack. ddd provides good interface for you to examine C program