Übersicht Debugging-Tools

von
Carsten Jahn

Bekanntlicherweise machen Programme nicht immer genau das, was sie sollen. Dieses Problem tritt vielleicht verstärkt bei der selbstgemachten Software auf, deshalb sollte man wissen, wie man übliche Fehler ausmachen kann. Um die Fehlersuche zu erleichtern, gibt es einige Tools, die sich mit verschiedenen Aspekten beschäftigen.

Den sauberen Umgang mit dem RAM-Speicher überwacht das vermutlich bekannteste Tool, der Enforcer. Über spezielle Schaltkreise im Prozessor des Rechners werden Lese- und Schreibzugriffe auf Speicherbereiche, die dem Programm nicht gehören, dem Enforcer gemeldet. Ein anderes Programm, Mungwall, erkennt nach dem Freigeben von Speicherbereichen, ob das Programm auch fremde Bereiche vor und nach reserviertem Bereich beschrieben hat. Dafür ist kein spezieller Prozessor nötig.

Gegen die falsche Benutzung einiger Systemfunktionen hilft Patchwork. Es schaltet sich z.B. vor Libraryfunktionen wie DeleteMsgPort() und prüft, ob wirklich keine Messages mehr am Port liegen, denn das ist Bedingung zum Aufruf von DeleteMsgPort().

Alle angeforderten Ressourcen müssen spätestens am Programmende wieder freigegeben werden. Ob das auch wirklich geschieht, läßt sich z.B. mit CodeWatcher prüfen.

Enforcer

Wichtig: um den Enforcer nutzen zu können, muß der eingebaute 68k- Prozessor über eine MMU verfügen. Prozessormodelle, die die Bezeichnung "EC" tragen, funktionieren nicht. So z.B. in den originalen A4000/030 von Commodore.

Mit dem Programm LawBreaker, das mit dem Enforcer kommt, läßt sich feststellen, ob der Enforcer richtig funktioniert. (Es müssen *mehrere* Hits beim Start erscheinen.)

Der Enforcer läßt sich sogar per Icon starten, vernünftige Voreinstellungen für die Optionen finden sich in den ToolTypes. Um bei der Ausgabe eines Enforcer-Hits zu wissen, welches Programm den Fehler gemacht hat (und auch wo im Programm genau), sollte man möglichst früh in der Startup-Sequence das mitgelieferte SegTracker-Programm aufrufen (hinter SetPatch).

Wenn man sich später entschließt, Enforcer zu benutzen, hält SegTracker schon eine Liste der Tasks mit den Adressen ihrer Codesegmente bereit. Im Enforcer-Hit wird dann der Programmname, sowie Hunk und Offset angezeigt.

Diese beiden Werte lassen sich z.B. im Maxon-Debugger eingeben, um die Quelltextzeile anzeigen zu lassen, die dem fehlerauslösenden Code wahrscheinlich nahe liegt.

Das ist also eine etwas schwammige Sache, und ich habe die Erfahrung gemacht, daß der Enforcer-Hit recht oft völlig außerhalb meines Programmtextes liegt. Dann war es z.B. eine Linker-Library, die durch meinen Fehler verunsichert wurde. Oder eine Library-Funktion.

Da Enforcer aber auch den naheliegenden Stackinhalt zum Vergleich an den SegTracker schickt, ist es gut möglich, daß dort vorhandene Rücksprungadressen noch zu einer verwendbaren Quelltextstelle führen können. Natürlich kann eine Zahl auch rein zufällig eine Position in den Codesegmenten sein. Neben dem Stack können auch die Adress- und Datenregister von SegTracker überprüft werden.

Wenn man einen Compiler hat, der einen "LINE"-Debughunk erzeugen kann, kann man mit dem beigefügten FindHit-Programm den Quelltextnamen und die Zeile herausfinden, die zum Hunk-Offset-Wertepaar des Enforcerhits gehört.

Ein weiteres Zusatzprogramm, Move4K, sollte auf 68040-Systemen möglichst früh in der Startup-Sequence, auch nach SetPatch, aufgerufen werden. Es verhindert, daß Programme im allerersten MMU-Bereich (den ersten 4kB des Rechners) Speicher reservieren, denn Zugriffe darauf müssen umständlich abgefangen werden. Ab OS 3.0 ist Move4k überflüssig.

Wer einen A4000/EC030 sein eigen nennt, kann zwar nicht Enforcer nutzen, dafür aber den AmigaGuardian. Er trickst mit der Hardware, kann aber keine Hits in den ersten 4 kB bemerken. Der leere Speicher dort wird aber belegt und mit Zufallszahlen gefüllt, um im darauffolgenden Zugriff an der Adresse dieser Zufallszahl einen Hit zu bekommen.

Mit APurify kann man auch ohne MMU auskommen. Es ist ein Assemblercode- Preprozessor, der im vom Compiler generierten Asm-Code Überprüfungen einfügt, die einen Verstoß erkennen und ausgeben.

