Conseguir que o GDB salve uma lista de pontos de interrupção

129

OK, o info break lista os pontos de interrupção, mas não em um formato que funcione bem em reutilizá-los usando o comando - como nesta pergunta . O GDB tem um método para despejá-los em um arquivo aceitável para entrada novamente? Às vezes, em uma sessão de depuração, é necessário reiniciar o GDB após criar um conjunto de pontos de interrupção para teste.

O arquivo .gdbinit tem o mesmo problema que --command. O comando info break não lista comandos, mas uma tabela para consumo humano.

Para elaborar, aqui está uma amostra da quebra de informações :

(gdb) quebra de informação
Num Tipo Disp Enb Endereço O que
1 ponto de interrupção mantém y 0x08048517 <foo :: bar (void) +7>
casualcoder
fonte

Respostas:

204

A partir do GDB 7.2 (23-08-2011), agora você pode usar o comando save breakpoints .

save breakpoints <filename>
  Save all current breakpoint definitions to a file suitable for use
  in a later debugging session.  To read the saved breakpoint
  definitions, use the `source' command.

Use source <filename>para restaurar os pontos de interrupção salvos do arquivo.

aculich
fonte
2
e se forem de uma carga de biblioteca compartilhada? Ele responde N por padrão, ele parece ...Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
bjackfly
Observe que quando você tem uma condição de ponto de interrupção que não pode ser resolvida na inicialização ( break g_log if log_level==G_LOG_LEVEL_CRITICAL), pelo menos o gdb 7.8.1 irá parar de analisar outros comandos. Se você possui comandos adicionais que devem ser executados para esse ponto de interrupção, coloque a commandslinha antes da conditionlinha.
Lekensteyn
@ Andy Eu revirei sua edição para minha citação original porque o texto é uma citação literal da documentação ... Caso contrário, eu concordaria com sua edição se fossem minhas próprias palavras.
aculich
@aculich: Entendo. Eu recomendaria usar o estilo de citação em vez do estilo de código em qualquer caso.
Andry
26

Esta resposta está desatualizada. O GDB agora suporta salvar diretamente. Veja esta resposta .

Você pode usar o log:

(gdb) b main
Breakpoint 1 at 0x8049329
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>
(gdb) set logging file breaks.txt
(gdb) set logging on
Copying output to breaks.txt.
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>
(gdb) q

O arquivo breaks.txt agora contém:

Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>

É fácil escrever um script AWK que o transforme em um formato útil para o arquivo .gdbinitou --commandpara ele. Ou você pode até fazer o script emitir separado --eval-commandpara a linha de comando do GDB ...

Adicionar esta pequena macro ao .gdbinit ajudará você a fazer isso:

# Call with dump_breaks file.txt
define dump_breaks
    set logging file $arg0
    set logging redirect on
    set logging on
    info breakpoints
    set logging off
    set logging redirect off
end
Johannes Schaub - litb
fonte
Pode-se usar da mesma forma recortar e colar, mas o método de script parece ser o caminho a seguir.
casualcoder
1
eu não acho que copiar e colar é mais fácil do que escrever um script uma vez e depois usá-lo novamente :) afinal, essa foi a razão pela qual você fez essa pergunta em primeiro lugar, eu acho :)
Johannes Schaub - litb 1/02/09
Hum, eu quis dizer usar recortar e colar em vez do método de registro. Os scripts são até agora, com certeza.
casualcoder
Uau! gdb falhar! Eu uso todos os dias e adoro muitas de suas características. Mas a falta é simplesmente burra.
Deft_code 11/09/09
4
Agora, essa resposta tem mais de 2 anos e pode ser obsoleta se você estiver usando uma versão mais recente do gdb. A partir do gdb 7.2, agora você pode usar o save breakpointscomando
Aculich #
11

Coloque seus comandos e pontos de interrupção do GDB em um arquivo .gdbinit, assim como você pode digitá-los no gdb>prompt, e o GDB os carregará e executará automaticamente na inicialização. Este é um arquivo por diretório, para que você possa ter arquivos diferentes para diferentes projetos.

Paul Beckingham
fonte
1
Na verdade, isso não funciona, recebo "aviso: save-tracepoints: nenhum tracepoint para salvar. ' Isso apesar dos pontos de interrupção serem definidos .. Usando o gdb 6.8.
casualcoder
Isso funciona para mim. O GDB precisa da presença de um .gdbinit global no seu $ HOME / .gdbinit com o conteúdo 'add-auto-load-safe-path /home/johnny/src/.gdbinit' e, portanto, a pasta src / também possui um .gdbinit separado
Truthadjustr 5/05
9

Uma extensão da extensão de anon para a resposta de Johannes :

.gdbinit:

define bsave
    shell rm -f brestore.txt
    set logging file brestore.txt
    set logging on
    info break
    set logging off
    # Reformat on-the-fly to a valid GDB command file
    shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdb
end
document bsave
  store actual breakpoints
end

define brestore
  source brestore.gdb
end
document brestore
  restore breakpoints saved by bsave
end

Com brestorevocê, é possível restaurar os pontos de interrupção salvos com bsave.

Dan Berindei
fonte
Aqui está uma regex melhor: perl -ne "print \" break \ $ 1 \ n \ "if /at\s(.*:\d+)/" brestore.txt
George Godik
6

Extensão para a resposta de Johannes : você pode reformatar automaticamente a saída info breakem um arquivo de comando GDB válido:

.gdbinit:

define bsave
   shell rm -f brestore.txt
   set logging file brestore.txt
   set logging on
   info break
   set logging off
   # Reformat on-the-fly to a valid gdb command file
   shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdb
end
document bsave
  store actual breakpoints
end

Depois, você tem um arquivo de comando válido no brestore.gdb.

Isso funcionou para mim quando o aplicativo é compilado -g.

Também testei com sucesso o GDB v6.8 no Ubuntu 9.10 (Karmic Koala).

Peter Mortensen
fonte
1
Obrigado por este trecho! Funciona bem. Testado com sucesso com o GNU gdb 6.3.50-20050815 (versão da Apple gdb-966) no CarbonEmacs GNU Emacs 22.3.1 (i386-apple-darwin9.6.0, versão do Carbon 1.6.0) no Mac OS 10.5.8.
pestófago
3

Coloque o seguinte em ~ / .gdbinit para definir bsave e brestore como comandos do GDB para salvar e restaurar pontos de interrupção.

define bsave
    save breakpoints ~/.breakpoints
end

define brestore
   source ~/.breakpoints
end
badeip
fonte
1

aviso: o protocolo de saída atual não suporta redirecionamento

Também recebo esse erro / aviso no GDB ao tentar ativar o log no modo TUI . No entanto, o log parece funcionar quando no modo "não TUI". Portanto, deixo o modo TUI sempre que quero registrar algo. (Alterne para frente e para trás no modo TUI com Ctrl+X , Ctrl+A ).

Aqui está como eu trabalho:

  1. inicia o GDB (no modo normal)
  2. ativar o log: set logging on- agora não deve reclamar.
  3. alternar para o modo TUI e fazer coisas com GDB
  4. sempre que eu quiser registrar algo (como um enorme despejo de backtrace) - alterne para o modo normal
Magnux
fonte
Ah, e se você gosta de usar a "tela" (como eu), ficará um pouco confusa, pois usa as mesmas teclas de atalho.
Magnux
1

Eu achei a seguinte adição a uma resposta anterior útil para salvar / carregar os pontos de interrupção em um arquivo específico.

  • Salvar pontos de interrupção: bsave {filename}
  • Carregar pontos de interrupção: bload {filename}

Como na resposta anterior, adicione o seguinte código ao arquivo ~ / .gdbinit

# Save breakpoints to a file
define bsave
    if $argc != 1
        help bsave
    else
    save breakpoints $arg0
    end
end
document bsave
Saves all current defined breakpoints to the defined file in the PWD
Usage: bsave <filename>
end

# Loads breakpoints from a file
define bload
    if $argc != 1
        help bload
    else
        source $arg0
    end
end
document bload
Loads all breakpoints from the defined file in the PWD
Usage: bload <filename>
end
Mark A
fonte
0

O problema é que a definição de um ponto de interrupção é sensível ao contexto. E se você tiver duas funções estáticas chamadas foo ?

Se você já estiver depurando um dos módulos que define foo, o GDB assumirá que você o quis dizer. Mas se você simplesmente despejar "pausa foo" em um arquivo e, em seguida, ler esse arquivo no arranque, não ficará claro qual a função foo você quer dizer.

Michael Snyder
fonte
0

Alguma outra ideia? eu tenho

warning: Current output protocol does not support redirection

depois de

set logging on

EDITAR:

Eu sei que a pergunta é "como salvar uma lista de pontos de interrupção", mas acabei de descobrir que, com o GDB, podemos simplesmente definir os pontos de interrupção "salvos no arquivo"

gdb> source breakpoints.txt

Onde breakpoints.txt está um arquivo como este:

break main.cpp:25
break engine.cpp:465
break wheel.cpp:57
barulhento
fonte