Forum: Mikrocontroller und Digitale Elektronik A51.exe obj Datei ändert den hashwert


von Entwickler (Gast)


Lesenswert?

Hallo zusammen
ich will die Aquivalenz vor und nach Reformatieren des
Quellcodes prüfen. Leider scheint Keil Assembler
Irgendwas miteinzubauen sodass die hash Summe
Jedesmal sich ändert. Gibt es einen work around
dafür?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Entwickler schrieb:
> Leider scheint Keil Assembler Irgendwas miteinzubauen sodass die hash
> Summe Jedesmal sich ändert.
Hast du dir mal genauer angeschaut, was sich da ausser der Prüfsumme 
sonst noch ändert?
Compilierst du evtl. irgendwie die Uhrzeit mit rein?

von Entwickler (Gast)


Lesenswert?

$ cat asm.a51
inc ACC
end

$ A51.EXE asm.a51

A51 MACRO ASSEMBLER V8.2.7.0
COPYRIGHT ARM Germany GmbH 2016
ASSEMBLY COMPLETE.  0 WARNING(S), 0 ERROR(S)
$ md5sum.exe asm.OBJ
a2aa89cd02ac6f483b5435483b067cda *asm.OBJ

$ A51.EXE asm.a51
A51 MACRO ASSEMBLER V8.2.7.0
COPYRIGHT ARM Germany GmbH 2016
ASSEMBLY COMPLETE.  0 WARNING(S), 0 ERROR(S)
$ md5sum.exe asm.OBJ
fd6d3e300788f3b8e445c79be3206f35 *asm.OBJ

>>>Compilierst du evtl. irgendwie die Uhrzeit mit rein?
Das vermute ich. Dafür würde ich gerne jedem Compilerbauer den Arsch 
versollen.

von Entwickler (Gast)


Lesenswert?

$ cat m.c
int main() { return 0; }

$ sdcc -c m.c && md5sum.exe m.rel
02d5487d9856453c25d91448c051a21c *m.rel

$ sdcc -c m.c && md5sum.exe m.rel
02d5487d9856453c25d91448c051a21c *m.rel

nice guy

$ C51 m.c && md5sum.exe m.OBJ
C51 COMPILATION COMPLETE.  0 WARNING(S),  0 ERROR(S)
4895d6c0f84402c1c1b2a1e8cf483275 *m.OBJ

$ C51 m.c && md5sum.exe m.OBJ
96e9a7e82a74fa9bfb6ba3b59605d23b *m.OBJ

bad guy

Gibt es OMF51 diff tool?

von Nop (Gast)


Lesenswert?

Mach doch den Checksummentest einfach auf dem finalen Hex- oder Binfile, 
wo nur das drin ist, was auch wirklich geflasht wird.

von Peter D. (peda)


Lesenswert?

Lothar M. schrieb:
> Compilierst du evtl. irgendwie die Uhrzeit mit rein?

Das kann gut sein. Vielleicht benötigt der Compiler das für 
Optimierungsläufe, Abhängigkeiten oder Debuggen.
Das .obj ist ja auch nicht für den Anwender gedacht, sondern ein 
internes Zwischenformat.
Wenn Du Binärcode vergleichen willst, dann laß doch das Hex oder Bin 
ausgeben.

von Monster (Gast)


Lesenswert?

Check 1: Ist die Filegröße identisch?

Check 2: Lass dir von beiden Files die Strings ausgeben und mach einen 
Diff.
         Oft enthalten die Files auch noch Pfadnamen für Debugzwecke.

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Entwickler schrieb:
>>>>Compilierst du evtl. irgendwie die Uhrzeit mit rein?
> Das vermute ich. Dafür würde ich gerne jedem Compilerbauer den Arsch
> versollen.

hm...

aus Qualitäts-Sicherungs-Sicht scheint es mir grade wertvoll und 
richtig, dass jeder neuer Build von "irgendwas" auch eindeutig 
identifizierbar ist, selbst ohne "reformatieren von Quellcode". Ein 
geänderter hash scheint mir das mindeste zu sein. Gerne darf sich ein 
neuer Build auch an irgendeiner 3. oder 4. Stelle einer für den Nutzer 
sichtbaren Versionsnummer oder an einem (sekundengenauen) Build-Datum 
darstellen.

Wieso empfindest du solch ein Verhalten (das Objekte eindeutig 
unterscheidbar sind) denn als Nachteil?

Oder soll keiner "merken", das da etwas geändert wurde?

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Aber das ist doch gar kein Compiler sondern ein simpler Assembler, der 
gerade mal
1
   INC ACC
