109 votes

Pourquoi deux binaires de programmes dont seuls les commentaires ont été modifiés ne correspondent pas exactement dans gcc ?

J'ai donc créé deux programmes C

  1. Programme 1

    int main()
    {
    }
  2. Programme 2

    int main()
    {
    //Some Harmless comments
    }

AFAIK, lors de la compilation, le compilateur (gcc) devrait ignorer les commentaires et les espaces blancs redondants, et donc la sortie doit être similaire.

Mais quand j'ai vérifié les md5sums des binaires de sortie, ils ne correspondent pas. J'ai également essayé de compiler avec l'optimisation -O3 y -Ofast mais ils ne correspondaient toujours pas.

Alors, qu'est-ce qui se passe ici ?

EDIT : les commandes exactes et leurs md5sums sont (t1.c est le programme 1 et t2.c le programme 2)

gcc ./t1.c -o aaa
gcc ./t2.c -o bbb
98c1a86e593fd0181383662e68bac22f  aaa
c10293cbe6031b13dc6244d01b4d2793  bbb

gcc ./t2.c -Ofast -o bbb
gcc ./t1.c -Ofast -o aaa
2f65a6d5bc9bf1351bdd6919a766fa10  aaa
c0bee139c47183ce62e10c3dbc13c614  bbb

gcc ./t1.c -O3 -o aaa
gcc ./t2.c -O3 -o bbb
564a39d982710b0070bb9349bfc0e2cd  aaa
ad89b15e73b26e32026fd0f1dc152cd2  bbb

Et oui, les md5sums correspondent à travers plusieurs compilations avec les mêmes drapeaux.

BTW mon système est gcc (GCC) 5.2.0 y Linux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux

158voto

cyphar Points 1068

C'est parce que les noms de fichiers sont différents (bien que la sortie des chaînes soit la même). Si vous essayez de modifier le fichier lui-même (plutôt que d'avoir deux fichiers), vous remarquerez que les binaires de sortie ne sont plus différents. Comme Jens et moi-même l'avons dit, c'est parce que GCC déverse un grand nombre de métadonnées dans les binaires qu'il construit, y compris le nom exact du fichier source (et AFAICS aussi clang).

Essayez ça :

$ cp code.c code2.c subdir/code.c
$ gcc code.c -o a
$ gcc code2.c -o b
$ gcc subdir/code.c -o a2
$ diff a b
Binary files a and b differ
$ diff a2 b
Binary files a2 and b differ
$ diff -s a a2
Files a and a2 are identical

Cela explique pourquoi vos md5sums ne changent pas entre les builds, mais qu'ils sont différents entre les différents fichiers. Si vous voulez, vous pouvez faire ce que Jens a suggéré et comparer la sortie de strings pour chaque binaire, vous remarquerez que les noms de fichiers sont intégrés dans le binaire. Si vous voulez "réparer" cela, vous pouvez strip les binaires et les métadonnées seront supprimés :

$ strip a a2 b
$ diff -s a b
Files a and b are identical
$ diff -s a2 b
Files a2 and b are identical
$ diff -s a a2
Files a and a2 are identical

27voto

Jens Points 17702

Les raisons les plus courantes sont les noms de fichiers et les horodatages ajoutés par le compilateur (généralement dans la partie "debug info" des sections ELF).

Essayez de courir

 $ strings -a program > x
 ...recompile program...
 $ strings -a program > y
 $ diff x y

et vous pourriez voir la raison. J'ai une fois utilisé cette méthode pour comprendre pourquoi la même source produisait un code différent lorsqu'elle était compilée dans différents répertoires. La conclusion était que le __FILE__ étendu à une absolu nom du fichier, différent dans les deux arbres.

15voto

lserni Points 19089

UPDATE : rappelez-vous que le nom du fichier source va dans le binaire non dépouillé, donc deux programmes provenant de fichiers sources nommés différemment auront des hachages différents.

Réponse précédente (utile pour étudier des situations similaires si les réponses ci-dessus ne s'appliquent pas) :

Vous pouvez essayer :

  • en cours d'exécution strip contre le binaire pour enlever un peu de graisse. Si les binaires dépouillés sont les mêmes, alors il s'agissait de métadonnées qui ne sont pas essentielles au fonctionnement du programme.
  • générer une sortie intermédiaire d'assemblage pour vérifier que la différence ne se trouve pas dans les instructions réelles du CPU (ou, cependant, pour mieux localiser l'endroit où la différence se trouve réellement). est )
  • utiliser strings Vous pouvez aussi faire un dump des deux programmes en hexadécimal et lancer un diff sur les deux dumps hexadécimaux. Une fois que vous avez localisé la ou les différences, vous pouvez essayer de voir s'il y a une rime ou une raison à ces différences (PID, timestamps, timestamp du fichier source...). Par exemple, vous pouvez avoir une routine stockage de l'horodatage au moment de la compilation à des fins de diagnostic.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X