このトピックでは、デバッガー データ モデル C++ インターフェイスを使用してデバッガーの機能を拡張およびカスタマイズする方法の概要について説明します。
このトピックは、C++ からアクセスできるインターフェイス、C++ ベースのデバッガー拡張機能の構築に使用する方法、および C++ データ モデル拡張機能から他のデータ モデルコンストラクト (JavaScript や NatVis など) を使用する方法について説明するシリーズの一部です。
デバッガー データ モデル C++ インターフェイスの概要
デバッガー データ モデルは拡張可能なオブジェクト モデルであり、新しいデバッガー拡張機能 (JavaScript、NatVis、C++ を含む) がデバッガーからの情報を使用し、デバッガーやその他の拡張機能からアクセスできる情報を生成する方法の中心となります。 データ モデル API に書き込まれるコンストラクトは、デバッガーの新しい (dx) 式エバリュエーターおよび JavaScript 拡張機能または C++ 拡張機能から使用できます。
デバッガー データ モデルの目標を示すために、この従来のデバッガー コマンドを検討してください。
0: kd> !process 0 0
PROCESS ffffe0007e6a7780
SessionId: 1 Cid: 0f68 Peb: 7ff7cfe7a000 ParentCid: 0f34
DirBase: 1f7fb9000 ObjectTable: ffffc001cec82780 HandleCount: 34.
Image: echoapp.exe
...
デバッガー コマンドはバイナリ マスクを使用しており、標準以外の方法でテキストのみを出力します。 テキスト出力は使用、書式設定、または拡張が困難であり、レイアウトはこのコマンドに固有です。
これは、デバッガー データ モデル dx (デバッガー オブジェクト モデル式の表示) コマンドと対照的です。
dx @$cursession.Processes.Where(p => p.Threads.Count() > 5)
このコマンドは、検出可能で拡張可能で、均一な方法で構成できる標準データ モデルを使用します。
特定のオブジェクトに対して論理的に名前空間を設定し拡張することで、デバッガー拡張機能を発見することができます。
ヒント
C++ オブジェクトインターフェースが非常に詳細であるため、データモデル用の C++ ヘルパーライブラリを実装するには、C++ の例外処理とテンプレートプログラミングパラダイムを利用することが推奨されます。 詳細については、このトピック で後述する DbgModelClientEx ライブラリの使用 を参照してください。
データ モデルは、 WinDbg がほとんどのことを示す方法です。 新しい UI の多くの要素は、データ モデルを利用するため、クエリ、拡張、またはスクリプト化できます。 詳細については、「 WinDbg - データ モデル」を参照してください。
データ モデルのアーキテクチャ ビュー
次の図は、デバッガー データ モデル アーキテクチャの主要な要素をまとめたものです。
- 左側には、オブジェクトへのアクセスを提供し、LINQ クエリなどの機能をサポートする UI 要素が表示されます。
- 図の右側には、デバッガー データ モデルにデータを提供するコンポーネントがあります。 これには、カスタム NatVis、JavaScript、C++ デバッガー のデータ モデル拡張機能が含まれます。
オブジェクト モデル
デバッガー データ モデルの中心には、すべてが IModelObject インターフェイスのインスタンスである、統一されたオブジェクト表現があります。 このようなオブジェクトは、組み込み (整数値など) または別のデータ モデル インターフェイスを表す場合がありますが、多くの場合、動的オブジェクト (キー/値/メタデータタプルのディクショナリと、抽象動作を記述する概念のセット) を表します。
この図は、プロバイダーが作成、登録、操作できる値を IModelObject がキー ストアを使用して格納する方法を示しています。
- オブジェクト モデルに情報を提供する プロバイダーが表示されます
- 左側には、オブジェクトの操作に使用される一般的なオブジェクト モデルである IModelObject が表示されます。
- 中央には、値の格納とアクセスに使用される キー ストア があります。
- 下部には、表示可能な文字列に変換する機能やインデックスを作成する機能などの機能を持つオブジェクトをサポートする 概念 が表示されます。
データ モデル: コンシューマー ビュー
次の図は、データ モデルのコンシューマー ビューを示しています。 この例では、 dx (Display Debugger Object Model Expression) コマンドを使用して情報を照会しています。
- Dx コマンドは、シリアライザーを介してオブジェクト列挙インターフェイスと通信します。
- IDebugHost* オブジェクトは、デバッガー エンジンから情報を収集するために使用されます。
- 式エバリュエーターとセマンティック エバリュエーターは、デバッグ エンジンにリクエストを送信するために使用されます。
データ モデル: プロデューサー ビュー
この図は、データ モデルのプロデューサー ビューを示しています。
- 左側には、追加機能を定義する XML を使用する NatVis プロバイダーが表示されます。
- JavaScript プロバイダーでは、 動的プロバイダーの概念 を利用して、リアルタイムで情報を操作できます。
- 下部には、追加の機能を定義できるネイティブ コード プロバイダーが示されています。
データ モデル マネージャー
この図は、オブジェクトの管理においてデータ モデル マネージャーが果たす中心的な役割を示しています。
- データ モデル マネージャーは、すべてのオブジェクトの中央レジストラーとして機能します。
- 左側には、セッションやプロセスなどの標準デバッガー要素の登録方法が示されています。
- 名前空間ブロックには、中央登録リストが表示されます。
- 図の右側には、上部に NatVis 用と下部に C/C++ 拡張機能の 2 つのプロバイダーが示されています。
デバッガー データ モデル インターフェイスの概要
データ モデルのさまざまな部分を構成する多数の C++ インターフェイスがあります。 これらのインターフェイスに一貫性のある簡単な方法でアプローチするには、一般的なカテゴリ別に分類されます。 主な領域は次のとおりです。
一般オブジェクトモデル
インターフェイスの最初の最も重要なセットは、コア データ モデルにアクセスする方法と、オブジェクトにアクセスして操作する方法を定義します。 IModelObject は、データ モデル内のすべてのオブジェクト (C# のオブジェクトとよく似ています) を表すインターフェイスです。 これは、データ モデルに対するコンシューマーとプロデューサーの両方にとって関心のある主なインターフェイスです。 他のインターフェイスは、オブジェクトのさまざまな側面にアクセスするためのメカニズムです。 このカテゴリには、次のインターフェイスが定義されています。
DbgEng とデータ モデル間のブリッジ
IHostDataModelAccess の
メイン インターフェイス
IModelObject の
IKeyStore を
IModelIterator の
IModelPropertyAccessor の
IModelMethod の
IKeyEnumerator の
IRawEnumerator の
IModelKeyReference / IModelKeyReference2
概念インターフェイス
IStringDisplayableConcept の
IIterableConcept を
IIndexableConcept の
IPreferredRuntimeTypeConcept の
IDataModelConcept の
IDynamicKeyProviderConcept の
IDynamicConceptProviderConcept の
データ モデルと拡張性の管理
データ モデル マネージャーは、すべての拡張性の発生方法を管理するコア コンポーネントです。 これは、ネイティブ型を拡張ポイントにマップし、合成コンストラクトを拡張ポイントにマップする一連のテーブルの中央リポジトリです。 さらに、オブジェクトのボックス化 (序数値または文字列の IModelObject への変換) を担当するエンティティです。
このカテゴリには、次のインターフェイスが定義されています。
一般的なデータ モデル マネージャー のアクセス
IDataModelManager / IDataModelManager2
スクリプト管理
IDataModelScriptManager の
IDataModelScriptProviderEnumerator の
デバッガーの型システムとメモリスペースへのアクセス
デバッガーの基になる型システムとメモリ空間は、拡張機能を利用するために詳細に公開されます。 このカテゴリには、次のインターフェイスが定義されています。
一般的なホスト (デバッガー) インターフェイス
IDebugHost の
IDebugHostStatus の
IDebugHostContext の
IDebugHostMemory / IDebugHostMemory2
IDebugHostErrorSink の
IDebugHostEvaluator / IDebugHostEvaluator2
IDebugHostExtensibility の
ホスト (デバッガー) 型のシステム インターフェイス
IDebugHostSymbol / IDebugHostSymbol2
IDebugHostModule の
IDebugHostType / IDebugHostType2
IDebugHostConstant の
IDebugHostField の
IDebugHostData の
IDebugHostBaseClassIDebugHostPublic
IDebugHostModuleSignature の
IDebugHostTypeSignature の
スクリプトのホスト (デバッガー) のサポート
IDebugHostScriptHost の
スクリプトの作成と使用
データ モデルには、スクリプトとは何か、およびスクリプトをデバッグする方法についての一般的な概念もあります。 デバッガー拡張機能が一緒に来て、データ モデルと別の動的言語 (通常はスクリプト環境) の間の一般的なブリッジを定義することは完全に可能です。 この一連のインターフェイスは、これを実現する方法と、デバッガー UI でこのようなスクリプトを使用する方法です。
このカテゴリには、次のインターフェイスが定義されています。
一般的なスクリプト インターフェイス
IDataModelScriptProvider の
IDataModelScript の
IDataModelScriptClient の
IDataModelScriptHostContext の
IDataModelScriptTemplate の
IDataModelScriptTemplateEnumerator の
IDataModelNameBinder の
スクリプト デバッガー インターフェイス
IDataModelScriptDebug の
IDataModelScriptDebugClient の
IDataModelScriptDebugStack の
IDataModelScriptDebugStackFrame の
IDataModelScriptDebugVariableSetEnumerator の
IDataModelScriptDebugBreakpoint の
IDataModelScriptDebugBreakpointEnumerator の
DbgModelClientEx ライブラリの使用
概要
データ モデルへのデータ モデル C++ オブジェクト インターフェイスは、実装に非常に詳細な場合があります。 データ モデルを完全に操作できる一方で、データ モデルを拡張するには多数の小さなインターフェイスを実装する必要があります (たとえば、追加される動的フェッチ可能なプロパティごとに IModelPropertyAccessor の実装)。 これに加えて、HRESULT ベースのプログラミング モデルでは、エラー チェックに使用されるボイラー プレート コードが大量に追加されます。
この作業の一部を最小限に抑えるために、完全な C++ 例外とテンプレート プログラミング パラダイムを使用するデータ モデル用の完全な C++ ヘルパー ライブラリがあります。 このライブラリを使用すると、データ モデルを使用または拡張するときに、より簡潔なコードが可能になり、推奨されます。
ヘルパー ライブラリには、次の 2 つの重要な名前空間があります。
Debugger::DataModel::ClientEx - データモデルを使用するためのヘルパー
Debugger::DataModel::ProviderEx - データ モデルの拡張のためのヘルパー
DbgModelClientEx ライブラリの使用方法の詳細については、この github サイトの readme ファイルを参照してください。
https://github.com/Microsoft/WinDbg-Libraries/tree/master/DbgModelCppLib
HelloWorld C++ サンプル
DbgModelClientEx ライブラリを使用する方法については、ここでデータ モデル HelloWorld C++ サンプルを確認してください。
https://github.com/Microsoft/WinDbg-Samples/tree/master/DataModelHelloWorld
サンプルには次のものが含まれます。
HelloProvider.cpp - これは、プロセスのデバッガーの概念に新しいサンプル プロパティ "Hello" を追加するプロバイダー クラスの実装です。
SimpleIntroExtension.cpp - これは、新しいサンプル プロパティ "Hello" をデバッガーのプロセスの概念に追加する単純なデバッガー拡張機能です。 この拡張機能は、データ モデル C++17 ヘルパー ライブラリに対して記述されます。 必要な接着コードの量 (および複雑さ) のため、生の COM ABI ではなく、このライブラリに対して拡張機能を記述することをお勧めします。
JavaScript と COM のサンプル
データ モデルを使用してデバッガー拡張機能を記述するさまざまな方法をよりよく理解するために、ここでは 3 つのバージョンのデータ モデル HelloWorld 拡張機能を使用できます。
https://github.com/Microsoft/WinDbg-Samples/tree/master/DataModelHelloWorld
JavaScript - JavaScript で記述されたバージョン
C++17 - データ モデル C++17 クライアント ライブラリに対して記述されたバージョン
COM - 生の COM ABI に対して記述されたバージョン (COM ヘルパーに WRL のみを使用)