Interfaces C++ du modèle de données du débogueur
Cette rubrique fournit une vue d’ensemble de l’utilisation des interfaces C++ du modèle de données du débogueur pour étendre et personnaliser les fonctionnalités du débogueur.
Interfaces hôtes C++ du modèle de données du débogueur
Hôte du modèle de données du débogueur
Le modèle de données du débogueur est conçu pour être un système à composants qui peut être hébergé dans différents contextes. Normalement, le modèle de données est hébergé dans le contexte d’une application de débogueur. Pour être un hôte du modèle de données, un certain nombre d’interfaces doivent être implémentées pour exposer les principaux aspects du débogueur : son ciblage, ses espaces de mémoire, son évaluateur, son système symbolique et de type, etc. Bien que ces interfaces soient implémentées par toute application souhaitant héberger le modèle de données, elles sont consommées par le modèle de données de base ainsi que par toute extension qui interagit avec le modèle de données.
L’ensemble des interfaces principales est le suivant :
Nom de l'interface | Description |
---|---|
IDebugHost | Interface principale de l’hôte de débogage. |
IDebugHostStatus | Interface permettant à un client d’interroger la status de l’hôte. |
IDebugHostContext | Abstraction d’un contexte au sein de l’hôte (par exemple : une cible particulière, un processus particulier, un espace d’adressage particulier, etc.) |
IDebugHostErrorSink | Interface implémentée par les appelants pour recevoir des erreurs de certaines parties du modèle de données et de l’hôte |
IDebugHostEvaluator / IDebugHostEvaluator2 | Évaluateur d’expression de l’hôte de débogage. |
IDebugHostExtensibility | Interface permettant d’étendre les fonctionnalités de l’hôte ou de certaines parties de celui-ci (par exemple, l’évaluateur d’expression). |
Le système de type et les interfaces symboliques sont les suivants :
InterfaceName | Description |
---|---|
IDebugHostSymbols | Interface principale qui fournit l’accès aux symboles et leur résolution |
IDebugHostSymbol / IDebugHostSymbol2 | Représente un symbole unique de n’importe quel type. Le symbole particulier est une dérivation de cette interface. |
IDebugHostModule | Représente un module chargé dans un processus. C’est une sorte de symbole. |
IDebugHostType / IDebugHostType2 | Représente un type natif/de langue. |
IDebugHostConstant | Représente une constante dans les informations symboliques (par exemple, un argument de modèle sans type en C++) |
IDebugHostField | Représente un champ au sein d’une structure ou d’une classe. |
IDebugHostData | Représente des données au sein d’un module (s’il s’agissait d’une structure ou d’une classe, il s’agirait d’un champ IDebugHostField) |
IDebugHostBaseClass | Représente une classe de base. |
IDebugHostPublic | Représente un symbole dans la table public d’une PDB. Aucune information de type n’est associée à cette opération. Il s’agit d’un nom et d’une adresse. |
IDebugHostModuleSignature | Représente une signature de module : définition qui correspond à un ensemble de modules par nom et/ou version |
IDebugHostTypeSignature | Représente une signature de type : définition qui correspond à un ensemble de types par module et/ou nom |
Interface hôte principale : IDebugHost
L’interface IDebugHost est l’interface principale de tout hôte de modèle de données. La définition est la suivante :
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;
}
La méthode GetHostDefinedInterface retourne l’interface privée main de l’hôte, si elle existe pour l’hôte donné. Pour les outils de débogage pour Windows, l’interface retournée ici est un IDebugClient (cast vers IUnknown).
La méthode GetCurrentContext retourne une interface qui représente l’état actuel de l’hôte du débogueur. La signification exacte de cela est laissée à l’hôte, mais elle inclut généralement des éléments tels que la session, le processus et l’espace d’adressage qui est actif dans l’interface utilisateur de l’hôte de débogage. L’objet de contexte retourné est en grande partie opaque pour l’appelant, mais il s’agit d’un objet important à passer entre les appels à l’hôte de débogage. Lorsqu’un appelant lit, par instance, de la mémoire, il est important de savoir de quel processus et de quel espace d’adressage la mémoire est lue. Cette notion est encapsulée dans la notion de l’objet de contexte qui est retournée par cette méthode.
La méthode GetDefaultMetadata retourne un magasin de métadonnées par défaut qui peut être utilisé pour certaines opérations (par exemple, la conversion de chaînes) quand aucune métadonnées explicite n’a été passée. Cela permet à l’hôte de débogage d’avoir un certain contrôle sur la façon dont certaines données sont présentées. Par exemple, les métadonnées par défaut peuvent inclure une clé PreferredRadix, ce qui permet à l’hôte d’indiquer si les ordinaux doivent être affichés en décimal ou hexadécimal s’ils ne sont pas spécifiés autrement.
Notez que les valeurs de propriété sur le magasin de métadonnées par défaut doivent être résolues manuellement et doivent passer l’objet pour lequel les métadonnées par défaut sont interrogées. La méthode GetKey doit être utilisée à la place de GetKeyValue.
Interface d’état : IDebugHostStatus
L’interface IDebugHostStatus permet à un client du modèle de données ou de l’hôte de débogage de se renseigner sur certains aspects de la status de l’hôte de débogage. L’interface se définit comme suit :
DECLARE_INTERFACE_(IDebugHostStatus, IUnknown)
{
STDMETHOD(PollUserInterrupt)(_Out_ bool* interruptRequested) PURE;
}
La méthode PollUserInterrupt permet de déterminer si l’utilisateur de l’hôte de débogage a demandé une interruption de l’opération en cours. Un accesseur de propriété dans le modèle de données peut, par instance, appeler du code arbitraire (par exemple, une méthode JavaScript). Ce code peut prendre un temps arbitraire. Pour que l’hôte de débogage reste réactif, tout code de ce type qui peut prendre un temps arbitraire doit case activée pour une demande d’interruption en appelant cette méthode. Si la valeur interruptRequested revient à true, l’appelant doit immédiatement abandonner et retourner un résultat de E_ABORT.
Interface contextuelle : IDebugHostContext
Le contexte est l’un des aspects les plus importants du modèle de données et de l’hôte de débogage sous-jacent. Lorsque vous tenez un objet, il est important de pouvoir savoir d’où provient un objet: dans quel processus il se trouve, quel espace d’adressage est-il associé. La connaissance de ces informations permet d’interpréter correctement des éléments tels que les valeurs de pointeur. Un objet de type IDebugHostContext doit être passé à de nombreuses méthodes sur l’hôte de débogage. Cette interface peut être acquise de plusieurs façons :
- En obtenant le contexte actuel du débogueur : appel de la méthode GetCurrentContext de IDebugHost
- En obtenant le contexte d’un objet : appel de la méthode GetContext de IModelObject
- En obtenant le contexte d’un symbole : appel de la méthode GetContext de IDebugHostSymbol
En outre, il existe deux valeurs qui ont une signification particulière dans le contexte d’une interface IDebugHostContext qui est retournée ou transmise à un modèle de données ou à une méthode hôte de débogage :
nullptr : indique qu’il n’existe aucun contexte. Il est parfaitement valide que certains objets n’aient pas de contexte. L’objet Débogueur dans l’espace de noms racine du modèle de données ne fait référence à rien au sein d’un processus ou d’un espace d’adressage spécifique. Il n’a pas de contexte.
USE_CURRENT_HOST_CONTEXT : valeur sentinelle indiquant qu’il faut utiliser le contexte d’interface utilisateur actuel de l’hôte de débogage. Cette valeur ne sera jamais retournée à partir de l’hôte de débogage. Toutefois, elle peut être passée à n’importe quelle méthode hôte de débogage qui prend une entrée IDebugHostContext au lieu d’appeler explicitement la méthode GetCurrentContext de IDebugHost. Notez que le passage explicite USE_CURRENT_HOST_CONTEXT est souvent plus performant que l’obtention explicite du contexte actuel.
Les contextes d’un contexte hôte sont largement opaques pour l’appelant. La seule opération qu’un appelant en dehors de l’hôte de débogage principal peut effectuer avec un contexte hôte consiste à le comparer à un autre contexte hôte.
L’interface IDebugHostContext est définie comme suit :
DECLARE_INTERFACE_(IDebugHostContext, IUnknown)
{
STDMETHOD(IsEqualTo)(_In_ IDebugHostContext *pContext, _Out_ bool *pIsEqual) PURE;
}
La méthode IsEqualTo compare un contexte hôte à un autre contexte hôte. Si les deux contextes sont équivalents, une indication de ce est retournée. Notez que cette comparaison n’est pas une équivalence d’interface. Cela compare le contenu opaque sous-jacent du contexte lui-même.
Récepteur d’erreurs : IDebugHostErrorSink
IDebugHostErrorSink est un moyen par lequel un client peut recevoir des notifications d’erreurs qui se produisent pendant certaines opérations et les acheminer si nécessaire. L’interface se définit comme suit :
enum ErrorClass
{
ErrorClassWarning,
ErrorClassError
}
DECLARE_INTERFACE_(IDebugHostErrorSink, IUnknown)
{
STDMETHOD(ReportError)(_In_ ErrorClass errClass, _In_ HRESULT hrError, _In_ PCWSTR message) PURE;
}
La méthode ReportError est un rappel sur le récepteur d’erreurs pour l’informer qu’une erreur s’est produite et permettre au récepteur d’acheminer l’erreur vers l’interface utilisateur ou le mécanisme approprié.
Évaluateur hôte : IDebugHostEvaluator / IDebugHostEvaluator2
L’une des fonctionnalités les plus importantes que l’hôte de débogage fournit aux clients est l’accès à son évaluateur d’expression basée sur le langage. Les interfaces IDebugHostEvaluator et IDebugHostEvaluator2 permettent d’accéder à cette fonctionnalité à partir de l’hôte de débogage.
Les interfaces sont définies comme suit :
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;
}
La méthode EvaluateExpression permet aux demandes de l’hôte de débogage d’évaluer une expression de langage (par exemple, C++) et de retourner la valeur résultante de cette évaluation d’expression en tant qu’IModelObject. Cette variante particulière de la méthode autorise uniquement les constructions de langage. Toute fonctionnalité supplémentaire présentée dans l’évaluateur d’expression de l’hôte de débogage qui n’est pas présent dans le langage (par exemple, méthodes de requête LINQ) est désactivée pour l’évaluation.
La méthode EvaluateExtendedExpression est similaire à la méthode EvaluateExpression, sauf qu’elle retourne des fonctionnalités non linguistiques supplémentaires qu’un hôte de débogage particulier choisit d’ajouter à son évaluateur d’expression. Pour les outils de débogage pour Windows, par exemple, cela active les types anonymes, les requêtes LINQ, les qualificateurs de module, les spécificateurs de format et d’autres fonctionnalités non-C/C++.
IDebugHostEvaluator2
La méthode AssignTo effectue l’affectation en fonction de la sémantique du langage débogué.
Interface d’extensibilité de l’hôte : IDebugHostExtensibility
Certaines fonctionnalités de l’hôte de débogage sont éventuellement soumises à l’extensibilité. Cela peut, pour instance, inclure l’évaluateur d’expression. L’interface IDebugHostExtensibility est le moyen par lequel ces points d’extensibilité sont accessibles. L’interface se définit comme suit :
DECLARE_INTERFACE_(IDebugHostExtensibility, IUnknown)
{
STDMETHOD(CreateFunctionAlias)(_In_ PCWSTR aliasName, _In_ IModelObject *functionObject) PURE;
STDMETHOD(DestroyFunctionAlias)(_In_ PCWSTR aliasName) PURE;
}
La méthode CreateFunctionAlias crée un « alias de fonction », un « alias rapide » pour une méthode implémentée dans une extension. La signification de cet alias est spécifique à l’hôte. Il peut étendre l’évaluateur d’expression de l’hôte avec la fonction ou faire quelque chose de complètement différent.
La méthode DestroyFunctionAlias annule un appel antérieur à la méthode CreateFunctionAlias. La fonction ne sera plus disponible sous le nom de l’alias rapide.
Accès au modèle de données
Tout d’abord, les API d’extensibilité du modèle de données sont conçues pour être neutres pour l’application (généralement un débogueur) qui agit comme hôte du modèle de données. En théorie, n’importe quelle application peut héberger le modèle de données en fournissant un ensemble d’API hôtes qui exposent le système de type des cibles de débogage de l’application et un ensemble d’objets projetés dans l’espace de noms du modèle de données sur les cibles, processus, threads, etc... se trouvent dans ces cibles de débogage.
Bien que les API de modèle de données -- celles qui commencent IDataModel, IDebugHost et les ramifications d’IModelObject -- soient conçues pour être portables, elles ne définissent pas ce qu’est une « extension de débogueur ». Aujourd’hui, un composant qui souhaite étendre les outils de débogage pour Windows et le moteur qu’il fournit doit écrire une extension de moteur afin d’accéder au modèle de données. Cette extension de moteur doit uniquement être une extension de moteur dans la mesure où il s’agit du mécanisme de chargement et de démarrage de l’extension. Par conséquent, une implémentation minimale fournirait :
- DebugExtensionInitialize : méthode qui utilise un IDebugClient créé pour accéder au modèle de données et configurer des manipulations de modèle objet.
- DebugExtensionUninitialize : méthode qui annule les manipulations de modèle objet effectuées dans DebugExtensionInitialize.
- DebugExtensionCanUnload : méthode qui retourne si l’extension peut décharger. S’il existe encore des objets COM actifs dans l’extension, cela doit l’indiquer. Il s’agit de l’équivalent du débogueur de DLLCanUnloadNow de COM. Si cela retourne l’S_FALSE indication de l’impossibilité de décharger, le débogueur peut l’interroger ultérieurement pour voir si un déchargement est sécurisé ou s’il peut réinitialiser l’extension en appelant à nouveau DebugExtensionInitialize. L’extension doit être préparée pour gérer les deux chemins.
- DebugExtensionUnload : méthode qui effectue tout nettoyage final requis juste avant le déchargement de la DLL
Interface de pont : IHostDataModelAccess
Comme mentionné précédemment, lorsque DebugExtensionInitialize est appelé, il crée un client de débogage et obtient l’accès au modèle de données. Cet accès est fourni par une interface de pont entre les interfaces IDebug* héritées des outils de débogage pour Windows et le modèle de données. Cette interface de pont est « IHostDataModelAccess et est définie comme suit :
DECLARE_INTERFACE_(IHostDataModelAccess, IUnknown)
{
STDMETHOD(GetDataModel)(_COM_Outptr_ IDataModelManager** manager, _COM_Outptr_ IDebugHost** host) PURE;
}
La méthode GetDataModel est la méthode de l’interface de pont qui permet d’accéder aux deux côtés du modèle de données : l’hôte de débogage (le bord inférieur du débogueur) est exprimé par l’interface IDebugHost retournée Le composant main du modèle de données : le gestionnaire de modèle de données est exprimé par l’interface IDataModelManager retournée
Interfaces système du modèle de données du débogueur
Hôte du modèle de données
Le modèle de données du débogueur est conçu pour être un système à composants qui peut être hébergé dans différents contextes. Normalement, le modèle de données est hébergé dans le contexte d’une application de débogueur. Pour être un hôte du modèle de données, un certain nombre d’interfaces doivent être implémentées pour exposer les principaux aspects du débogueur : son ciblage, ses espaces de mémoire, son évaluateur, son système symbolique et de type, etc... Bien que ces interfaces soient implémentées par n’importe quelle application souhaitant héberger le modèle de données, elles sont consommées à la fois par le modèle de données de base ainsi que par toute extension qui interagit avec le modèle de données.
Le système de type et les interfaces symboliques sont les suivants :
Nom de l'interface | Description |
---|---|
IDebugHostSymbols | Interface principale qui fournit l’accès et la résolution des symboles |
IDebugHostSymbol / IDebugHostSymbol2 | Représente un symbole unique de n’importe quel type. Le symbole particulier est une dérivation de cette interface. |
IDebugHostModule | Représente un module chargé dans un processus. C’est une sorte de symbole. |
IDebugHostType / IDebugHostType2 | Représente un type natif/de langue. |
IDebugHostConstant | Représente une constante dans les informations symboliques (par exemple, un argument de modèle non de type en C++) |
IDebugHostField | Représente un champ au sein d’une structure ou d’une classe. |
IDebugHostData | Représente des données au sein d’un module (s’il s’agit d’une structure ou d’une classe, il s’agirait d’un IDebugHostField) |
IDebugHostBaseClass | Représente une classe de base. |
IDebugHostPublic | Représente un symbole dans la table publique d’un PDB. Les informations de type ne sont pas associées à cette opération. Il s’agit d’un nom et d’une adresse. |
IDebugHostModuleSignature | Représente une signature de module : définition qui correspond à un ensemble de modules par nom et/ou version |
IDebugHostTypeSignature | Représente une signature de type : définition qui correspond à un ensemble de types par module et/ou nom |
Les autres interfaces principales sont les suivantes :
Nom de l'interface | Description |
---|---|
IDebugHost | Interface principale de l’hôte de débogage. |
IDebugHostStatus | Interface permettant à un client d’interroger le status de l’hôte. |
IDebugHostContext | Abstraction d’un contexte au sein de l’hôte (par exemple : une cible particulière, un processus particulier, un espace d’adressage particulier, etc.) |
IDebugHostErrorSink | Interface implémentée par les appelants pour recevoir des erreurs de certaines parties du modèle de données et de l’hôte |
IDebugHostEvaluator / IDebugHostEvaluator2 | Évaluateur d’expression de l’hôte de débogage. |
IDebugHostExtensibility | Interface permettant d’étendre les fonctionnalités de l’hôte ou de certaines parties de celui-ci (par exemple, l’évaluateur d’expression). |
Interface symbolique principale : IDebugHostSymbols
L’interface IDebugHostSymbols est le point de départ main pour accéder aux symboles dans la cible de débogage. Cette interface peut être interrogée à partir d’un instance de IDebugHost et est définie comme suit :
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;
}
La méthode CreateModuleSignature crée une signature qui peut être utilisée pour faire correspondre un ensemble de modules spécifiques par nom et éventuellement par version. Une signature de module comporte trois composants :
- Un nom : un module correspondant doit avoir un nom qui est une correspondance exacte qui ne respecte pas la casse par rapport au nom dans la signature
- Version minimale : si elle est spécifiée, un module correspondant doit avoir une version minimale qui est au moins aussi élevée que cette version. Les versions sont spécifiées au format « A.B.C.D », chaque partie suivante étant moins importante que la précédente. Seul le premier segment est obligatoire.
- Version maximale : si elle est spécifiée, un module correspondant doit avoir une version maximale qui n’est pas supérieure à cette version. Les versions sont spécifiées au format « A.B.C.D », chaque partie suivante étant moins importante que la précédente. Seul le premier segment est obligatoire.
La méthode CreateTypeSignature crée une signature qui peut être utilisée pour faire correspondre un ensemble de types concrets en contenant le nom du module et du type. Le format de la chaîne de signature de nom de type est spécifique à la langue en cours de débogage (et à l’hôte de débogage). Pour C/C++, la chaîne de signature équivaut à une spécification de type NatVis. Autrement dit, la chaîne de signature est un nom de type où les caractères génériques (spécifiés sous la forme *) sont autorisés pour les arguments de modèle.
CreateTypeSignatureForModuleRange
La méthode CreateTypeSignatureForModuleRange crée une signature qui peut être utilisée pour faire correspondre un ensemble de types concrets par signature de module et nom de type. Ceci est similaire à la méthode CreateTypeSignature, sauf qu’au lieu de passer un module spécifique pour correspondre à la signature, l’appelant passe les arguments nécessaires pour créer une signature de module (comme si la signature de module avait été créée avec la méthode CreateModuleSignature).
La méthode EnumerateModules crée un énumérateur qui énumère chaque module disponible dans un contexte hôte particulier. Ce contexte hôte peut encapsuler un contexte de processus ou peut encapsuler quelque chose comme le noyau Windows.
La méthode FindModuleByName examine le contexte d’hôte donné et recherche un module qui a le nom spécifié et y retourne une interface. Il est légal de rechercher le module par son nom avec ou sans l’extension de fichier.
La méthode FindModuleByLocation examine le contexte d’hôte donné et détermine quel module contient l’adresse donnée par l’emplacement spécifié. Il retourne ensuite une interface à ce module.
GetMostDerivedObject utilise le système de type du débogueur pour déterminer le type d’exécution d’un objet à partir de son type statique. Cette méthode utilise uniquement les informations symboliques et les heuristiques disponibles au niveau de la couche système de type pour effectuer cette analyse. Ces informations peuvent inclure des informations RTTI C++ (informations sur le type d’exécution) ou l’analyse de la forme des tables de fonctions virtuelles de l’objet. Il n’inclut pas d’éléments tels que le concept de type d’exécution préféré sur un IModelObject. Si l’analyse ne trouve pas un type d’exécution ou ne trouve pas un type d’exécution différent du type statique passé dans la méthode, l’emplacement et le type d’entrée peuvent être passés. La méthode n’échoue pas pour ces raisons.
Interface de symbole individuel de base : IDebugHostSymbol
Chaque symbole qui peut être retourné à partir de l’hôte du modèle de données dérive d’une certaine manière de IDebugHostSymbol. Il s’agit de l’interface principale que chaque symbole implémente, quel que soit le type de symbole. Selon le type de symbole, un symbole donné peut implémenter un ensemble d’autres interfaces qui retournent des attributs plus spécifiques au type de symbole représenté par cette interface. L’interface IDebugHostSymbol2/IDebugHostSymbol est définie comme suit :
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;
}
Il est très important de noter que cette interface représente de nombreux types de symboles, délimités par l’énumération SymbolKind qui a des valeurs comme suit :
Enumarant | Signification |
---|---|
Symbole | Type de symbole non spécifié |
SymbolModule | Le symbole est un module et peut être interrogé pour IDebugHostModule |
SymbolType | Le symbole est un type et peut être interrogé pour IDebugHostType |
SymbolField | Le symbole est un champ (membre de données au sein d’une structure ou d’une classe) et peut être interrogé pour IDebugHostField |
SymbolConstant | Le symbole est une valeur constante et peut être interrogé pour IDebugHostConstant |
SymbolData | Le symbole est des données qui ne sont pas membres d’une structure ou d’une classe et qui peuvent être interrogés pour IDebugHostData |
SymbolBaseClass | Le symbole est une classe de base et peut être interrogé pour IDebugHostBaseClass |
SymbolPublic | Le symbole est une entrée dans la table publique d’un module (sans informations de type) et peut être interrogé pour IDebugHostPublic |
SymbolFunction | Le symbole est une fonction et peut être interrogé pour IDebugHostData |
La méthode GetContext retourne le contexte dans lequel le symbole est valide. Bien que cela représente des éléments tels que la cible de débogage et l’espace de processus/d’adressage dans lequel le symbole existe, il peut ne pas être aussi spécifique qu’un contexte récupéré à partir d’autres moyens (par exemple, à partir d’un IModelObject).
La méthode EnumerateChildren retourne un énumérateur qui énumère tous les enfants d’un symbole donné. Pour un type C++, par exemple, les classes de base, les champs, les fonctions membres et autres sont tous considérés comme des enfants du symbole de type.
Interface du module : IDebugHostModule
La notion du débogueur d’un module chargé dans un espace d’adressage est représentée de deux manières distinctes dans le modèle de données : au niveau du système de type via l’interface IDebugHostModule. Ici, un module est un symbole et les attributs principaux du module sont des appels de méthode d’interface projetés au niveau du modèle de données via le modèle de données Debugger.Models.Module. Il s’agit d’une encapsulation extensible de la représentation de type système IDebugHostModule d’un module.
L’interface IDebugHostModule est définie comme suit (en ignorant les méthodes génériques pour 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;
}
La méthode GetImageName retourne le nom de l’image du module. Selon la valeur de l’argument allowPath, le nom de l’image retournée peut inclure ou non le chemin d’accès complet à l’image.
La méthode GetBaseLocation retourne l’adresse de charge de base du module en tant que structure d’emplacement. La structure d’emplacement retournée pour un module fait généralement référence à une adresse virtuelle.
La méthode GetVersion retourne des informations de version sur le module (en supposant que ces informations peuvent être lues correctement dans les en-têtes). Si une version donnée est demandée (via un pointeur de sortie non nullptr) et qu’elle ne peut pas être lue, un code d’erreur approprié est retourné à partir de l’appel de méthode.
La méthode FindTypeByName recherche un type défini dans le module par le nom de type et retourne un symbole de type pour celui-ci. Cette méthode peut retourner un IDebugHostType valide qui ne serait jamais retourné via une récursivité explicite des enfants du module. L’hôte de débogage peut autoriser la création de types dérivés, des types qui ne sont jamais utilisés dans le module lui-même, mais dérivés de types qui le sont. Par exemple, si la structure MyStruct est définie dans les symboles du module mais que le type MyStruct ** n’est jamais utilisé, la méthode FindTypeByName peut légitimement renvoyer un symbole de type pour MyStruct ** même si ce nom de type n’apparaît jamais explicitement dans les symboles du module.
La méthode FindSymbolByRVA trouvera un seul symbole correspondant à l’adresse virtuelle relative donnée dans le module. S’il n’y a pas un seul symbole au niveau de l’appliance virtuelle RVA fournie (par exemple, il existe plusieurs correspondances), une erreur est retournée par cette méthode. Notez que cette méthode préférera retourner un symbole privé plutôt qu’un symbole dans la table publique.
La méthode FindSymbolByName trouvera un seul symbole global du nom donné dans le module. S’il n’existe pas de symbole correspondant au nom donné, une erreur est retournée par cette méthode. Notez que cette méthode préférera retourner un symbole privé plutôt qu’un symbole dans la table publique.
Accès au système de type : IDebugHostType2 / IDebugHostType
Un type de langue/natif donné est décrit par les interfaces IDebugHostType2 ou IDebugHostType. Notez que certaines des méthodes de ces interfaces s’appliquent uniquement à des types spécifiques de types. Un symbole de type donné peut faire référence à l’un des types suivants, comme décrit par l’énumération TypeKind :
Type Kind | Description |
---|---|
TypeUDT | Type défini par l’utilisateur (struct, classe, union, etc...). Un objet de modèle qui a un type natif dont le type est TypeUDT a une représentation canonique d’ObjectTargetObject où le type est toujours conservé à l’intérieur de l’IModelObject correspondant. |
TypePointer | Pointeur. Un objet de modèle qui a un type natif dont le type est TypePointer a une représentation canonique d’ObjectIntrinsic où la valeur du pointeur est égale à zéro étendue à VT_UI8 et conservée en tant que données intrinsèques dans cette forme 64 bits. Tout symbole de type de TypePointer a un type de base (tel que retourné par la méthode GetBaseType) du type vers lequel pointe le pointeur. |
TypeMemberPointer | Pointeur vers un membre de classe. Un objet de modèle qui a un type natif dont le type est TypeMemberPointer a une représentation canonique qui est intrinsèque (la valeur étant identique à la valeur du pointeur). La signification exacte de cette valeur est spécifique au compilateur/à l’hôte de débogage. |
TypeArray | Tableau. Un objet de modèle qui a un type natif dont le type est TypeArray a une représentation canonique d’ObjectTargetObject. L’adresse de base du tableau est l’emplacement de l’objet (récupéré via la méthode GetLocation) et le type du tableau est toujours conservé. Tout symbole de type de TypeArray a un type de base (tel que retourné par la méthode GetBaseType) du type dont le tableau est un tableau. |
TypeFunction | Fonction. |
TypeTypedef | Typedef. Un objet de modèle qui a un type natif dont le type serait Sinon TypeTypedef a une représentation canonique identique à la représentation canonique du type final sous-jacent au typedef. Cela semble complètement transparent pour l’utilisateur final de l’objet et les informations de type, sauf si les méthodes typedef explicites de IDebugHostType2 sont utilisées pour interroger les informations typedef ou s’il existe un modèle de données explicite inscrit auprès du typedef. Notez que la méthode GetTypeKind ne retournera jamais TypeTypedef. Chaque méthode retourne ce que le type final sous-jacent au typedef retournerait. Il existe des méthodes spécifiques à typedef sur IDebugHostType2 qui peuvent être utilisées pour obtenir les informations spécifiques à typedef. |
TypeEnum | Énumération. Un objet de modèle qui a un type natif dont le type est TypeEnum a une représentation canonique d’ObjectIntrinsic où la valeur et le type de l’intrinsèque sont identiques à la valeur d’énumération. |
TypeIntrinsic | Intrinsèque (type de base). Un objet de modèle qui a un type natif dont le type est TypeIntrinsic a une représentation canonique d’ObjectIntrinsic. Les informations de type peuvent ou non être conservées, en particulier si le type sous-jacent est entièrement décrit par le type de données variant (VT_*) des données intrinsèques stockées dans l’IModelObject |
L’interface globale IDebugHostType2 /IDebugHostType est définie comme suit (à l’exclusion des méthodes 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;
}
Méthodes générales IDebugHostType2/IDebugHostType
Les méthodes IDebugHostType suivantes sont générales à tout type, quel que soit le type retourné par la méthode 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;
La méthode GetTypeKind retourne le type de type (pointeur, tableau, intrinsèque, etc...) auquel le symbole fait référence.
La méthode GetSize retourne la taille du type (comme si l’on avait effectué sizeof(type) en C++).
Si le type est un dérivé d’un autre type unique (par exemple , car MyStruct * est dérivé de MyStruct'), la méthode GetBaseType retourne le type de base de la dérivation. Pour les pointeurs, cela retourne le type pointé vers. Pour les tableaux, cela retourne ce dont le tableau est un tableau. Si le type n’est pas un tel type dérivé, une erreur est retournée.
La méthode GetHashCode retourne un code de hachage 32 bits pour le type . À l’exception d’une correspondance globale (par exemple, une signature de type équivalente à * qui correspond à tout si l’hôte l’autorise), tout type instance qui peut correspondre à une signature de type particulière doit retourner le même code de hachage. Cette méthode est utilisée conjointement avec les signatures de type afin de faire correspondre les signatures de type aux instances de type.
Méthodes intrinsèques IDebugHostType2/IDebugHostType
Les méthodes IDebugHostType suivantes sont spécifiques aux types intrinsèques (ou aux types qui contiennent des données intrinsèques telles que des énumérations) :
STDMETHOD(GetIntrinsicType)(_Out_opt_ IntrinsicKind *intrinsicKind, _Out_opt_ VARTYPE *carrierType) PURE;
La méthode GetIntrinsicType retourne des informations sur le type d’intrinsèque du type. Deux valeurs sont retournées à partir de cette méthode :
- Le type intrinsèque indique le type global (par exemple, entier, non signé, virgule flottante) mais pas la taille du type (par exemple : 8 bits, 16 bits, 32 bits, 64 bits)
- Le type porteur indique comment le type intrinsèque est incorporé dans une structure VARIANT. Il s’agit d’une constante VT_*.
La combinaison des deux valeurs fournit l’ensemble complet d’informations sur l’intrinsèque.
Méthodes bitfield IDebugHostType2/IDebugHostType
Les méthodes IDebugHostType suivantes sont spécifiques aux types qui stockent des données dans des champs de bits. Les informations sur le positionnement du champ de bits dans une intrinsèque sont stockées dans le cadre du symbole de type dans le modèle de données plutôt que comme un attribut de l’emplacement.
STDMETHOD(GetBitField)(_Out_ ULONG* lsbOfField, _Out_ ULONG* lengthOfField) PURE;
Si un membre donné d’une structure de données est un champ de bits (par exemple, ULONG MyBits:8), les informations de type du champ comportent des informations sur le placement du champ binaire. La méthode GetBitField peut être utilisée pour récupérer ces informations. Cette méthode échoue sur n’importe quel type qui n’est pas un champ de bits. C’est la seule raison pour laquelle la méthode échoue. Il suffit d’appeler cette méthode et d’examiner la réussite/l’échec pour distinguer un champ bit d’un champ non bit. Si un type donné se trouve être un champ de bits, les positions de champ sont définies par l’ensemble demi-ouvert (lsbOfField + lengthOfField : lsbOfField]
Méthodes associées au pointeur IDebugHostType2/IDebugHostType
Les méthodes IDebugHostType suivantes sont spécifiques aux types de pointeurs. Tels sont les types où GetTypeKind retourne TypePointer ou TypeMemberPointer':
STDMETHOD(GetPointerKind)(_Out_ PointerKind* pointerKind) PURE;
STDMETHOD(GetMemberType)(_Out_ IDebugHostType** memberType) PURE;
Pour les types qui sont des pointeurs, la méthode GetPointerKind retourne le type de pointeur. Cela est défini par l’énumération PointerKind.
Pour les types qui sont pointeur vers membre (comme indiqué par un type de type TypeMemberPointer), la méthode GetMemberType retourne la classe dont le pointeur est un pointeur vers un membre.
Méthodes associées à IDebugHostType2/IDebugHostType Array
Les tableaux sont des types où GetTypeKind retourne TypeArray. Notez que les tableaux définis par le système de type de l’hôte de débogage ne sont pas identiques aux tableaux unidimensionnels monodimensionnels, basés sur un index zéro, empaquetés et unidimensionnels linéaires que C utilise. Les tableaux de style C s’intègrent dans la définition, mais l’étendue globale d’un tableau est plus large dans IDebugHostType. Un tableau dans l’hôte de débogage peut être multidimensionnel et chaque dimension du tableau est définie par un descripteur appelé ArrayDimensionThis descripteur comporte les champs suivants :
Champ | Signification |
---|---|
LowerBound | Index de base du tableau sous forme de valeur 64 bits signée. Pour un tableau de style C, il s’agit toujours de zéro. Ce n’est pas nécessaire. Une dimension individuelle d’un tableau peut être considérée comme commençant à n’importe quel index 64 bits, même négatif. |
Longueur | Longueur de la dimension de tableau sous forme de valeur 64 bits non signée. Les indics du tableau s’étendent sur le jeu à moitié ouvert [LowerBound, LowerBound + Length). |
Stride | Définit la foulée de la dimension de tableau. Pour une augmentation d’un (de N à N + 1) dans l’index de cette dimension, cela indique le nombre d’octets à déplacer dans la mémoire. Pour un tableau de style C, il s’agit de la taille de chaque élément du tableau. Ce n’est pas nécessaire. Le remplissage entre les éléments peut être exprimé sous la forme d’une foulée supérieure à la taille de chaque élément individuel. Pour les tableaux multidimensionnels, cette valeur indique comment déplacer une dimension entière vers l’avant. Prenons l’exemple d’une matrice M x N. Cela peut être décrit sous forme de ligne principale sous la forme de deux dimensions : |
{ [LowerBound: 0, Length: M, Stride: N \* sizeof(element)], [LowerBound: 0, Length: N, Stride: sizeof(element)]}
ou il peut être décrit sous forme de colonne principale comme deux dimensions :
{ [LowerBound: 0, Length: M, Stride: sizeof(element)], [LowerBound: 0, Length: N, Stride: M \* sizeof(element)]}
Le concept ArrayDimension permet ce degré de flexibilité.
Les méthodes IDebugHostType suivantes sont spécifiques aux types de tableau.
STDMETHOD(GetArrayDimensionality)(\_Out_ ULONG64\* arrayDimensionality) PURE;
STDMETHOD(GetArrayDimensions)(\_In_ ULONG64 dimensions, \_Out_writes_(dimensions) ArrayDimension \*pDimensions) PURE;
La méthode GetArrayDimensionality retourne le nombre de dimensions dans laquelle le tableau est indexé. Pour les tableaux de style C, la valeur retournée ici est toujours 1.
La méthode GetArrayDimensions retourne un ensemble de descripteurs, un pour chaque dimension du tableau, comme indiqué par la méthode GetArrayDimensionality. Chaque descripteur est une structure ArrayDimension qui décrit l’index de départ, la longueur et la foulée avant de chaque dimension de tableau. Cela permet de descriptions de constructions de tableau beaucoup plus puissantes que celles autorisées dans le système de type C.
Pour les tableaux de style C, une dimension de tableau unique est retournée ici avec des valeurs qui sont toujours les suivantes :
- LowerBound = 0
- Length = ARRAYSIZE(array)
- Stride = sizeof(elementType)
IDebugHostType2/IDebugHostType, méthodes associées à la fonction
Les types qui indiquent qu’ils sont des types de fonction via un type de TypeFunction prennent en charge les méthodes suivantes dans IDebugHostType et 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;
La méthode GetFunctionCallingConvention retourne la convention d’appel de la fonction. Ce type est retourné en tant que membre de l’énumération CallingConventionKind.
La méthode GetFunctionReturnType retourne le type de retour de la fonction.
La méthode GetFunctionParameterTypeCount retourne le nombre d’arguments que prend la fonction. Notez que le marqueur d’argument de variable basé sur des points de suspension C/C++ n’est pas pris en compte dans ce nombre. La présence de tels doit être détectée via la méthode GetFunctionVarArgsKind. Cela inclut uniquement les arguments avant les points de suspension.
La méthode GetFunctionParameterTypeAt retourne le type de l’argument i-th à la fonction .
La méthode GetFunctionVarArgsKind retourne si une fonction donnée utilise une liste d’arguments de variable et, le cas échéant, le style d’arguments de variable qu’elle utilise. Tel est défini par un membre de l’énumération VarArgsKind définie comme suit :
Énumération | Signification |
---|---|
VarArgsNone | La fonction ne prend pas d’arguments de variable. |
VarArgsCStyle | La fonction est une fonction varargs de style C (returnType(arg1, arg2, ...)). Le nombre d’arguments signalés par la fonction n’inclut pas l’argument de sélection. Tout passage d’argument de variable se produit après le nombre d’arguments retourné par la méthode GetFunctionParameterTypeCount. |
IDebugHostType2 GetFunctionVarArgsKind
La méthode GetFunctionVarArgsKind retourne si une fonction donnée utilise une liste d’arguments de variable et, le cas échéant, le style d’arguments de variable qu’elle utilise. Tel est défini par un membre de l’énumération VarArgsKind définie comme suit :
Méthodes liées au typedef IDebugHostType2/IDebugHostType
Tout type qui est un typedef se comporte comme si le type était le type final sous-jacent au typedef. Cela signifie que les méthodes telles que GetTypeKind n’indiquent pas que le type est un typedef. De même, GetBaseType ne retourne pas le type auquel la définition fait référence. Ils indiquent plutôt qu’ils se comportent comme s’ils avaient été appelés sur la définition finale sous-jacente au typedef. Par exemple :
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
Un IDebugHostType pour « PMYSTRUCT ou PTRMYSTRUCT » signale les informations suivantes :
- La méthode GetTypeKind renvoie TypePointer. Le dernier type sous-jacent MYSTRUCT * est en effet un pointeur.
- La méthode GetBaseType retourne un type pour MYSTRUCT. Le type sous-jacent de MYSTRUCT * est MYSTRUCT.
La seule différence ici est la façon dont les méthodes spécifiques à typedef sur IDebugHostType2 se comportent. Ces méthodes sont les suivantes :
STDMETHOD(IsTypedef)(_Out_ bool* isTypedef) PURE;
STDMETHOD(GetTypedefBaseType)(_Out_ IDebugHostType2** baseType) PURE;
STDMETHOD(GetTypedefFinalBaseType)(_Out_ IDebugHostType2** finalBaseType) PURE;
Dans cet exemple :
- La méthode IsTypedef retourne true pour PMYSTRUCT et PTRMYSTRUCT
- La méthode GetTypedefBaseType renvoie MYSTRUCT * pour PMYSTRUCT et PMYSTRUCT pour PTRMYSTRUCT
- La méthode GetTypedefFinalBaseType retourne MYSTRUCT * pour les deux types
La méthode IsTypedef est la seule méthode capable de voir si un type est un typedef. La méthode GetTypeKind se comporte comme si elle était appelée sur le type sous-jacent.
La méthode GetTypedefBaseType retourne ce que la définition immédiate du typedef. Dans les exemples décrits dans la documentation :
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
cette méthode retourne MYSTRUCT * pour PMYSTRUCT et PMYSTRUCT pour PTRMYSTRUCT.
La méthode GetTypedefFinalBaseType retourne le type final pour lequel le typedef est une définition. Si le typedef est une définition d’un autre typedef, cela continuera à suivre la chaîne de définition jusqu’à ce qu’il atteigne un type qui n’est pas un typedef et ce type est retourné. Dans les exemples décrits dans la documentation :
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
cette méthode retourne MYSTRUCT * lorsqu’elle est appelée sur PMYSTRUCT ou PTRMYSTRUCT.
Méthodes de création de type 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;
Valeurs du symbole de constante : IDebugHostConstant
Pour les emplacements où des valeurs constantes sont présentes dans des informations symboliques (où une valeur particulière est un symbole qui peut ou non être une valeur constante), l’interface IDebugHostConstant exprime la notion d’une telle constante. Cela est généralement utilisé à des endroits comme les arguments de modèle où un argument donné est généralement un type, mais peut être un argument de modèle non de type (par exemple, une constante).
L’interface IDebugHostConstant est définie comme suit (en ignorant les méthodes génériques implémentées par IDebugHostSymbol) :
DECLARE_INTERFACE_(IDebugHostConstant, IDebugHostSymbol)
{
STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}
La méthode GetValue retourne la valeur de la constante empaquetée dans un VARIANT. Il est important de noter que la méthode GetType sur IDebugHostSymbol peut retourner un symbole de type spécifique pour la constante. Dans ce cas, il n’existe aucune garantie que l’empaquetage de la valeur constante telle que définie par le symbole de type est identique à l’empaquetage retourné par la méthode GetValue ici.
Accès aux membres de données : IDebugHostField
La classe IDebugHostField représente un symbole qui est un membre de données d’une classe, d’une structure, d’une union ou d’une autre construction de type. Il ne représente pas les données gratuites (par exemple, les données globales). L’interface est définie comme suit (en ignorant les méthodes génériques pour 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;
}
La méthode GetLocationKind retourne le type d’emplacement où se trouve le symbole en fonction de l’énumération LocationKind. Cette énumération peut être l’une des valeurs suivantes :
Énumération | Signification |
---|---|
LocationMember | Le champ est un membre de données régulier d’une classe, d’une structure, d’une union ou d’une autre construction de type. Il a un décalage qui est relatif à l’adresse de base de la construction de type contenant. Cette adresse de base est généralement représentée par le pointeur this. Le décalage du champ peut être récupéré via la méthode GetOffset. Les méthodes GetLocation et GetValue échouent pour un champ qui est LocationMember. |
LocationStatic | Le champ est statique et a sa propre adresse. La méthode GetLocation retourne l’emplacement abstrait (par exemple, l’adresse) du champ statique. Les méthodes GetOffset et GetValue échouent pour un champ qui est LocationStatic. |
LocationConstant | Le champ est une constante et a une valeur. La méthode GetValue retourne la valeur de la constante. Les méthodes GetOffset et GetLocation échouent pour un champ qui est LocationConstant |
LocationNone | Le champ n’a pas d’emplacement. Il peut avoir été optimisé par le compilateur ou il peut s’agir d’un champ statique qui est déclaré mais jamais défini. Quelle que soit la façon dont un tel champ est devenu, il n’a aucune présence physique ni valeur. Il n’est que dans les symboles. Toutes les méthodes d’acquisition (GetOffset, GetLocation et GetValue) échouent pour un champ qui est LocationNone. |
Pour les champs qui ont un décalage (par exemple, les champs dont le type d’emplacement indique LocationMember), la méthode GetOffset renvoie le décalage de l’adresse de base du type conteneur (le pointeur this) aux données du champ lui-même. Ces décalages sont toujours exprimés sous forme de valeurs 64 bits non signées. Si le champ donné n’a pas d’emplacement qui est un décalage par rapport à l’adresse de base du type conteneur, la méthode GetOffset échoue.
Pour les champs qui ont une adresse, quel que soit le type particulier instance (par exemple, les champs dont le type d’emplacement indique LocationStatic), la méthode GetLocation renvoie l’emplacement abstrait (adresse) du champ. Si le champ donné n’a pas d’emplacement statique, la méthode GetLocation échoue.
Pour les champs qui ont une valeur constante définie dans les informations symboliques (par exemple, les champs dont le type d’emplacement indique LocationConstant), la méthode GetValue retourne la valeur constante du champ. Si le champ donné n’a pas de valeur constante, la méthode GetValue échoue.
Accès gratuit aux données : IDebugHostData
Les données des modules qui ne sont pas membres d’un autre type sont représentées par l’interface IDebugHostData. Cette interface est définie comme suit (en ignorant les méthodes génériques pour IDebugHostSymbol) :
DECLARE_INTERFACE_(IDebugHostData, IDebugHostSymbol)
{
STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}
Toutes ces méthodes sont sémantiquement équivalentes à leurs équivalents dans IDebugHostField. La seule différence est que la méthode GetLocationKind ne renverra jamais LocationMember pour les données gratuites.
La méthode GetLocationKind retourne le type d’emplacement où se trouve le symbole en fonction de l’énumération LocationKind. Vous trouverez la description de cette énumération dans la documentation pour IDebugHostField.
Pour les données qui ont une adresse, la méthode GetLocation retourne l’emplacement abstrait (adresse) du champ. Si les données données n’ont pas d’emplacement statique, la méthode GetLocation échoue.
Pour les données dont une valeur constante est définie dans les informations symboliques (par exemple, les données dont le type d’emplacement indique LocationConstant), la méthode GetValue retourne la valeur constante du champ. Si les données données n’ont pas de valeur constante, la méthode GetValue échoue.
Classes de base : IDebugHostBaseClass
La hiérarchie d’héritage d’un type donné est exprimée par les enfants d’un symbole de type. Si un type donné dérive (au niveau de l’héritage) d’un ou plusieurs types, il y aura un ou plusieurs enfants SymbolBaseClass du symbole de type pour le type. Chacun de ces symboles SymbolBaseClass représente l’héritage immédiat d’un type particulier. Le nom de la classe de base est à la fois le nom du symbole SymbolBaseClass et celui du symbole de type pour la classe de base. La méthode GetType sur le symbole SymbolBaseClass peut être utilisée pour obtenir le symbole de type pour la classe de base elle-même. La hiérarchie d’héritage complète peut être parcourue en explorant de manière récursive les symboles enfants SymbolBaseClass. Chacun de ces symboles de classe de base est exprimé par l’interface IDebugHostBaseClass qui est définie comme suit (en ignorant les méthodes génériques pour IDebugHostSymbol) :
DECLARE_INTERFACE_(IDebugHostBaseClass, IDebugHostSymbol)
{
STDMETHOD(GetOffset)(_Out_ ULONG64* offset) PURE;
}
La méthode GetOffset retourne le décalage de la classe de base à partir de l’adresse de base de la classe dérivée. Ce décalage peut être égal à zéro ou être une valeur 64 bits non signée positive.
Symboles publics : IDebugHostPublic
Les symboles publics représentent des éléments de la table publique dans un fichier de symboles. Il s’agit en fait d’adresses d’exportation. Aucune information de type n’est associée à un symbole public, mais uniquement une adresse. À moins qu’un symbole public ne soit explicitement demandé par l’appelant, l’hôte de débogage préfère retourner des symboles privés pour chaque requête. Un symbole public est exprimé par l’interface IDebugHostPublic qui est définie comme suit (en ignorant les méthodes qui sont génériques pour IDebugHostSymbol) :
DECLARE_INTERFACE_(IDebugHostPublic, IDebugHostSymbol)
{
STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
}
Toutes ces méthodes sont sémantiquement équivalentes à leurs équivalents dans IDebugHostField. La seule différence est que la méthode GetLocationKind ne renverra jamais LocationMember ou LocationConstant pour ces symboles.
La méthode GetLocationKind retourne le type d’emplacement où se trouve le symbole en fonction de l’énumération LocationKind. Vous trouverez la description de cette énumération dans la documentation pour IDebugHostField.
Pour les données qui ont une adresse, la méthode GetLocation retourne l’emplacement abstrait (adresse) du champ. Si le public donné n’a pas d’emplacement statique, la méthode GetLocation échoue.
Signatures de module et correspondance de version : IDebugHostModuleSignature
Les signatures de module représentent un moyen de case activée si un module donné répond à un ensemble de critères concernant l’attribution de noms et le contrôle de version. Une signature de module est créée via la méthode CreateModuleSignature sur IDebugHostSymbols. Il peut correspondre au nom du module et à une plage facultative de numéros de version pour le module. Une fois qu’une telle signature est créée, le client reçoit une interface IDebugHostModuleSignature qui est définie comme suit :
DECLARE_INTERFACE_(IDebugHostModuleSignature, IUnknown)
{
STDMETHOD(IsMatch)(_In_ IDebugHostModule* pModule, _Out_ bool* isMatch) PURE;
}
La méthode IsMatch compare un module particulier (tel qu’indiqué par un symbole IDebugHostModule) à une signature, en comparant le nom et la version du module à la plage de noms et de versions indiquées dans la signature. Une indication indiquant si le symbole de module donné correspond à la signature est retournée.
Signatures de type et correspondance de type : IDebugHostTypeSignature
Les signatures de type représentent un moyen de case activée si un type donné instance répond à un ensemble de critères concernant le nom du type, les arguments génériques du type et le module dans lequel se trouve le type. Une signature de type est créée via la méthode CreateTypeSignature sur IDebugHostSymbols. Une fois qu’une telle signature est créée, le client reçoit une interface IDebugHostTypeSignature qui est définie comme suit :
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;
}
La méthode GetHashCode retourne un code de hachage 32 bits pour la signature de type. L’hôte de débogage garantit qu’il existe une synchronisation dans l’implémentation entre le code de hachage retourné pour les instances de type et le code de hachage retourné pour les signatures de type. À l’exception d’une correspondance globale, si un type instance est capable de correspondre à une signature de type, les deux ont le même code de hachage 32 bits. Cela permet une comparaison et une correspondance rapides initiales entre un type instance et une pléthore de signatures de type enregistrées auprès du gestionnaire de modèle de données.
La méthode IsMatch retourne une indication indiquant si un type particulier instance correspond aux critères spécifiés dans la signature de type. Si c’est le cas, une indication de ceci est retournée, ainsi qu’un énumérateur qui indique toutes les parties spécifiques du type instance (sous forme de symboles) qui correspondent aux caractères génériques dans la signature de type.
La méthode CompareAgainst compare la signature de type à une autre signature de type et retourne la façon dont les deux signatures se comparent. Le résultat de comparaison retourné est un membre de l’énumération SignatureComparison qui est définie comme suit :
Énumération | Signification |
---|---|
Unrelated | Il n’existe aucune relation entre les deux signatures ou types comparés. |
Ambigu | Une signature ou un type compare de manière ambiguë à l’autre. Pour deux signatures de type, cela signifie qu’il existe des instances de type potentielles qui peuvent correspondre à l’une ou l’autre signature également. Par exemple, les deux signatures de type présentées ci-dessous sont ambiguës. Signature 1 : std::pair<*, int> Signature 2 : std::pair<int,*> car le type instance std::pair<int, int> correspond également à un (les deux ont une correspondance concrète et une correspondance de caractères génériques). |
LessSpecific | Une signature ou un type est moins spécifique que l’autre. Souvent, cela signifie que la signature la moins spécifique a un caractère générique où la plus spécifique a un type concret. Par exemple, la première signature ci-dessous est moins spécifique que la deuxième. Signature 1 : std::pair<*, int> Signature 2 : std::pair<int, int> car elle a un caractère générique (le * ) où la seconde a un type concret (int). |
MoreSpecific | Une signature ou un type est plus spécifique que l’autre. Souvent, cela signifie que la signature la plus spécifique a un type concret où la moins spécifique a un caractère générique. Par exemple, la première signature ci-dessous est plus spécifique que la deuxième. Signature 1 : std::pair<int, int> Signature 2 : std::pair<*, int> car elle a un type concret (int) où le second a un caractère générique (le * ). |
Identique | Les deux signatures ou types sont identiques. |
Voir aussi
Cette rubrique fait partie d’une série qui décrit les interfaces accessibles à partir de C++, comment les utiliser pour créer une extension de débogueur C++ et comment utiliser d’autres constructions de modèles de données (par exemple, JavaScript ou NatVis) à partir d’une extension de modèle de données C++.
Vue d’ensemble du modèle de données C++ du débogueur
Interfaces C++ du modèle de données du débogueur
Objets C++ du modèle de données du débogueur
Interfaces supplémentaires du modèle de données C++ du débogueur