2012-04-06 6 views
9

¿Dónde/cómo las manzanas GCC almacenan DWARF dentro de un archivo ejecutable?dónde/cómo guarda Apples GCC DWARF dentro de un archivo ejecutable

Recopilé un archivo binario a través de gcc -gdwarf-2 (Apples GCC). Sin embargo, ni objdump -g ni objdump -h me muestran ninguna información de depuración.

También libbfd no encuentra ninguna información de depuración. (Lo pregunté en el binutils-mailinglist al respecto here.)

Sin embargo, puedo extraer la información de depuración a través de dsymutil (en un dSYM). libbfd también puede leer esas informaciones de depuración.

Respuesta

35

En Mac OS X hubo una decisión de que el vinculador (ld) no procesara toda la información de depuración cuando vincula su programa. La información de depuración suele ser 10 veces más grande que el ejecutable del programa, por lo que hacer que el enlazador procese toda la información de depuración e incluirla en el binario ejecutable fue un grave perjuicio para los tiempos de enlace. Para el desarrollo iterativo, compilar, vincular, compilar, vincular, depurar, compilar enlace, esto fue un verdadero éxito.

En su lugar, el compilador genera la información de depuración DWARF en los archivos .s, el ensamblador lo genera en los archivos .o, y el enlazador incluye un "mapa de depuración" en el binario ejecutable que informa a los usuarios los símbolos fueron reubicados durante el enlace.

Un consumidor (haciendo la depuración de archivos .o) carga el mapa de depuración desde el ejecutable y procesa todo el DWARF en los archivos .o según sea necesario, reasignando los símbolos según las instrucciones del mapa de depuración.

dsymutil se puede considerar como un enlazador de información de depuración. Realiza este mismo proceso: lea el mapa de depuración, cargue el DWARF de los archivos .o, reubique todas las direcciones, y luego emite un solo binario de todos los DWARF en sus direcciones finales y vinculadas. Este es el paquete dSYM.

Una vez que tiene un paquete dSYM, tiene un DWARF normal antiguo que cualquier herramienta de lectura enana (que puede tratar con archivos binarios Mach-O) puede procesar.

Hay un refinamiento adicional que hace que todo este trabajo, los UUID incluidos en los binarios de Mach-O. Cada vez que el enlazador crea un binario, emite un UUID de 128 bits en el comando de carga LC_UUID (v. otool -hlv o dwarfdump --uuid). Esto identifica de manera única ese archivo binario. Cuando dsymutil crea el dSYM, incluye ese UUID. Los depuradores solo asociarán un dSYM y un ejecutable si tienen UUID coincidentes, sin marcas de tiempo de mod de archivo dudosas ni nada de eso.

También podemos usar los UUID para ubicar los dSYM para binarios. Aparecen en informes de fallos, incluimos un importador de Spotlight que puede usar para buscarlos, p. mdfind "com_apple_xcode_dsym_uuids == E21A4165-29D5-35DC-D08D-368476F85EE1" si el dSYM se encuentra en una ubicación indexada de Spotlight. Incluso puede tener un repositorio de dSYM para su empresa y un programa que puede recuperar el dSYM correcto dado un UUID - tal vez una pequeña base de datos mysql o algo así - para que ejecute el depurador en un ejecutable aleatorio y tenga al instante toda la depuración información para ese ejecutable. Hay algunas cosas bonitas que puedes hacer con los UUID.

Pero de todos modos, para responder a su pregunta de origen: El binario sin comprimir tiene el mapa de depuración, los archivos .o tienen el DWARF, y cuando se ejecuta dsymutil, estos se combinan para crear el paquete dSYM.

Si quiere ver las entradas del mapa de depuración, haga nm -pa executable y todas están allí. Están en la forma de los viejos registros de la lista de apuñalamientos (el vinculador ya sabía cómo procesar las puñaladas, así que era más fácil usarlas), pero verás cómo funciona sin muchos problemas, tal vez refiéraste a la documentación de algunas estacas si eres incierto.

+0

¿Cómo sabe 'dsymutil' dónde están los archivos .o? No veo ninguna opción en la página de manual para contarlo. También necesito compilar el binario '-g3', y si es así, ¿puedo quitarlo después de' dsymutil''d? Gracias. – mxcl

+1

Hay entradas de "depuración de mapa" en el ejecutable antes de que se elimine con los nombres de archivo de los archivos .o. 'nm -pa binario | grep OSO' los listará. Están en la forma del antiguo formato de depuración de amenazas (porque el enlazador ya sabía cómo manejar ese formato). Después de haber creado su dSYM, puede quitarlos del ejecutable. No debería necesitar usar '-g3' en la plataforma Mac,' -g' debería ser suficiente. Creo que las salidas '-g3' preprocesan la información macro pero lldb no lee eso en Mac OS X (y no sé si el sonido incluso lo emite). –