assemblieren soll. Da gibt es überhaupt keinen Spielraum für 
Optimierungen oder Datum und Uhrzeit.
Es gilt also, herauszufinden, was die Herren da zusammensammeln, um die 
Ckecksumme zu basteln.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Wegstaben V. schrieb:
> Wieso empfindest du solch ein Verhalten (das Objekte eindeutig
> unterscheidbar sind) denn als Nachteil?

Hier gibt's da ein paar Erklärungen dazu.
https://reproducible-builds.org/

Matthias

von Nop (Gast)


Lesenswert?

Wegstaben V. schrieb:

> aus Qualitäts-Sicherungs-Sicht scheint es mir grade wertvoll und
> richtig, dass jeder neuer Build von "irgendwas" auch eindeutig
> identifizierbar ist

Nein, ganz im Gegenteil, weil Du dann nicht mehr feststellen kannst, ob 
ein bestimmtes Binary wirklich zu einem bestimmten Source gehört. 
Deswegen gibt es z.B. bei Linux ernsthafte Anstrengungen zu 
"reproducible builds".

Aber auch bei embedded ist das Erste, was ich nach dem Aufsetzen einer 
Toolchain für ein bestehendes Projekt mache, das Bauen eines Binaries, 
was exakt identisch zum eingecheckten Binary sein muß. Sonst stimmt 
etwas mit dem Setup nicht, und es können unerwartete Effekte auftreten. 
Besonders wichtig ist das bei Projekten, bei denen die IDE aus den 
IDE-Settings automatisch Code generiert, z.B. Startup-Code.

von Peter D. (peda)


Lesenswert?

Matthias S. schrieb:
> Aber das ist doch gar kein Compiler sondern ein simpler Assembler

Das OBJ-Format ist aber für Compiler und Assembler gemeinsam, damit man 
auch beides miteinander linken kann.
Wie gesagt, es ist ein rein internes Format der Toolchain. Du kannst 
z.B. kein OBJ von Keil mit einem von IAR zusammen linken.

von Mox (Gast)


Lesenswert?

Kannst Du nicht einfach AX51.exe verwenden? Das dürfte die einfachste 
Lösung sein, denke ich.

von Schlaumaier (Gast)


Lesenswert?

Entwickler schrieb:
> Das vermute ich. Dafür würde ich gerne jedem Compilerbauer den Arsch
> versollen.

Und ich würde sie beschützen.

Beim Testen kann es nämlich sehr schnell passieren das man alten Code 
(vor 2 Minuten) benutzt. Das ist besonders wichtig, wenn man Programme 
andere Programme aufrufen lässt.

Die Versions-Nr. würden durch die Decke gehen, wenn ich jedes mal wenn 
ich F5 Drücke eine neue bekomme.

Ich habe nebenbei schon oft erlebt, das die Version-Nr. gleich ist, das 
Datum anders und die neue Version lief.

von Georg (Gast)


Lesenswert?

Peter D. schrieb:
> Du kannst
> z.B. kein OBJ von Keil mit einem von IAR zusammen linken.

Das mag sein, ist aber eigentlich nicht der Sinn der Sache, eher ein 
Missbrauch. Ich habe oft OBJ-Files aus Assemblern und Compilern ganz 
verschiedener Hersteller zusammengelinkt, das würde ja nie funktionieren 
wenn jeder sein eigenes OBJ-Format macht.

Georg

von Nop (Gast)


Lesenswert?

Schlaumaier schrieb:

> Beim Testen kann es nämlich sehr schnell passieren das man alten Code
> (vor 2 Minuten) benutzt. Das ist besonders wichtig, wenn man Programme
> andere Programme aufrufen lässt.

Dazu kannst Du die Makros _DATE__ und __TIME_ benutzen, dann hast Du 
das selber unter Kontrolle. Sollte man halt nur für Debug-Versionen 
machen und nicht für Releases.

> Die Versions-Nr. würden durch die Decke gehen, wenn ich jedes mal wenn
> ich F5 Drücke eine neue bekomme.

Das hat damit genau gar nichts zu tun.

> Ich habe nebenbei schon oft erlebt, das die Version-Nr. gleich ist, das
> Datum anders und die neue Version lief.

Das passiert, wenn man bei der Versionskontrolle schlampt oder gleich 
gar keine benutzt.

von Thomas Z. (usbman)


Lesenswert?

