2010-01-30 11 views
8

Estoy tratando de resolver automáticamente los typedefs en proyectos arbitrarios de C++ o C.Resolviendo typedefs en C y C++

Debido a que algunos de los typedefs se definen en los archivos de cabecera del sistema (por ejemplo uint32), actualmente estoy tratando de lograr esto mediante la ejecución del preprocesador gcc en mis archivos de código y luego escanear los archivos preprocesados ​​para typedefs. Debería poder reemplazar los typedefs en los archivos de código del proyecto.

Me pregunto, si hay otra forma, quizás más simple, me falta. Puedes pensar en una?

La razón, por la que quiero hacer esto: estoy extrayendo métricas de código de los proyectos C/C++ con diferentes herramientas. Las métricas están basadas en métodos. Después de extraer las métricas, tengo que fusionar los datos, que son producidos por las diferentes herramientas. El problema es que una de las herramientas resuelve typedefs y otras no. Si hay typedefs usados ​​para los tipos de parámetros de métodos, tengo métricas asignadas a diferentes nombres de métodos, que en realidad se refieren al mismo método en el código fuente.

parece este método en el código fuente: int test(uint32 par1, int par2)
Después de ejecutar mis herramientas tengo métricas, asignadas a un método denominado int test(uint32 par1, int par2) y algunos de mis métricas se asignan a int test(unsigned int par1, int par2).

+5

¿También puede darnos alguna información sobre por qué necesita eliminar estos typedefs de su código? Probablemente, eso ayudará a sugerir una solución. – Jay

Respuesta

5

Si no te importa averiguar dónde están definidos, puedes usar objdump para volcar la tabla de símbolos de C++ que resuelve typedefs.

lorien$ objdump --demangle --syms foo 

foo:  file format mach-o-i386 

SYMBOL TABLE: 
00001a24 g  1e SECT 01 0000 .text dyld_stub_binding_helper 
00001a38 g  1e SECT 01 0000 .text _dyld_func_lookup 
... 
00001c7c g  0f SECT 01 0080 .text foo::foo(char const*) 
... 

Este fragmento es de la siguiente definición de la estructura:

typedef char const* c_string; 
struct foo { 
    typedef c_string ntcstring; 
    foo(ntcstring s): buf(s) {} 
    std::string buf; 
}; 

Esto requiere que se compila todo y sólo se mostrará símbolos en el ejecutable resultante por lo que hay algunas limitaciones.La otra opción es hacer que el enlazador volque un mapa de símbolos. Para herramientas GNU, agregue -Wl,-map y -Wl,name donde name es el nombre del archivo que se va a generar (vea la nota). Este enfoque no exige los nombres, pero con un poco de trabajo puede realizar una ingeniería inversa de las convenciones de manipulación del compilador. La salida del fragmento anterior incluirá algo como:

0x00001CBE 0x0000005E [ 2] __ZN3fooC2EPKc 
0x00001D1C 0x0000001A [ 2] __ZN3fooC1EPKc 

Puede decodificar estos utilizando la especificación C++ ABI. Una vez que se sienta cómodo con la forma en que esto funciona, el mangling table incluido con el ABI no tiene precio. La derivación en este caso es:

<mangled-name>   ::= '_Z' <encoding> 
<encoding>    ::= <name> <bare-function-type> 
    <name>     ::= <nested-name> 
    <nested-name>  ::= 'N' <source-name> <ctor-dtor-name> 'E' 
     <source-name>  ::= <number> <identifier> 
     <ctor-dtor-name> ::= 'C2' # base object constructor 
    <bare-function-type> ::= <type>+ 
     <type>    ::= 'P' <type> # pointer to 
     <type>   ::= <cv-qualifier> <type> 
      <cv-qualifier> ::= 'K' # constant 
      <type>  ::= 'c' # character 

Nota: se ve como GNU cambia los argumentos a ld lo que es posible que desee comprobar el manual local (man ld) para asegurarse de que los comandos de generación de archivo de mapa son -mapfilename en su versión. En versiones recientes, use -Wl,-M and redirect stdout to a file.

+0

Cuando intento ejecutar mi compilador de esta manera: 'g ++ foo.cpp -Wl, -map -Wl, mapname' Obtengo el error'/usr/bin/ld: modo de emulación no reconocido: ap Emulaciones compatibles: elf_i386 i386linux' . ¿Estoy usando los parámetros correctamente? (versión de g ++: 4.4.2 20091208 (versión preliminar), versión de ld: 2.20.0.20091101) – Customizer

+0

Actualicé mi respuesta. Mi versión local todavía está en 4.0.1 y parece que los argumentos han cambiado. Pruebe 'g ++ foo.cpp -Wl, -M> foo.map'. –

+1

El programa C++ filt se puede usar para exigir los nombres. – Tronic

2

GCC-XML puede ayudar a resolver los typedefs, que tendría que seguir las de tipo-ids de <Typedef> elementos hasta que se resuelve en un elemento <FundamentalType>, <Struct> o <Class>.

Para reemplazar los typedefs en su proyecto, tiene un problema más fundamental: no puede simplemente buscar y reemplazar, ya que tendría que respetar el alcance de los nombres, p. Ej. function-local typedefs, namespace aliases o using directivas.

Dependiendo de lo que realmente está tratando de lograr, tiene que haber una manera mejor.

Actualización: En realidad, en el contexto dado de la fijación de datos de métricas, el reemplazo de los nombres de tipo con gcc-xml debería funcionar bien si es compatible con su código base.

+0

No estoy seguro, pero creo que GCC-XML en realidad ya no se desarrolla activamente. La última versión oficial es, según el sitio web, de 2004. Y si no recuerdo mal, la versión de CVS solo se basa en alguna versión 3.x de gcc. Realmente no lo sé, si eso importa, sin embargo. Hmm, espacios de nombres. Aún no había pensado en eso, para ser honesto. Eso complica el asunto ... – Customizer

+0

Pensé que querías decir reemplazar los tipos en la fuente, eso se habría vuelto más complicado. Si solo necesita corregir los datos de las métricas y no la fuente, gcc-xml debería ser suficiente si es compatible con su código base. –

+0

En realidad, creo que los proyectos, estoy analizando, deberían ser compilables por un gcc v. 3.x. Entonces esto podría funcionar – Customizer

3

Puede usar Clang (el front-end LLVM C/C++ compilador) para analizar el código de una manera que preserve la información sobre typedefs e incluso macros. Tiene una muy buena API C++ para leer los datos después de leer el código fuente en el AST (árbol de sintaxis abstracta). http://clang.llvm.org/

Si en su lugar busca un programa simple que ya resuelva por usted (en lugar de la API de programación Clang), creo que no tiene suerte, ya que nunca había visto tal cosa.

+0

Creo que el analizador de C++ de clangs no está completo aún? –

+0

La generación de código es bastante incompleta, pero ya puede manejar la mayoría de la biblioteca estándar, así como muchas bibliotecas externas. El analizador es más completo, pero aún le faltan algunas cosas (por lo que no puede usarlo, por ejemplo, con Boost Spirit.Qi). Aún así, creo que podría ser la mejor opción disponible para lo que el Personalizador está pidiendo. – Tronic

+0

La API se ve realmente genial. Tengo mucha curiosidad por probarlo cuando se estabilice. –