Panoramica del modello di dati del debugger C++

Questo argomento offre una panoramica di come usare interfacce C++ del modello di dati debugger per estendere e personalizzare le funzionalità del debugger.

Questo argomento fa parte di una serie che descrive le interfacce accessibili da C++, come usarle per creare un'estensione del debugger basata su C++ e come usare altri costrutti di modelli di dati (ad esempio JavaScript o NatVis) da un'estensione del modello di dati C++.

Panoramica del modello di dati del debugger C++

Interfacce C++ del modello di dati del debugger

Oggetti C++ del modello di dati debugger

Interfacce aggiuntive del modello di dati del debugger C++

Concetti relativi al modello di dati del debugger C++

Script C++ del modello di dati del debugger


Panoramica dell'interfaccia C++ del modello di dati debugger

Il modello dati del debugger è un modello a oggetti estendibile che è fondamentale per il modo in cui le nuove estensioni del debugger (incluse quelle in JavaScript, NatVis e C++) usano le informazioni del debugger e producono informazioni a cui è possibile accedere dal debugger e altre estensioni. I costrutti scritti nelle API del modello di dati sono disponibili nell'analizzatore di espressioni (dx) più recente del debugger, nonché da estensioni JavaScript o estensioni C++.

Per illustrare gli obiettivi del modello di dati del debugger, considerare questo comando del debugger tradizionale.

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

Il comando del debugger usa una maschera binaria e fornisce solo l'output di testo in modi non standard. L'output del testo è difficile da utilizzare, formattare o estendere e il layout è specifico per questo comando.

Contrasto con il comando dx del modello di dati del debugger (Display Debugger Object Model Expression).

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

Questo comando usa un modello di dati standard individuabile, estendibile e componibile in modi uniformi.

La spaziatura logica delle cose e l'estensione su oggetti specifici consente l'individuazione delle funzionalità di estensione del debugger.

Suggerimento

Poiché le interfacce oggetto C++ del modello di dati possono essere molto dettagliate per implementare una libreria helper C++ completa per il modello di dati che usa un'eccezione C++ completa e un paradigma di programmazione modello è consigliabile. Per altre informazioni, vedere Uso della libreria DbgModelClientEx più avanti in questo argomento.

Il modello di dati è il modo in cui WinDbg mostra la maggior parte delle cose. Molti elementi nella nuova interfaccia utente possono essere sottoposti a query, estese o script, perché sono basate sul modello di dati. Per altre informazioni, vedere WinDbg - Data Model.

Screenshot del modello di dati esplorare la finestra che visualizza processi e thread.

Visualizzazione architettura del modello di dati

Il diagramma seguente riepiloga gli elementi principali dell'architettura del modello di dati del debugger.

  • Sul lato sinistro, gli elementi dell'interfaccia utente vengono visualizzati che forniscono l'accesso agli oggetti e supportano tali funzionalità come query LINQ.
  • Sul lato destro del diagramma sono componenti che forniscono dati al modello di dati del debugger. Ciò include estensioni del modello di dati del debugger NatVis, JavaScript e C++ personalizzate.

Diagramma che mostra l'architettura del modello di dati con modello a oggetti comune nel centro e nei provider a destra.

Modello a oggetti

Al centro del Debugger Data Model è una rappresentazione uniforme dell'oggetto in cui tutto è un'istanza dell'interfaccia IModelObject. Sebbene tale oggetto possa rappresentare un oggetto intrinseco (ad esempio, un valore intero) o un'altra interfaccia del modello di dati, spesso rappresenta un oggetto dinamico, un dizionario di tupla chiave/valore/metadati e un set di concetti che descrivono comportamenti astratti.

Questo diagramma illustra come IModelObject usa archivi chiavi per contenere valori che un provider può creare, registrare e modificare.

  • Mostra un provider, che fornisce informazioni al modello a oggetti
  • A sinistra mostra IModelObject, ovvero il modello a oggetti comune usato per modificare gli oggetti.
  • Nel centro è l'archivio chiavi usato per archiviare e accedere ai valori.
  • Nella parte inferiore mostra Concetti che supportano gli oggetti con funzionalità, ad esempio la possibilità di convertire in una stringa visualizzabile o di essere indicizzata.

Diagramma che mostra l'architettura del modello di dati con IModelObject come input e un archivio chiavi tuple.

