Durch Eclipse wird Debugging von Linux-Systemen so komfortabel wie ein Tool vom Hersteller Remote-Debugging mit Eclipse

Das Debugging von Code, der nicht auf dem Entwicklungs-PC, sondern auf einem Board mit einem anderen Prozessor läuft, war unter Linux ursprünglich nicht vorgesehen. Doch inzwischen ist die Entwicklungsumgebung Eclipse so ausgereift, dass eine TCP/IP-Verbindung zum Zielsystem reicht, um alle Debug-Funktionen zu nutzen – und mit zusätzlichen Open-Source-Tools lassen sich sogar Speicherfehler aufspüren.

In der Welt der betriebssystemlosen Entwicklung mit herstellerspezifischen Tools ist das Remote- Debugging Standard. Ein Hardware- Debugger wird beispielsweise per JTAG an die Ziel-CPU angeschlossen und per USB an den Entwicklungs- PC. Dieser hat eine CPUHersteller- spezifische Entwicklungsumgebung installiert, die das Embedded- System mittels des Hardware-Debuggers „fernsteuert“. Damit sind beliebige Zugriffe auf den Speicher und die Prozessorregister möglich. Mittels Schreibzugriffen auf Speicher und Register kann nun die Entwicklungsumgebung beliebige Programme auf der Ziel-CPU starten. Zusätzlich lassen sich eventuell vorhandene Debugging-Register nutzen, um den Programmablauf zu steuern. Aber auch ohne solche Register ist das Setzen von Breakpoints möglich. Es werden unterbrechende Prozessorbefehle eingefügt und bei Erreichen durch die Ziel-CPU von Hardware- Debuggern erkannt und entsprechend behandelt. Durch die nahtlose Integration der Debugging-Funktion in den Editor und ergänzt um den Compiler und andere Tools entsteht dann eine sehr komfortable Entwicklungsumgebung. Brüche durch den Wechsel zu einem anderen Tool oder durch unnötige Standardaufgaben wie etwa das Kopieren von Dateien oder Beschreiben von Flash-Speichern werden vermieden. Beispiele für solche hochintegrierten Entwicklungsumgebungen (IDE) sind Freescales Codewarrior oder VisualDSP von ADI.

Entwicklungsland Linux

In der Entwicklung von Applikations- Software für Embedded-Linux-Systeme sah es lange Zeit ganz anders aus. Compiler, Editor und Debugger waren nur lose oder gar nicht miteinander gekoppelt. Zusätzlich waren oft einige Schritte Handarbeit erforderlich, um ein Programm auf der Ziel-CPU starten zu können. Durch Netzlaufwerke, die vom Entwicklungsrechner auf das Embedded- System eingebunden werden können, kann zwar eine sehr kurze Turn-around- Zeit in der Test- Compile-Phase erreicht werden, dann jedoch steht noch kein „echter“ Debugger zur Verfügung und der Entwickler ist auf Trace-Meldungen (siehe Kasten „Trace-Meldungen oder printf()-Debugging“) aus dem Programm angewiesen. Debugging von Programmen in einem Embedded-Linux-System unter Einsatz eines Hardware-Debuggers ist wegen der strikten Trennung zwischen virtuellen und physikalischen Adressen von erheblicher Komplexität und wird daher praktisch nicht eingesetzt. Applikations-Programme für Linux werden mit dem GNU-Debugger, kurz gdb, debuggt. gdb ist der Debugger in der Linux- und Unix-Welt schlechthin. Seine Entwicklung ist eng an die des Standard-Compilers gcc gekoppelt. Der gdb wird typischerweise eingesetzt, wenn es um das Debugging von PC-Software geht. Dabei wird fast immer auf ein grafisches Front-End gesetzt, das die Bedienung des gdb vereinfacht.

Remote-Debugging mit dem gdbserver

