Warum stimmen zwei Binärdateien von Programmen mit nur geänderten Kommentaren nicht genau in gcc überein?

Lesezeit: 6 Minuten

Benutzeravatar des registrierten Benutzers
registrierter Nutzer

Ich habe zwei C-Programme erstellt

  1. Programm 1

    int main()
    {
    }
    
  2. Programm 2

    int main()
    {
    //Some Harmless comments
    }
    

AFAIK, beim Kompilieren sollte der Compiler (gcc) die Kommentare und redundanten Whitespaces ignorieren, und daher muss die Ausgabe ähnlich sein.

Aber als ich die MD5-Summen der Ausgabebinärdateien überprüft habe, stimmen sie nicht überein. Ich habe auch versucht, mit Optimierung zu kompilieren -O3 und -Ofast aber sie passten immer noch nicht zusammen.

Was passiert hier?

BEARBEITEN: die genauen Befehle und dort md5sums sind (t1.c ist Programm 1 und t2.c ist Programm 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

Und ja, md5sums stimmen über mehrere Kompilationen mit denselben Flags überein.

BTW mein System ist gcc (GCC) 5.2.0 und Linux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux

  • Bitte geben Sie Ihre genauen Befehlszeilen-Flags an. Sind zum Beispiel Debug-Informationen überhaupt in den Binärdateien enthalten? Wenn ja, würde sich die Änderung der Zeilennummern offensichtlich darauf auswirken …

    – Jon Skeet

    4. September 2015 um 14:51 Uhr

  • Ist die MD5-Summe über mehrere Builds desselben Codes konsistent?

    – wenig begeisterter Benutzer

    4. September 2015 um 14:51 Uhr

  • Ich kann das nicht reproduzieren. Ich hätte vermutet, dass dies daran liegt, dass der GCC beim Kompilieren eine ganze Reihe von Metadaten in Binärdateien einbettet (einschließlich Zeitstempel). Wenn Sie das hinzufügen könnten präzise Befehlszeilen-Flags, die Sie verwendet haben, das wird nützlich sein.

    – Cyphar

    4. September 2015 um 14:53 Uhr


  • Anstatt nur MD5-Summen zu überprüfen und hängen zu bleiben, hexdump und diff, um genau zu sehen, welche Bytes sich unterscheiden

    – MM

    5. September 2015 um 10:39 Uhr

  • Obwohl die Antwort auf die Frage “Was ist der Unterschied zwischen den beiden Compilerausgaben?” Interessant ist, stelle ich fest, dass die Frage eine ungerechtfertigte Annahme hat: dass die beiden Ausgänge sollte gleich sein und dass wir welche benötigen Erläuterung warum sie anders sind. Alles, was der Compiler Ihnen verspricht, ist, dass, wenn Sie ihm ein legales C-Programm geben, die Ausgabe eine legale ausführbare Datei ist, die dieses Programm implementiert. Dass zwei beliebige Ausführungen des Compilers dieselbe Binärdatei erzeugen, ist keine Garantie des C-Standards.

    – Eric Lippert

    5. September 2015 um 18:47 Uhr

Benutzeravatar von cyphar
Cyphar

Das liegt daran, dass die Dateinamen unterschiedlich sind (obwohl die Ausgabe der Zeichenfolgen dieselbe ist). Wenn Sie versuchen, die Datei selbst zu ändern (anstatt zwei Dateien zu haben), werden Sie feststellen, dass die ausgegebenen Binärdateien nicht mehr unterschiedlich sind. Wie sowohl Jens als auch ich sagten, liegt es daran, dass GCC eine ganze Menge Metadaten in die von ihm erstellten Binärdateien ablegt, einschließlich des genauen Quelldateinamens (und AFAICS tut das auch).

Versuche dies:

$ 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

Dies erklärt, warum sich Ihre MD5-Summen zwischen Builds nicht ändern, aber zwischen verschiedenen Dateien unterschiedlich sind. Wenn Sie möchten, können Sie tun, was Jens vorgeschlagen hat, und die Ausgabe von vergleichen strings Für jede Binärdatei werden Sie feststellen, dass die Dateinamen in die Binärdatei eingebettet sind. Wenn Sie dies “reparieren” möchten, können Sie dies tun strip Die Binärdateien und die Metadaten werden entfernt:

$ 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

  • BEARBEITEN: Aktualisiert, um zu sagen, dass Sie die Binärdateien entfernen können, um das Problem zu “beheben”.

    – Cyphar

    4. September 2015 um 15:21 Uhr

  • Und deshalb sollten Sie die Assembly-Ausgabe vergleichen, nicht MD5-Prüfsummen.

    – Leichtigkeitsrennen im Orbit

    4. September 2015 um 18:06 Uhr

  • Ich habe hier eine Anschlussfrage gestellt.

    – Federico Poloni

    5. September 2015 um 13:27 Uhr

  • Je nach Objektdateiformat wird auch die Kompilierzeit in den Objektdateien gespeichert. Die Verwendung von COFF-Dateien zum Beispiel wäre also nicht identisch mit den Dateien a und a2.

    – Martin Rosenau

    6. September 2015 um 9:41 Uhr

Benutzeravatar von Jens
Jens

Der häufigste Grund sind Dateinamen und Zeitstempel, die vom Compiler hinzugefügt wurden (normalerweise im Debug-Info-Teil der ELF-Abschnitte).

Versuchen Sie es mit Laufen

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

und Sie könnten den Grund sehen. Ich habe dies einmal verwendet, um herauszufinden, warum dieselbe Quelle unterschiedlichen Code verursachen würde, wenn sie in verschiedenen Verzeichnissen kompiliert wird. Die Feststellung war, dass die __FILE__ Makro erweitert zu einem absolut Dateiname, in beiden Bäumen unterschiedlich.

  • Entsprechend gcc.gnu.org/ml/gcc-help/2007-05/msg00138.html (veraltet, ich weiß) sie speichern keine Zeitstempel und es könnte ein Linker-Problem sein. Ich erinnere mich jedoch, dass ich kürzlich eine Geschichte darüber gelesen habe, wie eine Sicherheitsfirma die Arbeitsgewohnheiten eines Hackerteams mithilfe der GCC-Zeitstempelinformationen in ihren Binärdateien profiliert hat.

    – Cyphar

    4. September 2015 um 15:01 Uhr

  • Und ganz zu schweigen davon, dass OP angibt, dass “md5sums über mehrere Kompilierungen mit denselben Flags übereinstimmen”, was darauf hinweist, dass es wahrscheinlich nicht die Zeitstempel sind, die das Problem verursachen. Dies liegt wahrscheinlich daran, dass es sich um unterschiedliche Dateinamen handelt.

    – Cyphar

    4. September 2015 um 15:04 Uhr

  • @cyphar Unterschiedliche Dateinamen sollten auch vom strings/diff-Ansatz erfasst werden.

    – Jens

    4. September 2015 um 15:16 Uhr

Benutzeravatar von LSerni
LSerni

Notiz: Denken Sie daran, dass die Quelldateiname geht in die nicht gestrippte Binärdatei, sodass zwei Programme, die aus unterschiedlich benannten Quelldateien stammen, unterschiedliche Hashes haben.

In ähnlichen Situationen sollte das oben Gesagte nicht zutreffenDu kannst es versuchen:

  • laufend strip gegen die Binärdatei, um etwas Fett zu entfernen. Wenn die entfernten Binärdateien dieselben sind, dann waren es einige Metadaten, die für den Programmbetrieb nicht wesentlich sind.
  • Generieren einer Assembly-Zwischenausgabe, um zu überprüfen, ob der Unterschied nicht in den eigentlichen CPU-Anweisungen liegt (oder um besser zu lokalisieren, wo der Unterschied tatsächlich liegt ist)
  • verwenden strings, oder geben Sie beide Programme in Hex aus und führen Sie einen Diff auf den beiden Hex-Dumps aus. Sobald Sie die Unterschiede gefunden haben, können Sie versuchen zu sehen, ob sie einen Reim oder Grund haben (PID, Zeitstempel, Zeitstempel der Quelldatei …). Beispielsweise könnten Sie eine Routine haben, die den Zeitstempel zur Kompilierzeit zu Diagnosezwecken speichert.

  • Mein System ist gcc (GCC) 5.2.0 und Linux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux

    – Registrierter Nutzer

    4. September 2015 um 15:09 Uhr


  • Du solltest es versuchen eigentlich Erstellen von zwei separaten Dateien. Ich konnte es auch nicht reproduzieren, indem ich eine einzelne Datei änderte.

    – Cyphar

    4. September 2015 um 15:10 Uhr

  • Ja, Dateinamen sind schuld. Ich kann dieselben MD5-Summen erhalten, wenn ich die Programme mit demselben Namen kompiliere.

    – Registrierter Nutzer

    4. September 2015 um 15:17 Uhr

1422040cookie-checkWarum stimmen zwei Binärdateien von Programmen mit nur geänderten Kommentaren nicht genau in gcc überein?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy