2012-08-29 20 views
6

Estoy construyendo un proyecto que construye múltiples bibliotecas compartidas y archivos ejecutables. Todos los archivos fuente que se usan para construir estos binarios están en un directorio único/src. Por lo tanto, no es obvio averiguar qué archivos fuente se usaron para compilar cada uno de los binarios (hay una relación muchos a muchos).¿Cómo encontrar los archivos * .c y * .h que se usaron para construir un archivo binario?

Mi objetivo es escribir un script que analice un conjunto de archivos C para cada binario y asegúrese de que solo se invocan las funciones correctas de ellos.

Una opción parece ser intentar extraer esta información de Makefile. Pero esto no funciona bien con los archivos generados y los encabezados (debido a la dependencia de las inclusiones).

Otra opción podría ser simplemente navegar por los gráficos de llamadas, pero esto se volvería complicado, ya que se utilizan muchas funciones mediante el uso de punteros a funciones.

¿Alguna otra idea?

+1

Solo por curiosidad: ¿por qué estás intentando esto? – stefan

+0

El mecanismo del paquete de distribución conoce todas las dependencias ... –

+0

¿Tiene una definición precisa de lo que significa "se llaman las funciones correctas"? No es obvio y no es simple. –

Respuesta

6

Primero puede compilar su proyecto con información de depuración (gcc -g) y usar objdump para obtener los archivos fuente que se incluyeron.

objdump -W <some_compiled_binary> 

El formato de enano debe contener la información que está buscando.

<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit) 
    < c> DW_AT_producer : (indirect string, offset: 0x5f): GNU C 4.4.3 
    <10> DW_AT_language : 1 (ANSI C) 
    <11> DW_AT_name  : (indirect string, offset: 0x28): test_3.c  
    <15> DW_AT_comp_dir : (indirect string, offset: 0x36): /home/auselen/trials  
    <19> DW_AT_low_pc  : 0x82f0 
    <1d> DW_AT_high_pc  : 0x8408 
    <21> DW_AT_stmt_list : 0x0 

En este ejemplo, he compilado fichero objeto de test_3, y se ubicó en el directorio .../ensayos. Luego, por supuesto, debe escribir un guión para recoger los nombres de los archivos de origen relacionados.

2

Aquí hay una idea, debe refinarse en función de su compilación específica. Cree una compilación, regístrela con una secuencia de comandos (por ejemplo, script log.txt make clean all). El último (o uno de los últimos) pasos debe ser la vinculación de los archivos objeto. (Sugerencia: busque cc -o <your_binary_name>). Esa línea debe vincular todos los archivos .o que deben tener los archivos correspondientes .c en su árbol. A continuación, grep esos archivos .c para todos los archivos de encabezado incluidos.

Si tiene nombres duplicados en sus archivos .c en su árbol, entonces necesitaremos ver la ruta completa en la línea del enlazador o trabajar desde el Makefile.

Lo que Mahmood sugiere a continuación debería funcionar también. Si tiene una imagen con símbolos, strings <debug_image> | grep <full_path_of_src_directory> debería darle una lista de archivos C.

+0

. Buena idea también. Pero no estoy familiarizado con los Makefiles para GCC, pero lo hago con VS y VS no mostrará ese paso en muchos detalles, sino que enumerará los archivos de la biblioteca con los que está enlazando. –

2

Primero debe separar los símbolos de depuración del binario que acaba de compilar. compruebe esta pregunta sobre cómo hacerlo: How to generate gcc debug symbol outside the build target?

Luego puede intentar analizar este archivo por su cuenta. Sé cómo hacerlo para Visual Studio, pero como está utilizando GCC, no podré ayudarlo más.

+0

¡Esto debería funcionar también! – jman

1

Puede usar la herramienta unix nm. Muestra todos los símbolos que están definidos en el objeto. Por lo que necesita:

  1. Run nm en su binario y agarrar todos los símbolos no definidos
  2. ldd Ejecutar en su binario a la lista de todas sus dependencias dinámicas agarrar (archivos .so su binario se enlaza a)
  3. nm ejecutar en cada archivo .so Youf encontró en el paso 2.

que le dará la lista completa de los dinámicas símbolos que su uso binario.

Ejemplo:

nm -C --dynamic /bin/ls 
....skipping..... 
00000000006186d0 A _edata 
0000000000618c70 A _end 
       U _exit 
0000000000410e34 T _fini 
0000000000401d88 T _init 
       U _obstack_begin 
       U _obstack_newchunk 
       U _setjmp 
       U abort 
       U acl_extended_file 
       U bindtextdomain 
       U calloc 
       U clock_gettime 
       U closedir 
       U dcgettext 
       U dirfd 

Todos esos símbolos con capital "U" son utilizados por comando ls.

1

Si su objetivo es analizar archivos fuente C, puede hacerlo personalizando el compilador GCC. Puede usar MELT para ese propósito (MELT es un lenguaje específico de dominio de alto nivel para extender GCC) -agregar sus propios pases de análisis codificados en MELT dentro de GCC-, pero primero debe aprender acerca de las representaciones internas de GCC de nivel medio (Gimple, Tree , ...).

Personalización de GCC lleva varios días de trabajo (sobre todo porque los internos de GCC son bastante complejos en los detalles).

No dudes en preguntarme más acerca de MELT.

Cuestiones relacionadas