2012-04-06 3 views
9

Où/comment Apple GCC stocke-t-il DWARF dans un exécutable?où/comment Apple GCC stocke-t-il DWARF dans un exécutable

J'ai compilé un binaire via gcc -gdwarf-2 (Apples GCC). Cependant, ni objdump -g ni objdump -h ne me montre d'informations de débogage.

De même, libbfd ne trouve aucune information de débogage. (J'ai demandé sur le binutils-mailinglist à ce sujet here.)

Je suis capable cependant d'extraire les informations de débogage via dsymutil (dans un dSYM). libbfd est également capable de lire ces informations de débogage.

Répondre

35

Sur Mac OS X, il a été décidé que l'éditeur de liens (ld) ne traitait pas toutes les informations de débogage lorsque vous liez votre programme. L'information de débogage est souvent 10 fois la taille de l'exécutable du programme, donc avoir l'éditeur de liens traiter toutes les informations de débogage et l'inclure dans le fichier exécutable binaire était un sérieux préjudice aux temps de liaison. Pour le développement itératif - compiler, lier, compiler, lier, déboguer, compiler le lien - ce fut un réel succès. Au lieu de cela, le compilateur génère les informations de débogage DWARF dans les fichiers .s, l'assembleur les affiche dans les fichiers .o et l'éditeur de liens inclut une "carte de débogage" dans le fichier binaire exécutable qui indique aux utilisateurs d'informations de débogage les symboles ont été déplacés pendant le lien. Un consommateur (effectuant le débogage .o-fichier) charge la carte de débogage à partir de l'exécutable et traite tous les DWARF dans les fichiers .o selon les besoins, remappant les symboles conformément aux instructions de la carte de débogage. Peut être considéré comme un éditeur de liens d'informations de débogage. Il fait ce même processus - lire la carte de débogage, charger le DWARF à partir des fichiers .o, relocaliser toutes les adresses - et ensuite sortir un seul binaire de tous les DWARF à leurs adresses liées finales. C'est le bundle dSYM. Une fois que vous avez un ensemble dSYM, vous avez un ancien DWARF standard que n'importe quel outil de lecture nain (qui peut traiter les fichiers binaires Mach-O) peut traiter.

Il existe un raffinement supplémentaire qui fait tout ce travail, les UUID inclus dans les binaires Mach-O. Chaque fois que l'éditeur de liens crée un binaire, il émet un UUID de 128 bits dans la commande de chargement LC_UUID (v. otool -hlv ou dwarfdump --uuid). Ceci identifie de manière unique ce fichier binaire. Lorsque dsymutil crée le dSYM, il inclut cet UUID. Les débogueurs n'associeront un dSYM et un exécutable que s'ils ont des UUID correspondants - pas d'horodatage de fichier dodgy mod ou quelque chose comme ça.

Nous pouvons également utiliser les UUID pour localiser les dSYM pour les binaires. Ils apparaissent dans les rapports d'erreur, nous incluons un importateur Spotlight que vous pouvez utiliser pour les rechercher, par ex. mdfind "com_apple_xcode_dsym_uuids == E21A4165-29D5-35DC-D08D-368476F85EE1" si le dSYM est situé dans un emplacement indexé Spotlight. Vous pouvez même avoir un référentiel de dSYMs pour votre entreprise et un programme qui peut récupérer le bon dSYM étant donné un UUID - peut-être une petite base de données mysql ou quelque chose comme ça - alors vous exécutez le débogueur sur un exécutable aléatoire et vous avez instantanément tout le déboguage info pour cet exécutable. Il y a quelques choses intéressantes que vous pouvez faire avec les UUID.

Mais de toute façon, pour répondre à votre question d'origine: Le binaire non déstructuré a la carte de débogage, les fichiers .o ont le DWARF, et lorsque dsymutil est exécuté, ils sont combinés pour créer le paquet dSYM.

Si vous voulez voir les entrées de débogage, faites nm -pa executable et ils sont tous là. Ils sont sous la forme des anciens dossiers stabs nlist - l'éditeur de liens savait déjà comment traiter les poignées de sorte qu'il était plus facile de les utiliser - mais vous verrez comment cela fonctionne sans trop de problèmes, peut-être se référer à la documentation si vous êtes incertain.

+0

Comment 'dsymutil' sait-il où sont les fichiers .o? Je ne vois aucune option dans la page de manuel pour le dire. Aussi ai-je besoin de compiler le binaire '-g3', et si oui, puis-je le supprimer après l'avoir' dsymutil''d? Merci. – mxcl

+1

Il existe des entrées "debug map" dans l'exécutable avant qu'il ne soit supprimé avec les noms de fichier des fichiers .o. 'nm -pa binaire | grep OSO' les liste. Ils sont sous la forme de l'ancien format debab de stabs (parce que l'éditeur de liens savait déjà comment gérer ce format). Après avoir créé votre dSYM, vous pouvez les supprimer de l'exécutable. Vous ne devriez pas avoir besoin d'utiliser '-g3' sur la plate-forme Mac,' -g' devrait suffire. Je pense que '-g3' sort des informations de macro de preprocess mais lldb ne les lit pas sur Mac OS X (et je ne sais pas si clang les sort même.) –