Modello di dati: visualizzazione consumer

Il diagramma successivo mostra una visualizzazione consumer del modello di dati. Nell'esempio viene usato il comando dx (Display Debugger Object Model Expression) per eseguire query sulle informazioni.

  • Il comando Dx comunica tramite un serializzatore all'interfaccia di enumerazione dell'oggetto.
  • Gli oggetti IDebugHost* vengono usati per raccogliere informazioni dal motore del debugger.
  • Gli analizzatori di espressioni e semantiche vengono usati per inviare la richiesta al motore del debugger.

Diagramma che mostra l'architettura del modello di dati con l'alimentazione dell'interfaccia utente nei analizzatori che si connettono a IDebugHost.

Modello di dati: visualizzazione producer

Questo diagramma mostra una visualizzazione producer del modello di dati.

  • Un provider NatVis viene visualizzato a sinistra che usa XML che definisce funzionalità aggiuntive.
  • Un provider JavaScript può sfruttare i vantaggi dei concetti del provider dinamico per modificare le informazioni in tempo reale.
  • Nella parte inferiore viene visualizzato un provider di codice nativo che può anche definire funzionalità aggiuntive.

Diagramma che mostra l'architettura del modello di dati con IModelObject connesso a NatVis, JavaScript e Consumer di codice nativo.

Data Model Manager

Questo diagramma mostra il ruolo centrale che il gestore modelli di dati svolge nella gestione degli oggetti.

  • Data Model Manager funge da registrar centrale per tutti gli oggetti.
  • A sinistra viene illustrato come vengono registrati gli elementi del debugger standard, ad esempio sessioni e processi.
  • Il blocco dello spazio dei nomi mostra l'elenco di registrazione centrale.
  • Il lato destro del diagramma mostra due provider, uno per NatVis nella parte superiore e un'estensione C/C++ nella parte inferiore.

Diagramma che mostra l'architettura del modello di dati con nomi registrati a cui si accede dal gestore modelli di dati.

Riepilogo delle interfacce del modello di dati del debugger

Esistono numerose interfacce C++ che comprendono parti diverse del modello di dati. Per approcciare queste interfacce in modo coerente e semplice, vengono suddivise in base alla categoria generale. Le principali aree qui:

Modello a oggetti generale

