Ich habe hier den Inhalt des Flahsspeichers aus einen STM32 und ein Git-Repository mit mehreren Versionsständen des Codes. Ich soll nun herausfinden, welcher Versionsstand genau den vorhandenen Flashinhalt ergeben hat. Beim Kompilieren erhalte ich eine Datei.elf, das Speicherabbild trägt die Erweiterung.bin. Es ist exakt zwei Megabyte groß, genau so groß wie der Flash des STM32. Ein direkter Vergleich mit der Datei.elf ist gar nicht nötig, da sie nur wenige Kilobyte groß und damit sicher verschieden ist. Ich habe mit dem objcopy.exe aus einem Unterverzeichnis des STM32CubeIDE aus der Datei.elf eine Datei.bin gemacht um sie mit dem Flashinhalt vergleichen zu können, sie ist aber nicht zwei Megabyte groß. Gibt es eine Möglichkeit, die kompilierte .elf so mit dem .bin zu vergleichen, dass Equivalenz festgestellt werden kann (oder .hex oder wasauchimmer mit den beiden vorhandenen Dateien möglich ist)?
Vermutlich wurde das bin File nicht erzeugt, sonder aus gelesen. Es ist größer, als das Programm. Ein direkter 1:1 Vergleich wird nicht gehen. Ich würde versuchen, nur die ersten n Bytes zu vergleichen, entsprechend der kleineren bin Datei.
Im bin sollte doch eine Versionsnummer zu finden sein, wird doch als Info im Programm angezigt oder ?
Lukas S. schrieb: > Gibt es eine Möglichkeit, die kompilierte .elf so mit dem .bin zu > vergleichen, dass Equivalenz festgestellt werden kann (oder .hex oder > wasauchimmer mit den beiden vorhandenen Dateien möglich ist)? Möglicherweise wird ein einfacher Vergleich nicht reichen: https://www.google.com/search?q=reproducible+builds
Du brauchst die toolchain-Version, die für die Erzeugung des Flashinhalts benutzt wurde, dazu die verwendeten Optionen. Das kann kompliziert werden. Wie schon gesagt wurde, wenns da irgendwelche Strings gibt, die die Version identifizieren, kanst du mit einem hex-Editor danach suchen. Oliver
Rüdiger B. schrieb: > Im bin sollte doch eine Versionsnummer zu finden sein Das setzt voraus, daß derjenige, der die Compilate erzeugte, über soviel Selbstdisziplin verfügte, diese für jeden Durchlauf hochzusetzen. Ich habe mir angewöhnt, im lokalen Git auch die erzeugen Binaries als Assets zu speichern. Die nehmen zwar mehr Platz weg als der reine Sourcecode, sind aber an anderer Stelle ungemein praktisch.
Harald K. schrieb: > Das setzt voraus, daß derjenige, der die Compilate erzeugte, über soviel > Selbstdisziplin verfügte, diese für jeden Durchlauf hochzusetzen. Das kann man automatisieren.
Man könnte es durch Ghidra jagen und anschließend durch eine KI. Lukas S. schrieb: > Ich habe hier den Inhalt des Flahsspeichers aus einen STM32 und ein > Git-Repository mit mehreren Versionsständen des Codes. Wieviele Kandidaten kommen in Frage? Lukas S. schrieb: > Ich soll nun herausfinden, welcher Versionsstand genau den vorhandenen > Flashinhalt ergeben hat. Wie wichtig ist das, wirst Du extra dafür bezahlt, hast Du ein paar Wochen Zeit?
G. K. schrieb: > Das kann man automatisieren. Auch das erfordert die nötige Disziplin, es zu tun. Wenn man eh' so arbeitet, ist das kein Problem, aber eben nicht jeder arbeitet so. Wieviele Projekte mir schon über den Weg gelaufen sind, in denen die Versionskennung einfach ein #define mit einem String waren, in dem dann auch irgendein Datum stand ... Strukturiert arbeiten geht anders.
Rüdiger B. schrieb: > Im bin sollte doch eine Versionsnummer zu finden sein, wird doch als > Info im Programm angezigt oder ? Leider nein. Das Gerät bietet keine Möglichkeit an, eine Firmwareversion auszulesen. Kein Display und auch auf keinem Datenbus.
Dann wird es schwierig bzw. langwierig. Die genaue Konfiguration der Toolchain ist meistens im Makefile abgebildet, aber wie schon erwähnt können unterschiedliche Versionen des Compilers unterschiedlichen Output erzeugen. Auch eine andere Version einer verwendeten C-Library erzeugt ggf. anderen Output, auch wenn dein eigener Quelltext identisch compiliert wird. Vielleicht kannst du hier anhand des Zeitraums des Builds und der verwendeten Umgebung raten, welche Versionen wahrscheinlich zum Einsatz kamen. In der Luftfahrt haben wir bei Software zwingend einen "Software Configuration Index" (SCI), wo neben dem Quellcode und Konfigurationsparametern der Software selbst auch alle relevanten Details zur Build-Umgebung und deren Konfiguration mit abgelegt werden müssen. Ein Test ist, dass jemand nur mit den Daten des SCI einen binär identischen Output erzeugen kann. Wir compilieren zur Sicherheit immer in einer virtuellen Maschine und archivieren die zusammen mit dem Quellcode und dem SCI. So kann auch ein älterer Code einen Bugfix bekommen, ohne große Wahrscheinlichkeit, neue Fehler einzuführen. Getestet wird natürlich trotzdem.
Lukas S. schrieb: > Gibt es eine Möglichkeit, die kompilierte .elf so mit dem .bin zu > vergleichen, dass Equivalenz festgestellt werden kann (oder .hex oder > wasauchimmer mit den beiden vorhandenen Dateien möglich ist)? Das ginge nur, wenn schon ein paar Varianten als Referenzen zum Vergleichen da wären. Im Hexeditor kann man so einiges machen, z.B. auch den überflüssigen Teil der Hochsprache wegknipsen. Mit einem Emu könntest du einfach mehrere Versionen erstellen, und beide Gruppen nach z.B. nach Größe sortieren und schauen, was das hergibt. Oliver S. schrieb: > Das kann > kompliziert werden. Das vermute ich auch, man könnte schauen, ob Programme wie Peid (als Plugin) oder elfdiff, objcopy, Rust usw. noch was bringen. Je mehr man sucht und Hilfen nutzt, desto höher die Wahrscheinlichkeit, brauchbare Ansätze zu finden. Lukas S. schrieb: > Ich habe mit dem objcopy.exe aus einem Unterverzeichnis des STM32CubeIDE > aus der Datei.elf eine Datei.bin gemacht um sie mit dem Flashinhalt > vergleichen zu können Um objcopy sinnvoll zu nutzen, braucht es wohl noch eine gewisse Einarbeitung?
Bevor ich mir da große Gedanken über die Theorie machen würde, würde ich einfach mal die generierte bin und das Speicherabbild in Beyond Compare reinwerfen und schauen was rauskommt. Das geht schneller als hier einen Post zu verfassen. Wenn's nix bringt, hat man zwei Minuten "verloren", kann aber immernoch in der Theorie rumstochern...
Das kommt in Klitschen und auch in renommierten Firmen immer wieder vor.
Die ganz große Inventur ist wie folgt:
1) Hinweise im Bin
Nimm das 2MB bin und untersuche es auf Zeichenpattern, die wie ein
* Datum (also sowas wie "2023" oder oder "11.23", manchmal auch mit je
einem '.' dazwischen)
* Pfad ("c:\...")
* Version (egal ob Compiler oder Programmversion)
* Build-Nummer
aussehen.
2) Sammeln: Sammel alle .elf Files, die in Frage kommen können und schau
Dir Gemeinsamkeiten/Unterschiede an (Größe, Datum, ...)
3) Speicherabbild: Lade das heute aktuelle Elf-File in den Prozessor.
Stelle sicher, dass es richtig ist, die HW läuft. Dann lese den
Prozessor zurück und vergleiche elf/bin. So gewinnst Du eine Idee, wo
genau das elf im Prozessor-Abbild liegt
4) Toolchain: Bild den aktuellen Code und schaue, ob das aktuelle
elf-File rausfällt. Falls nein, schaue wo die Unterschiede liegen. Falls
ja, hast Du vielleicht die "richtige" Toolchain mit den richtigen
Einstellungen.
5) Puzzelarbeit: Ohne jeden Hinweis bleibt Dir nur, die bisherigen
Git-Stände auszuchecken, zu kompilieren, in den Prozessor einzubrennen
und den Prozessor zurückzulesen. Mit ein paar Erfahrungen aus 1-4 kannst
Du Dir hoffentlich einige Schritte sparen.
Rbx schrieb: > Das vermute ich auch, man könnte schauen, ob Programme wie Peid (als > Plugin) oder elfdiff, objcopy, Rust usw. noch was bringen. Na ja, man sollte ja zumindest die Basics beherrschen, und zumindest einen guten Hexeditor und ebenso guten Diassembler haben und auch benutzen können. Ansonsten wirds völlig unmöglich. Wie gesagt, ich würde als erstes die Quellen diffen, und schauen, wo da überhaupt die Unterschiede zwischen den Versionen sind. Gibts da eindeutige Strings, wirds einfach. Wenn nicht, muß man halt nach anderen Unterschieden suchen, die sich in einem disassemblierten Kompilat identifizieren lassen. Aber selbst wenn man die Version dann identifiziert hat, kommt beim Kompilieren vermutlich nicht 1:1 das selben Kompilat raus. Wenn das das Ziel ist, muss man halt noch mit toolchains und Optionen spielen. Oliver
:
Bearbeitet durch User
Oliver S. schrieb: > Wenn nicht, muß man halt nach anderen > Unterschieden suchen, die sich in einem disassemblierten Kompilat > identifizieren lassen. Ich hatte ganz vergessen, hinzuschreiben, dass man auch Tests oder Profiler einsetzen kann um Unterschiede zu finden, sofern solche Möglichkeiten verfügbar sind.
G. K. schrieb: > Harald K. schrieb: > >> Das setzt voraus, daß derjenige, der die Compilate erzeugte, über soviel >> Selbstdisziplin verfügte, diese für jeden Durchlauf hochzusetzen. > > Das kann man automatisieren. Ironischer weise macht genau dass eine einfache Auffindbarkeit durch Vergleichen unmöglich, da damit die einfache Reproduzierbarkeit nicht gegeben ist. Noch schlimmer wird es nur wenn die _ DATE __ oder _ TIME __ Makros verwendet wurden. Also manuell hochgezählte Versionsinfos (in der Versionsverwaltung eingecheckt) in das Kompilat einbinden (dann ist es reproduzierbar). Und/oder den Kompilat Durchlauf und den GIT Hash als extra Informationen hinten ans Binary anhängen. Dann lässt sich wenigstens mit wenig Aufwand ein individuelles Vergleichstool schreiben. Und das Compilieren wenn es zu einem Kunden geht nur einem Buildserver erledigen lassen, dann landen nicht versehentlich lokale Änderungen im Kompilat. Dem TO viel Erfolg. Seine Aufgabe reicht irgendwo von leicht bis unmöglich.
Malte _. schrieb: > Also manuell hochgezählte Versionsinfos (in der Versionsverwaltung > eingecheckt) in das Kompilat einbinden (dann ist es reproduzierbar). Wenn in der Versionsverwaltung zehn Commits mit gleicher Versionsinformation sind ...
Harald K. schrieb: > Wenn in der Versionsverwaltung zehn Commits mit gleicher > Versionsinformation sind ... Vermutlich könnte man auch mit einem Hook bei jedem Commit ein Inkrement mit einchecken, dann wäre das auch gegeben. Ansonsten, 10 Versionen ließen sich auch durchprobieren, besser als völlig im Trüben zu stochern. Reproduzierbarkeit ist das Wichtigste. Dazu gehört auch die Bibliotheken und den Compiler zu archivieren. Notfalls sucht dann der Buildserver ein Wochenende lang automatisiert durch neu kompilieren und Vergleichen das richtige Kompilat.
Harald K. schrieb: > Wenn in der Versionsverwaltung zehn Commits mit gleicher > Versionsinformation sind ... Bei SVN wäre es üblich (weil einfach), die Revision ins Compilat einzubauen (Version oder Text) und gleichzeitig ein Zeichen, ob es lokale Modifikationen oder Mixed-Range gibt. Z.B. V12_B4711M für lokale Modifikationen und V12_B4711 ohne.
Den ausgelesenen EEPROM Dump gegen eine lokal erzeugte Datei nur simple 1:1 binär zu vergleichen schlägt idR immer Fehl, da der Programmcode idR nur ab einer bestimmten Adresse im Dump anfängt und oft hinter dem Programmcode ein Speicherblock kommt in dem das Programm persitent zu speichernde Werte ablegt wie die Konfiguration oder irgendwelche Zähler wenn das nötig ist (z.B. Betriebsstunden, Lifecyle, Abnutzungszähler für Werkzeuge/ Betriebsmittel, Fehlerzähler). Ich hatte schonmal an meinen Flashversuchen gezweifelt, da beim verifizieren /runterladen des EEPROMS immer ein anderer HASH rauskam als beim Hochladen. Bis ich im Hex/Binärvergleich per Hand gesehen habe, dass nach dem Flashen sofort das Program beim Aufstart seine Konfig/Zähler initialisiert hatte und daher nur ein Speicherblock irgendwo hinter dem Programm abweichungen zum geflashten File hatte....
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.