调试器数据模型 C++ 接口
本主题提供并概述如何使用调试器数据模型 C++ 接口来扩展和自定义调试器的功能。
调试器数据模型 C++ 主机接口
调试器数据模型主机
调试器数据模型设计为可托管在各种不同的上下文中的组件化系统。 通常,数据模型托管在调试器应用程序的上下文中。 为了成为数据模型的主机,需要实现许多接口来公开调试器的核心方面:其目标、内存空间、计算器、符号和类型系统等...虽然这些接口由任何希望托管数据模型的应用程序实现,但它们由核心数据模型以及与数据模型互操作的任何扩展使用。
核心接口集包括:
接口名称 | 说明 |
---|---|
IDebugHost | 调试主机的核心接口。 |
IDebugHostStatus | 允许客户端查询主机状态的接口。 |
IDebugHostContext | 主机中上下文的抽象 (例如:特定目标、特定进程、特定地址空间等...) |
IDebugHostErrorSink | 调用方实现的接口,用于从主机和数据模型的某些部分接收错误 |
IDebugHostEvaluator / IDebugHostEvaluator2 | 调试主机的表达式计算器。 |
IDebugHostExtensibility | 一个接口,用于扩展主机的功能或其部分 (,例如表达式计算器) 。 |
类型系统和符号接口包括:
InterfaceName | 说明 |
---|---|
IDebugHostSymbols | 提供对符号的访问和解析的核心接口 |
IDebugHostSymbol / IDebugHostSymbol2 | 表示任何类型的单个符号。 特定符号是此接口的派生。 |
IDebugHostModule | 表示在进程中加载的模块。 这是一种符号。 |
IDebugHostType / IDebugHostType2 | 表示本机/语言类型。 |
IDebugHostConstant | 表示符号信息 (中的常量,例如:C++ 中的非类型模板参数) |
IDebugHostField | 表示结构或类中的字段。 |
IDebugHostData | 表示模块中的数据 (如果此数据位于结构或类中,则为 IDebugHostField) |
IDebugHostBaseClass | 表示基类。 |
IDebugHostPublic | 表示 PDB 的公共表内的符号。 这没有与之关联的类型信息。 它是名称和地址。 |
IDebugHostModuleSignature | 表示模块签名 -- 将按名称和/或版本匹配一组模块的定义 |
IDebugHostTypeSignature | 表示类型签名 -- 将按模块和/或名称匹配一组类型的定义 |
核心主机接口:IDebugHost
IDebugHost 接口是任何数据模型主机的核心接口。 它的定义如下:
DECLARE_INTERFACE_(IDebugHost, IUnknown)
{
STDMETHOD(GetHostDefinedInterface)(_COM_Outptr_ IUnknown** hostUnk) PURE;
STDMETHOD(GetCurrentContext)(_COM_Outptr_ IDebugHostContext** context) PURE;
STDMETHOD(GetDefaultMetadata)(_COM_Outptr_ IKeyStore** defaultMetadataStore) PURE;
}
GetHostDefinedInterface 方法返回主机的main专用接口(如果给定主机存在)。 对于 Windows 调试工具,此处返回的接口是 IDebugClient (强制转换为 IUnknown) 。
GetCurrentContext 方法返回一个接口,该接口表示调试器主机的当前状态。 具体含义由主机决定,但它通常包括会话、进程和调试主机用户界面中处于活动状态的地址空间等内容。 返回的上下文对象对调用方来说基本上是不透明的,但它是在对调试主机的调用之间传递的重要对象。 例如,当调用方正在读取内存时,必须知道从哪个进程和地址空间读取内存。 该概念封装在从此方法返回的上下文对象的概念中。
GetDefaultMetadata 方法返回一个默认元数据存储区,该存储区可用于某些操作 (例如:未传递显式元数据时字符串转换) 。 这样,调试主机就可以对某些数据的显示方式进行某种控制。 例如,默认元数据可能包含 PreferredRadix 键,使主机能够指示在未指定的情况下,是应以十进制还是十六进制显示序号。
请注意,默认元数据存储中的属性值必须手动解析,并且必须传递要为其查询默认元数据的对象。 应使用 GetKey 方法代替 GetKeyValue。
状态接口:IDebugHostStatus
IDebugHostStatus 接口允许数据模型或调试主机的客户端查询调试主机状态的某些方面。 接口定义如下:
DECLARE_INTERFACE_(IDebugHostStatus, IUnknown)
{
STDMETHOD(PollUserInterrupt)(_Out_ bool* interruptRequested) PURE;
}
PollUserInterrupt 方法用于查询调试主机的用户是否已请求中断当前操作。 例如,数据模型中的属性访问器可以调用任意代码 (例如:javaScript 方法) 。 该代码可能需要任意时间。 为了使调试主机保持响应,任何可能需要任意时间的此类代码都应通过调用此方法检查中断请求。 如果 interruptRequested 值返回为 true,则调用方应立即中止并返回E_ABORT的结果。
上下文接口:IDebugHostContext
上下文是数据模型和基础调试主机最重要的方面之一。 当你持有对象时,必须能够知道对象来自何处--它所在的进程,它与哪个地址空间相关联。 了解此信息可以正确解释指针值等内容。 必须将 IDebugHostContext 类型的对象传递给调试主机上的许多方法。 可以通过多种方式获取此接口:
- 通过获取调试器的当前上下文:调用 IDebugHost 的 GetCurrentContext 方法
- 通过获取对象的上下文:调用 IModelObject 的 GetContext 方法
- 通过获取符号的上下文:调用 IDebugHostSymbol 的 GetContext 方法
此外,还有两个值在 IDebugHostContext 接口的上下文中具有特殊含义,这些接口从数据模型或调试主机方法返回或传递给该接口:
nullptr:指示没有上下文。 对于某些对象来说,没有上下文是完全有效的。 数据模型的根命名空间中的 Debugger 对象不引用特定进程或地址空间中的任何内容。 它没有上下文。
USE_CURRENT_HOST_CONTEXT:一个 sentinel 值,指示应使用调试主机的当前 UI 上下文。 此值永远不会从调试主机返回。 但是,它可以传递给任何采用输入 IDebugHostContext 的调试主机方法,而不是显式调用 IDebugHost 的 GetCurrentContext 方法。 请注意,显式传递USE_CURRENT_HOST_CONTEXT通常比显式获取当前上下文的性能更高。
主机上下文的上下文对调用方而言基本上是不透明的。 核心调试主机外部的调用方可以对主机上下文执行的唯一操作是将其与其他主机上下文进行比较。
IDebugHostContext 接口定义如下:
DECLARE_INTERFACE_(IDebugHostContext, IUnknown)
{
STDMETHOD(IsEqualTo)(_In_ IDebugHostContext *pContext, _Out_ bool *pIsEqual) PURE;
}
IsEqualTo 方法将主机上下文与另一个主机上下文进行比较。 如果两个上下文是等效的,则返回此指示。 请注意,此比较不是接口等效性。 这会比较上下文本身的基础不透明内容。
错误接收器: IDebugHostErrorSink
IDebugHostErrorSink 是客户端接收某些操作期间发生的错误的通知,并在需要时路由这些错误的方法。 接口定义如下:
enum ErrorClass
{
ErrorClassWarning,
ErrorClassError
}
DECLARE_INTERFACE_(IDebugHostErrorSink, IUnknown)
{
STDMETHOD(ReportError)(_In_ ErrorClass errClass, _In_ HRESULT hrError, _In_ PCWSTR message) PURE;
}
ReportError 方法是对错误接收器的回调,用于通知错误已发生,并允许接收器将错误路由到任何合适的 UI 或机制。
主机计算器:IDebugHostEvaluator/IDebugHostEvaluator2
调试主机向客户端提供的最重要功能之一是访问其基于语言的表达式计算器。 IDebugHostEvaluator 和 IDebugHostEvaluator2 接口是从调试主机访问该功能的方法。
接口定义如下:
DECLARE_INTERFACE_(IDebugHostEvaluator2, IDebugHostEvaluator)
{
//
// IDebugHostEvaluator:
//
STDMETHOD(EvaluateExpression)(_In_ IDebugHostContext* context, _In_ PCWSTR expression, _In_opt_ IModelObject* bindingContext, _COM_Errorptr_ IModelObject** result, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
STDMETHOD(EvaluateExtendedExpression)(_In_ IDebugHostContext* context, _In_ PCWSTR expression, _In_opt_ IModelObject* bindingContext, _COM_Errorptr_ IModelObject** result, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
//
// IDebugHostEvaluator2:
//
STDMETHOD(AssignTo)(_In_ IModelObject* assignmentReference, _In_ IModelObject* assignmentValue, _COM_Errorptr_ IModelObject** assignmentResult, _COM_Outptr_opt_result_maybenull_ IKeyStore** assignmentMetadata) PURE;
}
EvaluateExpression 方法允许请求调试主机计算语言 (例如:C++) 表达式,并返回该表达式计算的结果值(装箱为 IModelObject)。 方法的此特定变体仅允许语言构造。 调试主机的表达式计算器中呈现的、语言 (中不存在的任何其他功能,例如:) 的 LINQ 查询方法已关闭用于计算。
EvaluateExtendedExpression 方法类似于 EvaluateExpression 方法,只不过它重新启用特定调试主机选择添加到其表达式计算器的其他非语言功能。 例如,对于 Windows 调试工具,这将启用匿名类型、LINQ 查询、模块限定符、格式说明符和其他非 C/C++ 功能。
IDebugHostEvaluator2
AssignTo 方法根据所调试语言的语义执行赋值。
主机扩展性接口:IDebugHostExtensibility
调试主机的某些功能(可选)受扩展性的约束。 例如,这可能包括表达式计算器。 IDebugHostExtensibility 接口是访问这些扩展点的方式。 接口定义如下:
DECLARE_INTERFACE_(IDebugHostExtensibility, IUnknown)
{
STDMETHOD(CreateFunctionAlias)(_In_ PCWSTR aliasName, _In_ IModelObject *functionObject) PURE;
STDMETHOD(DestroyFunctionAlias)(_In_ PCWSTR aliasName) PURE;
}
CreateFunctionAlias 方法创建“函数别名”,即在某些扩展中实现的方法的“快速别名”。 此别名的含义特定于主机。 它可能会使用 函数扩展主机的表达式计算器,也可以执行完全不同的操作。
DestroyFunctionAlias 方法撤消先前对 CreateFunctionAlias 方法的调用。 该函数将不再在快速别名下可用。
访问数据模型
首先,数据模型扩展性 API 设计为对应用程序 (通常是充当数据模型的主机的调试器) 。 从理论上讲,任何应用程序都可以通过提供一组主机 API 来托管数据模型,这些 API 公开应用程序的调试目标的类型系统 () 和一组投影对象到数据模型的命名空间中,了解目标、进程、线程等...位于这些调试目标 () 中。
虽然数据模型 API(以 IDataModel、IDebugHost 和 IModelObject 的分支开头的 API)设计为可移植,但它们不定义什么是“调试器扩展”。 目前,希望扩展 Windows 调试工具的组件及其提供的引擎必须编写引擎扩展才能访问数据模型。 该引擎扩展只需是引擎扩展,就像扩展的加载和引导机制一样。 因此,最小实现将提供:
- DebugExtensionInitialize:一种利用创建的 IDebugClient 来访问数据模型并设置对象模型操作的方法。
- DebugExtensionUninitialize:一种撤消在 DebugExtensionInitialize 中执行的对象模型操作的方法。
- DebugExtensionCanUnload:返回扩展是否可以卸载的方法。 如果扩展中仍有实时 COM 对象,则必须指示这一点。 这是调试器相当于 COM 的 DllCanUnloadNow。 如果这会返回无法卸载的S_FALSE指示,则调试器稍后可以查询此卸载是否安全,或者它可能通过再次调用 DebugExtensionInitialize 重新初始化扩展。 扩展必须准备好处理这两个路径。
- DebugExtensionUnload:在 DLL 卸载之前执行所需的任何最终清理的方法
Bridge 接口:IHostDataModelAccess
如前所述,调用 DebugExtensionInitialize 时,它会创建调试客户端并获取对数据模型的访问权限。 此类访问由 Windows 调试工具的旧 IDebug* 接口和数据模型之间的桥接接口提供。 此桥接口为“IHostDataModelAccess”,定义如下:
DECLARE_INTERFACE_(IHostDataModelAccess, IUnknown)
{
STDMETHOD(GetDataModel)(_COM_Outptr_ IDataModelManager** manager, _COM_Outptr_ IDebugHost** host) PURE;
}
GetDataModel 方法是桥接口上的方法,该方法提供对数据模型的两端的访问:调试主机 (调试器) 的下边缘由返回的 IDebugHost 接口表示。数据模型的main组件 - 数据模型管理器由返回的 IDataModelManager 接口表示
调试器数据模型系统接口
数据模型主机
调试器数据模型设计为可托管在各种不同的上下文中的组件化系统。 通常,数据模型托管在调试器应用程序的上下文中。 为了成为数据模型的主机,需要实现许多接口来公开调试器的核心方面:其目标、内存空间、计算器、符号和类型系统等...虽然这些接口由任何希望托管数据模型的应用程序实现,但它们由核心数据模型以及与数据模型互操作的任何扩展使用。
类型系统和符号接口包括:
接口名称 | 说明 |
---|---|
IDebugHostSymbols | 提供对符号的访问和解析的核心接口 |
IDebugHostSymbol / IDebugHostSymbol2 | 表示任何类型的单个符号。 特定符号是此接口的派生。 |
IDebugHostModule | 表示在进程中加载的模块。 这是一种符号。 |
IDebugHostType / IDebugHostType2 | 表示本机/语言类型。 |
IDebugHostConstant | 表示符号信息 (中的常量,例如:C++ 中的非类型模板参数) |
IDebugHostField | 表示结构或类中的字段。 |
IDebugHostData | 表示模块中的数据 (如果此数据位于结构或类中,则为 IDebugHostField) |
IDebugHostBaseClass | 表示基类。 |
IDebugHostPublic | 表示 PDB 的公共表内的符号。 这没有与之关联的类型信息。 它是名称和地址。 |
IDebugHostModuleSignature | 表示模块签名 -- 将按名称和/或版本匹配一组模块的定义 |
IDebugHostTypeSignature | 表示类型签名 -- 将按模块和/或名称匹配一组类型的定义 |
其他核心接口包括:
接口名称 | 说明 |
---|---|
IDebugHost | 调试主机的核心接口。 |
IDebugHostStatus | 允许客户端查询主机状态的接口。 |
IDebugHostContext | 主机中上下文的抽象 (例如:特定目标、特定进程、特定地址空间等...) |
IDebugHostErrorSink | 调用方实现的接口,用于接收来自主机和数据模型某些部分的错误 |
IDebugHostEvaluator / IDebugHostEvaluator2 | 调试主机的表达式计算器。 |
IDebugHostExtensibility | 一个接口,用于扩展主机或其部分的功能 (,例如表达式计算器) 。 |
主符号接口:IDebugHostSymbols
IDebugHostSymbols 接口是访问调试目标中的符号main起点。 可以从 IDebugHost 实例查询此接口,定义如下:
DECLARE_INTERFACE_(IDebugHostSymbols, IUnknown)
{
STDMETHOD(CreateModuleSignature)(_In_z_ PCWSTR pwszModuleName, _In_opt_z_ PCWSTR pwszMinVersion, _In_opt_z_ PCWSTR pwszMaxVersion, _Out_ IDebugHostModuleSignature** ppModuleSignature) PURE;
STDMETHOD(CreateTypeSignature)(_In_z_ PCWSTR signatureSpecification, _In_opt_ IDebugHostModule* module, _Out_ IDebugHostTypeSignature** typeSignature) PURE;
STDMETHOD(CreateTypeSignatureForModuleRange)(_In_z_ PCWSTR signatureSpecification, _In_z_ PCWSTR moduleName, _In_opt_z_ PCWSTR minVersion, _In_opt_z_ PCWSTR maxVersion, _Out_ IDebugHostTypeSignature** typeSignature) PURE;
STDMETHOD(EnumerateModules)(_In_ IDebugHostContext* context, _COM_Outptr_ IDebugHostSymbolEnumerator** moduleEnum) PURE;
STDMETHOD(FindModuleByName)(_In_ IDebugHostContext* context, _In_z_ PCWSTR moduleName, _COM_Outptr_ IDebugHostModule **module) PURE;
STDMETHOD(FindModuleByLocation)(_In_ IDebugHostContext* context, _In_ Location moduleLocation, _COM_Outptr_ IDebugHostModule **module) PURE;
STDMETHOD(GetMostDerivedObject)(_In_opt_ IDebugHostContext *pContext, _In_ Location location, _In_ IDebugHostType* objectType, _Out_ Location* derivedLocation, _Out_ IDebugHostType** derivedType) PURE;
}
CreateModuleSignature 方法创建一个签名,该签名可用于按名称和版本(可选)匹配一组特定模块。 模块签名有三个组件:
- 名称:匹配模块的名称必须与签名中的名称完全不区分大小写
- 最低版本:如果指定,匹配的模块必须具有至少与此版本一样高的最低版本。 版本以“A.B.C.D”格式指定,每个后续部分都不像之前部分那么重要。 只有第一个段是必需的。
- 最大版本:如果指定,匹配的模块必须具有不高于此版本的最大版本。 版本以“A.B.C.D”格式指定,每个后续部分都不像之前部分那么重要。 只有第一个段是必需的。
CreateTypeSignature 方法创建一个签名,该签名可用于通过包含模块和类型名称来匹配一组具体类型。 类型名称签名字符串的格式特定于正在调试 (和调试主机) 的语言。 对于 C/C++,签名字符串等效于 NatVis 类型规范。 也就是说,签名字符串是一种类型名称,其中 (指定为 *) 的通配符可用于模板参数。
CreateTypeSignatureForModuleRange
CreateTypeSignatureForModuleRange 方法创建一个签名,该签名可用于按模块签名和类型名称匹配一组具体类型。 这类似于 CreateTypeSignature 方法,不同之处在于调用方传递创建模块签名所需的参数,而不是传递特定模块以匹配签名 (就好像模块签名是使用 CreateModuleSignature 方法) 创建的。
EnumerateModules 方法创建枚举器,该枚举器将枚举特定主机上下文中可用的每个模块。 该主机上下文可能封装进程上下文,也可能封装类似 Windows 内核的内容。
FindModuleByName 方法将查看给定的主机上下文,并找到具有指定名称的模块,并返回一个接口。 使用或不带文件扩展名按名称搜索模块是合法的。
FindModuleByLocation 方法将查看给定的主机上下文,并确定哪个模块包含指定位置提供的地址。 然后,它会将接口返回到此类模块。
GetMostDerivedObject 将使用调试器的类型系统从其静态类型确定对象的运行时类型。 此方法将仅使用类型系统层中提供的符号信息和启发法来执行此分析。 此类信息可能包括 C++ RTTI (运行时类型信息,) 或分析对象的虚拟函数表的形状。 它不包括 IModelObject 上的首选运行时类型概念等内容。 如果分析找不到运行时类型或找不到不同于传递到 方法的静态类型的运行时类型,则可能会传递输入位置和类型。方法不会因为这些原因而失败。
核心单个符号接口:IDebugHostSymbol
可从数据模型主机返回的每个符号都将以某种方式从 IDebugHostSymbol 派生。 这是每个符号实现的核心接口,无论符号的类型如何。 根据符号类型,给定符号可以实现一组其他接口,这些接口返回此接口所表示的特定符号类型更独特的属性。 IDebugHostSymbol2 /IDebugHostSymbol 接口定义如下:
DECLARE_INTERFACE_(IDebugHostSymbol2, IDebugHostSymbol)
{
//
// IDebugHostSymbol:
//
STDMETHOD(GetContext)(_COM_Outptr_ IDebugHostContext** context) PURE;
STDMETHOD(EnumerateChildren)(_In_ SymbolKind kind, _In_opt_z_ PCWSTR name, _Out_ IDebugHostSymbolEnumerator **ppEnum) PURE;
STDMETHOD(GetSymbolKind)(_Out_ SymbolKind *kind) PURE;
STDMETHOD(GetName)(_Out_ BSTR* symbolName) PURE;
STDMETHOD(GetType)(_Out_ IDebugHostType** type) PURE;
STDMETHOD(GetContainingModule)(_Out_ IDebugHostModule **containingModule) PURE;
STDMETHOD(CompareAgainst)(_In_ IDebugHostSymbol *pComparisonSymbol, _In_ ULONG comparisonFlags, _Out_ bool *pMatches) PURE;
//
// IDebugHostSymbol2
//
STDMETHOD(EnumerateChildrenEx)(_In_ SymbolKind kind, _In_opt_z_ PCWSTR name, _In_opt_ SymbolSearchInfo* searchInfo, _Out_ IDebugHostSymbolEnumerator **ppEnum) PURE;
}
请务必注意,此接口表示多种符号 -- 由 SymbolKind 枚举描述,其值如下所示:
Enumarant | 含义 |
---|---|
符号 | 未指定的符号类型 |
SymbolModule | 符号是一个模块,可以查询 IDebugHostModule |
SymbolType | 符号是一种类型,可以查询 IDebugHostType |
SymbolField | 符号是结构或类) 中的数据成员 (字段,可查询 IDebugHostField |
SymbolConstant | 符号是一个常量值,可查询 IDebugHostConstant |
SymbolData | 符号是非结构或类成员且可查询 IDebugHostData 的数据 |
SymbolBaseClass | 符号是基类,可查询 IDebugHostBaseClass |
SymbolPublic | 符号是模块的公共表中的条目, (没有) 类型信息,并且可查询 IDebugHostPublic |
SymbolFunction | 符号是一个函数,可查询 IDebugHostData |
GetContext 方法返回符号有效的上下文。 虽然这将表示符号所在的调试目标和进程/地址空间等内容,但它可能不像从其他方式检索 (上下文那样具体,例如:从 IModelObject) 。
EnumerateChildren 方法返回枚举器,该枚举器将枚举给定符号的所有子级。 例如,对于 C++ 类型,基类、字段、成员函数等都被视为类型符号的子级。
模块接口:IDebugHostModule
调试器对在某些地址空间中加载的模块的概念在数据模型中以两种不同的方式表示:在类型系统级别,通过 IDebugHostModule 接口。 在这里,模块是一个符号,模块的核心属性是接口方法调用,通过 Debugger.Models.Module 数据模型在数据模型级别投影。 这是模块的类型系统 IDebugHostModule 表示形式的可扩展封装。
IDebugHostModule 接口定义如下, (忽略 IDebugHostSymbol) 通用的方法:
DECLARE_INTERFACE_(IDebugHostModule, IDebugHostSymbol)
{
//
// IDebugHostModule:
//
STDMETHOD(GetImageName)(_In_ bool allowPath, _Out_ BSTR* imageName) PURE;
STDMETHOD(GetBaseLocation)(_Out_ Location* moduleBaseLocation) PURE;
STDMETHOD(GetVersion)(_Out_opt_ ULONG64* fileVersion, _Out_opt_ ULONG64* productVersion) PURE;
STDMETHOD(FindTypeByName)(_In_z_ PCWSTR typeName, _Out_ IDebugHostType** type) PURE;
STDMETHOD(FindSymbolByRVA)(_In_ ULONG64 rva, _Out_ IDebugHostSymbol** symbol) PURE;
STDMETHOD(FindSymbolByName)(_In_z_ PCWSTR symbolName, _Out_ IDebugHostSymbol** symbol) PURE;
}
GetImageName 方法返回模块的图像名称。 根据 allowPath 参数的值,返回的图像名称可能包含也可能不包含图像的完整路径。
GetBaseLocation 方法将模块的基本加载地址作为位置结构返回。 模块返回的位置结构通常引用虚拟地址。
GetVersion 方法返回有关模块 (的版本信息,前提是此类信息可以成功从) 标头中读出。 如果通过非 nullptr 输出指针) 请求 (给定版本,并且无法读取该版本,则将从方法调用返回相应的错误代码。
FindTypeByName 方法查找模块中按类型名称定义的类型,并为其返回类型符号。 此方法可能会返回有效的 IDebugHostType,该类型永远不会通过模块子级的显式递归返回。 调试主机可能允许创建派生类型 -- 类型从未在模块本身中使用过,但派生自的类型。 例如,如果结构 MyStruct 在模块的符号中定义,但从未使用 MyStruct ** 类型,则 FindTypeByName 方法可能会合法地返回 MyStruct ** 的类型符号,尽管该类型名称从未显式出现在模块的符号中。
FindSymbolByRVA 方法将在模块中给定的相对虚拟地址处查找单个匹配符号。 如果提供的 RVA (没有单个符号,例如:) 有多个匹配项,则此方法将返回错误。 请注意,此方法更倾向于返回私有符号,而不是 publics 表中的符号。
FindSymbolByName 方法将在模块中查找给定名称的单个全局符号。 如果没有与给定名称匹配的单个符号,此方法将返回错误。 请注意,此方法更倾向于返回私有符号,而不是 publics 表中的符号。
访问类型系统:IDebugHostType2 /IDebugHostType
给定的语言/本机类型由 IDebugHostType2 或 IDebugHostType 接口描述。 请注意,这些接口上的某些方法仅适用于特定类型的类型。 给定的类型符号可以引用 TypeKind 枚举所述的以下类型之一:
类型类型 | 说明 |
---|---|
TypeUDT | 用户定义的类型 (结构、类、联合等...) 。具有类型为 TypeUDT 的本机类型的模型对象具有 ObjectTargetObject 的规范表示形式,其中类型始终保留在相应的 IModelObject 中。 |
TypePointer | 指针。 具有类型为 TypePointer 的本机类型的模型对象具有 ObjectIntrinsic 的规范表示形式,其中指针的值为零扩展到VT_UI8,并保留为 64 位形式的内部数据。 TypePointer 的任何类型符号都具有由 GetBaseType 方法返回的基类型 () 指针指向的类型。 |
TypeMemberPointer | 指向类成员的指针。 具有类型为 TypeMemberPointer 的本机类型的模型对象具有规范表示形式,该规范表示形式是内部 (值与指针值) 相同。 此值的确切含义是特定于编译器/调试主机的。 |
TypeArray | 一个数组。 具有类型为 TypeArray 的本机类型的模型对象具有 ObjectTargetObject 的规范表示形式。 数组的基址是对象的位置, (通过 GetLocation 方法检索) 并且始终保留数组的类型。 TypeArray 的任何类型符号都具有由 getBaseType 方法返回的基类型 () 数组所返回的类型。 |
TypeFunction | 函数。 |
TypeTypedef | typedef。 具有本机类型的模型对象,其类型为 TypeTypedef,其规范表示形式与 typedef 基础的最终类型的规范表示形式相同。 除非使用 IDebugHostType2 的显式 typedef 方法查询 typedef 信息,或者存在针对 typedef 注册的显式数据模型,否则这看起来对对象和类型信息的最终用户完全透明。 请注意,GetTypeKind 方法永远不会返回 TypeTypedef。 每个方法都将返回 typedef 将返回的最终类型。 IDebugHostType2 上有特定于 typedef 的方法,可用于获取 typedef 特定信息。 |
TypeEnum | 枚举。 具有类型为 TypeEnum 的本机类型的模型对象具有 ObjectIntrinsic 的规范表示形式,其中内部函数的值和类型与枚举值相同。 |
TypeIntrinsic | 内部 (基类型) 。 具有类型为 TypeIntrinsic 的本机类型的模型对象具有 ObjectIntrinsic 的规范表示形式。 类型信息可能保留,也可能不保留 -- 特别是当基础类型由存储在 IModelObject 中的内部数据的变体数据类型 (VT_*) 完全描述时 |
整体 IDebugHostType2/IDebugHostType 接口定义如下 (不包括 IDebugHostSymbol 方法) :
DECLARE_INTERFACE_(IDebugHostType2, IDebugHostType)
{
//
// IDebugHostType:
//
STDMETHOD(GetTypeKind)(_Out_ TypeKind *kind) PURE;
STDMETHOD(GetSize)(_Out_ ULONG64* size) PURE;
STDMETHOD(GetBaseType)(_Out_ IDebugHostType** baseType) PURE;
STDMETHOD(GetHashCode)(_Out_ ULONG* hashCode) PURE;
STDMETHOD(GetIntrinsicType)(_Out_opt_ IntrinsicKind *intrinsicKind, _Out_opt_ VARTYPE *carrierType) PURE;
STDMETHOD(GetBitField)(_Out_ ULONG* lsbOfField, _Out_ ULONG* lengthOfField) PURE;
STDMETHOD(GetPointerKind)(_Out_ PointerKind* pointerKind) PURE;
STDMETHOD(GetMemberType)(_Out_ IDebugHostType** memberType) PURE;
STDMETHOD(CreatePointerTo)(_In_ PointerKind kind, _COM_Outptr_ IDebugHostType** newType) PURE;
STDMETHOD(GetArrayDimensionality)(_Out_ ULONG64* arrayDimensionality) PURE;
STDMETHOD(GetArrayDimensions)(_In_ ULONG64 dimensions, _Out_writes_(dimensions) ArrayDimension *pDimensions) PURE;
STDMETHOD(CreateArrayOf)(_In_ ULONG64 dimensions, _In_reads_(dimensions) ArrayDimension *pDimensions, _COM_Outptr_ IDebugHostType** newType) PURE;
STDMETHOD(GetFunctionCallingConvention)(_Out_ CallingConventionKind* conventionKind) PURE;
STDMETHOD(GetFunctionReturnType)(_COM_Outptr_ IDebugHostType** returnType) PURE;
STDMETHOD(GetFunctionParameterTypeCount)(_Out_ ULONG64* count) PURE;
STDMETHOD(GetFunctionParameterTypeAt)(_In_ ULONG64 i, _Out_ IDebugHostType** parameterType) PURE;
STDMETHOD(IsGeneric)(_Out_ bool* isGeneric) PURE;
STDMETHOD(GetGenericArgumentCount)(_Out_ ULONG64* argCount) PURE;
STDMETHOD(GetGenericArgumentAt)(_In_ ULONG64 i, _Out_ IDebugHostSymbol** argument) PURE;
//
// IDebugHostType2:
//
STDMETHOD(IsTypedef)(_Out_ bool* isTypedef) PURE;
STDMETHOD(GetTypedefBaseType)(_Out_ IDebugHostType2** baseType) PURE;
STDMETHOD(GetTypedefFinalBaseType)(_Out_ IDebugHostType2** finalBaseType) PURE;
STDMETHOD(GetFunctionVarArgsKind)(_Out_ VarArgsKind* varArgsKind) PURE;
}
IDebugHostType2/IDebugHostType 常规方法
以下 IDebugHostType 方法适用于任何类型,无论从 GetTypeKind 方法返回哪种类型:
STDMETHOD(GetTypeKind)(_Out_ TypeKind *kind) PURE;
STDMETHOD(GetSize)(_Out_ ULONG64* size) PURE;
STDMETHOD(GetBaseType)(_Out_ IDebugHostType** baseType) PURE;
STDMETHOD(GetHashCode)(_Out_ ULONG* hashCode) PURE;
GetTypeKind 方法返回 (指针、数组、内部函数等类型...) 符号所引用的类型。
GetSize 方法返回类型 (的大小,就像在 C++) 中 (类型) 一样。
如果类型是另一个类型 (例如:MyStruct * 派生自 MyStruct') ,则 GetBaseType 方法返回派生的基类型。 对于指针,这将返回指向的类型。 对于数组,这将返回数组的数组。 如果该类型不是此类派生类型,则返回错误。
GetHashCode 方法返回类型的 32 位哈希代码。 除了全局匹配 (例如:与 * 等效的类型签名(如果主机) 允许)匹配所有内容,任何可以匹配特定类型签名的类型实例都必须返回相同的哈希代码。 此方法与类型签名结合使用,以便将类型签名与类型实例匹配。
IDebugHostType2/IDebugHostType 内部方法
以下 IDebugHostType 方法特定于内部类型 (或保存内部数据(如枚举) )的类型:
STDMETHOD(GetIntrinsicType)(_Out_opt_ IntrinsicKind *intrinsicKind, _Out_opt_ VARTYPE *carrierType) PURE;
GetIntrinsicType 方法返回有关类型内部类型的信息。 此方法返回两个值:
- 内部类型指示总体类型 (例如:整数、无符号、浮点) 但不是类型 (的大小,例如:8 位、16 位、32 位、64 位)
- 载体类型指示内部类型如何打包到 VARIANT 结构中。 这是一个 VT_* 常量。
这两个值的组合提供了有关内部函数的完整信息集。
IDebugHostType2/IDebugHostType Bitfield 方法
以下 IDebugHostType 方法特定于在位字段中存储数据的类型。 有关内部函数中位域放置的信息作为数据模型中的类型符号的一部分存储,而不是作为位置的属性。
STDMETHOD(GetBitField)(_Out_ ULONG* lsbOfField, _Out_ ULONG* lengthOfField) PURE;
如果数据结构的给定成员是位字段 (例如:ULONG MyBits:8) ,则字段的类型信息附带有关位域放置的信息。 GetBitField 方法可用于检索该信息。 此方法在非位域的任何类型上都将失败。 这是该方法失败的唯一原因。 只需调用此方法并查看成功/失败即可区分位字段和非位字段。 如果给定的类型恰好是位字段,则字段位置由半开集 (lsbOfField + lengthOfField : lsbOfField] 定义。
IDebugHostType2/IDebugHostType 指针相关方法
以下 IDebugHostType 方法特定于指针类型。 此类类型为 GetTypeKind 返回 TypePointer 或 TypeMemberPointer':
STDMETHOD(GetPointerKind)(_Out_ PointerKind* pointerKind) PURE;
STDMETHOD(GetMemberType)(_Out_ IDebugHostType** memberType) PURE;
对于指针类型,GetPointerKind 方法返回指针的类型。 这由 PointerKind 枚举定义。
对于由 TypeMemberPointer) 类型所指示的指针到成员 (的类型,GetMemberType 方法返回指针指向成员的类。
IDebugHostType2/IDebugHostType 数组相关方法
数组是 GetTypeKind 返回 TypeArray 的类型。 请注意,由调试主机的类型系统定义的数组与 C 使用的单维、基于零索引的打包线性一维数组不同。 C 样式数组适合定义,但在 IDebugHostType 中,数组的总体范围更广。 调试主机中的数组可以是多维的,数组中的每个维度都由名为 ArrayDimension 的描述符定义。此描述符具有以下字段:
字段 | 含义 |
---|---|
LowerBound | 数组的基索引,作为有符号 64 位值。 对于 C 样式数组,这始终为零。 它不需要。 可以将数组的单个维度视为从任何 64 位索引开始,即使是负索引。 |
Length | 作为无符号 64 位值的数组维度的长度。 数组的索引跨半打开集 [LowerBound, LowerBound + Length) 。 |
跨距 | 定义数组维度的步长。 如果此维度的索引将一 (从 N 增加到 N + 1) ,则指示在内存中向前移动的字节数。 对于 C 样式数组,这是数组中每个元素的大小。 它不需要。 元素之间的填充可以表示为大于每个单个元素大小的步长。 对于多维数组,此值将指示如何向前移动整个维度。 考虑 M x N 矩阵。 这可以在行主窗体中描述为两个维度: |
{ [LowerBound: 0, Length: M, Stride: N \* sizeof(element)], [LowerBound: 0, Length: N, Stride: sizeof(element)]}
或者,也可以以列主形式将其描述为两个维度:
{ [LowerBound: 0, Length: M, Stride: sizeof(element)], [LowerBound: 0, Length: N, Stride: M \* sizeof(element)]}
ArrayDimension 概念允许这种程度的灵活性。
以下 IDebugHostType 方法特定于数组类型。
STDMETHOD(GetArrayDimensionality)(\_Out_ ULONG64\* arrayDimensionality) PURE;
STDMETHOD(GetArrayDimensions)(\_In_ ULONG64 dimensions, \_Out_writes_(dimensions) ArrayDimension \*pDimensions) PURE;
GetArrayDimensionality 方法返回数组索引的维度数。 对于 C 样式数组,此处返回的值将始终为 1。
GetArrayDimensions 方法返回一组描述符,一个描述符用于数组的每个维度,如 GetArrayDimensionality 方法所示。 每个描述符都是一个 ArrayDimension 结构,用于描述每个数组维度的起始索引、长度和前进步幅。 这允许描述比 C 类型系统中允许的更强大的数组构造。
对于 C 样式数组,此处返回一个数组维度,其值始终为:
- LowerBound = 0
- Length = ARRAYSIZE (array)
- Stride = sizeof (elementType)
IDebugHostType2/IDebugHostType 函数相关方法
通过 TypeFunction 类型指示它们是函数类型的类型支持 IDebugHostType 和 IDebugHostType2 中的以下方法。
//
// IDebugHostType:
//
STDMETHOD(GetFunctionCallingConvention)(_Out_ CallingConventionKind* conventionKind) PURE;
STDMETHOD(GetFunctionReturnType)(_COM_Outptr_ IDebugHostType** returnType) PURE;
STDMETHOD(GetFunctionParameterTypeCount)(_Out_ ULONG64* count) PURE;
STDMETHOD(GetFunctionParameterTypeAt)(_In_ ULONG64 i, _Out_ IDebugHostType** parameterType) PURE;
//
// IDebugHostType2:
//
STDMETHOD(GetFunctionVarArgsKind)(_Out_ VarArgsKind* varArgsKind) PURE;
GetFunctionCallingConvention 方法返回函数的调用约定。 此类作为 CallingConventionKind 枚举的成员返回。
GetFunctionReturnType 方法返回函数的返回类型。
GetFunctionParameterTypeCount 方法返回函数采用的参数数。 请注意,此计数中不考虑基于 C/C++ 省略号的变量参数标记。 必须通过 GetFunctionVarArgsKind 方法检测是否存在此类内容。 这将仅包括省略号前的参数。
GetFunctionParameterTypeAt 方法将 i-th 参数的类型返回到函数。
GetFunctionVarArgsKind 方法返回给定函数是否利用变量参数列表,如果是,则返回它利用的变量参数样式。 此类由 VarArgsKind 枚举的成员定义,定义如下:
枚举 | 含义 |
---|---|
VarArgsNone | 函数不采用任何变量参数。 |
VarArgsCStyle | 函数是一个 C 样式 varargs 函数, (returnType (arg1、 arg2、 ...) ) 。函数报告的参数数不包括省略号参数。 任何变量参数传递都发生在 GetFunctionParameterTypeCount 方法返回的参数数之后。 |
IDebugHostType2 GetFunctionVarArgsKind
GetFunctionVarArgsKind 方法返回给定函数是否利用变量参数列表,如果是,则返回它利用的变量参数样式。 此类由 VarArgsKind 枚举的成员定义,定义如下:
IDebugHostType2/IDebugHostType Typedef 相关方法
作为 typedef 的任何类型的行为就像类型是 typedef 的基础的最终类型一样。 这意味着 GetTypeKind 等方法不会指示类型为 typedef。 同样,GetBaseType 不会返回定义引用的类型。 它们将指示其行为就像是在 typedef 基础的最终定义上调用的。 示例:
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
PMYSTRUCT 或 PTRMYSTRUCT 的 IDebugHostType 将报告以下信息:
- GetTypeKind 方法将返回 TypePointer。 最终的基础类型 MYSTRUCT * 确实是指针。
- 'GetBaseType 方法将返回 MYSTRUCT 的类型。 MYSTRUCT * 的基础类型是 MYSTRUCT。
此处唯一的区别在于 IDebugHostType2 上的 typedef 特定方法的行为方式。 这些方法是:
STDMETHOD(IsTypedef)(_Out_ bool* isTypedef) PURE;
STDMETHOD(GetTypedefBaseType)(_Out_ IDebugHostType2** baseType) PURE;
STDMETHOD(GetTypedefFinalBaseType)(_Out_ IDebugHostType2** finalBaseType) PURE;
在此示例中:
- IsTypedef 方法将为 PMYSTRUCT 和 PTRMYSTRUCT 返回 true
- GetTypedefBaseType 方法将为 PMYSTRUCT 返回 MYSTRUCT * ,为 PTRMYSTRUCT 返回 PMYSTRUCT
- GetTypedefFinalBaseType 方法将返回两种类型的 MYSTRUCT *
IsTypedef 方法是唯一能够查看类型是否为 typedef 的方法。 GetTypeKind 方法的行为就像在基础类型上调用一样。
GetTypedefBaseType 方法将返回 typedef 的直接定义。 在文档中描述的示例中:
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
此方法将为 PMYSTRUCT 返回 MYSTRUCT * ,为 PTRMYSTRUCT 返回 PMYSTRUCT。
GetTypedefFinalBaseType 方法将返回 typedef 为其定义的最终类型。 如果 typedef 是另一个 typedef 的定义,则它将继续遵循定义链,直到它到达一个不是 typedef 的类型,并且将返回该类型。 在文档中描述的示例中:
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
在 PMYSTRUCT 或 PTRMYSTRUCT 上调用时,此方法将返回 MYSTRUCT *。
IDebugHostType2/IDebugHostType 类型创建方法
STDMETHOD(CreatePointerTo)(_In_ PointerKind kind, _COM_Outptr_ IDebugHostType** newType) PURE;
STDMETHOD(CreateArrayOf)(_In_ ULONG64 dimensions, _In_reads_(dimensions) ArrayDimension *pDimensions, _COM_Outptr_ IDebugHostType** newType) PURE;
常量符号值:IDebugHostConstant
对于常量值存在于符号信息中的位置, (特定值是符号,该符号可以是或可能不是) 常量值,IDebugHostConstant 接口表示此类常量的概念。 这通常用于模板参数等位置,其中给定参数通常为类型,但可能改为非类型模板参数 (例如:常量) 。
IDebugHostConstant 接口定义如下, (忽略 IDebugHostSymbol) 实现的泛型方法:
DECLARE_INTERFACE_(IDebugHostConstant, IDebugHostSymbol)
{
STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}
GetValue 方法返回打包到 VARIANT 中的常量的值。 请务必注意,IDebugHostSymbol 上的 GetType 方法可能会返回常量的特定类型符号。 在这种情况下,无法保证由类型符号定义的常量值的打包与此处的 GetValue 方法返回的打包相同。
数据成员访问:IDebugHostField
IDebugHostField 类表示一个符号,该符号是类、结构、联合或其他类型构造的数据成员。 它不表示免费数据 (例如:全局数据) 。 接口的定义如下, (忽略 IDebugHostSymbol) 的泛型方法:
DECLARE_INTERFACE_(IDebugHostField, IDebugHostSymbol)
{
STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
STDMETHOD(GetOffset)(_Out_ ULONG64* offset) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}
GetLocationKind 方法根据 LocationKind 枚举返回符号所在的位置类型。 此类枚举可以是以下值之一:
枚举 | 含义 |
---|---|
LocationMember | 字段是类、结构、联合或其他类型构造的常规数据成员。 它具有相对于包含类型构造的基址的偏移量。 此类基址通常由此指针表示。 可以通过 GetOffset 方法检索字段的偏移量。 对于 LocationMember 字段,GetLocation 和 GetValue 方法将失败。 |
LocationStatic | 字段是静态的,并且具有自己的地址。 GetLocation 方法将返回抽象位置 (例如静态字段的地址) 。 对于 LocationStatic 字段,GetOffset 和 GetValue 方法将失败。 |
LocationConstant | 字段是一个常量,并且具有值。 GetValue 方法将返回常量的值。 对于 LocationConstant 字段,GetOffset 和 GetLocation 方法将失败 |
LocationNone | 字段没有位置。 它可能已被编译器优化,也可能是声明但从未定义的静态字段。 无论这种领域是如何出现,它都没有物理存在或价值。 它仅在符号中。 对于 LocationNone 字段, (GetOffset、GetLocation 和 GetValue) 的所有获取方法都将失败。 |
对于具有偏移 (的字段,例如位置类型指示 LocationMember) 的字段,GetOffset 方法将返回包含类型的基址的偏移量, (此指针) 字段本身的数据。 此类偏移量始终表示为无符号 64 位值。 如果给定字段没有与包含类型的基址偏移的位置,则 GetOffset 方法将失败。
对于具有地址的字段,而不考虑特定类型实例 (例如:其位置类型指示 LocationStatic) 的字段,GetLocation 方法将返回该字段的抽象位置 (地址) 。 如果给定字段没有静态位置,则 GetLocation 方法将失败。
对于在符号信息中定义了常量值的字段 (例如,其位置类型指示 LocationConstant) 的字段,GetValue 方法将返回字段的常量值。 如果给定字段没有常量值,则 GetValue 方法将失败。
免费数据访问:IDebugHostData
不是其他类型的成员的模块中的数据由 IDebugHostData 接口表示。 该接口的定义如下 (忽略 IDebugHostSymbol) 的泛型方法:
DECLARE_INTERFACE_(IDebugHostData, IDebugHostSymbol)
{
STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}
所有这些方法在语义上都等效于 IDebugHostField 中的对应方法。 唯一的区别是 GetLocationKind 方法永远不会返回免费数据的 LocationMember。
GetLocationKind 方法根据 LocationKind 枚举返回符号所在的位置类型。 此枚举的说明可在 IDebugHostField 的文档中找到。
对于具有地址的数据,GetLocation 方法将返回字段的抽象位置 (地址) 。 如果给定的数据没有静态位置,则 GetLocation 方法将失败。
对于在符号信息 (定义常量值的数据,例如,其位置类型指示 LocationConstant) 的数据,GetValue 方法将返回字段的常量值。 如果给定数据没有常量值,则 GetValue 方法将失败。
基类:IDebugHostBaseClass
给定类型的继承层次结构通过类型符号的子级表示。 如果给定类型从一个或多个类型) (继承派生,则类型符号将有一个或多个 SymbolBaseClass 子级。 其中每个 SymbolBaseClass 符号都表示特定类型的直接继承。 基类的名称既是 SymbolBaseClass 符号的名称,也是基类的类型符号的名称。 SymbolBaseClass 符号上的 GetType 方法可用于获取基类本身的类型符号。 可以通过递归浏览 SymbolBaseClass 子符号来遍历完整的继承层次结构。 每个基类符号都由 IDebugHostBaseClass 接口表示,该接口定义如下 (忽略 IDebugHostSymbol) 的泛型方法:
DECLARE_INTERFACE_(IDebugHostBaseClass, IDebugHostSymbol)
{
STDMETHOD(GetOffset)(_Out_ ULONG64* offset) PURE;
}
GetOffset 方法从派生类的基址返回基类的偏移量。 此类偏移量可以是零,也可以是正无符号 64 位值。
公共符号:IDebugHostPublic
公共符号表示符号文件中公共表中的内容。 实际上,它们是导出地址。 没有与公共符号关联的类型信息 -- 只有地址。 除非调用方显式请求公共符号,否则调试主机更愿意为每个查询返回私有符号。 公共符号由 IDebugHostPublic 接口表示,该接口定义如下 (忽略 IDebugHostSymbol) 通用方法:
DECLARE_INTERFACE_(IDebugHostPublic, IDebugHostSymbol)
{
STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
}
所有这些方法在语义上都等效于 IDebugHostField 中的对应方法。 唯一的区别是 GetLocationKind 方法永远不会为此类符号返回 LocationMember 或 LocationConstant。
GetLocationKind 方法根据 LocationKind 枚举返回符号所在的位置类型。 此枚举的说明可在 IDebugHostField 的文档中找到。
对于具有地址的数据,GetLocation 方法将返回字段的抽象位置 (地址) 。 如果给定的公共没有静态位置,则 GetLocation 方法将失败。
模块签名和版本匹配:IDebugHostModuleSignature
模块签名表示一种检查给定模块是否满足一组有关命名和版本控制的条件的方法。 模块签名是通过 IDebugHostSymbols 上的 CreateModuleSignature 方法创建的。 它可以匹配模块名称和模块的可选版本号范围。 创建此类签名后,客户端将收到一个 IDebugHostModuleSignature 接口,该接口定义如下:
DECLARE_INTERFACE_(IDebugHostModuleSignature, IUnknown)
{
STDMETHOD(IsMatch)(_In_ IDebugHostModule* pModule, _Out_ bool* isMatch) PURE;
}
IsMatch 方法将 IDebugHostModule 符号 (的特定模块) 与签名进行比较,并将模块名称和版本与签名中指示的名称和版本范围进行比较。 返回给定模块符号是否与签名匹配的指示。
类型签名和类型匹配:IDebugHostTypeSignature
类型签名表示检查给定类型实例是否满足有关类型名称、类型泛型参数以及类型所在模块的一组条件的方法。 类型签名是通过 IDebugHostSymbols 上的 CreateTypeSignature 方法创建的。 创建此类签名后,客户端将收到一个 IDebugHostTypeSignature 接口,该接口定义如下:
DECLARE_INTERFACE_(IDebugHostTypeSignature, IUnknown)
{
STDMETHOD(GetHashCode)(_Out_ ULONG* hashCode) PURE;
STDMETHOD(IsMatch)(_In_ IDebugHostType* type, _Out_ bool* isMatch, _COM_Outptr_opt_ IDebugHostSymbolEnumerator** wildcardMatches) PURE;
STDMETHOD(CompareAgainst)(_In_ IDebugHostTypeSignature* typeSignature, _Out_ SignatureComparison* result) PURE;
}
GetHashCode 方法返回类型签名的 32 位哈希代码。 调试主机保证为类型实例返回的哈希代码与为类型签名返回的哈希代码之间的实现同步。 除了全局匹配之外,如果类型实例能够匹配类型签名,则两者将具有相同的 32 位哈希代码。 这允许在类型实例与向数据模型管理器注册的过多类型签名之间进行初始快速比较和匹配。
IsMatch 方法返回特定类型实例是否与类型签名中指定的条件匹配的指示。 如果已返回,则返回此指示以及一个枚举器,该枚举器将指示类型实例的所有特定部分 (作为符号) 与类型签名中的通配符匹配。
CompareAgainst 方法将类型签名与其他类型签名进行比较,并返回两个签名的比较方式。 返回的比较结果是 SignatureComparison 枚举的成员,定义如下:
枚举 | 含义 |
---|---|
Unrelated | 比较的两个签名或类型之间没有关系。 |
不明确 | 一个签名或类型与另一个签名或类型进行比较不明确。 对于两个类型签名,这意味着存在可能匹配任一签名的可能类型实例。 例如,下面显示的两个类型签名不明确。 签名 1: std::pair<*, int> 签名 2: std::pair<int,*> 因为类型实例 std::pair<int, int> 匹配任意一个同样良好, (两者都有一个具体匹配项和一个通配符匹配) 。 |
LessSpecific | 一个签名或类型不如另一个签名或类型具体。 通常,这意味着不太具体的签名具有通配符,其中更具体的签名具有具体类型。 例如,下面的第一个签名不如第二个签名具体。 签名 1: std::pair<*, int> 签名 2: std::pair<int, int> 因为它具有通配符 (* ) ,其中第二个具有具体类型 (int) 。 |
MoreSpecific | 一个签名或类型比另一个签名或类型更具体。 通常,这意味着更具体的签名具有具体类型,其中不太具体的签名具有通配符。 例如,下面的第一个签名比第二个签名更具体。 签名 1: std::pair<int, int> 签名 2: std::pair<*, int> 因为它具有具体类型 (int) 其中第二个具有通配符 (* ) 。 |
相同 | 这两个签名或类型相同。 |
另请参阅
本主题是一系列文章的一部分,该系列介绍了可从 C++ 访问的接口、如何使用接口生成基于 C++ 的调试器扩展,以及如何利用其他数据模型构造 (例如:JavaScript 或 NatVis) 从 C++ 数据模型扩展。