mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Strategien zur Wartung von unübersichtlichem Code (ASM/8051)


Autor: Reinhard R. (reinhardr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich sitze zur Zeit an einem Projekt dass mir nicht sehr viel Freude 
bereitet. Es geht darum eine nicht von mir geschriebene Firmware zu 
verstehen und später ev. ein wenig zu erweitern. Dabei gibt es aber zwei 
Probleme:
Erstens war die FW bzw. das Protokoll über dass das Gerät angesteuert 
wird (RS232) niemals dokumentiert bzw. ist die Dokumentation verloren 
gegangen.
Zweitens ist der Code ausgesprochen unübersichtlich. Es handelt sich um 
ca. 3600 Zeilen Assemblercode in einer Datei. Dieser hat einige 
Eigenschaften die eine Nachvollziehbarkeit stark erschweren (viel 
Spagetticode, wenig aussagekräftige Bezeichnungen, exotische 
Betriebsmodi die nicht klar vom normalen Ablauf getrennt sind, usw...). 
Die FW entstand über Jahre in einem evolutionärem aber ungeplantem 
Prozess. Man könnte auch sagen: Das Ding funktioniert zuverlässig, aber 
keiner weiß wieso. ;-)

Mein Hauptproblem ist jetzt herauszufinden wie das Ding genau 
funktioniert. Meine erster Versuch den Code einfach im Editor 
nachzuvollziehen hat sich als sehr mühsam und langwierig erwiesen.
Jetzt denke ich daran den Code vorsichtig ein wenig zu refaktorisieren 
ohne aber den entstehenden Maschinencode zu ändern, um unerwartete 
Konsequenzen auszuschließen. Es wird sich also auf das Umbenennen, 
Kommentieren und Formatieren beschränken. Bei der Gelegenheit lassen 
sich auch schon kleinere Abschnitte dokumentieren.

Allerdings bleibt dann immer noch das Problem den Programmablauf zu 
verstehen. Gibt es dazu bewährte Strategien oder Tools? Wie sind eure 
Erfahrungen dazu?

Gruß
Reinhard

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Reinhard R. schrieb:
> Gibt es dazu bewährte Strategien oder Tools? Wie sind eure
> Erfahrungen dazu?

Ich kenne da nur eine bewährte Methode:
1. den Code wegschmeißen
2. anhand der Gerätefunktion und Unterlagen ein Pflichtenheft erstellen
3. in C neu programmieren

Klingt erstmal schmerzhaft, aber ist der sauberste Weg.


Peter

