Condividi tramite


Panoramica del modello di dati del debugger C++

In questo argomento viene fornita una panoramica dell'uso delle interfacce C++ del modello di dati del 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 compilare 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++.

Interfacce C++ del Modello 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


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

Il modello di 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++) utilizzano informazioni dal debugger e producono informazioni accessibili dal debugger e altre estensioni. I costrutti scritti nelle API del modello di dati sono disponibili nell'analizzatore di espressioni più recente (dx) del debugger, nonché nelle estensioni JavaScript o nelle estensioni C++.

Per illustrare gli obiettivi del modello di dati del debugger, prendere in considerazione 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 debugger usa una maschera binaria e fornisce solo output di testo in modi non standard. L'output di testo è difficile da utilizzare, formattare o estendere e il layout è specifico per questo comando.

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

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

Questo comando usa un modello di dati standard che è individuabile, estendibile e componibile in modo uniforme.

Assegnare un nome logico alla spaziatura e all'estensione su oggetti specifici consente l'individuazione delle funzionalità di estensione del debugger.

Suggerimento

Poiché le interfacce oggetto C++ del modello di dati possono risultare prolisse, è consigliato implementare una libreria helper C++ completa per il modello di dati che utilizza completamente le eccezioni C++ e un paradigma di programmazione a template. 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 sottoposte a script, perché sono basate sul modello di dati. Per altre informazioni, vedere WinDbg - Data Model.

Screenshot della finestra di esplorazione del modello di dati che mostra processi e thread.

Vista architetturale del modello di dati

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

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

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

Modello a oggetti

Al centro del modello di dati del debugger è una rappresentazione uniforme dell'oggetto in cui tutto è un'istanza dell'interfaccia IModelObject. Anche se tale oggetto può rappresentare un valore intrinseco (ad esempio, un valore intero) o un'altra interfaccia del modello di dati, spesso rappresenta un oggetto dinamico, ovvero un dizionario di tuple chiave/valore/metadati e un set di concetti che descrivono comportamenti astratti.

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

  • Mostra un provider che fornisce informazioni al modello di oggetti
  • A sinistra viene visualizzato l'oggetto 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 oggetti con funzionalità come la possibilità di convertire in una stringa visualizzabile o di essere indicizzati.

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

Modello dei dati: una vista del consumatore

Il diagramma seguente 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 semantici vengono usati per inviare la richiesta al motore del debugger.

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

Modello di Dati: Vista del Produttore

Questo diagramma mostra una vista del produttore del modello di dati.

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

Diagramma che mostra l'architettura del modello di dati con IModelObject connesso ai consumer di codice NatVis, JavaScript e Native.

Responsabile del Modello Dati

Questo diagramma mostra il ruolo centrale svolto dal gestore di modelli di dati nella gestione degli oggetti.

  • Data Model Manager funge da registrar centrale per tutti gli oggetti.
  • A sinistra viene illustrato come vengono registrati elementi del debugger standard, ad esempio sessioni e processi.
  • Il blocco dello spazio dei nomi mostra l'elenco centrale delle registrazioni.
  • 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 tramite il gestore del modello di dati.

Riepilogo delle interfacce del modello di dati del debugger

Sono disponibili numerose interfacce C++ che comprendono parti diverse del modello di dati. Per affrontare queste interfacce in modo coerente e semplice, vengono suddivise per categoria generale. Le aree principali qui:

Modello a oggetti generale

Il primo e il set più importante di interfacce definiscono 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 di C#). Questa è l'interfaccia principale di interesse sia per gli utenti che per i produttori del modello di dati. Le altre interfacce sono meccanismi per l'accesso a diversi aspetti degli oggetti. Per questa categoria sono definite le interfacce seguenti:

Ponti 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 ed 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 mappano sia i tipi nativi ai punti di estensione sia i costrutti sintetici. Inoltre, è l'entità responsabile dell'incapsulamento (boxing) degli oggetti, ovvero la conversione di valori ordinali o stringhe in IModelObject.

Per questa categoria sono definite le interfacce seguenti:

Accesso generale a Data Model Manager

IDataModelManager / IDataModelManager2

Gestione script

IDataModelScriptManager

IDataModelScriptProviderEnumerator

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

Il sistema dei tipi sottostante e gli spazi di memoria del debugger sono dettagliatamente esposti per permettere l'uso da parte delle estensioni. Per questa categoria sono definite le interfacce seguenti:

Le interfacce host generali del 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 per lo scripting dell'host (debugger)

IDebugHostScriptHost

Creazione e utilizzo di script

Il modello di dati ha anche una nozione generale di cos'è uno script e come eseguirne il debug. È completamente possibile che un'estensione del debugger venga stabilita e definisci un bridge generale tra il modello di dati e un altro linguaggio dinamico (in genere un ambiente di scripting). Questo set di interfacce serve per realizzare questo scopo e anche per consentire a un'interfaccia utente del debugger di utilizzare questi script.

Per questa categoria sono definite le interfacce seguenti:

Interfacce generali degli script

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 a oggetti 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'eccezione C++ completa e un paradigma di programmazione dei modelli. L'uso di questa libreria consente un codice più conciso quando si utilizza o si estende il modello di dati ed è consigliabile.

Nella libreria di supporto ci sono due namespace importanti:

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

Debugger::DataModel::ProviderEx - Helper per l'estensione del modello di dati

Per altre informazioni sull'uso della libreria DbgModelClientEx, vedere il file leggimi in questo sito di 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 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 - Una versione sviluppata per la libreria client del modello di dati C++17

  • COM - versione scritta contro il COM ABI grezzo (solo con WRL per gli helper COM)


Vedere anche

Interfacce C++ del Modello 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