.. | ||
asm | ||
c | ||
README.org |
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]