+1

Gracias por esta respuesta detallada y útil. – mxcl

2

Parece que en realidad no es así.

He rastreado dsymutil y lee todos los archivos *.o. objdump -h también enumera toda la información de depuración en ellos.

Parece que esa información no se copia en el binario.


Algunos comentarios relacionados acerca de esto también se puede encontrar here.

0

Apple almacena la información de depuración en archivos separados llamados * .dSYM. Puede ejecutar dwarfdump en esos archivos y ver las entradas de información de depuración DWARF.

+0

No. Puede crear * * la dSYM a través de 'dsymutil'. Pero mi pregunta era, ¿dónde está la información de depuración? Es decir. de donde viene 'dsymutil'. Pero ya tengo la respuesta (ver mi propia respuesta). En realidad, no están en el binario, el binario hace referencia a los archivos '* .o' y también es de donde' dsymutil' obtiene los datos. – Albert

+0

Bueno, tu pregunta era vaga. Lo interpreté para indicar dónde se almacena la información de depuración cuando se usa con un ejecutable en el depurador. – Bogatyr

+0

Sí, esa era mi pregunta. Y la respuesta es que está almacenado en los archivos '* .o'. Y cuando creas un dSYM, entonces por supuesto tienes otra copia en el dSYM. Pero antes de crear el dSYM, no hay dSYM. Eso es lo que dije en mi pregunta. ("Sin embargo, puedo extraer la información de depuración a través de' dsymutil'. ") No obtiene automáticamente el dSYM. Tienes que llamar a 'dsymutil'. (Creo que cuando usas Xcode, Xcode lo hace automáticamente.) ¿O estoy equivocado allí? – Albert

0

Parece que hay dos maneras para OSX para colocar información de depuración:

  1. En los .o archivos de objetos utilizados para la compilación. El binario almacena una referencia a estos archivos (por ruta absoluta).

  2. en un paquete separado (directorio) llamado .dSYM

Si compilo con Clang de Apple utilizando g++ -g main.cpp -o foo consigo el paquete llamado foo.dSYM. Sin embargo, si uso CMake obtengo la información de depuración en los archivos del objeto. Supongo que porque hace un paso gcc -c main.cpp -o main.o por separado

De todos modos yo encontramos este comando muy útil para el caso 1:

$ dsymutil -dump-debug-map main 
--- 
triple:   'x86_64-apple-darwin' 
binary-path:  main 
objects:   
    - filename:  /Users/tim/foo/build/CMakeFiles/main.dir/main.cpp.o 
    timestamp:  1485951213 
    symbols:   
     - { sym: __ZNSt3__111char_traitsIcE11eq_int_typeEii, objAddr: 0x0000000000000D50, binAddr: 0x0000000100001C90, size: 0x00000020 } 
     - { sym: __ZNSt3__111char_traitsIcE6lengthEPKc, objAddr: 0x0000000000000660, binAddr: 0x00000001000015A0, size: 0x00000020 } 
     - { sym: GCC_except_table3, objAddr: 0x0000000000000DBC, binAddr: 0x0000000100001E2C, size: 0x00000000 } 
     - { sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000F40, size: 0x00000090 } 
     - { sym: __ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m, objAddr: 0x00000000000001F0, binAddr: 0x0000000100001130, size: 0x00000470 } 
     - { sym: ___clang_call_terminate, objAddr: 0x0000000000000D40, binAddr: 0x0000000100001C80, size: 0x00000010 } 
     - { sym: GCC_except_table5, objAddr: 0x0000000000000E6C, binAddr: 0x0000000100001EDC, size: 0x00000000 } 
     - { sym: __ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_, objAddr: 0x0000000000000680, binAddr: 0x00000001000015C0, size: 0x000006C0 } 
     - { sym: __ZNSt3__14endlIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_, objAddr: 0x00000000000000E0, binAddr: 0x0000000100001020, size: 0x00000110 } 
     - { sym: GCC_except_table2, objAddr: 0x0000000000000D7C, binAddr: 0x0000000100001DEC, size: 0x00000000 } 
     - { sym: __ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc, objAddr: 0x0000000000000090, binAddr: 0x0000000100000FD0, size: 0x00000050 } 
     - { sym: __ZNSt3__111char_traitsIcE3eofEv, objAddr: 0x0000000000000D70, binAddr: 0x0000000100001CB0, size: 0x0000000B } 
... 
Cuestiones relacionadas