Wipeout und Mungwall

Diese beiden Programme tun in etwa das gleiche: sie patchen die Speicherallozier- und freigabefunktionen. Beim Allozieren von Speicher wird der vom Programm benötigte Bereich vergrößert und ein "Cookie" vor und hinter dem zurückgelieferten Bereich gesetzt. Verlangt das Programm nicht die Auffüllung des Speichers mit Nullen, wird er mit allerhand Schrott gefüllt, damit es dem Programmierer auffällt, wenn doch Nullen vorausgesetzt werden.

Beim Freigeben des Speichers prüfen die Programme, ob der Cookie vor und hinter dem Speicherbereich noch intakt ist. Ist er es nicht, wurde er (höchstwahrscheinlich von dem Programm, das sich den Speicher geholt hat) überschrieben.

Am Programmstart wird der gesamte freie Speicher mit der Zahl 0xabadcafe gefüllt, tritt beim Enforcer nun ein Lese- oder Schreibversuch an dieser Adresse auf, hat das Programm Speicher angefaßt, in dem es eigentlich nichts zu suchen hat.

Während es Mungwall schon lange gibt, ist Wipeout erst vor kurzem erschienen und ist moderner gestaltet. Es unterstützt z.B. Memory Pools direkt.

Beide Programme machen ihre Ausgaben in die serielle Schnittstelle. Wer also keinen alten Compi daran hängen hat, sollte die Ausgaben mit Sushi oder Sashimi in ein Fenster auf der Workbench umleiten.

Patchwork

Wie oben schon angesprochen, überprüft Patchwork, ob einige Funktionen in den Libraries richtig benutzt werden. Der Autor Richard Körber hat sich die AutoDocs genau angesehen und potentielle Fehlerquellen aufgedeckt.

Patchwork patcht viele Funktionen der Standard-Libraries und überprüft deren Argumente. Es gibt bis jetzt nur Prereleases, aber die sind schon einen Blick wert.

Aktuell ist derzeit die Version 0.11, bei der einige Libraries hinzugekommen sind. Patchwork kann eine Enforcer-ähnliche Ausgabe machen und arbeitet auch mit SegTracker zusammen, um Hunk und Offset des fehlerhaften Aufrufs herauszufinden.

Die Fehler sind in vier Stufen eingeteilt, so kann man beim Aufruf von Patchwork erreichen, daß die leichten Verstöße ausgeblendet werden.

Es ist auch möglich, beim Aufruf von Patchwork die OS-Version anzugeben, die das zu testende Programm mindestens benötigt. Dann werden Verstöße, die ab einer bestimmten OS-Version keine mehr sind (z.B. wenn ab OS 3.0 die Übergabe einer Null doch erlaubt ist), nicht angezeigt.

Wer die Weiterentwicklung des Programms sichern will, ist aufgerufen, dem Autor eine eMail zu schreiben.

Codewatcher

...hat bei mir früher mal tadellos funktioniert, aber als ich ihn für diesen Artikel ausprobiert habe, stürzt er immer nur ab. Bei Andreas Schlick (er schreibt auch für den AmZeiger, übrigens...) ist es genauso.

Naja, für die Glücklichen, die nicht schon beim Debuggen vom List-Befehl einen Absturz erleben, hier eine kurze Beschreibung:

Der Codewatcher wird aus der Shell gestartet. Als Argument übergibt man Pfad und Namen von dem Programm, das man überprüfen möchte, sowie evtl. die Parameter, die dieses Programm braucht. Codewatcher startet das Programm und wacht im Hintergrund über die Funktionen, die Ressourcen anfordern und freigeben. Wenn des Programm beendet wird, gibt Codewatcher alle nicht freigegebenen Ressourcen aus.

Das gleiche schafft der Maxon-C++-Debugger, aber leider ist er mir beim Ressourcen-Tracking auch schon oft abgestürzt.

Scratch

...ist noch ein Kaputtmacher, für Assembler-Programmierer interessant. Es bewirkt, daß die Register des Prozessors, die nach einem Library-Aufruf zerstört sein können (Scratch-Register), auch wirklich einen anderen Inhalt haben. Wer sich auf solch ein Register verlassen hat, merkt es sofort... (Scratch gibt es auf der Amiga Developer CD.)

Wie man schon bei Wipeout gesehen hat, ergänzen sich die Debugging-Tools ganz gut. Man sollte sie ruhig gleichzeitig laufen lassen, aber nicht ständig.

Enforcer kann manche Systeme etwas ausbremsen, Wipeout benötigt zum Erstellen und Prüfen der Cookies Prozessorzeit, und außerdem will man sicher auch Software weiterbenutzen, die öfter mal einen Hit wirft... Wenn man z.B. Bangermenu benutzt, kann man eine extra Startup-Sequence mit den Debugger-Aufrufen anlegen, die man dann zum Hardcore-Betatesten benutzt. :-)


Prev Inhaltsverzeichnis Next
©`98 Der AmZeiger