+1

Merci pour cette réponse détaillée et utile. – mxcl

2

Il semble que ce n'est pas le cas. J'ai tracé dsymutil et il lit tous les fichiers *.o. objdump -h répertorie également toutes les informations de débogage en eux.

Il semble donc que ces informations ne sont pas copiées sur le binaire.


Certains commentaires à propos de cela peuvent également être trouvés here.

0

Apple stocke les informations de débogage dans des fichiers distincts nommés * .dSYM. Vous pouvez exécuter dwarfdump sur ces fichiers et voir les entrées d'informations de débogage DWARF.

+0

Non, vous pouvez créer * * le dSYM via 'dsymutil'. Mais ma question était, où sont les informations de débogage. C'est à dire. D'où dsymutil' l'obtient-il? Mais j'ai déjà la réponse (voir ma propre réponse). Ils ne sont pas réellement dans le binaire, le binaire fait référence aux fichiers '* .o' et c'est aussi là que' dsymutil' obtient les données. – Albert

+0

Eh bien, votre question était vague. Je l'ai interprété comme signifiant où sont stockées les informations de débogage lorsqu'elles sont utilisées avec un exécutable dans le débogueur. – Bogatyr

+0

Oui, c'était ma question. Et la réponse est, il est stocké dans les fichiers '* .o'. Et quand vous créez un dSYM, alors bien sûr vous avez une autre copie dans le dSYM. Mais avant de créer le dSYM, il n'y a pas de dSYM. C'est ce que j'ai dit dans ma question. ("Je suis cependant capable d'extraire les informations de débogage via' dsymutil'. ") Vous n'obtenez pas automatiquement le dSYM. Vous devez appeler 'dsymutil'. (Je pense que lorsque vous utilisez Xcode, Xcode le fait automatiquement.) Ou ai-je tort? – Albert

0

Il semble qu'il ya deux façons pour Mac OS X pour placer des informations de débogage:

  1. Dans les fichiers objets .o utilisés pour la compilation. Le binaire stocke une référence à ces fichiers (par chemin absolu).

  2. Dans un paquet séparé (répertoire) appelé .dSYM

Si je compile avec Clang d'Apple en utilisant g++ -g main.cpp -o foo je reçois le paquet appelé foo.dSYM. Cependant, si j'utilise CMake, j'obtiens les informations de débogage dans les fichiers objets. Je suppose que parce qu'il fait une étape distincte gcc -c main.cpp -o main.o?

Quoi qu'il en soit, je trouve cette commande très utile pour le cas 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 } 
... 
Questions connexes