Debuggerdatenmodell C++-Übersicht

Dieses Thema bietet eine Übersicht über die Verwendung von Debuggerdatenmodell-C++-Schnittstellen zum Erweitern und Anpassen der Funktionen des Debuggers.

Dieses Thema ist Teil einer Reihe, in der die Schnittstellen beschrieben werden, auf die über C++ zugegriffen werden kann, wie sie zum Erstellen einer C++-basierten Debuggererweiterung verwendet werden und wie andere Datenmodellkonstrukte (z. B. JavaScript oder NatVis) aus einer C++-Datenmodellerweiterung verwendet werden.

Debuggerdatenmodell C++-Übersicht

Debuggerdatenmodell-C++-Schnittstellen

Debuggerdatenmodell C++-Objekte

Debuggerdatenmodell C++-Zusätzliche Schnittstellen

Debuggerdatenmodell-C++-Konzepte

Debuggerdatenmodell C++-Skripterstellung


Übersicht über die Debuggerdatenmodell-C++-Schnittstelle

Das Debuggerdatenmodell ist ein erweiterbares Objektmodell, das von zentraler Bedeutung dafür ist, wie neue Debuggererweiterungen (einschließlich der in JavaScript, NatVis und C++) vom Debugger bereitgestellte Informationen nutzen und Informationen erzeugen, auf die vom Debugger und von anderen Erweiterungen zugegriffen werden kann. Konstrukte, die in die Datenmodell-APIs geschrieben werden, sind im neueren Ausdrucksauswertungs-Evaluator des Debuggers sowie aus JavaScript-Erweiterungen oder C++-Erweiterungen verfügbar.

Um die Ziele des Debuggerdatenmodells zu veranschaulichen, betrachten Sie diesen herkömmlichen Debuggerbefehl.

0: kd> !process 0 0 
PROCESS ffffe0007e6a7780
    SessionId: 1  Cid: 0f68    Peb: 7ff7cfe7a000  ParentCid: 0f34
    DirBase: 1f7fb9000  ObjectTable: ffffc001cec82780  HandleCount:  34.
    Image: echoapp.exe
...

Der Debuggerbefehl verwendet eine binäre Maske und stellt nur Textausgabe auf nicht standardmäßige Weise bereit. Die Textausgabe kann nur schwer verarbeitet, formatiert oder erweitert werden, und das Layout ist spezifisch für diesen Befehl.

Kontrastieren Sie dies mit dem Befehl Debuggerdatenmodell dx (Debuggerobjektmodellausdruck anzeigen).

dx @$cursession.Processes.Where(p => p.Threads.Count() > 5)

Dieser Befehl verwendet ein Standarddatenmodell, das auf einheitliche Weise auffindbar, erweiterbar und zusammensetzbar ist.

Durch logisches Benennen von Abständen und Erweitern auf bestimmte Objekte können Debuggererweiterungsfunktionen ermittelt werden.

Tipp

Da die Datenmodell-C++-Objektschnittstellen sehr ausführlich sein können, wird empfohlen, eine vollständige C++-Hilfsbibliothek für das Datenmodell zu implementieren, die eine vollständige C++-Ausnahme verwendet, und das Programmierparadigma für Vorlagen wird empfohlen. Weitere Informationen finden Sie weiter unten in diesem Thema unter Verwenden der DbgModelClientEx-Bibliothek .

Das Datenmodell ist die Art und Weise, wie WinDbg die meisten Dinge zeigt. Viele Elemente in der neuen Benutzeroberfläche können abgefragt, erweitert oder skriptiert werden, da sie vom Datenmodell unterstützt werden. Weitere Informationen finden Sie unter WinDbg – Datenmodell.

Screenshot: Fenster

Architekturansicht des Datenmodells

Das folgende Diagramm fasst die wichtigsten Elemente der Debuggerdatenmodellarchitektur zusammen.

  • Auf der linken Seite werden UI-Elemente angezeigt, die den Zugriff auf die Objekte ermöglichen und funktionen wie LINQ-Abfragen unterstützen.
  • Auf der rechten Seite des Diagramms befinden sich Komponenten, die Daten für das Debuggerdatenmodell bereitstellen. Dies umfasst benutzerdefinierte NatVis-, JavaScript- und C++-Debugger-Datenmodellerweiterungen.

