Freigeben über


Debugger Datenmodell C++ – Übersicht

Dieses Thema enthält 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 von C++ zugänglichen Schnittstellen beschrieben werden, wie sie zum Erstellen einer C++-basierten Debuggererweiterung und zur Verwendung anderer Datenmodellkonstrukte (z. B. JavaScript oder NatVis) aus einer C++-Datenmodellerweiterung verwendet werden.

Debuggerdatenmodell-C++-Schnittstellen

Debugger-Datenmodell-C++-Objekte

Zusätzliche Schnittstellen für das Debuggerdatenmodell C++

Debuggerdatenmodell-C++-Konzepte

Debuggerdatenmodell C++-Skripting


Übersicht über die Debugger-Datenmodell-C++-Schnittstelle

Das Debuggerdatenmodell ist ein erweiterbares Objektmodell, das zentral für die Art und Weise ist, in der neue Debuggererweiterungen (einschließlich derer in JavaScript, NatVis und C++) sowohl Informationen vom Debugger nutzen als auch Informationen erzeugen, auf die über den Debugger sowie andere Erweiterungen zugegriffen werden kann. Konstrukte, die in die Datenmodell-APIs geschrieben werden, sind im neueren (dx)-Ausdrucks-Evaluator des Debuggers sowie aus JavaScript-Erweiterungen oder C++-Erweiterungen verfügbar.

Betrachten Sie diesen herkömmlichen Debuggerbefehl, um die Ziele des Debuggerdatenmodells zu veranschaulichen.

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 verwendet, formatiert oder erweitert werden, und das Layout ist für diesen Befehl spezifisch.

Im Gegensatz dazu steht der Befehl "dx (Ausdruck des Debuggerobjektmodells anzeigen)" des Debuggerdatenmodells.

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

Dieser Befehl verwendet ein Standarddatenmodell, das auf einheitliche Weise auffindbar, erweiterbar und komponiert werden kann.

Durch logisches Namespacing und die Erweiterung bestimmter Objekte wird die Entdeckung von Debugger-Erweiterungsfunktionen ermöglicht.

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 das komplette C++-Paradigma für Ausnahmebehandlung und Vorlagenprogrammierung verwendet. Weitere Informationen finden Sie unter Verwenden der DbgModelClientEx-Bibliothek weiter unten in diesem Thema.

Das Datenmodell ist die Art und Weise, wie WinDbg die meisten Dinge anzeigt. 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 des Fensters zur Erkundung des Datenmodells, das Prozesse und Threads anzeigt.

Architekturansicht des Datenmodells

Das folgende Diagramm fasst die wichtigsten Elemente der Debuggerdatenmodellarchitektur zusammen.

  • Auf der linken Seite werden UI-Elemente angezeigt, die Zugriff auf die Objekte ermöglichen und diese Funktionalität wie LINQ-Abfragen unterstützen.
  • Auf der rechten Seite des Diagramms handelt es sich um Komponenten, die Daten für das Debuggerdatenmodell bereitstellen. Dazu gehören benutzerdefinierte NatVis-, JavaScript- und C++-Debuggerdatenmodellerweiterungen.

Diagramm, das die Datenmodellarchitektur mit allgemeinem Objektmodell in der Mitte und anbietern auf der rechten Seite zeigt.

Objektmodell

In der Mitte des Debugger-Datenmodells handelt es sich um eine einheitliche Objektdarstellung, in der alles eine Instanz der IModelObject-Schnittstelle ist. Ein solches Objekt kann zwar ein systeminternes (z. B. ein ganzzahliger Wert) oder eine andere Datenmodellschnittstelle darstellen, stellt es jedoch häufig ein dynamisches Objekt dar – ein Wörterbuch mit Schlüssel-Wert-/Metadaten-Tupeln 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 zeigt einen Anbieter, der Informationen für das Objektmodell bereitstellt.
  • Auf der linken Seite wird das IModelObject angezeigt, d. h. das allgemeine Objektmodell, das zum Bearbeiten von Objekten verwendet wird.
  • Im Zentrum befindet sich der Schlüsselspeicher , der zum Speichern und Zugreifen auf Werte verwendet wird.
  • Unten sehen Sie Konzepte , die Objekte mit Funktionen unterstützen, z. B. die Möglichkeit, in eine anzeigefähige Zeichenfolge zu konvertieren oder indiziert zu werden.

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

