本主题概述如何使用调试器数据模型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 - 数据模型。
数据模型体系结构视图
下图汇总了调试器数据模型体系结构的主要元素。
- 在左侧,会显示 UI 元素,这些元素提供对对象的访问权限,并支持 LINQ 查询等功能。
- 关系图右侧是向调试器数据模型提供数据的组件。 这包括自定义 NatVis、JavaScript 和 C++ 调试器数据模型扩展。
显示数据模型体系结构的示意图,其中特定对象模型位于中央,提供程序位于右侧。
对象模型
调试器数据模型的中心是统一的对象表示形式,其中一切都是 IModelObject 接口的实例。 虽然此类对象可能表示内部函数(例如整数值)或其他数据模型接口,但它通常表示动态对象 - 键/值/元数据元组字典以及描述抽象行为的概念集。
此图显示 IModelObject 如何使用密钥库来存储提供程序可以创建、注册和操作的值。
- 它显示向对象模型提供信息的提供程序
- 左侧显示 IModelObject,这是用于操作对象的常见对象模型。
- 中心是用于存储和访问值的 密钥存储 。
- 在底部,它显示了支持具有功能的对象 的概念 ,例如能够转换为可显示字符串或编制索引。
数据模型:使用者视图
下图显示了数据模型的使用者视图。 在示例中, dx(Display Debugger 对象模型表达式) 命令用于查询信息。
- Dx 命令通过序列化程序与对象枚举接口进行通信。
- IDebugHost* 对象用于从调试器引擎收集信息。
- 表达式和语义计算器用于将请求发送到调试器引擎。
数据模型:生成者视图
此图显示了数据模型的生成者视图。
- NatVis 提供程序显示在左侧,使用 XML 来定义附加功能。
- JavaScript 提供程序可以利用 动态提供程序概念 来实时处理信息。
- 底部显示一个本机代码提供程序,该提供程序还可以定义其他功能。
数据模型管理器
此图显示了数据模型管理器在对象管理中扮演的核心角色。
- 数据模型管理器充当所有对象的中央注册机构。
- 左侧显示了注册会话和进程等标准调试器元素的方式。
- 命名空间块显示中央注册列表。
- 关系图右侧显示两个提供程序,一个用于顶部的 NatVis,另一个是底部的 C/C++ 扩展。
调试器数据模型接口摘要
有许多C++接口构成数据模型的不同部分。 为了以一致且简单的方式处理这些接口,它们按常规类别细分。 此处的主要区域:
常规对象模型
第一组也是最重要的一组接口定义了如何访问核心数据模型以及如何访问和操作对象。 IModelObject 是表示数据模型中每个对象的接口(非常类似于 C# 的对象)。 这是数据模型的使用者和生成者感兴趣的主要接口。 其他接口是用于访问对象的不同方面的机制。 为此类别定义了以下接口:
DbgEng 与数据模型之间的桥梁
主接口
IModelKeyReference / IModelKeyReference2
概念接口
IDynamicConceptProviderConcept
管理数据模型和扩展性
数据模型管理器是管理所有扩展性发生方式的核心组件。 它是一组表的中心存储库,这些表将本机类型映射到扩展点,并将合成构造映射到扩展点。 此外,它是负责对象装箱的实体(将序号值或字符串转换为 IModelObject 的实体)。
为此类别定义了以下接口:
常规数据模型管理器访问
IDataModelManager / IDataModelManager2
脚本管理
IDataModelScriptProviderEnumerator
访问调试器的类型系统和内存空间
调试器的基础类型系统和内存空间是详细公开的,供扩展使用。 为此类别定义了以下接口:
常规主机(调试器)接口
IDebugHostMemory / IDebugHostMemory2
IDebugHostEvaluator / IDebugHostEvaluator2
主机(调试器)类型系统接口
IDebugHostSymbol / IDebugHostSymbol2
IDebugHostType / IDebugHostType2
IDebugHostBaseClassIDebugHostPublic
主机(调试器)对脚本的支持
创作和使用脚本
数据模型还大致了解脚本是什么以及如何调试脚本。 调试器扩展完全有可能在数据模型和另一个动态语言(通常是脚本环境)之间定义一个通用桥。 这组接口是如何完成的,以及调试器 UI 如何使用此类脚本。
为此类别定义了以下接口:
常规脚本接口
IDataModelScriptTemplateEnumerator
脚本调试器接口
IDataModelScriptDebugStackFrame
IDataModelScriptDebugVariableSetEnumerator
IDataModelScriptDebugBreakpoint
IDataModelScriptDebugBreakpointEnumerator
使用 DbgModelClientEx 库
概述
数据模型的C++对象接口实现起来可能非常冗长。 尽管它们允许对数据模型进行全面操作,但需要实现多个小型接口来扩展数据模型(例如:为每一个新增的可动态提取属性实现 IModelPropertyAccessor 接口)。 除此之外,基于 HRESULT 的编程模型还添加了大量用于错误检查的锅炉板代码。
为了最大程度地减少其中一些工作,数据模型提供了完整的C++帮助程序库,该库使用完整的C++异常和模板编程范例。 使用此库可以在使用或扩展数据模型时提供更简洁的代码,建议使用。
帮助程序库中有两个重要的命名空间:
Debugger::D ataModel::ClientEx - 数据模型的使用帮助程序
Debugger::DataModel::ProviderEx - 数据模型扩展的辅助工具
有关使用 DbgModelClientEx 库的其他信息,请参阅此 github 站点上的自述文件:
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 示例
为了更好地了解使用数据模型编写调试器扩展的不同方法,此处提供了三个版本的数据模型 HelloWorld 扩展:
https://github.com/Microsoft/WinDbg-Samples/tree/master/DataModelHelloWorld
JavaScript - 用 JavaScript 编写的版本
C++17 - 针对数据模型编写的C++17 客户端库版本
COM - 针对原始 COM ABI 编写的版本(仅对 COM 辅助工具使用 WRL)