Hallo,
ich habe ein Projekt für einen xmega128a3u, welches ich mit der Atmel
Toolchain übersetze. In der Zusammenarbeit mit Kollegen hat sich
herausgestellt, dass das generierte hexfile unterschiedlich ist, wenn
man es unter Windows und unter Linux compiliert.
Hier die Toolchain unter Linux:
Der diff ergibt, dass das Ende der Hexfiles gleich aussieht, nur die
Anfänge unterscheiden sich (also vermutlich irgendwelche libs?).
Meine Frage: Was sind die Unterschiede und wie kann ich identische
Hexfiles erzeugen? Vielen Dank schonmal!
Gruß
Rüdiger F. schrieb:> Meine Frage: Was sind die Unterschiede
Wie soll man diese erkennen, wenn Du sie nicht zeigst?
"Ich habe zwei Hemden im Kleiderschrank. Was sind die Unterschiede?"
Zeig bitte auch für beide Betriebssysteme, wie der Code compiliert wird,
also sämtliche Compiler- und Linkeraufrufe. Dort könnten auch
verschiedene Optimierungsstufen bzw. andere Compilerflags benutzt worden
sein.
Leider ist es mir nicht erlaubt, die originalen Hexfiles zu posten. Ich
werde mal kurz ein kleines Testprojekt erstellen. Meine Frage zielte
aber auch auf die Unterschiede der beiden Toolchains - also der
Schneider und nicht der Hemden ;)
Zum Thema Flags und Aufrufe:
Es wird das identische Makefile genutzt. Nur der Pfad der Toolchain ist
anders.
Rüdiger F. schrieb:> Leider ist es mir nicht erlaubt, die originalen Hexfiles zu posten.
Dann wird es Stochern im Dunkeln.
Schon die Verwendung von
1
__DATE__ __TIME__
im Code wird einen Unterschied erzeugen. Du wirst dann antworten, dass
beide Konstanten nicht verwendet werden. Und so geht das Spielchen dann
weiter - ohne echtes Ergebnis.
Voschlag:
Compiliere einen möglichst kleinen, öffentlich zugänglichen Source auf
beiden Rechnern und poste dann die Unterschiede. Darüber kann man dann
disktutieren.
Aber bei einem Closed-Source, wo sogar die HEX-Files geheim sind, kannst
Du das absolut vergessen. Hast Du jetzt Schiss, dass einer der beiden
Varianten nicht korrekt arbeitet?
> Voschlag:>> Compiliere einen möglichst kleinen, öffentlich zugänglichen Source auf> beiden Rechnern und poste dann die Unterschiede. Darüber kann man dann> disktutieren.
mach ich. (coming soon..)
> Aber bei einem Closed-Source, wo sogar die HEX-Files geheim sind, kannst> Du das absolut vergessen. Hast Du jetzt Schiss, dass einer der beiden> Varianten nicht korrekt arbeitet?
nein. Bei uns steht die CRC übers Hexfile im Release-Protokoll.
Danke bis hierhin.
Rüdiger F. schrieb:> Bei uns steht die CRC übers Hexfile im Release-Protokoll.
CRCs sind gut, um Übertragungsfehler zu erkennen.
Wenn man sich sicher sein will, dass zwei Dokumente gleich sind,
sollte man lieber eine kryptografische Prüfsumme wie SHA256 nutzen.
Jörg W. schrieb:> Rüdiger F. schrieb:>> Bei uns steht die CRC übers Hexfile im Release-Protokoll.>> CRCs sind gut, um Übertragungsfehler zu erkennen.>> Wenn man sich sicher sein will, dass zwei Dokumente gleich sind,> sollte man lieber eine kryptografische Prüfsumme wie SHA256 nutzen.
ja. ich weiß. Ist etwas komplizierter und definitiv OT, warum es hier
mit CRC gemacht wird. Hat z.T. damit zu tun dass das auch noch auf dem
MC gerechnet wird. Aber wenn schon OT: Geht denn SHA256 in schnell auf
nem xmega?
Rüdiger F. schrieb:> Geht denn SHA256 in schnell auf nem xmega?
Hab' ich noch nicht probiert. Für den Controller würde ich auch
erstmal zu CRC tendieren (ggf. halt CRC-32). SHA war eher fürs
Release-Management offline gemeint.
Rüdiger F. schrieb:> Hier die Toolchain unter Linux:avr-gcc --version> avr-gcc (AVR_8_bit_GNU_Toolchain_3.5.3_1700) 4.9.2> [...]>> Und hier unter Windows:avr-gcc.exe --version> avr-gcc.exe (AVR_8_bit_GNU_Toolchain_3.5.3_1700) 4.9.2> [...]
Ok, die Compiler haben die gleiche Version. Aber was ist mit den
Binutils und der AVR-Libc? Ich vermute, dass ihr bei letzterer zwei
verschiedene Version habt.
Yalu X. schrieb:> Ich vermute, dass ihr bei letzterer zwei> verschiedene Version habt.
Da es die von Atmel herausgegebene Toolchain ist, sollten sie
eigentlich die gleiche Basis benutzt haben.
Jörg W. schrieb:> Da es die von Atmel herausgegebene Toolchain ist, sollten sie> eigentlich die gleiche Basis benutzt haben.
Upps, das habe ich überlesen. Ja, dann hätte ich eigentlich auch gleiche
Ergebniss erwartet (bis vielleicht auf die LF bzw. CR/LF-Zeilenenden im
Hexfile).
Trotzdem würde ich die Versionen mal vergleichen. Es könnte ja sein,
dass aus Versehen zwei Installationen vermischt wurden oder bei Atmel
jemand geschludert hat. Irgendwo muss der Unterschied ja schließlich
herkommen.
Yalu X. schrieb:> bis vielleicht auf die LF bzw. CR/LF-Zeilenenden im> Hexfile
Selbst die sollten gleich sein, denn Intel Hex ist nun einmal mit
<CR><LF>-Zeilenenden definiert.
Yalu X. schrieb:> Ja, dann hätte ich eigentlich auch gleiche> Ergebniss erwartet (bis vielleicht auf die LF bzw. CR/LF-Zeilenenden im> Hexfile).Rüdiger F. schrieb:> Der diff ergibt, dass das Ende der Hexfiles gleich aussieht, nur die> Anfänge unterscheiden sich (also vermutlich irgendwelche libs?).
Es ist also definitiv mehr als CRLF vs. LF. Aus dem Bauch heraus würde
ich denken, dass die Libs eher am Ende des HEX-Files liegen. Oder geht
das wild durcheinander?
Frank M. schrieb:> Jörg W. schrieb:>> Der Startup-Code steht zumindest am Anfang.>> :-)
Naja, er muss ja an sich nur logisch am Anfang sein; der erste
Sprung (Reset-Vektor) springt dahin. Im Prinzip könnte man ihn
also (bis auf die Vektortabelle) ans Ende linken lassen. Machen
die üblichen Linkerscripte aber nicht, sie setzen ihn wirklich
nach der Vektortabelle.
Logisch gesehen ist er jedoch Bestandteil der Bibliothek.
Ich würde als erstes Mal den erzeugten Assemblercode und die Map-Files
vergleichen.
Ansonsten: ist die Linkreihenfolge der Objektdateien und der libs
wirklich identisch?
Oliver
Habe gerade mal den Code auf eine leere Main-Loop reduziert und dann die
gleichen Makefiles verwendet (gleiche CFLAGS wie beim vollständigen
Projekt). Ergebnis: Gleiches Hex-File.
Die Map-Files im Original sind definitiv unterschiedlich. Hier fällt auf
das sich die Adressen+Größen der .debug_str unterscheiden. Heißt das
irgendwas? Sollten die nicht gleich sein? Eigentlich sollten die dann im
Release eh weg sein..
Rüdiger F. schrieb:> Hier fällt auf das sich die Adressen+Größen der .debug_str> unterscheiden. Heißt das irgendwas?
Dass die Pfadnamen sich unterscheiden. ;-)
OK. Stimmt natürlich. Aber selbst mit -g0 bekomme ich keine gleichen
Ergebnisse. Frage am Rande: wenn die Größe des Segments mit 0x00
angegeben ist, dann wandert da doch nichts ins Hexfile, oder?
Rüdiger F. schrieb:> OK. Stimmt natürlich. Aber selbst mit -g0 bekomme ich keine gleichen> Ergebnisse.
-g0 beeinflusst nur die aktuelle Compilation, nicht aber das, was
ggf. aus der Bibliothek mit eingeschleppt wird.
> Frage am Rande: wenn die Größe des Segments mit 0x00> angegeben ist, dann wandert da doch nichts ins Hexfile, oder?
Ein Segment von 0 Byte Größe kann auch im Hexfile nur 0 Byte
belegen. ;-)
Rüdiger F. schrieb:> OK, Korrektur: der Anfang ist gleich:> $ diff linux.hex win.hex -y | head -n 10
Vielleicht solltest Du die beiden hexen lieber erstmal disassemblieren
bevor Du sie vergleichst. Oder machst Du das im Kopf?
Was mir an der ganzen Diskussion fehlt, ist ein Vergleich der
ELF-Dateien. Sind die (gestrippt) byteweise identisch oder gibt es schon
dort Unterschiede? Und wenn es Unterschiede gibt, wo befinden sich die?
Aus einem Hexfile irgendwas rauszulesen ist sportlich und vor allem
extrem unnütz, wenn es auch besser geht. ;-)
S. R. schrieb:> Was mir an der ganzen Diskussion fehlt, ist ein Vergleich der> ELF-Dateien.
Wenn die Hex-Dateien unterschiedlich sind, dann müssen es die
ELF-Dateien auch sein (OK, gleiche Zeilenlänge natürlich mal
vorausgesetzt).
Andererseits heißt nicht jeder Unterschied in den ELF-Dateien, dass
der tatsächliche Code sich wirklich unterscheiden würde. Sowas wie
Debug-Info wurde ja schon genannt.
Guten Morgen und erstmal vielen Dank für die -wie ich finde, Gewinn
bringende- Diskusion und Beteiligung. Leider hab ich grad noch allerhand
andere Baustellen, also nicht wundern wenn es nicht gleich weiter geht..
Zum Thema map-File: mit -g0 finde ich jetzt zumindest keine Stelle mehr,
an welcher sich Adressen unterscheiden (mit Außnahme einer .debug_str
section, deren Größe aber 0 ist; ?aus ner lib?).
Vielleicht ist die Info noch nützlich dass ich zunächst tatsächlich das
elf File erzeuge und mit objcopy dann das hexfile.
Ich hab das Ganze übrigens zum Test auch mal mit dem IAR-Compiler und
dessen libs übersetzt. Da sind die hexfiles identisch.
Rüdiger F. schrieb:> Ich hab das Ganze übrigens zum Test auch mal mit dem IAR-Compiler und> dessen libs übersetzt. Da sind die hexfiles identisch.
Zwischen Linux und Windows? Gibt's denn IAR neuerdings für Linux?
Rüdiger F. schrieb:> Wollte halt nur mal sehen, ob da die Umgebung auch Einfluss hat.
Nö, kann keinen Einfluss haben.
Wenn du da Unterschiede rausbekommst jenseits der Debugsymbole, dann
heißt das, dass Atmel trotz gleicher Release-Nummern doch nicht so
ganz die gleiche Basis für ihre veröffentlichten Toolchains benutzt
hat.
Vermutlich sind die Unterschiede harmlos, aber sie deuten natürlich
darauf hin, dass sie da irgendwie ihre Release-Prozesse nicht im
Griff haben.
Wenn euch exakte Gleichheit wichtig ist, bliebe natürlich immer noch,
sich die Toolchains komplett selbst zu compilieren. Ist ja keine
Raketenwissenschaft …
Jörg W. schrieb:> Wenn euch exakte Gleichheit wichtig ist, bliebe natürlich immer noch,> sich die Toolchains komplett selbst zu compilieren. Ist ja keine> Raketenwissenschaft …
Ich werde es mal versuchen.
Rüdiger F. schrieb:> Habe gerade mal den Code auf eine leere Main-Loop reduziert und dann die> gleichen Makefiles verwendet (gleiche CFLAGS wie beim vollständigen> Projekt). Ergebnis: Gleiches Hex-File.
Es wäre natürlich schon geschickt, wenn du das Problem anhand eines
einfachen Beispiels, das nicht der Geheimhaltung unterliegt,
reproduzieren könntest.
Wenn du wieder etwas Zeit hast, könntest du ja das leere Main mal mit
etwas Inhalt füllen, insbesondere mit ein paar Aufrufen von Funktionen
aus der C-Bibliothek, die auch in der eigentlichen Applikation verwendet
werden. Das Programm muss nichts Sinnvolles tun, es geht nur darum, dass
es nicht leer ist und der Linker eine halbwegs repräsentative Auswahl
von Bibliotheksfunktionen anfügt.
Falls du es auf diese Weise schaffst, zwei unterschiedliche Binaries zu
erstellen, postets du am besten die beiden ELF-Dateien. Wenn man diese
disassembliert, sollte man eigentlich erkennen können, wo der Hund
begraben liegt.
Noch zwei Fragen hätte ich:
Verwendet ihr eigene Bibliotheken, die beim Bauen der Software nicht
jedesmal kompiliert, sondern nur als Binärcode hinzugelinkt werden?
Falls ja, könnte es hier einen Versionsunterschied geben?
Und du bist auch sicher, dass beim Bauen sämtliche Quelldateien
kompiliert werden? Nicht, dass da noch ältere .o-Dateien herumliegen,
die – aus welchen Gründen auch immer – durch Make nicht aktualisiert
werden.
Yalu X. schrieb:> Verwendet ihr eigene Bibliotheken, die beim Bauen der Software nicht> jedesmal kompiliert, sondern nur als Binärcode hinzugelinkt werden?> Falls ja, könnte es hier einen Versionsunterschied geben?
Nein und nein.
> Und du bist auch sicher, dass beim Bauen sämtliche Quelldateien> kompiliert werden? Nicht, dass da noch ältere .o-Dateien herumliegen,> die – aus welchen Gründen auch immer – durch Make nicht aktualisiert> werden.
Nein, ich lösche jedesmal den kompletten Build-Ordner.
warum vergleichst Du nicht einfach die jeweiligen Disassemblies der
beiden Hex-Dateien und schaust einfach nach worin der Untersschied
besteht anstatt darüber zu grübeln und zu spekulieren?
Jörg W. schrieb:> Wenn die Hex-Dateien unterschiedlich sind, dann müssen es die> ELF-Dateien auch sein (OK, gleiche Zeilenlänge natürlich mal> vorausgesetzt).
Dass es einen Unterschied gibt, ist unstrittig. Aber die ELF-Datei kann
auch sagen, wo es den Unterschied gibt. Genauso kann man auch die
einzelnen Objectfiles strippen und dann vergleichen, die müssen auch
identisch sein.
Rüdiger F. schrieb:> Vielleicht ist die Info noch nützlich dass ich zunächst tatsächlich das> elf File erzeuge und mit objcopy dann das hexfile.
Davon sind wir, glaube ich, alle ausgegangen.
S. R. schrieb:> Aber die ELF-Datei kann auch sagen, wo es den Unterschied gibt.
Sinnvolle Möglichkeiten, ELF-Dateien logisch zu vergleichen, kenne
ich nicht. Physischer Vergleich hilft kaum mehr als bei Hex-Dateien.
Bliebe nur das Disassemblieren und anschließende Vergleichen, aber
das geht mit den Hexdateien auch.
Die ELF-Datei hat den Vorteil, dass man mit Hilfe der Symboltabelle –
zumindest ungefähr – die Funktion (und damit auch das Programmmodul oder
die Bibliothek) ermitteln kann, in der der Unterschied liegt.