Entwickler schrieb:
> Leider scheint Keil Assembler Irgendwas miteinzubauen sodass die hash
> Summe
> Jedesmal sich ändert. Gibt es einen work around dafür?
Nun ja das ist eigendlich ja offensichtlich. Schau dir mal mit einem OMF 
Viewer* die Obj Files an. Neben den eigentlichen Code records gibt's da 
viele andere Records z.B debug Records mit Zeilen Nummern und auch ein 
paar wenig dokumentierte Record Typen. Durch eine Neuformatierung wird 
sich also in jedem Fall das obj File ändern. Du könntest das in den 
Griff bekommen wenn du deine MD Summe auf die Code records beschränkt 
(relativ und absolute Records) Diese enthalten letztendlich den code.

Soweit mir bekannt ist gibt es auch einen Record Typ der Zeit 
Informationen enthält, bin mir aber nicht sicher ob das erst mit omf2 
eingeführt wurde.

Für Total Commander gibt's ein OMF Viewer plugin.

von Entwickler (Gast)


Lesenswert?

Schlaumaier schrieb:
> Entwickler schrieb:
>> Das vermute ich. Dafür würde ich gerne jedem Compilerbauer den Arsch
>> versollen.
>
> Und ich würde sie beschützen.
>
> Beim Testen kann es nämlich sehr schnell passieren das man alten Code
> (vor 2 Minuten) benutzt. Das ist besonders wichtig, wenn man Programme
> andere Programme aufrufen lässt.
>
> Die Versions-Nr. würden durch die Decke gehen, wenn ich jedes mal wenn
> ich F5 Drücke eine neue bekomme.
>
> Ich habe nebenbei schon oft erlebt, das die Version-Nr. gleich ist, das
> Datum anders und die neue Version lief.

wie schon jemand oben geschrieben hat, geht es um reproducable builds.

Wenn die Hashsumme des Binary sich immer und jedes Mal ändert, dann 
kannst Du weder den Schluss daraus ziehen, dass der Quellcode sich 
geändert hat, noch den Schluss ziehen, dass der Quellcode sich nicht 
geändert hat.
Richtig, Du weißt in dem Fall nichts.

Binary soll eine mathematische Funktion des Quellcodes sein.
Quellcode -> [Compiler] -> Binary

Wenn im Binary Zeitstempel drin sind, dann ist Compiler keine
mathematische Funktion des Quellcodes, sondern da kommt Global State 
rein.

Ich versuche mein Quellcode so zu organisieren, dass alle Quellen lokal 
liegen. Auch controllertypischen Includes kopiere ich rein, damit IDE
sie nicht aus C:/IDE/Dingsbums_Version_ratemal reinholt.
Ich habe auch schon Compiler, Linker lokal kopiert und aus Makefile
aufgerufen, um die möglichen Verhaltensänderungen des Compilers zu 
umgehen.

von Thomas Z. (usbman)


Lesenswert?

Entwickler schrieb:
> Binary soll eine mathematische Funktion des Quellcodes sein.
> Quellcode -> [Compiler] -> Binary

Das ist auch so. Du machst halt den Fehler anzunehmen dass dein obj File 
schon das binary ist. Ist es aber nicht. Kann es auch gar nicht sein, 
weil im obj viele zusätzliche Informationen eincodiert werden.
Nun ist omf(51) ein properitäres Format von Keil was nur in Teilen 
dokumentiert ist. Wenn du ax51 verwendest wird omf2 verwendet.

Vielleicht reicht es ja schon aus, die Debug Infos auszuschalten die bei 
asm Files ja keine große Bedeutung haben, damit die md Summe gleich 
bleibt.

von Entwickler (Gast)


Lesenswert?

Thomas Z. schrieb:
> Nun ist omf(51) ein properitäres Format von Keil was nur in Teilen
> dokumentiert ist. Wenn du ax51 verwendest wird omf2 verwendet.

AX51 wollte noch die Register Definitionen includiert bekommen,
hat sich in dieser Hinsicht aber genauso verhalten.

> Vielleicht reicht es ja schon aus, die Debug Infos auszuschalten die bei
> asm Files ja keine große Bedeutung haben, damit die md Summe gleich
> bleibt.

Nein, das reicht nicht aus. Siehe Minimalbeispiel oben.
Allerdings muss man Debuginfos ausschalten, weil ansonsten
Code miteingbaut wird und eine Whitespace Änderung den Hash ändert.

Die Lösung ist jetzt für mein Empfinden schon zu aufwendig.
Vielleicht für jemand nützlich ...

    cat test1.asm | sed 's/\$DB/\$PL(80)/' > test.a51
    A51.EXE test.a51
    LIB51.EXE transfer test.OBJ to test.LIB
    md5sum.exe test.LIB

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.