¿Cómo recargar un binario recompilado en gdb sin salir y perder puntos de interrupción?

4 minutos de lectura

avatar de usuario de user280937
usuario280937

De acuerdo a esta excelente guia uno debería poder recompilar un archivo fuente y simplemente usar ‘r’ para que gdb comience a depurar el nuevo binario modificado.

Esto también parecía implícito en el manual de gdb por “Si el tiempo de modificación de su archivo de símbolos ha cambiado desde la última vez que GDB leyó sus símbolos, GDB descarta su tabla de símbolos y la vuelve a leer”.

Estoy tratando de depurar un archivo .cpp simple y único en Ubuntu 16.10. Después de compilar a través de g++ -ggdb -std=c++11 foo.cpppuedo depurar como de costumbre.

GNU gdb (Ubuntu 7.11.90.20161005-0ubuntu2) 7.11.90.20161005-git
[...]
(gdb) break main
Breakpoint 1 at 0x2754: file foo.cpp, line 204.
(gdb) r
Starting program: /home/code/foo

Breakpoint 1, main () at foo.cpp:204
(gdb) n
(gdb) k
Kill the program being debugged? (y or n) y

Aquí, realizo un cambio menor en el archivo fuente y luego vuelvo a compilar. Al intentar ejecutar el archivo de nuevo:

(gdb) r
/home/code/foo' has changed; re-reading symbols.
Error in re-setting breakpoint 1: Cannot access memory at address 0x55555555674b
Starting program: /home/code/598
warning: Probes-based dynamic linker interface failed.
Reverting to original interface.

[Inferior 1 (process 20898) exited normally]

¿Hay alguna manera de recargar con éxito el binario mientras se mantienen intactos mis puntos de interrupción?

EDITAR: Esta publicación tenía la respuesta que estaba buscando. Recargas el ejecutable con el file binaryname dominio.

(gdb) file foo
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
A program is being debugged already.
Load new symbol table from "foo"? (y or n) y
Reading symbols from foo...done.
Error in re-setting breakpoint 1: Cannot access memory at address 0x274b
Error in re-setting breakpoint 2: Cannot access memory at address 0x274b

Vemos que los puntos de interrupción todavía están allí, simplemente deshabilitados:

(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x0000555555556754
        breakpoint already hit 1 time
2       breakpoint     keep n   0x000055555555677b 

Y entonces simplemente los habilitamos:

(gdb) enable
(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000555555556754 
        breakpoint already hit 1 time
2       breakpoint     keep y   0x000055555555677b
(gdb) 

Esto funciona, pero me encantaría saber si alguien tiene más consejos o comentarios sobre si simplemente usar run de hecho debería funcionar.

  • El punto de interrupción probablemente se encontraba en una ubicación que ya no es válida con su nuevo código. Y recuerda que incluso si todavía está en una ubicación válida, es posible que no sea la misma ubicación que esperas.

    – Un tipo programador

    26 de marzo de 2018 a las 9:24


  • Además, piense en el título de la pregunta que publicó. La cuestión no es realmente recargar el programa, sino mantener los puntos de interrupción.

    – Un tipo programador

    26 de marzo de 2018 a las 9:25

  • Editado con la solución, que efectivamente existe en GDB desde hace mucho tiempo. El punto de interrupción era válido, los ejemplos que se muestran eran una diferencia de un solo carácter en la fuente. No pude encontrar otras referencias o preguntas con respecto a la recarga del mismo binario, además de algunas guías que implican (gdb) r recargará mágicamente todo. Esto es algo que aquellos menos familiarizados con gdb podrían encontrar y tener dificultades.

    – usuario280937

    26 de marzo de 2018 a las 9:42


  • El avion run el enfoque funciona para mí. Por qué está fallando para usted es algo que vale la pena investigar. Quizás presente un error de gdb con detalles.

    –Tom Tromey

    26 de marzo de 2018 a las 14:29

  • En caso de que necesite reiniciar su computadora stackoverflow.com/questions/501486/…

    – norte 1.8e9-dónde-está-mi-participación m.

    19 de diciembre de 2018 a las 20:49

Cuando estaba usando gdb 5, usar solo ‘ejecutar’ después de la recompilación fue suficiente para recargar los símbolos. Ahora, con gdb 8.1, necesito escribir ‘archivo ejecutable’ antes de ‘ejecutar’ para obligar a gdb a recargar los símbolos después de la recompilación.

  • En gdb 7.7, también necesito ejecutar file /PATH/TO/EXECUTABLE antes de run dominio

    – Jamón

    18 de enero a las 4:46

Aquí hay un script que uso en gdb 8.3 (ligeramente adaptado para esta respuesta):

define make
    shell make
    python gdb.execute("file " + gdb.current_progspace().filename)
    # clear cache
    directory
end

Necesita tener gdb con Python. Nota la directory comando que actualiza la memoria caché de los archivos de origen.

El problema específicamente con los puntos de interrupción y PIE parece haberse solucionado en gdb 8.3.1 – ver https://www.gnu.org/software/gdb/noticias/ y PR 25011.

Dado que el problema se debe a los ejecutables independientes de la posición (PIE), volver a vincular el programa con -no-pie también debe evitarlo.

El problema que me llevó a esta pregunta fue que la recarga automática de símbolos parecía haberse roto en el nuevo gdb, pero parece que el cambio no estaba en gdb sino que las distribuciones de Linux comenzaron a habilitar PIE de forma predeterminada en gcc. Vinculación con -no-pie también se arregló la recarga de símbolos para mí.

¿Ha sido útil esta solución?