Neue Debugger So wird der Debugger zum Basiswerkzeug für Integration und Test

Autor / Redakteur: Heiko Rießland * / Margit Kuther

Die immensen Datenmengen heutiger Embedded Software bedürfen einer neuen Generation von Debuggern, die neben den klassischen Basisfunktionen umfangreiche Testmöglichkeiten auf Systemebene bis hin zur automatischen Generierung von Reports bieten.

Anbieter zum Thema

Big Data: Moderne Debugger bieten neben klassischen Basisfunktionen auch umfangreiche Testmöglichkeiten auf Systemebene.
Big Data: Moderne Debugger bieten neben klassischen Basisfunktionen auch umfangreiche Testmöglichkeiten auf Systemebene.
(Bild: © kras99 - Fotolia)

Komplexe Embedded-Softwareprogramme mit mehreren 100 MByte Quellcode und die ständig steigenden Qualitätsanforderungen erfordern zunehmend weitgehend automatisierte Testprogramme.

Wenn die Entwicklung in größeren Teams an verteilten Standorten stattfindet, sind solche Testmethoden für die sichere Zusammenführung der einzelnen Softwareteile unerlässlich. Teilweise werden sie durch einschlägige Normen wie die für den Automobilbereich geltende ISO2626 inzwischen sogar zwingend vorgeschrieben.

Bildergalerie

Die gewünschte Effektivität lässt sich allerdings nur erreichen, wenn der verwendete Debugger seine Funktionalität und seine grafische Bedienoberfläche auch tatsächlich uneingeschränkt in einer für automatisierte Tests geeigneten Form zur Verfügung stellt.

Dafür wird ein Werkzeug benötigt, das neben den klassischen Eigenschaften eines Debuggers, z.B. die Steuerung und Beobachtung des Targets mit vielfältigen Anzeige- und Analysemöglichkeiten, über ein grafisches Nutzerinterface weitere neue Möglichkeiten bietet. Die komplette Funktionalität muss auch im voll- oder halbautomatischen Betrieb nutzbar sein.

Ein typisches Beispiel für solche Vorgänge, die mit entsprechend ausgestatteten Tools völlig autonom ablaufen können, sind Regressionstests. Hierfür werden für bestimmte Funktionen der Software vorab eindeutige Testroutinen entwickelt, beispielsweise beschrieben durch Ein- und Ausgaben für Funktionen oder Module. Solche im Idealfall automatisierten Testläufe dienen dem sicheren Nachweis einer bestimmten Funktionalität auch nach mehrfachen Änderungen an der Software. Bei dieser Art der Anwendung übernimmt häufig ein drittes Programm die Verwaltung und Steuerung der Testfälle. Die eigentliche Bedienoberfläche des Debuggers kommt also gar nicht zur Anwendung, nur seine Funktionalität.

Halbautomatische Nutzung des Debuggers

Für die Integration verschiedener Softwareteile zu einer Gesamtapplikation ist wiederum eine halbautomatische Nutzung des Debuggers besonders interessant. Die Anwendung wird dabei unter verschiedenen Betriebsbedingungen manuell durch Bedienung über das grafische Nutzerinterface getestet. Neben dem Debugger ist das Steuergerät dabei noch mit einem komplexen Hardware-in-the-Loop (HiL)-System verbunden, welches die vorgesehene Steuergeräteumgebung simuliert. Besonders wichtig dabei: Skripte, welche die Debugger-Funktionalität nutzen, können bei auftretenden Anomalien oder Fehlern sofort einen detaillierten Report über den Zustand des Targets und der Applikationssoftware liefern. Dabei werden beispielsweise am Ort eines Breakpoints in einer Fehler- oder Trap-Funktion alle relevanten Variablen, Register, Speicherinhalte, usw. für eine Analyse bzw. spätere erneute Verifikation der Software gespeichert.