Diagramm: Datenmodellarchitektur mit allgemeinem Objektmodell in der Mitte und Anbietern auf der rechten Seite

Objektmodell

Im Mittelpunkt des Debuggerdatenmodells steht eine einheitliche Objektdarstellung, bei der alles ein instance der IModelObject-Schnittstelle ist. Ein solches Objekt kann zwar einen intrinsischen (z. B. einen ganzzahligen Wert) oder eine andere Datenmodellschnittstelle darstellen, stellt jedoch häufig ein dynamisches Objekt dar – ein Wörterbuch mit Schlüssel-Wert-/Metadatentupeln und eine Reihe von Konzepten, die abstrakte Verhaltensweisen beschreiben.

Dieses Diagramm zeigt, wie das IModelObject Schlüsselspeicher verwendet, um Werte zu enthalten, die ein Anbieter erstellen, registrieren und bearbeiten kann.

  • Es wird ein Anbieter angezeigt, der Informationen zum Objektmodell bereitstellt.
  • Auf der linken Seite wird das IModelObject angezeigt, d. h. das allgemeine Objektmodell, das zum Bearbeiten von Objekten verwendet wird.
  • In der Mitte befindet sich der Schlüsselspeicher , der zum Speichern und Zugreifen auf Werte verwendet wird.
  • Unten werden Konzepte angezeigt, die Objekte mit Funktionalität unterstützen, z. B. die Möglichkeit, in eine anzeigebare Zeichenfolge zu konvertieren oder indiziert zu werden.

Diagramm, das die Datenmodellarchitektur mit IModelObject als Eingabe und einem Tupelschlüsselspeicher zeigt.

Das Datenmodell: Eine Consumeransicht

Das nächste Diagramm zeigt eine Consumeransicht des Datenmodells. Im Beispiel wird der Befehl dx (Debugger-Objektmodellausdruck anzeigen) verwendet, um Informationen abzufragen.

  • Der Dx-Befehl kommuniziert über ein Serialisierer mit der Objektaufzählungsschnittstelle.
  • IDebugHost*-Objekte werden verwendet, um Informationen aus der Debugger-Engine zu sammeln.
  • Ausdrucks- und semantische Auswertungen werden verwendet, um die Anforderung an die Debugger-Engine zu senden.

Diagramm: Datenmodellarchitektur mit Benutzeroberflächeneinspeisung in Evaluatoren, die eine Verbindung mit IDebugHost herstellen

Das Datenmodell: Eine Produceransicht

Dieses Diagramm zeigt eine Produceransicht des Datenmodells.

  • Auf der linken Seite wird ein NatVis-Anbieter angezeigt, der XML nutzt, das zusätzliche Funktionen definiert.
  • Ein JavaScript-Anbieter kann dynamische Anbieterkonzepte nutzen, um Informationen in Echtzeit zu bearbeiten.
  • Unten wird ein systemeigener Codeanbieter angezeigt, der auch zusätzliche Funktionen definieren kann.

Diagramm: Datenmodellarchitektur mit IModelObject, das mit NatVis, JavaScript und nativen Code-Consumern verbunden ist.

Datenmodell-Manager

Dieses Diagramm zeigt die zentrale Rolle, die der Datenmodell-Manager bei der Verwaltung von Objekten spielt.

  • Der Datenmodell-Manager fungiert als zentrale Registrierungsstelle für alle Objekte.
  • Auf der linken Seite wird gezeigt, wie Standarddebuggerelemente wie Sitzungen und Prozesse registriert werden.
  • Der Namespaceblock zeigt die zentrale Registrierungsliste an.
  • Die rechte Seite des Diagramms zeigt zwei Anbieter, einen für NatVis oben und eine C/C++-Erweiterung unten.

Diagramm: Datenmodellarchitektur mit registrierten Namen, auf die der Datenmodell-Manager zugreift.

Zusammenfassung der Debuggerdatenmodellschnittstellen

