Conseguir que GDB guarde una lista de puntos de interrupción

129

De acuerdo, el salto de información enumera los puntos de corte, pero no en un formato que funcione bien al reutilizarlos utilizando el comando --como en esta pregunta . ¿GDB tiene un método para volcarlos en un archivo aceptable para la entrada nuevamente? A veces, en una sesión de depuración, es necesario reiniciar GDB después de crear un conjunto de puntos de interrupción para las pruebas.

El archivo .gdbinit tiene el mismo problema que --command. El comando info break no enumera los comandos, sino más bien una tabla para consumo humano.

Para elaborar, aquí hay una muestra del corte de información :

(gdb) pausa de información
Núm. Tipo Disp Enb Dirección Qué
1 punto de interrupción keep y 0x08048517 <foo :: bar (void) +7>
casualcoder
fuente

Respuestas:

204

A partir de GDB 7.2 (2011-08-23) ahora puede usar el comando guardar puntos de interrupción .

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 los puntos de interrupción guardados del archivo.

aculich
fuente
2
¿Qué pasa si son de una carga de lib compartida? Responde N por defecto parece ...Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
bjackfly
Tenga en cuenta que cuando tiene una condición de punto de interrupción que no se puede resolver en el inicio ( break g_log if log_level==G_LOG_LEVEL_CRITICAL), al menos gdb 7.8.1 dejará de analizar más comandos. Si tiene comandos adicionales que deben ejecutarse para ese punto de interrupción, coloque la commandslínea antes de la conditionlínea.
Lekensteyn
@Andry Revertí tu edición a mi blockquote original porque el texto es una cita textual de la documentación ... De lo contrario, estaría de acuerdo con tu edición si fueran mis propias palabras.
aculich
@aculich: Ya veo. En cualquier caso, recomendaría usar el estilo de comillas en lugar del estilo de código.
Andry
26

Esta respuesta está desactualizada. GDB ahora admite guardar directamente. Mira esta respuesta .

Puede usar el registro:

(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

El archivo breaks.txt ahora contiene:

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

Escribir una secuencia de comandos AWK que lo transforma en un formato útil para el archivo .gdbinito --commandes fácil. O incluso puede hacer que el script emita separadamente --eval-commanda la línea de comando GDB ...

Agregar esta pequeña macro a .gdbinit lo ayudará a hacerlo:

# 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
fuente
Uno podría usar fácilmente cortar y pegar, pero el método de script parece ser el camino a seguir.
casualcoder 01 de
1
No creo que cortar y pegar sea más fácil que simplemente escribir un guión una vez, y luego usarlo cada vez más :) después de todo, esa fue la razón por la que hiciste esta pregunta en primer lugar, creo :)
Johannes Schaub - litb 01 de
Um, quise decir cortar y pegar en lugar del método de registro. La secuencia de comandos es hasta ahora seguro.
casualcoder 01 de
¡Guauu! gdb fail! Lo uso todos los días y amo muchas de sus características. Pero la falta es simplemente tonta.
deft_code
44
Esta respuesta ahora tiene más de 2 años, por lo que puede ser obsoleta si está utilizando una versión más nueva de gdb. A partir de gdb 7.2 ahora puede usar el save breakpointscomando.
aculich
11

Coloque sus comandos y puntos de interrupción GDB en un archivo .gdbinit tal como podría escribirlos en el gdb>indicador, y GDB los cargará y ejecutará automáticamente al inicio. Este es un archivo por directorio, por lo que puede tener diferentes archivos para diferentes proyectos.

Paul Beckingham
fuente
1
Esto en realidad no funciona, me aparece "advertencia: save-tracepoints: no hay puntos de rastreo para guardar". Esto a pesar de que se establecieron puntos de interrupción. Uso de gdb 6.8.
casualcoder
Esto funciona para mi. GDB necesita la presencia de un .gdbinit global en su $ HOME / .gdbinit con el contenido 'add-auto-load-safe-path /home/johnny/src/.gdbinit' y, por lo tanto, la carpeta src / también tiene un .gdbinit separado
truthadjustr
9

Una extensión de la extensión de anon a la respuesta 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

Con brestoreusted puede restaurar los puntos de interrupción guardados con bsave.

Dan Berindei
fuente
Aquí hay una mejor expresión regular: perl -ne "print \" break \ $ 1 \ n \ "if /at\s(.*:\d+)/" brestore.txt
George Godik
6

Extensión a la respuesta de Johannes : puede reformatear automáticamente la salida de info breakun archivo 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

Luego tiene un archivo de comando válido brestore.gdb.

Esto funcionó para mí cuando se compila la aplicación -g.

También lo probé con éxito con GDB v6.8 en Ubuntu 9.10 (Karmic Koala).

Peter Mortensen
fuente
1
¡Gracias por este fragmento! Funciona genial. Probado con éxito con GNU gdb 6.3.50-20050815 (versión de Apple gdb-966) en CarbonEmacs GNU Emacs 22.3.1 (i386-apple-darwin9.6.0, Carbon Version 1.6.0) en Mac OS 10.5.8.
pesófago
3

Ponga lo siguiente en ~ / .gdbinit para definir bsave y brestore como comandos GDB para guardar y restaurar puntos de interrupción.

define bsave
    save breakpoints ~/.breakpoints
end

define brestore
   source ~/.breakpoints
end
badeip
fuente
1

advertencia: el protocolo de salida actual no admite la redirección

También recibo este error / advertencia en GDB cuando intento habilitar el registro en modo TUI . Sin embargo, el registro parece funcionar cuando está en modo "no TUI". Así que dejo el modo TUI cuando quiero registrar algo. (Cambia de un lado a otro en modo TUI con Ctrl+X , Ctrl+A ).

Así es como trabajo:

  1. iniciar GDB (en modo normal)
  2. habilitar el registro: set logging onahora no debería quejarse.
  3. alternar hacia atrás / adelante al modo TUI y hacer cosas GDB
  4. cada vez que quiero registrar algo (como un gran volcado de traza inversa): alternar al modo normal
Magnux
fuente
Ah, y si te gusta usar "pantalla" (como a mí), se pondrá un poco desordenado, ya que usa las mismas teclas de acceso rápido.
Magnux el
1

La siguiente adición a una respuesta anterior me pareció útil para guardar / cargar los puntos de interrupción en un archivo específico.

  • Guardar puntos de interrupción: bsave {filename}
  • Puntos de interrupción de carga: bload {filename}

Como en la respuesta anterior, agregue el siguiente código al archivo ~ / .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
fuente
0

El problema es que establecer un punto de interrupción es sensible al contexto. ¿Qué pasa si tiene dos funciones estáticas llamadas foo ?

Si ya está depurando uno de los módulos que define foo, entonces GDB asumirá que se refería a ese. Pero si simplemente descarga "break foo" en un archivo y luego lee ese archivo al inicio, no estará claro a qué función se refiere .

Michael Snyder
fuente
0

¿Alguna otra idea? tengo

warning: Current output protocol does not support redirection

después

set logging on

EDITAR:

Sé que la pregunta es "cómo guardar una lista de puntos de interrupción", sin embargo, acabo de descubrir que con GDB simplemente podemos establecer puntos de interrupción "guardados en el archivo"

gdb> source breakpoints.txt

donde breakpoints.txthay un archivo como este:

break main.cpp:25
break engine.cpp:465
break wheel.cpp:57
ruidoso
fuente