Bei korrekt laufender Software lässt sich im Idealfall zudem mittels vorbestimmter Funktionen ein Skript zur automatischen Code-Coverage-Analyse starten. Code Coverage ist ein Verfahren zur Messung der Testabdeckung und damit eine indirekte Bestimmung der Softwarequalität und wird in einschlägigen Normen wie der ISO26262 vorgeschrieben. Dabei wird ermittelt, ob während der Tests alle Instruktionen (Statement Coverage) und Verzweigungen (Branch Coverage) bzw. unterschiedliche logische Verknüpfungen (MC/DC) innerhalb einer Software durchlaufen werden.

Eine vollständige MC/DC-Analyse ist meist nur mit Code-Instrumentierung und damit einhergehender Veränderung der Laufzeit und Größe der Applikation möglich. Anwendungen, für die diese Variante aus technischen Gründen nicht in Frage kommt, verwenden stattdessen in der Regel auf in Echtzeit gewonnenen Trace-Daten basierendes Branch Coverage.

Soweit Compiler mit erweiterten Debug-Informationen zur Verfügung stehen, ist eine vollständige Branch-Coverage-Analyse sogar an hochoptimiertem Code möglich. In diesem Fall übernimmt der Debugger nicht nur die Steuerung des Targets und die Erfassung/Analyse der Trace-Daten. Er generiert auch einen automatischen Report, der seinerseits eine sichere Dokumentation und Wiederholbarkeit der Messungen garantiert (siehe Bildergalerie Bild 1). Die Anzeige der Code-Abdeckung ist für die Ebenen Funktion, Zeilennummer im Quelltext und auch Maschinenbefehl möglich. Im dargestellten Auszug ist der Quelltext eingeblendet. Über generierte Links an den Zeilennummern kann auf die Maschinencodeebene navigiert werden.

Als Standardausgabeformat wird HTML genutzt, über ein Stylesheet kann die Formatierung dabei einfach und ohne großen Aufwand an kundenspezifische Erfordernisse angepasst werden. Voraussetzung für die beschriebenen Automatisierungsverfahren ist die Bereitstellung der Debugger-Funktionalität über eine allgemein nutzbare Software-Schnittstelle.

Bildergalerie

Universal Debug Engine (UDE) von PLS

Bei der Universal Debug Engine (UDE) von PLS kommt hierfür als Basistechnologie das Component Object Model (COM) von Microsoft zum Einsatz, das sich über einen langen Zeitraum als De-facto-Standard in der Windows-Welt etabliert hat. Auch Windows selbst bietet einen großen Teil – insbesondere seiner neu hinzukommenden Funktionen – über COM-Schnittstellen an.

Das Objektmodell der UDE umfasst nahezu alle Funktionen des Debuggers wie Flash-Programmierung, Ablaufsteuerung, Lesen und Schreiben von Target-Speicher in symbolischer Form, Trace-Daten-Erfassung und -Analyse und vieles mehr (Bild 2, siehe Bildergalerie).

Ein großer Vorteil eines COM-basierten API beruht drauf, dass es von einer sehr großen Anzahl unterschiedlichster Sprachen nutzbar ist. C, C++, C# und andere .NET-Sprachen zählen hier genauso dazu wie die Skriptsprachen JavaScript, Python, Perl und VB Script oder die Windows-eigene PowerShell, da alle mit COM-Komponenten umgehen können. Bild 3 (siehe Bildergalerie) zeigt eine allgemeine Beschreibung der UDE-API auf Basis der Interface Description Language (IDL) und ihre Verwendung mit verschiedenen Sprachen.

Fazit:

Wenngleich die Integration und der Test hochkomplexer Embedded Software zunehmend automatisierte Arbeitsschritte erfordern, ist und bleibt der Debugger natürlich weiterhin die Schnittstelle zum Target.

Für die Praxis bedeutet dies, dass die komplette Funktionalität des Debuggers künftig möglichst uneingeschränkt im voll- oder halbautomatischen Betrieb nutzbar sein muss. Möglich ist das allerdings wiederum nur, wenn sie über standardisierte Technologien wie das Component Object Model (COM) anderen Werkzeugen zur Verfügung steht.

* Heiko Rießland leitet das Produktmarketing der PLS Programmierbare Logik & Systeme

Artikelfiles und Artikellinks

(ID:43586657)