Das Datenmodell: Eine Verbrauchersicht

Das nächste Diagramm zeigt eine Consumeransicht des Datenmodells. Im Beispiel wird der Befehl dx (Display Debugger Object Model Expression) verwendet, um Informationen abzufragen.

  • Der Befehl Dx kommuniziert über einen Serialisierer an die Objektenumerationsschnittstelle.
  • IDebugHost*-Objekte werden verwendet, um Informationen aus dem Debuggermodul zu sammeln.
  • Ausdrucks- und semantische Auswertungen werden verwendet, um die Anforderung an das Debuggermodul zu senden.

Diagramm, das die Datenmodellarchitektur mit der Benutzeroberfläche zeigt, die in Evaluatoren eingespeist wird, die eine Verbindung mit IDebugHost herstellen.

Das Datenmodell: Eine Produzentenansicht

Dieses Diagramm zeigt eine Produzentenansicht des Datenmodells.

  • Auf der linken Seite wird ein NatVis-Anbieter angezeigt, der XML verwendet, der zusätzliche Funktionen definiert.
  • Ein JavaScript-Anbieter kann die Vorteile dynamischer Anbieterkonzepte nutzen, um Informationen in Echtzeit zu bearbeiten.
  • Unten sehen Sie einen systemeigenen Codeanbieter, der auch zusätzliche Funktionen definieren kann.

Diagramm, das die Datenmodellarchitektur mit IModelObject zeigt, die 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, eine für NatVis oben und eine C/C++-Erweiterung unten.

Diagramm, das die Datenmodellarchitektur mit registrierten Namen zeigt, auf die vom Datenmodell-Manager zugegriffen wird.

Zusammenfassung der Debuggerdatenmodellschnittstellen

Es gibt eine Vielzahl von C++-Schnittstellen, die verschiedene Teile des Datenmodells umfassen. Um diese Schnittstellen auf einheitliche und einfache Weise anzugehen, werden sie nach allgemeiner Kategorie aufgeschlüsselt. Die wichtigsten Bereiche hier:

Das allgemeine Objektmodell

