調試程序數據模型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 方法會傳回主機的主要私人介面。 針對 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 -- 開頭為 IDataModel、IDebugHost,以及 IModelObject 的 offshoots -- 設計成可攜式,但它們不會定義「調試程式擴充功能」是什麼。 目前,想要擴充 Windows 偵錯工具的元件及其提供的引擎必須撰寫引擎延伸模組,才能存取數據模型。 該引擎擴充功能只需要是擴充功能的引擎擴充功能,就像擴充功能的載入和啟動載入機制一樣。 因此,最少的實作會提供:
- DebugExtensionInitialize:一種方法會利用建立的 IDebugClient 來存取數據模型並設定物件模型作。
- DebugExtensionUninitialize:一個方法,可復原在 DebugExtensionInitialize 中執行的物件模型作。
- DebugExtensionCanUnload:傳回延伸模組是否可以卸除的方法。 如果延伸模組中仍有即時 COM 物件,它必須指出這一點。 這是調試程式的對等 COM DllCanUnloadNow。 如果這會傳回無法卸除的S_FALSE指示,則調試程式稍後可以查詢此專案,以查看卸除是否安全,或可能會再次呼叫 DebugExtensionInitialize 重新初始化擴充功能。 擴充功能必須準備好處理這兩個路徑。
- DebugExtensionUnload:在 DLL 卸除之前執行任何最終清除所需的方法
網橋介面:IHostDataModelAccess
如前所述,呼叫DebugExtensionInitialize時,它會建立偵錯用戶端並取得數據模型的存取權。 這類存取是由舊版 IDebug* 介面的 Windows 偵錯工具與數據模型之間的網橋介面所提供。 此網橋介面是 'IHostDataModelAccess,且定義為下列專案:
DECLARE_INTERFACE_(IHostDataModelAccess, IUnknown)
{
STDMETHOD(GetDataModel)(_COM_Outptr_ IDataModelManager** manager, _COM_Outptr_ IDebugHost** host) PURE;
}
GetDataModel 方法是在網橋介面上提供數據模型兩端存取的方法:偵錯主機(調試程式的下邊緣)是由傳回的 IDebugHost 介面表示數據模型的主要元件 -- 數據模型管理員是由傳回的 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 介面是存取偵錯目標中符號的主要起點。 您可以從 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 中內建數據的 variant 數據類型 (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 一般方法
無論從 GetTypeKind 方法傳回何種類型,下列 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;
GetTypeKind 方法會傳回符號所參考的類型類型(指標、陣列、內建等...)。
GetSize 方法會傳回類型的大小(就像在 C++ 中已完成 sizeof(type) 一樣)。
如果類型是另一個單一類型的衍生專案(例如: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 方法專屬於將數據儲存在 bitfields 的類型。 內部函數中 bitfield 放置的相關信息會儲存為數據模型中類型符號的一部分,而不是位置的屬性。
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 中更為廣泛。 偵錯主機中的陣列可以是多維度,而且陣列中的每個維度都是由稱為ArrayDimensionThisscriptor的描述項定義,其欄位如下:
領域 | 意義 |
---|---|
LowerBound | 陣列的基底索引,做為帶正負號的64位值。 對於 C 樣式陣列,這一律為零。 它不需要。 陣列的個別維度可以視為從任何 64 位索引開始,甚至是負的索引。 |
長度 | 陣組維度的長度為不帶正負號的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++以省略號為基礎的省略號自變數標記。 必須透過 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;
此方法會針對 PTRMYSTRUCT 傳回 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 方法擷取。 GetLocation 和 GetValue 方法會針對LocationMember的欄位失敗。 |
LocationStatic | 欄位是靜態的,而且有自己的位址。 GetLocation 方法會傳回靜態字段的抽象位置(例如:address)。 GetOffset 和 GetValue 方法會針對LocationStatic的欄位失敗。 |
LocationConstant | 欄位是常數,且具有值。 GetValue 方法會傳回常數的值。 GetOffset 和 GetLocation 方法會針對 LocationConstant 的字段失敗 |
LocationNone | 欄位沒有位置。 它可能已由編譯程序優化,或者可能是已宣告但從未定義的靜態字段。 無論這類欄位如何出現,它都沒有實際存在或價值。 它只位於符號中。 所有擷取方法(GetOffset、GetLocation 和 GetValue)都會失敗,字段為LocationNone。 |
對於具有位移的欄位(例如:位置種類指出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 方法會傳回字段的抽象位置(address)。 如果指定的數據沒有靜態位置,GetLocation 方法將會失敗。
針對 datawhich 在符號資訊中定義的常數值(例如:位置種類指出 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 方法會傳回字段的抽象位置(address)。 如果指定的公用沒有靜態位置,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 列舉的成員,其定義如下:
列舉 | 意義 |
---|---|
不相關的 | 要比較的兩個簽章或類型之間沒有關聯性。 |
模糊 | 一個簽章或類型會模棱兩可地比較另一個簽章。 對於兩個類型簽章,這表示可能有可能符合任一個簽章的類型實例。 例如,下面顯示的兩個類型簽章模棱兩可。 簽章 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++為基礎的調試程式延伸模組,以及如何從C++數據模型延伸模組使用其他數據模型建構(例如:JavaScript 或 NatVis)。