Erfolgreiche ePaper selbst erstellen
Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.
Know-how<br />
www.linux-magazin.de Embedded Debugging 09/2013<br />
86<br />
Abbildung 1: Remote Debugging lässt sich über die Kommandozeile oder ein IDE wie Eclipse bewerkstelligen.<br />
informieren. Die Technik heißt, in Anlehnung<br />
an den Funktionsaufruf in C, meist<br />
einfach nur Printf. Sie hat den Nachteil,<br />
dass der Entwickler das Programm anpassen<br />
und die zu beobachtenden Teile<br />
vor dem Übersetzen kennen muss. Dafür<br />
steht der schlichte Ansatz fast immer zur<br />
Verfügung.<br />
Die Ausgabe muss nicht über einen Bildschirm<br />
laufen, für den die Zielsysteme oft<br />
keine Schnittstelle mitbringen, sondern<br />
kann über einen Ethernet-Port oder eine<br />
serielle RS232-Verbindung erfolgen. Fehlt<br />
auch diese, etwa bei sehr einfachen Systemen,<br />
lässt sich eine LED einsetzen, die<br />
ein Muster blinkt, das den Programmfortschritt<br />
anzeigt.<br />
Gemeinsam ist diesen Ansätzen, dass sie<br />
keine explizite Kopplung des Zielsystems<br />
mit dem Entwicklungssystem voraussetzen,<br />
sondern dass der Entwickler seine<br />
Schlüsse aus den Ausgaben des Zielsystems<br />
zieht, die er dann auf dem Entwicklungssystem<br />
umsetzt.<br />
Remote Debugging<br />
Eine komfortablere Fehlersuche schließt<br />
einen Debugger wie GDB [1] ein. Mit<br />
dessen Hilfe unterbricht der Entwickler<br />
die Ausführung seines Programms an bestimmten<br />
Stellen, verfolgt sie Quelltextzeile<br />
für Quelltextzeile weiter, kontrolliert<br />
und manipuliert den Inhalt von Registern<br />
und Variablen.<br />
In der klassischen Software-Entwicklung<br />
finden sowohl die Analyse als auch die<br />
Ausführung des Programms auf dem Entwicklungssystem<br />
statt, das dem Zielsys-<br />
tem sehr stark ähnelt. Eine Entwicklungsumgebung<br />
(Abbildung 1) unterstützt den<br />
Programmierer und erleichtert die Analyse.<br />
Dies setzt voraus, dass die untersuchte<br />
Software auf demselben Rechner<br />
läuft wie der Debugger beziehungsweise<br />
die Entwicklungsumgebung.<br />
Weil dies bei eingebetteten Systemen oft<br />
nicht zutrifft, kommt Remote Debugging<br />
zum Einsatz. Dabei startet der Entwickler<br />
auf dem Zielsystem eine Helfer-Applikation,<br />
mit der sich der Debugger des<br />
Entwicklungssystems verbindet, zum<br />
Beispiel über Ethernet oder die serielle<br />
RS232-Schnittstelle.<br />
Im Falle von GDB führt der Zielrechner<br />
einen GDB-Server aus, bei dem sich der<br />
GDB-Client auf dem Entwicklungssystem<br />
anmeldet. Der Client leitet nun Anweisungen<br />
an die Serverinstanz auf dem<br />
Zielsystem weiter, um zum Beispiel das<br />
untersuchte Programm anzuhalten oder<br />
die Registerinhalte auszulesen. Zugleich<br />
steuert der Programmierer die Anwendung<br />
auf diesem Weg.<br />
Der Server setzt die Anweisungen um<br />
und schickt die Resultate an das Entwicklungssystem<br />
zurück. Dessen Debugger<br />
Cross-Toolchain<br />
Bei der Entwicklung für eingebettete Systeme,<br />
die zum Beispiel ARM-Prozessoren verwenden,<br />
kann der Entwickler die systemeigene Compiler-Toolchain<br />
(Assembler, Compiler, Linker<br />
und Debugger) des Entwicklungssystems nicht<br />
verwenden, um Quelltext in Binärcode für das<br />
Zielsystem zu übersetzen.<br />
Hier kommt eine Cross-Toolchain zum Einsatz,<br />
die auf dem Entwicklungssystem läuft, während<br />
übernimmt dann die rechenintensiven<br />
Aufgaben. Er gleicht Assembler-Instruktionen<br />
mit bestimmten Quelltextzeilen ab<br />
und ordnet Variablen richtig zu.<br />
Debugging über Kreuz<br />
Unterscheiden sich die Architekturen von<br />
Entwicklungs- und Zielsystem, versteht<br />
der Debugger des Entwicklungssystems<br />
weder die Assembler-Instruktionen des<br />
Gegenübers, noch kennt er dessen Register.<br />
Das verhindert ein direktes Auswerten<br />
von Variablen und Zuordnen von<br />
Instruktionen zum Quelltext.<br />
Dieses Problem löst ein so genannter<br />
Cross-Debugger, der Bestandteil der<br />
Cross-Toolchain ist. Er lässt sich ebenfalls<br />
auf dem Entwicklungssystem ausführen,<br />
versteht jedoch die Assembler-Instruktionen<br />
des jeweiligen Zielsystems. Das<br />
macht es unter anderem möglich, mit<br />
Hilfe von Remote Debugging ein ARM-<br />
Programm auf einem x86-System zu untersuchen<br />
(Abbildung 2).<br />
Im Falle von Android stellt Google beispielsweise<br />
Entwicklungsumgebungen<br />
für Smartphone- und Tablet-Entwickler<br />
bereit. Letztere können beim Remote Debugging<br />
kaum noch unterscheiden, ob<br />
die Anwendung auf dem Endgerät oder<br />
dem Rechner des Entwicklers läuft. Auf<br />
dem Entwicklungssystem arbeitet dabei<br />
ein Emulator.<br />
DIY: Remote Debugging<br />
Die eben vorgestellte Form des Remote<br />
Debugging setzt voraus, dass das Zielsystem<br />
mehrere Programme zugleich<br />
ausführen kann, also mindestens das<br />
zu untersuchende Programm und ein<br />
Hilfsprogramm wie den GDB-Server. Das<br />
funktioniert zum Beispiel problemlos,<br />
wenn auf dem Zielsystem ein Betriebssystem<br />
wie etwa <strong>Linux</strong> läuft.<br />
der von ihr erzeugte Binärcode nur auf dem<br />
Zielsystem funktioniert. Gleiches gilt für den<br />
Debugger in der Cross-Toolchain, der nur den<br />
Binärcode des Zielsystems versteht.<br />
Cross-Toolchains auf GCC-Basis lassen sich bei<br />
den meisten <strong>Linux</strong>-Distributionen für verschiedene<br />
Zielarchitekturen aus der Paketverwaltung<br />
heraus installieren oder durch entsprechende<br />
Skripte einfach selbst übersetzen.