c debugging dynamic gdb call-graph

Haga que GDB imprima el flujo de control de funciones a medida que se llaman



debugging dynamic (5)

Puede llamar a gdb en modo por lotes (usando la opción -x ), dividir donde necesita y pedir egrep ( bt ), luego filtrar el resultado usando grep o egrep .

Las sangrías son más difíciles, sin embargo, la salida bt está ordenada por lo que tiene la función actual en la parte superior de la traza y la main en la parte inferior.

Entonces usted crea archivos con comandos:

br <function name where to break> run bt kill quit

luego ejecute gdb <program> -x<command file>

Cadenas de filtro que comienzan con #<digit> - obtienes rastros de pila.

¿Cómo puedo hacer que las funciones de impresión gdb sean interesantes a medida que se llaman, sangradas según la profundidad de la pila en que se encuentran?

Quiero poder decir algo como (inventado):

(gdb) trace Foo* Bar* printf

Y haga que gdb imprima todas las funciones que comienzan con Foo o Bar, como se llaman. Algo así como gnu cflow, excepto que utiliza los símbolos de depuración y solo las funciones de impresión que realmente se llaman, no todos los flujos de llamadas posibles.

Las herramientas que no son útiles incluyen cachegrind, callgrind y oprofile, que ordenan los resultados por los que se llamaron las funciones con más frecuencia. Necesito preservar el orden de las llamadas.

El wildcarding (o equivalente) es esencial, ya que hay muchos funcs Foo y Bar. Aunque me conformaría con registrar absolutamente todas las funciones. O, quizás diciéndole a gdb que grabe todas las funciones en una biblioteca en particular.

¡Algún asistente de GDB debe tener un script para este trabajo común!


En su caso, recurriría al comando define en gdb, que le permite definir una función, que puede tomar hasta 10 argumentos.

Puede pasar los nombres de las funciones para "rastrear" como argumentos a la función que defina, o registrarlos todos en la función misma. Haría algo como lo siguiente

define functiontrace if $arg0 break $arg0 commands where continue end end if $arg1 ...

Los argumentos de una función definida por el usuario en gdb se mencionan como $ arg0- $ arg9. De forma alternativa, puede registrar todas las funciones que desee rastrear en la función, en lugar de usar $ arg0-9.

Nota: esto no sangrará en cuanto a la profundidad en la traza de la pila, sino que imprimirá la traza de la pila cada vez que se llame a la función. Encuentro que este enfoque es más útil que strace, etc ... porque registrará cualquier función que desee, sistema, biblioteca, local o de otro tipo.


Hay rbreak cmd aceptando expresiones regulares para establecer puntos de interrupción. Puedes usar:

(gdb) rbreak Foo.* (gdb) rbreak Bar.* (gdb) break printf

Consulte esto para obtener detalles sobre los puntos de interrupción.

Luego use commands para imprimir cada función como se le llama. Por ejemplo, deje α = el número del último punto de interrupción (puede verificarlo con i br si se perdió) , luego haga:

(gdb) commands 1-α Type commands for breakpoint(s) 1-α, one per line. End with a line saying just "end". >silent >bt 1 >c >end (gdb)

Algunas elaboraciones: silent suprime mensajes informativos innecesarios, bt 1 imprime el último fotograma de backtrace (es decir, es la función actual) , c es un atajo para continue , para continuar la ejecución, y end es solo el delimitador de la lista de comandos.

NB : si rastreas las funciones de la biblioteca, es posible que desees esperar a que se cargue lib. Por ejemplo, establezca un corte en la función main o cualquiera, ejecute la aplicación hasta ese punto y solo luego configure los puntos de interrupción que desee.


¿Has visto el excelente perfil de litb en una publicación similar aquí ?

Usa readelf para obtener símbolos interesantes, comandos gdb para obtener la traza y awk para pegar todo eso.

Básicamente lo que tiene que cambiar es modificar su script de comando gdb para eliminar la profundidad 1 de la traza inversa para ver la pila y filtrar funciones específicas, y reformatear la salida con una secuencia de comandos awk / python / (...) para presentarla como una árbol. (Admito que soy demasiado vago para hacerlo ahora ...)