Gdb reloaded

Acho que encontrei um estímulo a mais para usar o gdb com frequência.

Outro dia comentei com o Fred (e enchi o saco dele com os meus screenshots) sobre o uso do emacs como front-end do gdb. É ótimo. Basta dar um M-x gdb e ele aparece bem do lado, se você tiver com duas views na tela. Caso não esteja, C-x 3, resolve.

Brinquei um pouco, achei interessante, mas aquela montoeira de etapas para se depurar me remeteram o meu velho assert ou mesmo usar puts e printf‘s bem colocados. Sim, meus programas são bem simples e isto me basta. Para que ficar carregando o gdb? Gdb, só quando a coisa fica muito feia.

Na realidade, escondo a minha preguiça em carregar os breakpoints e ao sair perdê-los… Sei que deve haver um jeito de fazer isto persistir entre sessões, mas sinceramente, estou usando o meu tempo para aprender `C’, mais e mais. (:-).

Hoje deparei com a dica sobre um truque interessante, visto na DDJ (sim a sempre querida DDJ!): Como colocar os breakpoints diretamente no seu código fonte!

Muito interessante e ainda de quebra achei utilidade prática, i.e. não somente para otimizar ou estilizar, para a técnica que o Fred sempre usa – asm inline.

O que o gdb precisa é de uma interrupção e ele para ali. Testei inicialmente o comando "embutido".

#define EMBED_BREAKPOINT asm volatile ("int3;")

E insere-se a macro no local de parada. Voilá ! Daí basta rodar o gdb e parar naquele ponto.

Bom… Mas nem tanto. Pois o gdb tem necessidades mais complexas. Afinal isto não é um breakpoint de fato, mas uma "parada brusca", aliás uma interrupção, na realidade uma TRAP, prevista no set de instruções do processador para efetuar estas paradas no código. Veja uma explicação melhor aqui.

Então, depois de indicado pela nossa leitura ao DDJ, cheguei neste blog, cujo nome é muito criativo: main is usually a function, o qual entendi que seja uma apologia declarada ao `C’. Lá é onde podemos ver a aplicação do recurso apresentado, só que em melhor estilo.

#define EMBED_BREAKPOINT                  \
    asm("0:"                              \
        ".pushsection embed-breakpoints;" \
        ".quad 0b;"                       \
        ".popsection;")

O que se faz neste hack é colocar labels nos pontos estratégicos para que o gdb os utilize ao rodar.

Vou poupá-los de códigos de demonstração, afinal eles estão no artigo original, no site do autor, os mesmo podem ser vistos e podem ser baixados via github.

Notas adicionais para que for compilar os exemplos apontados:

  • Instale o binutils-dev, o cabeçalho bfd.h – da library binary file descriptors – encontra-se lá.
  • Desnecessário dizer, mas não se esqueça de incluir -lbfd na linha de compilação.
  • Se for usar, como eu, o -std=c89, as declarações no interior dos `for’ devem ser retrabalhadas.
  • Há uma warning sobre redefinição do snprintf que não impede o funcionamento, entretanto, se usar -Werror, deve-se “pragmatizar”.
  • Se for usar o wrapper, melhor torná-lo acessível via /etc/alternatives (Debian, no meu caso):
  • # update-alternatives --install /usr/bin/dbg dbg /usr/local/bin/gdb-with-breakpoints 50
    
  • E, no caso do emacs, melhor customizar o GUD (Grand Unified Debugger).

No mais, o gdb-with-breakpoints funcionou bem aqui.

Customização do emacs

Ahh… Faltou encher o saco com screenshots!

Sei que isto dá manga para mais um artigo, mas como ralei aqui, neste ponto, o melhor é deixar registrado.

Abstrato: o emacs usa uma interface muito interessante para chamar um depurador, ele utiliza o GUD – Grand Unified Debugger, que permite “embrulhar” a interface de comandos, i.e atalhos e hooks, de modo conveniente para diversos debuggers, além do C. Ex.: perl, java, etc.
Neste caso, como eu criei um “embrulho” (wrapper) para chamar o gdb, o comando ficaria um pouco estranho, prejudicando o meu trabalho e eliminando a conveniência de tê-lo à mão, conforme sugerido no artigo.
Nestes links, obtive informações, um tanto desconectadas, pelo menos para mim que sou noob no emacs!

  • Hooks
  • Localizar os Hooks
  • Seguindo as instruções do segundo link, não achei a informação que me interessava, mas achei o modo que me interessa. Estando no emacs, execute os passos:

    1. M-x apropos$ gud.
    2. Mova o cursor e selecione a palavra gud.
    3. C-x o, mova para a outro buffer (* Customize Group: Gud *).
    4. Troque, na caixa (laranja aqui) a palavra gdb por dbg. Note que dbg já é a alternative que criei.
    5. Salve a configuração movendo o cursor sob a palavra [State] e escolha uma das alternativas.
    Pronto, agora o gdb será chamado com o wrapper gdb-with-breakpoints.
    Para restaurar, efetue o mesmo procedimento, trocando agora dbg por gdb.

    Abaixo uma sessão típica com os recursos citados (sorry… mais um screenshot!)

    Anúncios

    Deixe um comentário

    Faça o login usando um destes métodos para comentar:

    Logotipo do WordPress.com

    Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

    Imagem do Twitter

    Você está comentando utilizando sua conta Twitter. Sair / Alterar )

    Foto do Facebook

    Você está comentando utilizando sua conta Facebook. Sair / Alterar )

    Foto do Google+

    Você está comentando utilizando sua conta Google+. Sair / Alterar )

    Conectando a %s