Il primo e più importante set di interfacce definisce come ottenere l'accesso al modello di dati principale e come accedere e modificare gli oggetti. IModelObject è l'interfaccia che rappresenta ogni oggetto nel modello di dati (molto simile all'oggetto C#). Si tratta dell'interfaccia principale di interesse sia per i consumatori che per i produttori al modello di dati. Le altre interfacce sono meccanismi per l'accesso a diversi aspetti degli oggetti. Per questa categoria sono definite le interfacce seguenti:

Bridge tra DbgEng e il modello di dati

IHostDataModelAccess

Interfacce principali

IModelObject

IKeyStore

IModelIterator

IModelPropertyAccessor

IModelMethod

IKeyEnumerator

IRawEnumerator

IModelKeyReference / IModelKeyReference2

Interfacce di concetto

IStringDisplayableConcept

IIterableConcept

IIndexableConcept

IPreferredRuntimeTypeConcept

IDataModelConcept

IDynamicKeyProviderConcept

IDynamicConceptProviderConcept

Gestione di modelli di dati e estendibilità

Data Model Manager è il componente principale che gestisce il modo in cui si verifica tutta l'estendibilità. È il repository centrale di un set di tabelle che esegue il mapping di entrambi i tipi nativi ai punti di estensione e ai costrutti sintetici ai punti di estensione. Inoltre, è l'entità responsabile del boxing di oggetti (conversione di valori ordinali o stringhe in IModelObject).

Per questa categoria sono definite le interfacce seguenti:

Accesso di General Data Model Manager

IDataModelManager / IDataModelManager2

Gestione script

IDataModelScriptManager

IDataModelScriptProviderEnumerator

Accesso agli spazi di sistema dei tipi e della memoria del debugger

Gli spazi di memoria e di sistema dei tipi sottostanti del debugger vengono esposti in dettaglio per le estensioni da usare. Per questa categoria sono definite le interfacce seguenti:

Interfacce host generali (debugger)

IDebugHost

IDebugHostStatus

IDebugHostContext

IDebugHostMemory / IDebugHostMemory2

IDebugHostErrorSink

IDebugHostEvaluator / IDebugHostEvaluator2

IDebugHostExtensibility

Interfacce di sistema del tipo host (debugger)

IDebugHostSymbols

IDebugHostSymbol / IDebugHostSymbol2

IDebugHostModule

IDebugHostType / IDebugHostType2

IDebugHostConstant

IDebugHostField

IDebugHostData

IDebugHostBaseClassIDebugHostPublic

IDebugHostModuleSignature

IDebugHostTypeSignature

Supporto host (debugger) per lo scripting

IDebugHostScriptHost

Creazione e utilizzo di script

Il modello di dati ha anche una nozione generale di che cos'è uno script e come eseguirne il debug. È possibile che un'estensione del debugger venga eseguita e definiscano un ponte generale tra il modello di dati e un altro linguaggio dinamico (in genere un ambiente di scripting). Questo set di interfacce è il modo in cui viene eseguita e come un'interfaccia utente del debugger può usare tali script.

Per questa categoria sono definite le interfacce seguenti:

Interfacce script generali

IDataModelScriptProvider

IDataModelScript

IDataModelScriptClient

IDataModelScriptHostContext

IDataModelScriptTemplate

IDataModelScriptTemplateEnumerator

IDataModelNameBinder

Interfacce del debugger di script

IDataModelScriptDebug

IDataModelScriptDebugClient

IDataModelScriptDebugStack

IDataModelScriptDebugStackFrame

IDataModelScriptDebugVariableSetEnumerator

IDataModelScriptDebugBreakpoint

IDataModelScriptDebugBreakpointEnumerator

Uso della libreria DbgModelClientEx

Panoramica

Le interfacce oggetto C++ del modello di dati per il modello di dati possono essere molto verbose da implementare. Sebbene consentano la manipolazione completa del modello di dati, richiedono l'implementazione di una serie di interfacce di piccole dimensioni per estendere il modello di dati ,ad esempio un'implementazione IModelPropertyAccessor per ogni proprietà recuperabile dinamica aggiunta. Oltre a questo, il modello di programmazione basato su HRESULT aggiunge una quantità significativa di codice della lastra caldaia usato per il controllo degli errori.

Per ridurre al minimo alcune di queste operazioni, è disponibile una libreria helper C++ completa per il modello di dati che usa un paradigma di programmazione di modelli e eccezioni C++ completo. L'uso di questa libreria consente un codice più conciso quando si utilizza o si estende il modello di dati ed è consigliabile.

Nella libreria helper sono presenti due spazi dei nomi importanti:

Debugger::D ataModel::ClientEx - Helper per l'utilizzo del modello di dati

Debugger::D ataModel::P roviderEx - Helper per l'estensione del modello di dati

Per altre informazioni sull'uso della libreria DbgModelClientEx, vedere il file readme in questo sito github:

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

Esempio di C++ HelloWorld

Per informazioni sull'uso della libreria DbgModelClientEx, vedere l'esempio di Data Model HelloWorld C++ qui.

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

L'esempio include:

  • HelloProvider.cpp: si tratta di un'implementazione di una classe provider che aggiunge una nuova proprietà di esempio "Hello" alla nozione del debugger di un processo.

  • SimpleIntroExtension.cpp: si tratta di una semplice estensione del debugger che aggiunge una nuova proprietà di esempio "Hello" alla nozione del debugger di un processo. Questa estensione viene scritta nella libreria helper C++17 del modello di dati. È preferibile scrivere estensioni in questa libreria anziché nell'ABI COM non elaborato a causa del volume (e della complessità) del codice glue necessario.

Esempi di JavaScript e COM

Per comprendere meglio i diversi modi per scrivere un'estensione del debugger con il modello di dati, sono disponibili tre versioni dell'estensione HelloWorld del modello di dati qui:

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

  • JavaScript - Versione scritta in JavaScript

  • C++17 - Versione scritta sulla libreria client C++17 del modello di dati

  • COM: versione scritta nell'interfaccia ABI COM non elaborata (solo con WRL per gli helper COM)


Vedere anche

Interfacce C++ del modello di dati del debugger

Oggetti C++ del modello di dati del debugger

Interfacce aggiuntive del modello di dati del debugger C++

Concetti relativi al modello di dati del debugger C++

Scripting C++ del modello di dati del debugger