gdb-pratico/mods/04
2025-04-28 13:08:08 -03:00
..
asm conteúdo das partes 3 e 4 2025-04-26 11:45:42 -03:00
c conteúdo das partes 3 e 4 2025-04-26 11:45:42 -03:00
README.org conteúdo das partes 4 e 5 2025-04-28 13:08:08 -03:00

Curso prático de introdução ao GDB

4. Aplicações em baixo e alto nível

Objetivo

Conhecer os recursos do GDB que podem auxiliar no desenvolvimento e depuração de programas em assembly e em C/C++.

O GDB e a programação em baixo nível

O GDB permite observar e controlar a execução de programas no nível mais próximo da máquina, o que inclui:

  • Acompanhamento de registradores da CPU;
  • Inspeção de endereços de memória brutos;
  • Execução instrução por instrução em assembly (stepi, nexti);
  • Observação do stack frame e chamadas (backtrace, info frame);
  • Controle direto de flags, pilha, heap e segmentos do processo.

Isso o torna útil para:

  • Diagnóstico de segmentation faults;
  • Estudo de chamadas de sistema;
  • Reversão e engenharia de baixo nível;
  • Entendimento de como o compilador transforma código em instruções.

Exemplo com um programa em assembly

Código-fonte (soma.asm):

section .data
    a dq 10
    b dq 20
    resultado dq 0

section .text
    global _start

_start:
    mov rax, [a]
    add rax, [b]
    mov [resultado], rax

    mov rax, 60         ; syscall: exit
    xor rdi, rdi        ; status 0
    syscall

Montagem e link-edição:

nasm -f elf64 -g soma.asm -o soma.o
ld soma.o -o soma

Abertura com o GDB:

gdb ./soma
Reading symbols from ./soma...

Definindo _start como ponto de parada:

(gdb) b _start
Breakpoint 1 at 0x401000: file soma.asm, line 10.

Listando o fonte:

(gdb) l
1	section .data
2		a dq 10
3		b dq 20
4		resultado dq 0
5	
6	section .text
7	global _start
8	
9	_start:
10		mov rax, [a]
(gdb)
11		add rax, [b]
12		mov [resultado], rax
13	
14		mov rax, 60         ; syscall: exit
15		xor rdi, rdi        ; status 0
16		syscall

Executando:

(gdb) r
Starting program: /home/blau/git/gdb-pratico/mods/03/asm/soma

Breakpoint 1, _start () at soma.asm:10
10	    mov rax, [a]

Observando os dados rotulados como a, b e resultado (assembly não tem variáveis):

(gdb) x/1gx &a
0x402000 <a>:	0x000000000000000a
(gdb) x/1gx &b
0x402008 <b>:	0x0000000000000014
(gdb) x/1gx &resultado
0x402010 <resultado>:	0x0000000000000000

O comando x exibe um conteúdo na memória e, com as opções /1gx, eu estou pedindo para mostrar uma giant word (1g), que é uma palavra de 8bytes, em base hexadecimal (x).

Executando as três instruções seguintes:

(gdb) n
11	    add rax, [b]
(gdb)
12	    mov [resultado], rax
(gdb)
14	    mov rax, 60         ; syscall: exit

Observando o novo valor em resultado:

(gdb) x/1gx &resultado
0x402010 <resultado>:	0x000000000000001e

Exibindo o estado atual de todos os registradores da CPU:

(gdb) i registers
rax            0x1e                30
rbx            0x0                 0
rcx            0x0                 0
rdx            0x0                 0
rsi            0x0                 0
rdi            0x0                 0
rbp            0x0                 0x0
rsp            0x7fffffffe020      0x7fffffffe020
r8             0x0                 0
r9             0x0                 0
r10            0x0                 0
r11            0x0                 0
r12            0x0                 0
r13            0x0                 0
r14            0x0                 0
r15            0x0                 0
rip            0x401018            0x401018 <_start+24>
eflags         0x206               [ PF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
fs_base        0x0                 0
gs_base        0x0                 0

Continuando a execução até o término:

(gdb) c
Continuing.
[Inferior 1 (process 222188) exited normally]

Notações de tamanhos de palavra

Tamanho Arquitetura x86-64 NASM / Assembly GDB (comando x)
1 byte byte byte b
2 bytes word word h (halfword)
4 bytes doubleword dword w (word)
8 bytes quadword qword g (giant word)

O GDB e a programação em C/C++

O GDB tem suporte avançado para C e C++, oferecendo:

  • Identificação de tipos, nomes, escopos e estruturas;
  • Acesso a variáveis locais, globais e parâmetros;
  • Depuração de ponteiros e aritmética de ponteiros;
  • Interação com structs, typedef, enum, union, etc.;
  • Acompanhamento de chamadas recursivas e stack frames;
  • Em C++: suporte a classes, herança, namespaces e templates.

Exemplo com um programa em C

Código-fonte (soma.c):

#include <stdio.h>

int soma(int a, int b) {
    int resultado = a + b;
    return resultado;
}

int main() {
    int x = 10, y = 20;
    int z = soma(x, y);
    printf("Resultado: %d\n", z);
    return 0;
}

Compilação:

gcc -g -o soma soma.c

Abrindo com o GDB e definindo o ponto de parada na função soma:

:~$ gdb ./soma
Reading symbols from ./soma...
(gdb) b soma
Breakpoint 1 at 0x1143: file soma.c, line 4.

Iniciando a execução do programa:

(gdb) r
Starting program: /home/blau/git/gdb-pratico/mods/03/c/soma
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, soma (a=10, b=20) at soma.c:4
4	    int resultado = a + b;

Exibindo chamadas de funções na pilha:

(gdb) backtrace
#0  soma (a=10, b=20) at soma.c:4
#1  0x0000555555555178 in main () at somac.c:10

Executando passo a passo até a chamada da função printf:

(gdb) n
5	    return resultado;
(gdb) n
6	}
(gdb) n
main () at soma.c:11
11	    printf("Resultado: %d\n", z);
(gdb) backtrace
#0  main () at soma.c:11

Entrando na função printf (glibc):

(gdb) s
__printf (format=0x555555556004 "Resultado: %d\n") at ./stdio-common/printf.c:28
warning: 28	./stdio-common/printf.c: Arquivo ou diretório inexistente

Observando as chamadas de funções na pilha:

(gdb) backtrace
#0  __printf (format=0x555555556004 "Resultado: %d\n") at ./stdio-common/printf.c:28
#1  0x0000555555555194 in main () at somac.c:11

Continuando a execução até o término:

(gdb) c
Continuing.
Resultado: 30
[Inferior 1 (process 223980) exited normally]