Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
Cette rubrique fournit et 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 débogueur
l’hôte de 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 composant 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 par le modèle de données principal ainsi que par toute extension qui interopérait avec le modèle de données.
L’ensemble d’interfaces principales est :
| Nom de l’interface | Description |
|---|---|
| IDebugHost | Interface principale de l’hôte de débogage. |
| IDebugHostStatus | Interface permettant à un client d’interroger l’état 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 de l’hôte et du modèle de données |
| 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 des 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 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 un genre de symbole. |
| IDebugHostType / IDebugHostType2 | Représente un type natif/langage. |
| 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 dans une structure ou 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 IDebugHostField) |
| IDebugHostBaseClass | Représente une classe de base. |
| IDebugHostPublic | Représente un symbole dans la table publique d’une base de données PDB. Cela n’a pas d’informations de type associées. 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 |
l’interface hôte principale : IDebugHost
L’interface IDebugHost est l’interface principale de n’importe quel hôte de modèle de données. Elle est définie comme suit :
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 principale de l’hôte, le cas échéant 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 ceci 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 actif dans l’interface utilisateur de l’hôte de débogage. L’objet de contexte retourné est largement opaque pour l’appelant, mais il est important de passer entre les appels à l’hôte de débogage. Lorsqu’un appelant est, par exemple, la lecture de la mémoire, il est important de connaître le processus et l’espace d’adressage à partir duquel la mémoire est lue. Cette notion est encapsulée dans la notion de l’objet de contexte retourné 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) lorsqu’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 ordinales doivent être affichées en décimales ou hexadécimales si ce n’est pas le cas.
Notez que les valeurs de propriété dans le magasin de métadonnées par défaut doivent être résolues manuellement et doivent transmettre 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.
l’interface d’état : IDebugHostStatus
L’interface IDebugHostStatus permet à un client du modèle de données ou à l’hôte de débogage de se renseigner sur certains aspects de l’état de l’hôte de débogage. L’interface est définie comme suit :
DECLARE_INTERFACE_(IDebugHostStatus, IUnknown)
{
STDMETHOD(PollUserInterrupt)(_Out_ bool* interruptRequested) PURE;
}
La méthode PollUserInterrupt est utilisée pour déterminer si l’utilisateur de l’hôte de débogage a demandé une interruption de l’opération actuelle. Un accesseur de propriété dans le modèle de données peut, par exemple, appeler du code arbitraire (par exemple, une méthode JavaScript). Ce code peut prendre un certain temps. Afin de maintenir la réactivité de l’hôte de débogage, tout code de ce type qui peut prendre un certain temps doit rechercher une demande d’interruption via l’appel de cette méthode. Si la valeur interruptRequested revient comme true, l’appelant doit immédiatement abandonner et retourner un résultat de E_ABORT.
l’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 maintenez un objet, il est important de savoir à quel endroit un objet provient - quel processus est-il dans, l’espace d’adressage auquel il est associé. La connaissance de ces informations permet l’interprétation correcte des éléments tels que les valeurs de pointeur. Un objet du 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 d’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 d’IDebugHostSymbol
En outre, il existe deux valeurs qui ont une signification particulière dans le contexte d’une interface IDebugHostContext qui est retournée à partir d’un modèle de données ou à une méthode hôte de débogage :
nullptr: indication qu’il n’existe aucun contexte. Il est parfaitement valide pour certains objets d’avoir aucun contexte. L’objet Débogueur dans l’espace de noms racine du modèle de données ne fait référence à rien dans un processus ou un espace d’adressage spécifique. Il n’a pas de contexte.
USE_CURRENT_HOST_CONTEXT: valeur sentinelle indiquant qu’une valeur doit utiliser le contexte actuel de l’interface utilisateur 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 accepte un IDebugHostContext d’entrée au lieu d’appeler explicitement la méthode GetCurrentContext d’IDebugHost. Notez que le passage explicite de USE_CURRENT_HOST_CONTEXT est souvent plus performant que d’obtenir explicitement le 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 à la 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 ceci 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.
Le 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 acheminer ces erreurs si nécessaire. L’interface est définie 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é.
L’é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 sont les moyens 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 à 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 boxed 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, les 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 supplémentaires non linguistiques 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 permet des types anonymes, des requêtes LINQ, des qualificateurs de module, des spécificateurs de format et d’autres fonctionnalités autres que C/C++.
IDebugHostEvaluator2
La méthode AssignTo effectue une affectation en fonction de la sémantique du langage en cours de débogage.
l’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, par exemple, inclure l’évaluateur d’expression. L’interface IDebugHostExtensibility est le moyen par lequel ces points d’extensibilité sont accessibles. L’interface est définie 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.
l’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, toute 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 offshoots d’IModelObject -- sont conçus pour être portables, ils 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 ne doit être qu’une extension de moteur tant que c’est le 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 du modèle objet effectuées dans DebugExtensionInitialize.
- DebugExtensionCanUnload: méthode qui retourne si l’extension peut décharger. S’il existe toujours des objets COM en direct dans l’extension, il doit indiquer cela. Il s’agit de l’équivalent du débogueur de COM DllCanUnloadNow. Si cela retourne la S_FALSE indication de l’incapacité de décharger, le débogueur peut interroger cela ultérieurement pour voir si un déchargement est sécurisé ou peut réinitialiser l’extension en appelant DebugExtensionInitialize à nouveau. 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
l’interface bridge : IHostDataModelAccess
Comme mentionné, lorsque DebugExtensionInitialize est appelé, il crée un client de débogage et obtient l’accès au modèle de données. Un tel 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 sur l’interface de pont qui fournit l’accès 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ée par l’interface IDebugHost retournée Le composant principal du modèle de données - le gestionnaire de modèles de données est exprimé par l’interface IDataModelManager retournée.
interfaces système du modèle de données du débogueur
l’hôte de modèle de données
Le modèle de données du débogueur est conçu pour être un système composant 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 par le modèle de données principal ainsi que par toute extension qui interopérait 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 aux symboles 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 un genre de symbole. |
| IDebugHostType / IDebugHostType2 | Représente un type natif/langage. |
| 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 dans une structure ou 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 IDebugHostField) |
| IDebugHostBaseClass | Représente une classe de base. |
| IDebugHostPublic | Représente un symbole dans la table publique d’une base de données PDB. Cela n’a pas d’informations de type associées. 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 l’état 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 de l’hôte et du modèle de données |
| 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 des parties de celui-ci (par exemple, l’évaluateur d’expression). |
l’interface symbolique principale : IDebugHostSymbols
L’interface IDebugHostSymbols est le point de départ principal pour accéder aux symboles dans la cible de débogage. Cette interface peut être interrogée à partir d’une instance d’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. Il existe trois composants à une signature de module :
- 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
- Une 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 celle 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 celle 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 module et le nom de 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 comme *) 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. Cela est similaire à la méthode CreateTypeSignature, sauf que, au lieu de transmettre un module spécifique correspondant à la signature, l’appelant transmet les arguments nécessaires pour créer une signature de module (comme si la signature du module a é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 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 retourne une interface à celui-ci. Il est légal de rechercher le module par nom avec ou sans l’extension de fichier.
La méthode FindModuleByLocation examine le contexte hôte donné et détermine le module qui 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 des informations symboliques et des heuristiques disponibles au niveau de la couche système de type afin d’effectuer cette analyse. Ces informations peuvent inclure le RTTI C++ (informations de type d’exécution) ou l’analyse de la forme des tables de fonctions virtuelles de l’objet. Il n’inclut pas de choses telles 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 d’entrée et le type peuvent être passés. La méthode ne échoue pas pour ces raisons.
l’interface de symbole individuelle principale : IDebugHostSymbol
Chaque symbole qui peut être retourné à partir de l’hôte de modèle de données dérive à une certaine façon d’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 uniques au type particulier 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 | Sens |
|---|---|
| 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 sont interrogeables 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 traitement/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 les types similaires sont tous considérés comme des enfants du symbole de type.
l’interface de module : IDebugHostModule
La notion de 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 projecté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 IDebugHostModule du système de type d’un module.
L’interface IDebugHostModule est définie comme suit (ignorer 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 ou non inclure le chemin complet de l’image.
La méthode GetBaseLocation retourne l’adresse de chargement 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 avec succès sur 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é par le biais d’une récursivité explicite des enfants du module. L’hôte de débogage peut autoriser la création de types dérivés : les types qui ne sont jamais utilisés dans le module lui-même, mais dérivés de types qui 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 renvoyer légitimement un symbole de type pour MyStruct ** malgré ce nom de type qui n’apparaît jamais explicitement dans les symboles du module.
La méthode FindSymbolByRVA trouvera un symbole correspondant unique à l’adresse virtuelle relative donnée dans le module. S’il n’existe pas de symbole unique à 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ère retourner un symbole privé sur un symbole dans la table publique.
La méthode FindSymbolByName trouvera un symbole global unique 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ère retourner un symbole privé sur un symbole dans la table publique.
l’accès au système de type : IDebugHostType2 / IDebugHostType
Un type de langage/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 de type | Description |
|---|---|
| TypeUDT | Type défini par l’utilisateur (struct, classe, union, etc.). 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 du IModelObject correspondant. |
| TypePointer | Pointeur. 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 nulle étendue à VT_UI8 et conservée en tant que données intrinsèques dans cette forme 64 bits. Tout symbole de type TypePointer a un type de base (tel qu’il est retourné par la méthode GetBaseType) du type vers lequel pointe le pointeur. |
| TypeMemberPointer | Pointeur vers un membre de classe. Objet de modèle qui a un type natif dont le type est TypeMemberPointer a une représentation canonique intrinsèque (la valeur étant identique à la valeur du pointeur). La signification exacte de cette valeur est propre au compilateur/à l’hôte de débogage. |
| TypeArray | Tableau. 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 TypeArray a un type de base (tel qu’il est retourné par la méthode GetBaseType) du type dont le tableau est un tableau. |
| TypeFunction | Fonction. |
| TypeTypedef | Typedef. 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 apparaît complètement transparent pour l’utilisateur final de l’objet et les informations de type, sauf si les méthodes de typedef explicites d’IDebugHostType2 sont utilisées pour interroger les informations typedef ou si un modèle de données explicite est inscrit sur le typedef. Notez que la méthode GetTypeKind ne retourne jamais TypeTypedef. Chaque méthode retourne ce que le type final sous-jacent le typedef retournerait. Il existe des méthodes spécifiques typedef sur IDebugHostType2 qui peuvent être utilisées pour obtenir les informations spécifiques de typedef. |
| TypeEnum | Énumération. 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). 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 être conservées ou non, 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 le IModelObject |
L’interface IDebugHostType2 / IDebugHostType globale est définie comme suit (à l’exception 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 à n’importe quel 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’un avait fait sizeof(type) en C++).
Si le type est un dérivé d’un autre type unique (par exemple, en tant que 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 ce qui est autorisé par l’hôte), toute instance de type 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 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 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 d’opérateur indique comment le type intrinsèque est packé 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 l’emplacement du champ de bits au sein d’une intrinsèque sont stockées dans le cadre du symbole de type dans le modèle de données plutôt que d’être 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 pour le champ contiennent des informations sur le positionnement du champ de bits. 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 échouera. Il suffit d’appeler cette méthode et d’examiner la réussite/l’échec pour distinguer un champ de bits d’un champ non bit. Si un type donné se présente comme un champ de bits, les positions de champ sont définies par l’ensemble demi-ouvert (lsbOfField + lengthOfField : lsbOfField]
méthodes liées au pointeur IDebugHostType2/IDebugHostType
Les méthodes IDebugHostType suivantes sont spécifiques aux types de pointeurs. Il s’agit de 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 type TypeMemberPointer), la méthode GetMemberType retourne la classe dont le pointeur est un pointeur vers un membre.
méthodes connexes IDebugHostType2/IDebugHostType Array
Les tableaux sont des types où GetTypeKind retourne TypeArray. Notez que les tableaux tels que définis par le système de type de l’hôte de débogage ne sont pas identiques à ceux basés sur un index unidimensionnel unidimensionnel et unidimensionnel empaquetés, utilisés par C. 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 dans le tableau est définie par un descripteur appelé descripteur ArrayDimensionThis avec les champs suivants :
| Champ | Sens |
|---|---|
| LowerBound | Index de base du tableau sous forme de valeur 64 bits signée. Pour un tableau de style C, cela sera toujours égal à zéro. Il n’a pas besoin d’être. Une dimension individuelle d’un tableau peut être considérée comme commençant à n’importe quel index 64 bits, même un index négatif. |
| Longueur | Longueur de la dimension de tableau comme valeur 64 bits non signée. Les indicies du tableau s’étendent sur le demi-jeu ouvert [LowerBound, LowerBound + Length). |
| Enjambée | Définit le pas 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 vers l’avant en mémoire. Pour un tableau de style C, il s’agit de la taille de chaque élément du tableau. Il n’a pas besoin d’être. Le remplissage entre les éléments peut être exprimé sous la forme d’une progression 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. Considérez une matrice M x N. Cela peut être décrit sous forme principale de ligne sous la forme de deux dimensions : |
{ [LowerBound: 0, Length: M, Stride: N \* sizeof(element)], [LowerBound: 0, Length: N, Stride: sizeof(element)]}
ou il peut également être décrit sous forme principale de colonne sous la forme 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 tableaux.
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 sera 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 progression vers l’avant de chaque dimension de tableau. Cela permet des 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 :
- LowerBound = 0
- Length = ARRAYSIZE(array)
- Stride = sizeof(elementType)
méthodes liées à la fonction IDebugHostType2/IDebugHostType
Les types qui indiquent qu’ils sont des types de fonction via un type DeFunction 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. Tel 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 C/C++ n’est pas pris en compte dans ce nombre. La présence de ce type 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 variables et, le cas échéant, quel style d’arguments de variable il utilise. Cela est défini par un membre de l’énumération VarArgsKind définie comme suit :
| Énumération | Sens |
|---|---|
| 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 variable se produit après le nombre d’arguments retournés par la méthode GetFunctionParameterTypeCount. |
IDebugHostType2 GetFunctionVarArgsKind
La méthode GetFunctionVarArgsKind retourne si une fonction donnée utilise une liste d’arguments variables et, le cas échéant, quel style d’arguments de variable il utilise. Cela est défini par un membre de l’énumération VarArgsKind définie comme suit :
méthodes connexes typedef IDebugHostType2/IDebugHostType
Tout type qui est un typedef se comporte comme si le type est 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 étaient 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 retourne 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 retourne 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 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 que ce type sera 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 de symboles constants : IDebugHostConstant
Pour les emplacements où les 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 de 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 plutôt ê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’emballage de la valeur constante telle que définie par le symbole de type est identique à celui 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 (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 auquel se trouve le symbole en fonction de l’énumération LocationKind. Cette énumération peut être l’une des valeurs suivantes :
| Énumération | Sens |
|---|---|
| LocationMember | Le champ est un membre de données standard 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 conteneur. Cette adresse de base est généralement représentée par ce pointeur. 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, 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 aucun emplacement. Il a peut-être été optimisé par le compilateur ou il peut s’agir d’un champ statique déclaré mais jamais défini. Quelle que soit la façon dont un tel champ est venu être, il n’a pas de présence physique ou de valeur. Ce 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 (ce pointeur) 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 de l’adresse de base du type conteneur, la méthode GetOffset échoue.
Pour les champs qui ont une adresse indépendamment de l’instance de type particulière (par exemple, les champs dont le type d’emplacement indique LocationStatic), la méthode GetLocation retourne 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 (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 renvoie jamais LocationMember pour les données gratuites.
La méthode GetLocationKind retourne le type d’emplacement auquel se trouve le symbole en fonction de l’énumération LocationKind. Vous trouverez la description de cette énumération dans la documentation de 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 données n’ont pas d’emplacement statique, la méthode GetLocation échoue.
Pour datawhich a une valeur constante 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 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 (par 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 ainsi que 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 de 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 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 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 les éléments de la table publique dans un fichier de symboles. Elles sont, en effet, des adresses d’exportation. Il n’existe pas d’informations de type associées à un symbole public . Seule une adresse. Sauf si un symbole public est explicitement demandé par l’appelant, l’hôte de débogage préfère retourner des symboles privés pour chaque enquête. Un symbole public est exprimé par l’interface IDebugHostPublic qui est définie comme suit (ignorer les méthodes 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 renvoie jamais LocationMember ou LocationConstant pour ces symboles.
La méthode GetLocationKind retourne le type d’emplacement auquel se trouve le symbole en fonction de l’énumération LocationKind. Vous trouverez la description de cette énumération dans la documentation de 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 vérifier si un module donné répond à un ensemble de critères concernant le nommage 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 cette signature créée, le client reçoit une interface IDebugHostModuleSignature 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 (comme indiqué par un symbole IDebugHostModule) à une signature, comparant le nom et la version du module à la plage de noms et de version indiquée dans la signature. Indique si le symbole de module donné correspond à la signature est retourné.
Signatures de type et correspondance de type : IDebugHostTypeSignature
Les signatures de type représentent un moyen de vérifier si une instance de type donnée répond à un ensemble de critères relatifs au nom du type, aux arguments génériques au type et au module dans lequel se trouve le type. Une signature de type est créée via la méthode CreateTypeSignature sur IDebugHostSymbols. Une fois cette signature créée, le client reçoit une interface IDebugHostTypeSignature 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 une instance de type est capable de correspondre à une signature de type, les deux auront le même code de hachage 32 bits. Cela permet une comparaison et une correspondance rapides initiales entre une instance de type et une pléthore de signatures de type inscrites auprès du gestionnaire de modèles de données.
La méthode IsMatch retourne une indication indiquant si une instance de type particulière 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 de l’instance de type (en tant que 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 comparaison des deux signatures. Le résultat de comparaison retourné est un membre de l’énumération SignatureComparison qui est définie comme suit :
| Énumération | Sens |
|---|---|
| Sans rapport | Il n’existe aucune relation entre les deux signatures ou types comparés. |
| Ambigu | Une signature ou un type compare ambiguëment 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 des signatures également. Par exemple, les deux signatures de type indiquées ci-dessous sont ambiguës. Signature 1 : std::pair<*, int> Signature 2 : std::pair<int,*>, car l’instance de type std::pair<int, int> correspond également bien (ont une correspondance concrète et une correspondance générique). |
| LessSpecific | Une signature ou un type est moins spécifique que l’autre. Souvent, cela signifie que la signature moins spécifique a un caractère générique où le plus spécifique a un type concret. Par exemple, la première signature ci-dessous est moins spécifique que la seconde. Signature 1 : std::pair<*, int> Signature 2 : std::pair<int, int> parce qu’il a un caractère générique (le *) où le second 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ù le moins spécifique a un caractère générique. Par exemple, la première signature ci-dessous est plus spécifique que la seconde. 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 générer une extension de débogueur C++ et comment utiliser d’autres constructions de modèle 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 du débogueur C++
objets C++ du modèle de données du débogueur
modèle de données du débogueur C++ interfaces supplémentaires