resueltos - ¿Cómo imprimir cada línea ejecutada en GDB automáticamente hasta que se alcanza un punto de corte determinado?
valor ganado excel (4)
¿Qué tal si se hace así en gdb, usando un archivo de comando? Cambie el argumento del archivo y cuente el bucle según sea necesario.
gdb -x run.gdb
run.gdb:
set pagination off
set logging file gdb.log
set logging on
set $i = 0
file main
break main
break WriteData
# sadly, commands not getting executed on reaching breakpoint 2
commands 2
set $i=1000
print "commands 2 : %d",$i
end
run
while ( $i < 1000 )
step
# next
# continue
set $i = $i + 1
end
Me gustaría poder establecer un punto de interrupción en GDB y llevarlo hasta ese punto, y en el proceso, imprimir las líneas que ha "pisado".
Aquí hay un ejemplo, basado en este archivo simple con un main
y una función, y dos puntos de interrupción para cada uno:
$ cat > test.c <<EOF
#include "stdio.h"
int count=0;
void doFunction(void) {
// two steps forward
count += 2;
// one step back
count--;
}
int main(void) {
// some pointless init commands;
count = 1;
count += 2;
count = 0;
//main loop
while(1) {
doFunction();
printf("%d/n", count);
}
}
EOF
$ gcc -g -Wall test.c -o test.exe
$ chmod +x test.exe
$ gdb -se test.exe
...
Reading symbols from /path/to/test.exe...done.
(gdb) b main
Breakpoint 1 at 0x80483ec: file test.c, line 14.
(gdb) b doFunction
Breakpoint 2 at 0x80483c7: file test.c, line 7.
Para iniciar la sesión, necesito ejecutar ( r
) el programa, que luego se detendrá en el primer punto de interrupción ( main
):
(gdb) r
Starting program: /path/to/test.exe
Breakpoint 1, main () at test.c:14
14 count = 1;
(gdb)
En este punto, puedo, por ejemplo, presionar continuar ( c
); y el proceso se ejecutará, sin generar ningún resultado, y se interrumpirá en la línea solicitada:
(gdb) c
Continuing.
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb)
Por otro lado, en lugar de continuar, puedo ir línea por línea, ya sea usando paso ( s
) o siguiente ( n
); por ejemplo:
14 count = 1;
(gdb) n
15 count += 2;
(gdb) s
16 count = 0;
(gdb) s
19 doFunction();
(gdb) s
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb) s
9 count--;
(gdb) s
10 }
(gdb) s
main () at test.c:20
20 printf("%d/n", count);
(gdb) s
...
(gdb) s
_IO_vfprintf_internal (s=Cannot access memory at address 0xe5853361
) at vfprintf.c:210
210 vfprintf.c: No such file or directory.
in vfprintf.c
(gdb) s
245 in vfprintf.c
(gdb) s
210 in vfprintf.c
(gdb) n
245 in vfprintf.c
...
(gdb) n
2006 in vfprintf.c
(gdb) n
__printf (format=0x80484f0 "%d/n") at printf.c:39
39 printf.c: No such file or directory.
in printf.c
(gdb) n
main () at test.c:21
21 }
(gdb) n
19 doFunction();
(gdb) n
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb)
De todos modos, soy consciente de que puedo mantener presionado Enter , y el último comando ingresado (paso o siguiente) se repetirá ( dejó sesión un poco más larga en el segundo caso, para mostrar que ''next'' sigue en el mismo nivel, pasos ''step'' dentro de las funciones que se llaman ). Sin embargo, como se puede ver, dependiendo de si el paso o las próximas ejecuciones, puede tomar un tiempo hasta que se llegue a un resultado, así que no quiero sentarme durante 10 minutos con la mano pegada en el botón Enter :)
Entonces, mi pregunta es: ¿de alguna manera puedo ordenar a gdb
que corra al "punto de corte 2" sin más intervención del usuario, mientras imprimo las líneas por las que pasa, como si se hubiera presionado el paso (o el siguiente)?
Basado en el enlace en la respuesta de @ sdaau ( http://www.mail-archive.com/[email protected]/msg00031.html ), creé mi propio script para simplemente seguir enviando ''s'' y leyendo el resultado de gdb de forma continua, mientras imprime salida en archivo de texto y terminal, por supuesto, mi script puede modificarse para adaptarse a las necesidades de los demás, sin embargo, espero que la modificación que hice se ajuste a la mayoría de las necesidades de la gente.
http://www.codeground.net/coding/gdb-step-into-all-lines-to-get-full-application-flow/
wget http://www.codeground.net/downloads/gdbwalkthrough.c
gcc gdbwalkthrough.c -o gdbwalkthrough
./gdbwalkthrough <application full path> [application arguments]
Bueno, esto no fue fácil, pero creo que de alguna manera lo entendí :) Pasé por un montón de intentos fallidos (publicados here ); el código relevante está abajo.
Básicamente, el problema en un "siguiente / paso hasta el punto de interrupción" es cómo determinar si está "en" un punto de interrupción o no, si el depurador se detiene (en un paso). Tenga en cuenta también que uso GDB 7.2-1ubuntu11 (actual para Ubuntu 11.04). Entonces, fue así:
- Primero encontré acerca de las variables de conveniencia , y pensé que, dado que hay contadores de programas y tal disponibilidad, debe haber alguna variable de conveniencia GDB que proporcione el estado de "punto de interrupción" y se puede usar directamente en un script de GDB. Sin embargo, después de mirar el índice de referencia de GDB por un tiempo, simplemente no puedo encontrar ninguna de esas variables (mis intentos están en nub.gdb )
- A falta de dicha variable interna de "estado de punto de interrupción", lo único que queda por hacer es capturar la salida de línea de comando (''stdout'') de GDB (en respuesta a los comandos) como una cadena, y analizarla (buscar) Punto de interrupción ")
- Luego, descubrí Python API a GDB, y el
gdb.execute("CMDSTR", toString=True)
- que aparentemente es exactamente lo que se necesita para capturar la salida: " Por defecto, cualquier salida producida por comando se envía a la salida estándar de gdb. Si el parámetro to_string es True, la salida será recopilada por gdb.execute y devuelta como una cadena [ 1 ] "!- Entonces, primero intenté hacer un script ( pygdb-nub.py , gdbwrap ) que utilizara
gdb.execute
de la manera recomendada; falló aquí, debido a esto: - Entonces, pensé que usaría un script de python para
subprocess.Popen
Permitir el programa GDB, mientras reemplazaba su stdin y stdout; y luego proceder a controlar GDB desde allí ( pygdb-sub.py ) - que también falló ... ( aparentemente, porque no redirigí stdin / out a la derecha ) - Entonces, pensé que usaría scripts de Python para ser llamado desde GDB (a través de
source
), que internamente se convertiría en pty siempre que segdb.execute
, para capturar su salida ( pygdb-fork.gdb , pygdb-fork.py ) ... Esto casi funcionó, ya que hay cadenas devueltas; sin embargo, GDB nota que algo no está bien: " [tcsetpgrp falló en terminal_inferior: Operación no permitida] ", y las siguientes cadenas de retorno no parecen cambiar.
- Entonces, primero intenté hacer un script ( pygdb-nub.py , gdbwrap ) que utilizara
Y finalmente, el enfoque que funcionó fue: redirigir temporalmente la salida de GDB desde un gdb.execute
a un archivo de registro en RAM (Linux: /dev/shm
); y luego leerlo de nuevo, analizarlo e imprimirlo desde python: python también maneja un ciclo while simple que da pasos hasta llegar a un punto de interrupción.
La ironía es que la mayoría de estos errores, que causaron esta solución mediante la redirección del archivo de registro, en realidad se corrigieron recientemente en SVN; lo que significa que se propagarán a las distribuciones en el futuro cercano, y uno podrá usar gdb.execute("CMDSTR", toString=True)
directamente: / Sin embargo, como no puedo arriesgarme a generar GDB desde la fuente en este momento (y posiblemente en posibles nuevas incompatibilidades), esto es lo suficientemente bueno para mí también :)
Aquí están los archivos relevantes (parcialmente también en pygdb-fork.gdb , pygdb-fork.py ):
pygdb-logg.gdb
es:
# gdb script: pygdb-logg.gdb
# easier interface for pygdb-logg.py stuff
# from within gdb: (gdb) source -v pygdb-logg.gdb
# from cdmline: gdb -x pygdb-logg.gdb -se test.exe
# first, "include" the python file:
source -v pygdb-logg.py
# define shorthand for nextUntilBreakpoint():
define nub
python nextUntilBreakpoint()
end
# set up breakpoints for test.exe:
b main
b doFunction
# go to main breakpoint
run
pygdb-logg.py
es:
# gdb will ''recognize'' this as python
# upon ''source pygdb-logg.py''
# however, from gdb functions still have
# to be called like:
# (gdb) python print logExecCapture("bt")
import sys
import gdb
import os
def logExecCapture(instr):
# /dev/shm - save file in RAM
ltxname="/dev/shm/c.log"
gdb.execute("set logging file "+ltxname) # lpfname
gdb.execute("set logging redirect on")
gdb.execute("set logging overwrite on")
gdb.execute("set logging on")
gdb.execute(instr)
gdb.execute("set logging off")
replyContents = open(ltxname, ''r'').read() # read entire file
return replyContents
# next until breakpoint
def nextUntilBreakpoint():
isInBreakpoint = -1;
# as long as we don''t find "Breakpoint" in report:
while isInBreakpoint == -1:
REP=logExecCapture("n")
isInBreakpoint = REP.find("Breakpoint")
print "LOOP:: ", isInBreakpoint, "/n", REP
Básicamente, pygdb-logg.gdb
carga el script pygdb-logg.py
python, configura el alias nub
para nextUntilBreakpoint
e inicializa la sesión; todo lo demás lo maneja el script python. Y aquí hay una sesión de muestra: con respecto a la fuente de prueba en OP:
$ gdb -x pygdb-logg.gdb -se test.exe
...
Reading symbols from /path/to/test.exe...done.
Breakpoint 1 at 0x80483ec: file test.c, line 14.
Breakpoint 2 at 0x80483c7: file test.c, line 7.
Breakpoint 1, main () at test.c:14
14 count = 1;
(gdb) nub
LOOP:: -1
15 count += 2;
LOOP:: -1
16 count = 0;
LOOP:: -1
19 doFunction();
LOOP:: 1
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb) nub
LOOP:: -1
9 count--;
LOOP:: -1
10 }
LOOP:: -1
main () at test.c:20
20 printf("%d/n", count);
1
LOOP:: -1
21 }
LOOP:: -1
19 doFunction();
LOOP:: 1
Breakpoint 2, doFunction () at test.c:7
7 count += 2;
(gdb)
... justo como yo lo quería: P Simplemente no sé qué tan confiable es ( y si será posible usarlo en avr-gdb
, que es para lo que necesito esto :) EDIT: versión de avr-gdb en Ubuntu 11.04 es actualmente 6.4, que no reconoce el comando python :( )
Bueno, espero que esto ayude a alguien,
¡Aclamaciones!
Aquí algunas referencias:
- GDB: error detectado en stdin
- GDB tiene problemas para enviar comandos a STDIN
- Re: [Gdb] ¿Cómo uso GDB otra entrada?
- gdb no acepta entrada en stdin
- Usando gdb en un IDE - comp.os.linux.development.apps | grupos de Google
- rmathew: enfermedad terminal
- [TUTORIAL] Llamar a un programa externo en C (Linux) - GIDForums
- shell: cómo usar múltiples argumentos con un shebang (es decir, #!)? - Desbordamiento de pila
- ¿Redirigir / almacenar salida de shell en la variable GDB? - Desbordamiento de pila
- Corey Goldberg: Python - Redirigir o desactivar STDOUT y STDERR
- The Cliffs of Inanity> 9. Scripting gdb
- gdb python scripting: ¿dónde ha desaparecido
parse_and_eval
? - Desbordamiento de pila - shell - Invoque gdb para pasar automáticamente argumentos al programa que se está depurando -
- Almacenamiento de archivos / directorios en memoria con tmpfs | HowtoForge - Howtos y tutoriales sobre Linux
- forma simple de tocar un archivo si no existe | Python | Pitón
- os.fork () diferente en cgi-script? - Python
- java - Escritura de pruebas que usan GDB - ¿cómo capturar resultados? - Desbordamiento de pila
- Depuración con GDB: cómo crear comandos GDB en Python - Wiki
- Tarjeta de referencia GDB
Como una nueva respuesta, ya que lo anterior ya está acallado :) Básicamente, si el punto es observar la ejecución de las líneas de código de origen (y / o ensamblado) como el programa en ejecución, como la motivación a menudo es para mí al buscar en " automático impresión "- entonces, básicamente, una forma muy rápida es usar el modo GDB TUI; Yo cito:
c - comportamiento del gdb: valor optimizado - Desbordamiento de pila # 1354762
Use el modo GDB TUI. Mi copia de GDB lo habilita cuando escribo el signo menos y Enter. Luego escriba Cx 2 (que es mantener presionado Control y presione X, suelte ambos y luego presione 2). Eso lo pondrá en la pantalla de fuente y desensamblaje divididos. Luego use stepi y nexti para mover una instrucción de máquina a la vez. Use Cx o para alternar entre las ventanas de TUI.
El truco aquí es que, incluso si presionas continue
- esta fuente de tiempo se mostrará e indicará en la TUI; y seguido mientras el programa se ejecuta:
... y esto para mí evita muchas situaciones en las que tendría que guiar los puntos de interrupción en el "contexto de auto-escalonamiento" (aunque todavía existen tales situaciones) .. Documentos sobre TUI: TUI - Depuración con GDB
¡Aclamaciones!