Es gibt eine Vielzahl von C++-Schnittstellen, die verschiedene Teile des Datenmodells umfassen. Um diese Schnittstellen konsistent und einfach anzugehen, werden sie nach allgemeinen Kategorien aufgeschlüsselt. Hier Standard Bereiche:

Das allgemeine Objektmodell

Der erste und wichtigste Satz von Schnittstellen definieren, wie Sie Zugriff auf das Kerndatenmodell erhalten und wie Sie auf Objekte zugreifen und diese bearbeiten. IModelObject ist die Schnittstelle, die jedes Objekt im Datenmodell darstellt (ähnlich wie das C#-Objekt). Dies ist die Standard Schnittstelle, die sowohl für Verbraucher als auch für Produzenten von Interesse ist, zum Datenmodell. Die anderen Schnittstellen sind Mechanismen für den Zugriff auf verschiedene Aspekte von Objekten. Für diese Kategorie sind die folgenden Schnittstellen definiert:

Brücken zwischen DbgEng und dem Datenmodell

IHostDataModelAccess

Hauptschnittstellen

IModelObject

IKeyStore

IModelIterator

IModelPropertyAccessor

IModelMethod

IKeyEnumerator

IRawEnumerator

IModelKeyReference / IModelKeyReference2

Konzeptschnittstellen

IStringDisplayableConcept

IIterableConcept

IIndexableConcept

IPreferredRuntimeTypeConcept

IDataModelConcept

IDynamicKeyProviderConcept

IDynamicConceptProviderConcept

Verwaltung von Datenmodellen und Erweiterbarkeit

Der Datenmodell-Manager ist die Kernkomponente, die verwaltet, wie die gesamte Erweiterbarkeit erfolgt. Es ist das zentrale Repository einer Gruppe von Tabellen, die sowohl native Typen Erweiterungspunkten als auch synthetische Konstrukte Erweiterungspunkten zuordnen. Darüber hinaus ist es die Entität, die für das Boxen von Objekten (Konvertierung von Ordnungswerten oder Zeichenfolgen in IModelObjects) verantwortlich ist.

Für diese Kategorie sind die folgenden Schnittstellen definiert:

Allgemeiner Datenmodell-Manager-Zugriff

IDataModelManager / IDataModelManager2

Skriptverwaltung

IDataModelScriptManager

IDataModelScriptProviderEnumerator

Zugriff auf das Typsystem und die Speicherplätze des Debuggers

Das zugrunde liegende Typsystem und die Arbeitsspeicherplätze des Debuggers werden ausführlich für Erweiterungen verfügbar gemacht, die verwendet werden können. Für diese Kategorie sind die folgenden Schnittstellen definiert:

Allgemeine Hostschnittstellen (Debugger)

IDebugHost

IDebugHostStatus

IDebugHostContext

IDebugHostMemory / IDebugHostMemory2

IDebugHostErrorSink

IDebugHostEvaluator / IDebugHostEvaluator2

IDebugHostExtensibility

Host (Debugger) Typ Systemschnittstellen

IDebugHostSymbols

IDebugHostSymbol / IDebugHostSymbol2

IDebugHostModule

IDebugHostType / IDebugHostType2

IDebugHostConstant

IDebugHostField

IDebugHostData

IDebugHostBaseClassIDebugHostPublic

IDebugHostModuleSignature

IDebugHostTypeSignature

Hostunterstützung (Debugger) für Skripterstellung

IDebugHostScriptHostHost

Erstellen und Verwenden von Skripts

Das Datenmodell hat auch eine allgemeine Vorstellung davon, was ein Skript ist und wie es zu debuggen ist. Es ist durchaus möglich, dass eine Debuggererweiterung kommt und eine allgemeine Brücke zwischen dem Datenmodell und einer anderen dynamischen Sprache (normalerweise eine Skriptumgebung) definiert. Dieser Satz von Schnittstellen ist, wie dies erreicht wird, und wie eine Debugger-Benutzeroberfläche solche Skripts verwenden kann.

Für diese Kategorie sind die folgenden Schnittstellen definiert:

Allgemeine Skriptschnittstellen

IDataModelScriptProvider

IDataModelScript

IDataModelScriptClient

IDataModelScriptHostContext

IDataModelScriptTemplate

IDataModelScriptTemplateEnumerator

IDataModelNameBinder

Skriptdebuggerschnittstellen

IDataModelScriptDebug

IDataModelScriptDebugClient

IDataModelScriptDebugStack

IDataModelScriptDebugStackFrame

IDataModelScriptDebugVariableSetEnumerator

IDataModelScriptDebugBreakpoint

IDataModelScriptDebugBreakpointEnumerator

Verwenden der DbgModelClientEx-Bibliothek

Übersicht

Die Datenmodell-C++-Objektschnittstellen zum Datenmodell können sehr ausführlich zu implementieren sein. Sie ermöglichen zwar die vollständige Bearbeitung des Datenmodells, erfordern jedoch die Implementierung einer Reihe kleiner Schnittstellen, um das Datenmodell zu erweitern (z. B. eine IModelPropertyAccessor-Implementierung für jede hinzugefügte dynamisch abrufbare Eigenschaft). Darüber hinaus fügt das HRESULT-basierte Programmiermodell eine erhebliche Menge an Kesselplattencode hinzu, der für die Fehlerüberprüfung verwendet wird.

Um einige dieser Arbeiten zu minimieren, gibt es eine vollständige C++-Hilfsbibliothek für das Datenmodell, die ein vollständiges C++-Ausnahme- und Vorlagenprogrammierungsparadigma verwendet. Die Verwendung dieser Bibliothek ermöglicht präziseren Code beim Verwenden oder Erweitern des Datenmodells und wird empfohlen.

Es gibt zwei wichtige Namespaces in der Hilfsbibliothek:

Debugger::D ataModel::ClientEx – Hilfsprogramme für die Nutzung des Datenmodells

Debugger::D ataModel::P roviderEx – Hilfsprogramme für die Erweiterung des Datenmodells

Weitere Informationen zur Verwendung der DbgModelClientEx-Bibliothek finden Sie in der Infodatei auf dieser Github-Website:

https://github.com/Microsoft/WinDbg-Libraries/tree/master/DbgModelCppLib

HelloWorld C++-Beispiel

Informationen zur Verwendung der DbgModelClientEx-Bibliothek finden Sie im Data Model HelloWorld C++-Beispiel hier.

https://github.com/Microsoft/WinDbg-Samples/tree/master/DataModelHelloWorld

Das Beispiel umfasst Folgendes:

  • HelloProvider.cpp: Dies ist eine Implementierung einer Anbieterklasse, die der Vorstellung eines Prozesses des Debuggers eine neue Beispieleigenschaft "Hello" hinzufügt.

  • SimpleIntroExtension.cpp: Dies ist eine einfache Debuggererweiterung, die der Vorstellung eines Prozesses des Debuggers eine neue Beispieleigenschaft "Hello" hinzufügt. Diese Erweiterung wird für die Datenmodell-C++17-Hilfsbibliothek geschrieben. Es ist aufgrund des Volumens (und der Komplexität) von Glue-Code, das erforderlich ist, weit vorzuziehen, Erweiterungen für diese Bibliothek zu schreiben, anstatt den unformatierten COM-ABI.

JavaScript- und COM-Beispiele

Um die verschiedenen Möglichkeiten zum Schreiben einer Debuggererweiterung mit dem Datenmodell besser zu verstehen, stehen hier drei Versionen der Datenmodellerweiterung HelloWorld zur Verfügung:

https://github.com/Microsoft/WinDbg-Samples/tree/master/DataModelHelloWorld

  • JavaScript: Eine in JavaScript geschriebene Version

  • C++17: Eine Version, die für die C++17-Clientbibliothek des Datenmodells geschrieben wurde

  • COM: Eine Version, die für die unformatierte COM-ABI geschrieben wurde (nur mit WRL für COM-Hilfsprogramme)


Siehe auch

Debuggerdatenmodell-C++-Schnittstellen

Debuggerdatenmodell C++-Objekte

Debuggerdatenmodell C++-Zusätzliche Schnittstellen

Debuggerdatenmodell-C++-Konzepte

Debuggerdatenmodell C++-Skripterstellung