Der gdb ist aber genauso flexibel für Embedded-Systeme einsetzbar. Dazu enthält er den gdbserver, welcher als Stub das Debugging eines Programms auf einem anderen Rechner ermöglicht. Der gdbserver übernimmt alle Aufgaben des Debuggers auf der Embedded- Hardware, während der Entwickler mit dem gdb auf dem Entwicklungsrechner das eigentliche Debugging durchführt. Dazu wird zunächst der gdbserver auf dem Embedded- System gestartet. Als Parameter werden das zu debuggende Programm und ein TCP-Port angegeben:
gdbserver :7777 testapp
Unter der IP-Adresse der Ziel-CPU und dem konfigurierten TCP-Port kann dann der eigentliche gdb vom Entwicklungsrechner Kontakt mit dem gdbserver aufnehmen und diesem Befehle zum Debuggen des Programms geben (Bild 1). Der gdbserver fügt dann beispielsweise Breakpoints ein und meldet deren Erreichen per TCP/IP an den Entwicklungsrechner. Das Debugging der Applikations-Software auf der Ziel-CPU ist damit genauso möglich, als würde nur auf dem Host- PC gearbeitet. Das Protokoll, welches zwischen gdb und dem gdbserver genutzt wird, definiert alle erforderlichen Befehle und Datenformate für das Debugging. Es definiert keine Befehle für das Starten des Programms, die Parametrierung oder Ausgabe von Textmeldungen. Ebenso sieht es keine Möglichkeit vor, den eigentlichen Programmcode zu übertragen. Diese Aufgaben bleiben einer höheren Protokollschicht überlassen. Oft wurden sie jedoch manuell vom Entwickler für jeden Test-Compile-Zyklus durchgeführt. Dieses Vorgehen hat sich als fehleranfällig und damit als sehr frustrierend herausgestellt.

Eclipse bringt Komfort für Linux-Entwickler

Seit der Version Ganymede von Eclipse, einer Entwicklungsumgebung von IBM unter anderem für Java, C- und C++-Programme, wird das komplette Handling rund um den gdbserver von Eclipse übernommen und damit automatisiert. Tatsächlich übernehmen der Remote-System-Explorer und das Debugging- Plugin von Eclipse die eigentliche Arbeit beim Remote-Debugging. Es muss also sichergestellt werden, dass diese Plugins erfolgreich installiert wurden. Eclipse ist eine sehr vielfältige Entwicklungsumgebung, die weit über die Funktionen eines Editors mit Syntax- Highlighting hinausgeht.

Eclipse wurde ursprünglich von IBM zur Entwicklung von Software auf Basis von Suns Java entwickelt. Das erklärt zum einen den Namen (Sun = Sonne; Eclipse = Sonnenfinsternis) und zum anderen, warum Eclipse selbst in Java geschrieben wurde. Eclipse kann durch Plugins erweitert und modifiziert werden. Tatsächlich ist es sogar so, dass Plugins erforderlich sind, um überhaupt C/C++-Programme entwickeln zu können. Mit Hilfe der Plugins kann Eclipse automatisch Makefiles erzeugen, die die erforderliche Cross-Compilation für Embedded-Systeme sicher beherrschen. Komfortabel lässt sich die Entwicklung mit den Cross-Referenzierungs- Funktionen beschleunigen. Der Entwickler kann direkt vom Funktionsaufruf zur Deklaration der Funktion springen oder auch umgekehrt. Eclipse hält dazu eine Datenbank aller Funktionen und Variablen vor (Bild 2).

Bei Neuanlage einer Source-Code- Datei berücksichtigt Eclipse diese im Bauprozess, integriert sie in das Makefile und sorgt dafür, dass der Compiler den Code übersetzt. Der nachfolgende Linker integriert dann den Code in eine Library oder ein Executable. Der gesamte Bauprozess kann komfortabel per Mausklick von Eclipse durchgeführt werden. Treten Fehler auf, so zeigt Eclipse diese direkt im Code-Editor mit Korrekturzeichen an. Zum Debugging kann Eclipse auf Knopfdruck ein entsprechendes Binärprogramm erstellen lassen und hiermit auf dem Target, also auf der Embedded-Hardware eine Debugging- Sitzung starten (Bild 3). Dazu wird das Binärprogramm mittels scp auf das Embedded-System kopiert. Der Befehl scp steht für secure copy program. Er gehört in die Toolsuite rund um ssh (secure shell) und ermöglicht das sichere Kopieren einer Datei über TCP/IP-Netzwerke. Die Authentifizierung kann, wie bei ssh üblich, mit Benutzername und Passwort oder aber auch mit Public/Private Key erfolgen. In Eclipse kann der Speicherort des Programms auf dem Embedded-System beliebig festgelegt werden. Auf Read-only-Systemen kann hier eine RAM-Disk konfiguriert werden, sodass auch hierin Programme zum Debugging abgelegt werden können.