ADRIANOLAUREANO← Artigos
SÉRIE VIGIA · 03/03DWARFSTEPPING

Como o debugger encontra linhas e variáveis? Do DWARF ao stepping no código-fonte

A CPU parou num endereço. O editor mostra arquivo, linha, função e variáveis. De onde veio esse significado que não existe nos bytes da instrução?

ARTIGO 29 · VIGIA 1.0 · DWARF E CÓDIGO-FONTE

4modos de stepping

2direções de mapeamento

1protocolo para editor

VIGIA · CONGELANDO UM INSTANTE DA EXECUÇÃO
CÓDIGO-FONTE42 soma += item;
43● mostre(soma);
44 retorne soma;
VIGIA 1.0controle · inspeção · significado
CPU PAUSADARIP 0x4011a7
RSP 0x7fff…
CC → instrução original

VOCABULÁRIO VISUAL

As peças que tornam a pausa observável.

01DWARFdados que relacionam máquina e fonte
02DIEentrada estruturada de informação de debug
03Line tablemapa entre endereços e linhas
04Escopo léxicoregião onde um nome existe
05Locationreceita para encontrar uma variável
06DAPprotocolo entre editor e debugger
A CPU só conhece bytes e endereços; o Vigia reconstrói o significado por camadas.
01
O compilador precisa deixar pistas.
Símbolos não são DWARF
DadoResponde
Tabela de símbolos ELFonde começa uma função global?
DWARF line tablequal arquivo e linha correspondem ao endereço?
DWARF DIEsquais funções, escopos, tipos e variáveis existem?
Location expressiononde encontrar o valor neste ponto?

DWARF é um conjunto de seções estruturadas no executável. O artigo do LLVM ao executável mostrou a geração de máquina; agora usamos os metadados opcionais deixados ao lado dela.

02
Leia somente o DWARF que responde às nossas perguntas.
Unidades, DIEs e tabelas de linha
unidade de compilação fixture.c
├─ line program: endereço ↔ arquivo:linha
└─ DIE subprogram nivel_tres
   ├─ intervalo [0x401160, 0x401184)
   ├─ parâmetro valor → DW_OP_reg5
   └─ variável total → DW_OP_fbreg -20
Uma DIE é uma entrada hierárquica com atributos; a expressão é uma pequena receita de localização.

A biblioteca gimli decodifica unidades e formatos. O Vigia continua responsável por selecionar unidade, aplicar base relocada, percorrer escopos e avaliar o subconjunto de expressões documentado.

03
Linha para endereço; endereço para linha.
Duas buscas, respostas não necessariamente únicas

Uma linha pode gerar várias faixas de instruções; várias linhas podem apontar ao mesmo endereço. break fixture.c:17 escolhe o primeiro endereço executável da linha e informa alternativas. No sentido inverso, buscamos a última linha cujo endereço não ultrapassa RIP.

fixture.c:17 ──▶ 0x40116a, 0x401174
0x401172 ──────▶ fixture.c:17 · nivel_tres

endereço runtime = endereço DWARF + base PIE
O mapeamento é uma relação produzida pelo compilador, não uma propriedade natural do endereço.
04
“Próxima linha” pode significar centenas de instruções.
instruction, into, next e finish
ComandoEstratégia
stepiPTRACE_SINGLESTEP uma instrução
stepsingle-step até mudar linha; entra em chamadas
nextbreakpoint temporário após a chamada; não entra
finishbreakpoint temporário no endereço de retorno
linha 17: total = soma(a, b);
          mov edi,...  mov esi,...  call soma  mov [rbp-4],eax

step  → entra em soma
next  → pausa após call, ainda na função atual
stepi → avança somente mov edi
Breakpoints temporários reutilizam o mesmo gerenciador seguro do artigo 1.
05
Uma variável é uma receita dependente do instante.
Registrador, stack ou indisponível

O Vigia encontra o DIE da função, entra nos escopos que contêm RIP e avalia localizações simples: DW_OP_regN, DW_OP_fbreg, endereço constante e pequenas somas. Location lists permitem receita diferente em faixas distintas.

valor em RIP A → RDI
valor em RIP B → [RBP - 20]
valor em RIP C → <otimizado/indisponível>
Closures podem guardar capturas no heap; nem toda variável pertence ao frame comum.
(vigia) variables
valor: i32 = 7               @ rdi
total: i32 = 21              @ [rbp-20]
temporario: <otimizado>
06
A sessão completa, do fonte à CPU.
Vigia 1.0
$ vigia ./fixtures/chamadas
(vigia) break fixture.c:17
(vigia) run
fixture.c:17 · nivel_tres
15  int nivel_tres(int valor) {
16      int total = valor * 3;
17  ▶   return total;
(vigia) variables
valor = 7 · total = 21
(vigia) backtrace
#0 nivel_tres fixture.c:17
#1 nivel_dois fixture.c:23
(vigia) finish
fixture.c:23 · nivel_dois
07
A IDE é a janela, não o mecanismo.
Saída estruturada e DAP

--format json publica eventos stopped, frames, scopes e variables num protocolo mínimo. O Debug Adapter Protocol padroniza a conversa entre IDE e adaptador. GDB/LLDB possuem seus próprios núcleos; adaptadores traduzem comandos. O Vigia demonstra a fronteira, sem declarar compatibilidade completa.

clique no editor → arquivo:linha → adaptador
 → Vigia consulta DWARF → endereço runtime
 → escreve CC → CPU executa INT 3 → kernel envia SIGTRAP
 → Vigia restaura e interpreta estado
 → JSON de frames/variáveis → editor desenha a pausa
O caminho integral do ponto vermelho ao valor exibido.
08
Otimização muda a verdade observável.
Testes e limites honestos

Com -O0 -g -fno-omit-frame-pointer, linhas e variáveis são estáveis. Em -O2 -g, funções podem ser inline, linhas reordenadas e variáveis eliminadas. Sem -g, o Vigia continua depurando endereços e símbolos disponíveis, mas não inventa fonte.

O projeto cobre ELF/DWARF conhecido, expressões simples e x86_64. Não oferece depuração remota, core dumps, watchpoints de hardware, C++ completo ou todas as regras DWARF.

Fontes: DWARF Standard, Debug Adapter Protocol e documentação oficial do GDB sobre código otimizado.

Resposta final

O editor congela uma linha porque compilador, executável, kernel, CPU e debugger cooperam: DWARF encontra o endereço; 0xCC interrompe a instrução; ptrace entrega o estado; o Vigia reconstrói linhas, stack e variáveis.

PROJETO COMPLETO · ESTADO EXATO DESTE CAPÍTULO

Baixe o Vigia 1.0.

Pacote exclusivo com código Rust, fixture em C, opções de compilação, testes e limites documentados para Linux x86_64. O Vigia controla apenas filhos criados por ele.

Baixar Vigia 1.0 (.zip)Linux x86_64 · Rust · ELF · processos-fixture

O que este artigo fez você pensar?

Dúvidas, experiências e contrapontos ajudam a próxima pessoa a enxergar o assunto por outro ângulo.

Todos passam por moderação. Ao enviar, você concorda com a política de privacidade.

Receba os próximos artigos.

Uma mensagem quando uma nova investigação estiver pronta. Só isso.