Autor: Reinhard R. (reinhardr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

eine Neuimplementierung wäre zweifelsohne die sauberste Lösung, aber sie 
bringt mich in einem wichtigem Punkt nicht weiter: Ich will wissen wie 
sich über die Jahre hinweg ausgelieferte Geräte in einem 
undokumentierten Wartungsmodus verhalten. Der Wartungsmodus ist derzeit 
nur mit einem speziellem Tool zugänglich dessen Firmware ironischerweise 
genauso unübersichtlich und undokumentiert ist. Dieses Tool will ich 
durch eine Wartungssoftware ersetzen die auf einem normalen PC läuft.

Deshalb steht bei mir, zumindest kurzfristig, Reverseengineering auf dem 
Programm.

Autor: Wegstaben Verbuchsler (wegstabenverbuchsler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@PeDa


und nicht vergessen:

4. Den neuen Code sorgfältig kommentieren und dokumentieren
5. Den (die) vorherigen Entwickler teeren und federn

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo  Reinhard,

ich kenne deine Situation aus eigener Erfahrung. Bedingt durch
den kleinen HW-Stack war die Software für den PIC nicht als
"Funktionensammlung" partitioniert, sondern als Branches, die
irgendwann/irgendwo (abhängig von Bitflags) zurück in die
Hauptschleife geführt haben. Die Hälfte der Bitflags war historisch
gewachsen und hatte keine Funktion mehr. Es war nicht einfach, aber
sicher machbar. Voraussetzung ist, dass Du die Zeit dafür mitbringst.

Mir hat Notepad++ sehr gute Dienste geleistet. Du kannst dort einfach
rausfinden von wo überall ein label angesprungen wird. Diejenigen
die nur page-page Sprung machen (PIC Architektur), kannst Du 
entsprechend
umbenennen, damit sie Dir später nicht im Weg sind ... usw.

Viel Erfolg

Autor: Reinhard R. (reinhardr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Daniel,

Notepad++ ist bereits das Werkzeug meiner Wahl. Deine Idee mit dem 
Umbenennen der Labels gefällt mir. Da kann man einiges an 
Metainformationen verpacken, die einem später beim Verstehen des Codes 
hilft.

Danke,
Reinhard

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Es wird sich also auf das Umbenennen,
> Kommentieren und Formatieren beschränken. Bei der Gelegenheit lassen
> sich auch schon kleinere Abschnitte dokumentieren.

Aus dem wenigen was ich in Assembler gemacht habe (bzw. anderer Leute 
Code analysiert habe) ist mir noch im Gedächtnis geblieben, dass die 
ärgsten Fallstricke bei der Verwendung der Flags liegen.
In einem UP wird irgendwo das Zero-Flag gesetzt und 2 
Funktionshierarchien weiter drüber wird genau auf dieses Zero-Flag 
geprüft. Sowas ist extrem schwer zu finden und vor allen Dingen: Die 
richtigen Anweisungen ans Ende der Funktion mit rein oder einfach nur 2 
Anweisungen umgedreht oder vermeintlich 'vereinfacht' und plötzlich geht 
gar nichts mehr.

-> Für jede Funktion dokumentieren
 welche Register werden benutzt,
 was sieht so aus als ob es Input, Output in die Funktion wäre
 welche Register werden verändert (und nicht gepusht/gepopt)
 welche Flags haben beim Ret welchen Zustand und warum


Abgesehen davon geht nur:
Im Debugger durchsteppen, durchsteppen, durchsteppen
Und wenn du denkst, du hast alles durchschaut, dann noch mindestens 2 
mal durchsteppen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wegstaben Verbuchsler schrieb:
> @PeDa
>
>
> und nicht vergessen:
>
> 4. Den neuen Code sorgfältig kommentieren und dokumentieren
> 5. Den (die) vorherigen Entwickler teeren und federn


@WV + PeDa
6. Den Schachtel/CD mit dem Assembler nehmen und wegsperren.
8. Aus den Entwicklungsumgebungen den Assembler rauslöschen
   (sofern ihn nicht der C Compiler braucht)
7. Alle zu einem C-Kurs einladen

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da gibts noch viel schönere Möglichkeiten der "Code-Obfuscation", 
selbstmodifizierernder Code im Ram, oder Rücksprungadressen auf den 
Stack pushen und dann Return from Subroutine aufrufen.
Ich habe mal eine Apple2-Karte disassembliert, da hat die Software im 
Eprom sich selbst die oberen Adressleitungen umgeschaltet (nur 256 Byte 
waren im Adressbereich eingeblendet), und mußte an anderer Stelle im 
Eprom weiterlaufen, also eine Art Wurmloch im Programm - wer denkt sich 
sowas aus?
Außerdem war eine der Adressleitungen invertiert.

Autor: ,fbbkv (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mag zwar helfen, dass die dann nicht mehr in der Fa. in Assembler 
programmieren, aber saubere Kommentare kommen da nicht zwangslaeufig.

Gast

Autor: Reinhard R. (reinhardr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

falls es jemanden interessiert, hier eine kleine Beschreibung was ich 
letztendlich gemacht habe. Es war im Grunde genommen sehr banal da der 
Code nicht heimtückisch, sondern "nur" unübersichtlich war.

Zuerst wurde das Layout des Codes in einen konsistenten Zustand 
gebracht, um zumindest ansatzweise einen Blick für die Strukturdetails 
zu erhalten. Einen geeigneten Beautifier habe ich leider nicht gefunden, 
also wurde der Schritt manuell durchgeführt. Danach wurde jedes einzelne 
Label überprüft ob es "aus der Ferne" angesprungen wird (ab so ca. 50 
Zeilen) oder von mehreren Stellen angesprungen wird. Wenn das der Fall 
war wurde es so umbenannt, dass diese Metainformationen im Namen des 
Labels enthalten waren. Das war eigentlich der wichtigste Schritt um die 
Programmstrukturen sichtbar zu machen. Da die meisten Labels sehr 
kryptische Namen hatten, wurden sie um einen einfach zu merkenden Teil 
ergänzt - in meinem Fall griechische Buchstaben für die größten 
Strukturen und Tiernamen für den Rest ;-).
In einem weiteren Schritt hätte man natürlich jeden Abschnitt noch 
detaillierter analysieren können um einen sinnvolleren Namen zu 
vergeben, aber das war in meinem Fall nicht unbedingt notwendig. Das 
Verständnis der "Hauptstruktur" hat für meine Zwecke gereicht.

Parallel dazu wurden Informationen über den Code in einer Tabelle 
erfasst aus der sich dann ein Zustandsübergangsdiagramm erstellt wurde.

Während des gesamten Prozesses wurde immer wieder der Code übersetzt, 
und mit der ursprünglichen .HEX Datei verglichen. Das hat mehr als 
einmal eine versehentliche Modifikation aufgedeckt.

Ein bemerkenswerter Aspekt des Codes der sich im Laufe der Zeit immer 
mehr gezeigt hatte ist Redundanz. Es gibt drei "Paralleluniversen" 
zwischen denen in bester Spagetticodemanier hin und her gesprungen wird. 
Da das Ding in der Praxis gut funktioniert und es in Zukunft von einer 
kompletten Neuentwicklung ersetzt wird, habe ich darauf verzichtet 
diesen Umstand aus der Welt zu schaffen. Nur ein paar Kleinigkeiten, bei 
denen es offensichtlich war dass man sie ohne Gefahr vereinheitlichen 
kann und die man auch leicht testen kann, habe ich zusammengefasst. In 
diesen neuen Abschnitt sind dann auch ein paar Neuigkeiten 
hinzugekommen.

Nochmals danke an alle für die Anregungen.

Reinhard

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.