2012-04-06 11 views
9

Dove/come Apples GCC memorizza DWARF all'interno di un file eseguibile?dove/come Apples GCC memorizza DWARF all'interno di un eseguibile

Ho compilato un binario tramite gcc -gdwarf-2 (Mele GCC). Tuttavia, né objdump -gobjdump -h mi mostra alcuna informazione di debug.

Anche libbfd non trova alcuna informazione di debug. (Ho chiesto sulla binutils-mailinglist al riguardo here.)

Sono comunque in grado di estrarre le informazioni di debug tramite dsymutil (in un dSYM). libbfd è anche in grado di leggere quelle informazioni di debug allora.

risposta

35

Su Mac OS X è stato deciso che il linker (ld) non elabora tutte le informazioni di debug quando si collega il programma. Le informazioni di debug sono spesso 10 volte la dimensione dell'eseguibile del programma, in modo che il linker elabori tutte le informazioni di debug e includa nel binario eseguibile un grave danno ai tempi di collegamento. Per lo sviluppo iterativo - compilazione, collegamento, compilazione, collegamento, debug, compilazione di link - questo è stato un vero successo.

Invece il compilatore genera le informazioni di debug di DWARF nei file .s, l'assemblatore le pubblica nei file .o e il linker include una "mappa di debug" nel binario eseguibile che indica agli utenti di informazioni di debug dove tutto il i simboli sono stati trasferiti durante il collegamento.

Un consumatore (fare il debug .o file) carica la mappa di debug dall'eseguibile ed elabora tutto il nano nei file .o quando necessario, rimappare i simboli secondo le istruzioni della mappa di debug.

dsymutil può essere pensato come un linker di informazioni di debug. Fa lo stesso processo: legge la mappa di debug, carica il file DWG dai file .o, riposiziona tutti gli indirizzi e quindi genera un singolo binario di tutti i DWARF ai loro indirizzi finali collegati. Questo è il pacchetto dSYM.

Una volta che hai un bundle dSYM, hai un semplice vecchio standard DWARF che può essere elaborato da qualsiasi strumento di lettura nano (che può gestire file binari di Mach-O).

C'è un ulteriore raffinamento che fa funzionare tutto questo, gli UUID inclusi nei binari di Mach-O. Ogni volta che il linker crea un binario, emette un UUID a 128 bit nel comando di caricamento LC_UUID (v. otool -hlv o dwarfdump --uuid). Identifica in modo univoco quel file binario. Quando dsymutil crea il dSYM, include quell'UUID. I debugger associeranno solo un dSYM e un eseguibile se hanno UUID corrispondenti - nessun timestamp mod dodgy file o qualcosa del genere.

Possiamo anche utilizzare gli UUID per individuare i dSYM per i binari. Vengono visualizzati nei rapporti sugli arresti anomali, includiamo un importatore Spotlight che puoi utilizzare per cercarli, ad es. mdfind "com_apple_xcode_dsym_uuids == E21A4165-29D5-35DC-D08D-368476F85EE1" se il dSYM si trova in una posizione indicizzata Spotlight. Puoi anche avere un repository di dSYM per la tua azienda e un programma che può recuperare il dSYM corretto dato un UUID - forse un po 'di database mysql o qualcosa del genere - così si esegue il debugger su un eseguibile casuale e si ha istantaneamente tutto il debug informazioni per quell'eseguibile. Ci sono alcune cose carine che puoi fare con gli UUID.

Ma comunque, per rispondere alla tua domanda origine: Il binario unstripped ha la mappa di debug, i file .o hanno il nano, e quando viene eseguito dsymutil questi sono combinati per creare il fascio dSYM.

Se si desidera visualizzare le voci della mappa di debug, fare nm -pa executable e sono tutte lì. Sono nella forma dei vecchi record di pugnalate: il linker sapeva già come elaborare i pugni, quindi era più facile usarli, ma vedrai come funziona senza troppi problemi, magari riferirsi ad una documentazione di pugnalata se sei incerta.

+0

In che modo 'dsymutil' sa dove sono i file .o? Non vedo alcuna opzione nella manpage per dirlo. Inoltre ho bisogno di compilare il file binario '-g3', e in tal caso, posso spogliarlo dopo che ho' dsymutil''d? Grazie. – mxcl

+1

Ci sono voci "mappa di debug" nell'eseguibile prima che vengano eliminate con i nomi file dei file .o. 'nm -pa binario | grep OSO' li elencherà. Sono nella forma del vecchio formato di debug di stab (perché il linker sapeva già come gestire quel formato). Dopo aver creato il tuo dSYM, puoi eliminarli dal file eseguibile. Non dovresti aver bisogno di usare '-g3' sulla piattaforma Mac,' -g' dovrebbe essere sufficiente. Penso che '-g3' restituisca le informazioni macro di pre-elaborazione, ma Lldb non le legge su Mac OS X (e non so se clang ne possa persino produrre output.) –

+1

Grazie per questa risposta dettagliata e utile. – mxcl

2

Sembra che in realtà non lo sia.

Ho rintracciato dsymutil e legge tutti i file *.o. objdump -h elenca anche tutte le informazioni di debug in esse contenute.

Quindi sembra che quelle informazioni non vengano copiate nel binario.


Alcuni commenti correlati a questo proposito possono anche essere trovati here.

0

Apple memorizza le informazioni di debug in file separati denominati * .dSYM. È possibile eseguire dwarfdump su quei file e vedere le voci di informazioni di debug di DWARF.

+0

No. È possibile creare * * la dSYM tramite 'dsymutil'. Ma la mia domanda era, dove sono le informazioni di debug. Cioè da dove proviene 'dsymutil'. Ma ho già la risposta (vedi la mia risposta). Non sono in realtà nel binario, i binari fanno riferimento ai file '* .o' e questo è anche il punto in cui' dsymutil' sta ottenendo i dati. – Albert

+0

Beh, la tua domanda era vaga. L'ho interpretato per indicare dove sono archiviate le informazioni di debug quando utilizzate con un eseguibile nel debugger. – Bogatyr

+0

Sì, quella era la mia domanda. E la risposta è, è memorizzata nei file '* .o'. E quando crei un dSYM, ovviamente hai un'altra copia nel dSYM. Ma prima di creare il dSYM, non esiste dSYM. Questo è quello che ho detto nella mia domanda. ("Sono comunque in grado di estrarre le informazioni di debug tramite' dsymutil'. ") Non si ottiene automaticamente dSYM. Devi chiamare 'dsymutil'. (Penso che quando usi Xcode, Xcode lo faccia automaticamente.) O mi sbaglio? – Albert

0

sembra che ci siano due modi per OSX a posto le informazioni di debug:

  1. Nei file oggetto .o utilizzati per la compilazione. Il binario memorizza un riferimento a questi file (per percorso assoluto).

  2. In un fascio (directory) separata denominata .dSYM

Se compilo con Clang di Apple utilizzando g++ -g main.cpp -o foo ottengo il bundle chiamato foo.dSYM. Tuttavia se uso CMake ottengo le informazioni di debug nei file oggetto. Immagino perché fa un passo separato gcc -c main.cpp -o main.o?

Comunque ho trovato questo comando molto utile per il 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 } 
... 
Problemi correlati