Agregar automáticamente registros de función de entrada / salida a un proyecto

Tengo un código fuente de terceros que debo investigar. Quiero ver en qué orden se llaman las funciones, pero no quiero perder el tiempo escribiendo.

printf("Entered into %s", __FUNCTION__) 

y

 printf("Exited from %s", __FUNCTION__) 

para cada función, ni quiero tocar ningún archivo fuente.

¿Tienes alguna sugerencia? ¿Hay una bandera del comstackdor que automágicamente hace esto por mí?

Aclaraciones a los comentarios:

  • Haré una comstackción cruzada de la fuente para ejecutarla en ARM.
  • Lo comstackré con gcc.
  • No quiero analizar el código estático. Quiero rastrear el tiempo de ejecución. Entonces doxygen no hará mi vida más fácil.
  • Tengo la fuente y puedo comstackrla.
  • No quiero usar la Progtwigción Orientada a Aspectos.

EDIT: encontré que el comando ‘frame’ en el indicador gdb imprime el cuadro actual (o, nombre de la función, se podría decir) en ese momento. Quizás, es posible (usando scripts gdb) llamar al comando ‘frame’ cada vez que se llama a una función. ¿Qué piensas?

Además de la depuración habitual y las técnicas de progtwigción orientadas a aspectos, también puede inyectar sus propias funciones de instrumentación utilizando las opciones de línea de comando de -finstrument-functions . Tendrá que implementar sus propias __cyg_profile_func_enter() y __cyg_profile_func_exit() (declare esto como extern "C" en C ++).

Proporcionan un medio para rastrear qué función se llamó desde dónde. Sin embargo, la interfaz es un poco difícil de usar ya que la dirección de la función que se llama y su sitio de llamada se pasan en lugar de un nombre de función, por ejemplo. Puede registrar las direcciones y luego extraer los nombres correspondientes de la tabla de símbolos usando algo como objdump --syms o nm , suponiendo, por supuesto, que los símbolos no se han eliminado de los binarios en cuestión.

Puede ser más fácil usar gdb . YMMV. 🙂

¿Dijo “ni quiero tocar ningún archivo fuente” … juego limpio si deja que un guión lo haga por usted?

Ejecuta esto en todos tus archivos .cpp

 sed 's/^{/{ENTRY/' 

Para que los convierta en esto:

 void foo() {ENTRY // code here } 

Pon esto en un encabezado que puede ser #incluido por cada unidad:

 #define ENTRY EntryRaiiObject obj ## __LINE__ (__FUNCTION__); struct EntryRaiiObject { EntryRaiiObject(const char *f) : f_(f) { printf("Entered into %s", f_); } ~EntryRaiiObject() { printf("Exited from %s", f_); } const char *f_; }; 

Puede que tenga que ser más elegante con el script sed . También puede poner la macro ENTRY en cualquier otro lugar que desee sondear, como un scope interior profundamente nested de una función.

Utilice / Gh (Habilitar _penter Hook Function) y / GH (Enable _pexit Hook Function) el comstackdor cambia (si puede comstackr las fonts de curso)

NOTA: no podrá usar esas macro. Vea aquí (“necesitará obtener la dirección de la función (en el registro EIP) y compararla con las direcciones en el archivo del mapa que puede generar el enlazador (suponiendo que no se haya producido ninguna rebase). Sin embargo, será muy lento”. )

De acuerdo con William, use gdb para ver el flujo del tiempo de ejecución.
Hay un analizador de código estático que puede decir qué funciones llaman y cuál puede proporcionarle algún gráfico de flujo de llamadas. Una herramienta es “Comprender C ++” (compatible con C / C ++) pero eso no es gratis, supongo. Pero puedes encontrar herramientas similares.

Si está utilizando gcc, el indicador del comstackdor mágico es -g. Compile con símbolos de depuración, ejecute el progtwig bajo gdb y genere rastros de stack. También puede usar ptrace, pero probablemente sea mucho más fácil simplemente usar gdb.