Die erste und wichtigste Gruppe von Schnittstellen definieren, wie Sie Zugriff auf das Kerndatenmodell erhalten und wie Sie auf Objekte zugreifen und diese bearbeiten können. IModelObject ist die Schnittstelle, die jedes Objekt im Datenmodell darstellt (ähnlich wie das C#-Objekt). Dies ist die Hauptschnittstelle von Interesse sowohl für Verbraucher als auch für Produzenten bezüglich des Datenmodells. Die anderen Schnittstellen sind Mechanismen für den Zugriff auf verschiedene Aspekte von Objekten. Die folgenden Schnittstellen sind für diese Kategorie 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

IDynamicConceptProviderConceptProviderConcept

Verwaltung von Datenmodellen und Erweiterbarkeit

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

Die folgenden Schnittstellen sind für diese Kategorie definiert:

Allgemeiner Datenmodell-Manager-Zugriff

IDataModelManager / IDataModelManager2

Skriptverwaltung

IDataModelScriptManager-

IDataModelScriptProviderEnumerator-

Zugriff auf das Typsystem des Debuggers und Speicherplätze

Das zugrunde liegende Typsystem und Speicherplätze des Debuggers werden für Erweiterungen, die verwendet werden sollen, detailliert verfügbar gemacht. Die folgenden Schnittstellen sind für diese Kategorie definiert:

Allgemeine Hostschnittstellen (Debugger)

IDebugHost-

IDebugHostStatus-

IDebugHostContext-

IDebugHostMemory / IDebugHostMemory2

IDebugHostErrorSink-

IDebugHostEvaluator / IDebugHostEvaluator2

IDebugHostExtensibility

Systemschnittstellen vom Hosttyp (Debugger)

IDebugHostSymbols-

IDebugHostSymbol / IDebugHostSymbol2

IDebugHostModule-

IDebugHostType / IDebugHostType2

IDebugHostConstant

IDebugHostField-

IDebugHostData-

IDebugHostBaseClassIDebugHostPublic

IDebugHostModuleSignature

IDebugHostTypeSignature

Hostunterstützung (Debugger) für Skripting

IDebugHostScriptHost-

Erstellen und Verwenden von Skripts

Das Datenmodell hat auch eine allgemeine Vorstellung davon, was ein Skript ist und wie ein Skript gedebuggt wird. Es ist völlig möglich, dass eine Debuggererweiterung zusammenkommt und eine allgemeine Brücke zwischen dem Datenmodell und einer anderen dynamischen Sprache (in der Regel eine Skriptumgebung) definiert. Dieser Satz von Schnittstellen ist, wie dies erreicht wird und wie eine Debugger-Benutzeroberfläche solche Skripts verwenden kann.

Die folgenden Schnittstellen sind für diese Kategorie definiert:

Allgemeine Skriptschnittstellen

IDataModelScriptProvider-

IDataModelScript-

IDataModelScriptClient-

IDataModelScriptHostContext-

IDataModelScriptTemplate-

IDataModelScriptTemplateEnumerator

IDataModelNameBinder

Skriptdebuggerschnittstellen

IDataModelScriptDebug-

IDataModelScriptDebugClient-

IDataModelScriptDebugStack-

IDataModelScriptDebugStackFrame-

IDataModelScriptDebugVariableSetEnumerator

IDataModelScriptDebugBreakpoint-

IDataModelScriptDebugBreakpointEnumerator

Verwenden der DbgModelClientEx-Bibliothek

Übersicht

Die C++-Objektschnittstellen des Datenmodells können sehr aufwendig umgesetzt werden. Sie ermöglichen zwar die vollständige Manipulation des Datenmodells, erfordern jedoch die Implementierung einer Reihe kleiner Schnittstellen, um das Datenmodell zu erweitern (z. B. eine IModelPropertyAccessor-Implementierung für jede dynamische abrufbare Eigenschaft, die hinzugefügt wird). Darüber hinaus fügt das HRESULT-basierte Programmiermodell eine erhebliche Menge von Code für die Kesselplatte hinzu, die 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, das 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::DataModel::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

Wenn Sie sehen möchten, wie die DbgModelClientEx-Bibliothek verwendet werden kann, lesen Sie hier das Data Model HelloWorld C++-Beispiel.

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

Das Beispiel umfasst:

  • HelloProvider.cpp – Dies ist eine Implementierung einer Provider-Klasse, die dem Konzept eines Prozesses im Debugger eine neue Beispieleigenschaft "Hello" hinzufügt.

  • SimpleIntroExtension.cpp – Dies ist eine einfache Debuggererweiterung, die der Vorstellung eines Prozesses eine neue Beispieleigenschaft "Hello" hinzufügt. Diese Erweiterung wird für die Datenmodell-C++17-Hilfsbibliothek geschrieben. Es ist vorzuziehen, Erweiterungen für diese Bibliothek zu schreiben, anstatt dem rohen COM-ABI, wegen des Umfangs und der Komplexität des notwendigen Klebecodes.

JavaScript- und COM-Beispiele

Um die unterschiedlichen 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 mit dem Datenmodell C++17-Clientbibliothek geschrieben wurde

  • COM – Eine Version, die mit dem unformatierten COM ABI geschrieben wurde (nur mit WRL für COM-Hilfsprogramme)


Siehe auch

Debuggerdatenmodell-C++-Schnittstellen

Debugger-Datenmodell-C++-Objekte

Zusätzliche Schnittstellen für das Debuggerdatenmodell C++

Debuggerdatenmodell-C++-Konzepte

Debuggerdatenmodell C++-Skripting