Partilhar via


Interfaces do modelo de dados C++ do depurador

Este tópico fornece uma visão geral de como usar as interfaces C++ do Modelo de Dados do Depurador para estender e personalizar os recursos do depurador.

Depurador Data Model C++ Host Interfaces

O Host do Modelo de Dados do Depurador

O Modelo de Dados do Depurador foi projetado para ser um sistema componentizado que pode ser hospedado em uma variedade de contextos diferentes. Normalmente, o Modelo de Dados é hospedado no contexto de um aplicativo depurador. A fim de ser um host do modelo de dados, uma série de interfaces precisam ser implementadas para expor aspetos centrais do depurador: seu direcionamento, seus espaços de memória, seu avaliador, seu sistema simbólico e de tipo, etc... Embora essas interfaces sejam implementadas por qualquer aplicativo que deseje hospedar o modelo de dados, elas são consumidas tanto pelo modelo de dados principal quanto por qualquer extensão que interopere com o modelo de dados.

O conjunto de interfaces principais são:

Nome da interface Descrição
IDebugHost A interface principal para o host de depuração.
IDebugHostStatus Uma interface que permite que um cliente consulte o status do host.
IDebugHostContext Uma abstração de um contexto dentro do host (por exemplo: um alvo particular, um processo particular, um espaço de endereçamento particular, etc...)
IDebugHostErrorSink Uma interface implementada por chamadores para receber erros de determinadas partes do host e do modelo de dados
IDebugHostEvaluator / IDebugHostEvaluator2 O avaliador de expressão do host de depuração.
IDebugHostExtensibility Uma interface para estender as capacidades do anfitrião ou partes dele (como o avaliador de expressão).

O sistema de tipos e as interfaces simbólicas são:

Nome da interface Descrição
IDebugHostSymbols Interface central que fornece acesso e resolução de símbolos
IDebugHostSymbol / IDebugHostSymbol2 Representa um único símbolo de qualquer tipo. O símbolo particular é uma derivação desta interface.
IDebugHostModule Representa um módulo carregado dentro de um processo. Trata-se de uma espécie de símbolo.
IDebugHostType / IDebugHostType2 Representa um tipo nativo/idioma.
IDebugHostConstant Representa uma constante dentro de informações simbólicas (por exemplo: um argumento de modelo não-tipo em C++)
IDebugHostField Representa um campo dentro de uma estrutura ou classe.
IDebugHostData Representa dados dentro de um módulo (se isso estivesse dentro de uma estrutura ou classe, seria um IDebugHostField)
IDebugHostBaseClass Representa uma classe base.
IDebugHostPublic Representa um símbolo no quadro público de um APO. Isso não tem informações de tipo associadas a ele. É um nome e endereço.
IDebugHostModuleSignature Representa uma assinatura de módulo -- uma definição que corresponderá a um conjunto de módulos por nome e/ou versão
IDebugHostTypeSignature Representa uma assinatura de tipo -- uma definição que corresponderá a um conjunto de tipos por módulo e/ou nome

a interface principal do host: IDebugHost

A interface IDebugHost é a interface principal de qualquer host de modelo de dados. Define-se do seguinte modo:

DECLARE_INTERFACE_(IDebugHost, IUnknown)
{
    STDMETHOD(GetHostDefinedInterface)(_COM_Outptr_ IUnknown** hostUnk) PURE;
    STDMETHOD(GetCurrentContext)(_COM_Outptr_ IDebugHostContext** context) PURE;
    STDMETHOD(GetDefaultMetadata)(_COM_Outptr_ IKeyStore** defaultMetadataStore) PURE;
}

GetHostDefinedInterface

O método GetHostDefinedInterface retorna a interface privada principal do host, se tal existir para determinado host. Para Ferramentas de Depuração para Windows, a interface retornada aqui é um IDebugClient (convertido para IUnknown).

GetCurrentContext

O GetCurrentContext método retorna uma interface que representa o estado atual do host do depurador. O significado exato disso é deixado para o host, mas normalmente inclui coisas como a sessão, o processo e o espaço de endereçamento que está ativo na interface do usuário do host de depuração. O objeto de contexto retornado é em grande parte opaco para o chamador, mas é um objeto importante para passar entre chamadas para o host de depuração. Quando um chamador está, por exemplo, lendo memória, é importante saber de qual processo e espaço de endereçamento essa memória está sendo lida. Essa noção é encapsulada na noção do objeto de contexto que é retornado a partir deste método.

GetDefaultMetadata

O método GetDefaultMetadata retorna um repositório de metadados padrão que pode ser usado para determinadas operações (por exemplo: conversão de cadeia de caracteres) quando nenhum metadados explícito foi passado. Isso permite que o host de depuração tenha algum controle sobre a maneira como alguns dados são apresentados. Por exemplo, os metadados padrão podem incluir uma chave PreferredRadex, permitindo que o host indique se ordinais devem ser exibidos em decimal ou hexadecimal, se não especificado de outra forma.

Observe que os valores de propriedade no repositório de metadados padrão devem ser resolvidos manualmente e devem passar o objeto para o qual os metadados padrão estão sendo consultados. O GetKey método deve ser usado em vez de GetKeyValue.

A interface de status: IDebugHostStatus

A interface IDebugHostStatus permite que um cliente do modelo de dados ou do host de depuração pergunte sobre certos aspetos do status do host de depuração. A interface é definida da seguinte forma:

DECLARE_INTERFACE_(IDebugHostStatus, IUnknown)
{
    STDMETHOD(PollUserInterrupt)(_Out_ bool* interruptRequested) PURE;
}

PollUserInterrupt

O método PollUserInterrupt é usado para perguntar se o usuário do host de depuração solicitou uma interrupção da operação atual. Um acessador de propriedade no modelo de dados pode, por exemplo, chamar um código arbitrário (por exemplo: um método JavaScript). Esse código pode levar uma quantidade arbitrária de tempo. Para manter o host de depuração responsivo, qualquer código que possa levar uma quantidade arbitrária de tempo deve verificar se há uma solicitação de interrupção chamando esse método. Se o valor interruptRequested voltar como true, o chamador deverá abortar imediatamente e retornar um resultado de E_ABORT.

A interface de contexto: IDebugHostContext

O contexto é um dos aspetos mais importantes do modelo de dados e do host de depuração subjacente. Quando você segura um objeto, é importante ser capaz de saber de onde um objeto veio -- em que processo ele está, a que espaço de endereçamento ele está associado. Conhecer essas informações permite a interpretação correta de coisas como valores de ponteiro. Um objeto do tipo IDebugHostContext deve ser passado para muitos métodos no host de depuração. Esta interface pode ser adquirida de várias formas:

  • Obtendo o contexto atual do depurador: chamando o método GetCurrentContext de IDebugHost
  • Obtendo o contexto de um objeto: chamando o método GetContext de IModelObject
  • Obtendo o contexto de um símbolo: chamando o método GetContext de IDebugHostSymbol

Além disso, há dois valores que têm significado especial no contexto de uma interface IDebugHostContext que é retornada ou passada para um modelo de dados ou método de host de depuração:

nullptr: uma indicação de que não há contexto. É perfeitamente válido que alguns objetos não tenham contexto. O objeto Depurador no namespace raiz do modelo de dados não se refere a nada dentro de um processo específico ou espaço de endereço. Não tem contexto.

USE_CURRENT_HOST_CONTEXT: um valor sentinel que indica que se deve usar o contexto atual da interface do usuário do host de depuração. Esse valor nunca será retornado do host de depuração. No entanto, ele pode ser passado para qualquer método de host de depuração que usa uma entrada IDebugHostContext em vez de chamar explicitamente o método GetCurrentContext de IDebugHost. Observe que passar explicitamente USE_CURRENT_HOST_CONTEXT geralmente é mais eficiente do que obter explicitamente o contexto atual.

Os contextos de um contexto de host são em grande parte opacos para o chamador. A única operação que um chamador fora do host de depuração principal pode fazer com um contexto de host é compará-lo com outro contexto de host.

A interface IDebugHostContext é definida da seguinte forma:

DECLARE_INTERFACE_(IDebugHostContext, IUnknown)
{
    STDMETHOD(IsEqualTo)(_In_ IDebugHostContext *pContext, _Out_ bool *pIsEqual) PURE;
}

IsEqualTo

O método IsEqualTo compara um contexto de host com outro contexto de host. Se os dois contextos forem equivalentes, uma indicação disso será retornada. Note que esta comparação não é equivalência de interface. Isto compara o conteúdo opaco subjacente do próprio contexto.

O coletor de erros: IDebugHostErrorSink

O IDebugHostErrorSink é um meio pelo qual um cliente pode receber notificações de erros que ocorrem durante determinadas operações e rotear esses erros onde necessário. A interface é definida da seguinte forma:

enum ErrorClass
{
    ErrorClassWarning,
    ErrorClassError
}
DECLARE_INTERFACE_(IDebugHostErrorSink, IUnknown)
{
    STDMETHOD(ReportError)(_In_ ErrorClass errClass, _In_ HRESULT hrError, _In_ PCWSTR message) PURE;
}

ReportError

O método ReportError é um retorno de chamada no coletor de erros para notificá-lo de que ocorreu um erro e permitir que o coletor roteie o erro para qualquer interface do usuário ou mecanismo apropriado.

O Avaliador do Anfitrião: IDebugHostEvaluator / IDebugHostEvaluator2

Uma das partes mais importantes da funcionalidade que o host de depuração fornece aos clientes é o acesso ao seu avaliador de expressão baseado em linguagem. As interfaces IDebugHostEvaluator e IDebugHostEvaluator2 são os meios para acessar essa funcionalidade a partir do host de depuração.

As interfaces são definidas da seguinte forma:

DECLARE_INTERFACE_(IDebugHostEvaluator2, IDebugHostEvaluator)
{
    //
    // IDebugHostEvaluator:
    //
    STDMETHOD(EvaluateExpression)(_In_ IDebugHostContext* context, _In_ PCWSTR expression, _In_opt_ IModelObject* bindingContext, _COM_Errorptr_ IModelObject** result, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    STDMETHOD(EvaluateExtendedExpression)(_In_ IDebugHostContext* context, _In_ PCWSTR expression, _In_opt_ IModelObject* bindingContext, _COM_Errorptr_ IModelObject** result, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    //
    // IDebugHostEvaluator2:
    //
    STDMETHOD(AssignTo)(_In_ IModelObject* assignmentReference, _In_ IModelObject* assignmentValue, _COM_Errorptr_ IModelObject** assignmentResult, _COM_Outptr_opt_result_maybenull_ IKeyStore** assignmentMetadata) PURE;
}

EvaluateExpression

O método EvaluateExpression permite que solicite que o host de depuração avalie uma expressão de linguagem (por exemplo: C++) e retorne o valor resultante dessa avaliação de expressão encaixotado como um IModelObject. Esta variante particular do método só permite construções de linguagem. Qualquer funcionalidade adicional que é apresentada dentro do avaliador de expressão do host de depuração que não está presente na linguagem (por exemplo: métodos de consulta LINQ) é desativada para a avaliação.

EvaluateExtendedExpression

O método EvaluateExtendedExpression é semelhante ao método EvaluateExpression, exceto que ele ativa a funcionalidade adicional não linguística que um host de depuração específico escolhe adicionar ao seu avaliador de expressão. Para Ferramentas de Depuração para Windows, por exemplo, isso permite tipos anônimos, consultas LINQ, qualificadores de módulo, especificadores de formato e outras funcionalidades não C/C++.

IDebugHostEvaluator2

AssignTo

O método AssignTo executa a atribuição de acordo com a semântica da linguagem que está sendo depurada.

A interface de extensibilidade do host: IDebugHostExtensibility

Certas funcionalidades do host de depuração estão opcionalmente sujeitas à extensibilidade. Isto pode, por exemplo, incluir a expressão avaliador. A interface IDebugHostExtensibility é o meio pelo qual esses pontos de extensibilidade são acessados. A interface é definida da seguinte forma:

DECLARE_INTERFACE_(IDebugHostExtensibility, IUnknown)
{
    STDMETHOD(CreateFunctionAlias)(_In_ PCWSTR aliasName, _In_ IModelObject *functionObject) PURE;
    STDMETHOD(DestroyFunctionAlias)(_In_ PCWSTR aliasName) PURE;
}

CreateFunctionAlias

O método CreateFunctionAlias cria um "alias de função", um "alias rápido" para um método implementado em alguma extensão. O significado desse alias é específico do host. Pode estender o avaliador de expressão do anfitrião com a função ou pode fazer algo totalmente diferente.

DestroyFunctionAlias

O método DestroyFunctionAlias desfaz uma chamada anterior para o método CreateFunctionAlias. A função não estará mais disponível sob o nome de alias rápido.

Acessando o modelo de dados

Em primeiro lugar, as APIs de extensibilidade do modelo de dados são projetadas para serem neutras em relação ao aplicativo (normalmente um depurador) que atua como um host do modelo de dados. Em teoria, qualquer aplicativo pode hospedar o modelo de dados fornecendo um conjunto de APIs de host que expõem o sistema de tipos do(s) destino(s) de depuração do aplicativo e um conjunto de objetos projetados no namespace do modelo de dados sobre quais destinos, processos, threads, etc... estão nesses destino(s) de depuração.

Embora as APIs do modelo de dados -- aquelas que iniciam IDataModel, IDebugHoste as ramificações de IModelObject -- sejam projetadas para serem portáteis, elas não definem o que é uma "extensão do depurador". Hoje, um componente que deseja estender as Ferramentas de Depuração para Windows e o mecanismo que ele fornece deve escrever uma extensão de mecanismo para obter acesso ao modelo de dados. Essa extensão do motor só precisa ser uma extensão do motor, na medida em que esse é o mecanismo de carregamento e inicialização para a extensão. Como tal, uma implementação mínima proporcionaria:

  • DebugExtensionInitialize: Um método que utiliza um IDebugClient criado para obter acesso ao modelo de dados e configura manipulações de modelo de objeto.
  • DebugExtensionUninitialize: Um método que desfaz as manipulações de modelo de objeto que foram executadas em DebugExtensionInitialize.
  • DebugExtensionCanUnload: Um método que retorna se a extensão pode ser descarregada. Se ainda houver objetos COM ativos na extensão, ele deve indicar isso. Este é o equivalente do depurador ao DllCanUnloadNow do COM. Se isso retornar a indicação S_FALSE de incapacidade de descarregar, o depurador poderá consultá-la posteriormente para ver se uma descarga é segura ou poderá reinicializar a extensão chamando DebugExtensionInitialize novamente. A extensão deve estar preparada para lidar com ambos os caminhos.
  • DebugExtensionUnload: Um método que faz qualquer limpeza final necessária antes do DLL ser descarregado

a interface Bridge: IHostDataModelAccess

Como mencionado, quando DebugExtensionInitialize é chamado, ele cria um cliente de depuração e obtém acesso ao modelo de dados. Esse acesso é fornecido por uma interface de ponte entre as interfaces IDebug* herdadas das Ferramentas de Depuração para Windows e o modelo de dados. Esta interface de ponte é 'IHostDataModelAccess e é definida da seguinte forma:

DECLARE_INTERFACE_(IHostDataModelAccess, IUnknown)
{
   STDMETHOD(GetDataModel)(_COM_Outptr_ IDataModelManager** manager, _COM_Outptr_ IDebugHost** host) PURE;
}

GetDataModel

O método GetDataModel é o método na interface bridge que fornece acesso a ambos os lados do modelo de dados: O host de depuração (a borda inferior do depurador) é expresso pela interface IDebugHost retornada O componente principal do modelo de dados -- o gerenciador do modelo de dados é expresso pela interface IDataModelManager retornada

Interfaces de sistema do modelo de dados do depurador

O host do modelo de dados

O Modelo de Dados do Depurador foi projetado para ser um sistema componentizado que pode ser hospedado em uma variedade de contextos diferentes. Normalmente, o Modelo de Dados é hospedado no contexto de um aplicativo depurador. A fim de ser um host do modelo de dados, uma série de interfaces precisam ser implementadas para expor aspetos centrais do depurador: seu direcionamento, seus espaços de memória, seu avaliador, seu sistema simbólico e de tipo, etc... Embora essas interfaces sejam implementadas por qualquer aplicativo que deseje hospedar o modelo de dados, elas são consumidas tanto pelo modelo de dados principal quanto por qualquer extensão que interopere com o modelo de dados.

O sistema de tipos e as interfaces simbólicas são:

Nome da interface Descrição
IDebugHostSymbols Interface central que fornece acesso e resolução de símbolos
IDebugHostSymbol / IDebugHostSymbol2 Representa um único símbolo de qualquer tipo. O símbolo particular é uma derivação desta interface.
IDebugHostModule Representa um módulo carregado dentro de um processo. Trata-se de uma espécie de símbolo.
IDebugHostType / IDebugHostType2 Representa um tipo nativo/idioma.
IDebugHostConstant Representa uma constante dentro de informações simbólicas (por exemplo: um argumento de modelo não-tipo em C++)
IDebugHostField Representa um campo dentro de uma estrutura ou classe.
IDebugHostData Representa dados dentro de um módulo (se isso estivesse dentro de uma estrutura ou classe, seria um IDebugHostField)
IDebugHostBaseClass Representa uma classe base.
IDebugHostPublic Representa um símbolo no quadro público de um APO. Isso não tem informações de tipo associadas a ele. É um nome e endereço.
IDebugHostModuleSignature Representa uma assinatura de módulo -- uma definição que corresponderá a um conjunto de módulos por nome e/ou versão
IDebugHostTypeSignature Representa uma assinatura de tipo -- uma definição que corresponderá a um conjunto de tipos por módulo e/ou nome

As outras interfaces principais são:

Nome da interface Descrição
IDebugHost A interface principal para o host de depuração.
IDebugHostStatus Uma interface que permite que um cliente consulte o status do host.
IDebugHostContext Uma abstração de um contexto dentro do host (por exemplo: um alvo particular, um processo particular, um espaço de endereçamento particular, etc...)
IDebugHostErrorSink Uma interface implementada por chamadores para receber erros de determinadas partes do host e do modelo de dados
IDebugHostEvaluator / IDebugHostEvaluator2 O avaliador de expressão do host de depuração.
IDebugHostExtensibility Uma interface para estender as capacidades do anfitrião ou partes dele (como o avaliador de expressão).

A interface simbólica principal: IDebugHostSymbols

A interface IDebugHostSymbols é o principal ponto de partida para acessar símbolos no destino de depuração. Essa interface pode ser consultada a partir de uma instância de IDebugHost e é definida da seguinte forma:

DECLARE_INTERFACE_(IDebugHostSymbols, IUnknown)
{
    STDMETHOD(CreateModuleSignature)(_In_z_ PCWSTR pwszModuleName, _In_opt_z_ PCWSTR pwszMinVersion, _In_opt_z_ PCWSTR pwszMaxVersion, _Out_ IDebugHostModuleSignature** ppModuleSignature) PURE;
    STDMETHOD(CreateTypeSignature)(_In_z_ PCWSTR signatureSpecification, _In_opt_ IDebugHostModule* module, _Out_ IDebugHostTypeSignature** typeSignature) PURE;
    STDMETHOD(CreateTypeSignatureForModuleRange)(_In_z_ PCWSTR signatureSpecification, _In_z_ PCWSTR moduleName, _In_opt_z_ PCWSTR minVersion, _In_opt_z_ PCWSTR maxVersion, _Out_ IDebugHostTypeSignature** typeSignature) PURE;
    STDMETHOD(EnumerateModules)(_In_ IDebugHostContext* context, _COM_Outptr_ IDebugHostSymbolEnumerator** moduleEnum) PURE;
    STDMETHOD(FindModuleByName)(_In_ IDebugHostContext* context, _In_z_ PCWSTR moduleName, _COM_Outptr_ IDebugHostModule **module) PURE;
    STDMETHOD(FindModuleByLocation)(_In_ IDebugHostContext* context, _In_ Location moduleLocation, _COM_Outptr_ IDebugHostModule **module) PURE;
    STDMETHOD(GetMostDerivedObject)(_In_opt_ IDebugHostContext *pContext, _In_ Location location, _In_ IDebugHostType* objectType, _Out_ Location* derivedLocation, _Out_ IDebugHostType** derivedType) PURE;
}

CreateModuleSignature

O método CreateModuleSignature cria uma assinatura que pode ser usada para corresponder a um conjunto de módulos específicos por nome e, opcionalmente, por versão. Há três componentes para uma assinatura de módulo:

  • Um nome: um módulo correspondente deve ter um nome que seja uma correspondência exata que não diferencia maiúsculas de minúsculas com o nome na assinatura
  • Uma versão mínima: se especificado, um módulo correspondente deve ter uma versão mínima que seja pelo menos tão alta quanto esta versão. As versões são especificadas no formato "A.B.C.D", com cada parte subsequente sendo menos importante do que a anterior. Apenas o primeiro segmento é obrigatório.
  • Uma versão máxima: se especificado, um módulo correspondente deve ter uma versão máxima que não seja superior a esta versão. As versões são especificadas no formato "A.B.C.D", com cada parte subsequente sendo menos importante do que a anterior. Apenas o primeiro segmento é obrigatório.

CreateTypeSignature

O método CreateTypeSignature cria uma assinatura que pode ser usada para corresponder a um conjunto de tipos concretos contendo o nome do módulo e do tipo. O formato da cadeia de caracteres de assinatura do nome do tipo é específico para o idioma que está sendo depurado (e host de depuração). Para C/C++, a cadeia de caracteres de assinatura é equivalente a uma especificação de tipo NatVis. Ou seja, a cadeia de caracteres de assinatura é um nome de tipo onde curingas (especificados como *) são permitidos para argumentos de modelo.

CreateTypeSignatureForModuleRange

O método CreateTypeSignatureForModuleRange cria uma assinatura que pode ser usada para corresponder a um conjunto de tipos concretos por assinatura de módulo e nome do tipo. Isso é semelhante ao método CreateTypeSignature, exceto que, em vez de passar um módulo específico para corresponder à assinatura, o chamador passa os argumentos necessários para criar uma assinatura de módulo (como se a assinatura do módulo fosse criada com o método CreateModuleSignature).

EnumerateModules

O método EnumerateModules cria um enumerador que enumerará todos os módulos disponíveis em um contexto de host específico. Esse contexto de host pode encapsular um contexto de processo ou pode encapsular algo como o kernel do Windows.

FindModuleByName

O método FindModuleByName examinará o contexto de host fornecido e localizará um módulo que tem o nome especificado e retornará uma interface para ele. É legal procurar o módulo pelo nome com ou sem a extensão do arquivo.

FindModuleByLocation

O método FindModuleByLocation examinará o contexto de host fornecido e determinará qual módulo contém o endereço fornecido pelo local especificado. Em seguida, ele retornará uma interface para esse módulo.

GetMostDerivedObject

O GetMostDerivedObject usará o sistema de tipos do depurador para determinar o tipo de tempo de execução de um objeto a partir de seu tipo estático. Este método utilizará apenas informações simbólicas e heurísticas disponíveis na camada do sistema de tipo para realizar esta análise. Essas informações podem incluir C++ RTTI (informações de tipo de tempo de execução) ou análise da forma das tabelas de funções virtuais do objeto. Ele não inclui coisas como o conceito de tipo de tempo de execução preferido em um IModelObject. Se a análise não puder encontrar um tipo de tempo de execução ou não puder encontrar um tipo de tempo de execução diferente do tipo estático passado para o método, o local e o tipo de entrada poderão ser eliminados. O método não falhará por estas razões.

A interface de símbolo individual principal: IDebugHostSymbol

Cada símbolo que pode ser retornado do host do modelo de dados derivará de alguma forma de IDebugHostSymbol. Esta é a interface central que cada símbolo implementa, independentemente do tipo de símbolo. Dependendo do tipo de símbolo, um determinado símbolo pode implementar um conjunto de outras interfaces que retornam atributos mais exclusivos para o tipo particular de símbolo representado por essa interface. A interface IDebugHostSymbol2 / IDebugHostSymbol é definida da seguinte forma:

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;
}

É muito importante notar que essa interface representa muitos tipos de símbolos -- delineados pela enumeração SymbolKind que tem valores da seguinte maneira:

Enumarant Significado
Símbolo Tipo de símbolo não especificado
SymbolModule O símbolo é um módulo e pode ser consultado para IDebugHostModule
SymbolType O símbolo é um tipo e pode ser consultado para IDebugHostType
SymbolField O símbolo é um campo (um membro de dados dentro de uma estrutura ou classe) e pode ser consultado para IDebugHostField
SymbolConstant O símbolo é um valor constante e pode ser consultado para IDebugHostConstant
SymbolData O símbolo é um dado que não é um membro de uma estrutura ou classe e é consultável para IDebugHostData
SymbolBaseClass O símbolo é uma classe base e pode ser consultado por IDebugHostBaseClass
SímboloPúblico O símbolo é uma entrada na tabela publics de um módulo (sem informações de tipo) e pode ser consultado por IDebugHostPublic
SymbolFunction O símbolo é uma função e pode ser consultado por IDebugHostData

GetContext

O GetContext método retorna o contexto onde o símbolo é válido. Embora isso represente coisas como o destino de depuração e o espaço de processo/endereço no qual o símbolo existe, ele pode não ser tão específico quanto um contexto recuperado de outros meios (por exemplo: de um IModelObject).

EnumerateChildren

O método EnumerateChildren retorna um enumerador que enumerará todos os filhos de um determinado símbolo. Para um tipo C++, por exemplo, as classes base, campos, funções de membro e similares são todos considerados filhos do símbolo de tipo.

a interface do módulo: IDebugHostModule

A noção do depurador de um módulo que é carregado dentro de algum espaço de endereçamento é representada de duas maneiras distintas no modelo de dados: No nível do sistema de tipo através da interface IDebugHostModule. Aqui, um módulo é um símbolo e os atributos principais do módulo são chamadas de método de interface projetadas no nível do modelo de dados por meio do modelo de dados Debugger.Models.Module. Este é um encapsulamento extensível do tipo system IDebugHostModule representação de um módulo.

A interface IDebugHostModule é definida da seguinte forma (ignorando métodos que são genéricos para IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostModule, IDebugHostSymbol)
{
    //
    // IDebugHostModule:
    //
    STDMETHOD(GetImageName)(_In_ bool allowPath, _Out_ BSTR* imageName) PURE;
    STDMETHOD(GetBaseLocation)(_Out_ Location* moduleBaseLocation) PURE;
    STDMETHOD(GetVersion)(_Out_opt_ ULONG64* fileVersion, _Out_opt_ ULONG64* productVersion) PURE;
    STDMETHOD(FindTypeByName)(_In_z_ PCWSTR typeName, _Out_ IDebugHostType** type) PURE;
    STDMETHOD(FindSymbolByRVA)(_In_ ULONG64 rva, _Out_ IDebugHostSymbol** symbol) PURE;
    STDMETHOD(FindSymbolByName)(_In_z_ PCWSTR symbolName, _Out_ IDebugHostSymbol** symbol) PURE;
}

GetImageName

O GetImageName método retorna o nome da imagem do módulo. Dependendo do valor do argumento allowPath, o nome da imagem retornada pode ou não incluir o caminho completo para a imagem.

GetBaseLocation

O método GetBaseLocation retorna o endereço de carga base do módulo como uma estrutura de local. A estrutura de local retornada para um módulo normalmente se refere a um endereço virtual.

GetVersion

O método GetVersion retorna informações de versão sobre o módulo (supondo que essas informações possam ser lidas com êxito dos cabeçalhos). Se uma determinada versão for solicitada (através de um ponteiro de saída não-nullptr) e não puder ser lida, um código de erro apropriado será retornado da chamada do método.

FindTypeByName

O método FindTypeByName localiza um tipo definido dentro do módulo pelo nome do tipo e retorna um símbolo de tipo para ele. Este método pode retornar um IDebugHostType válido que nunca seria retornado via recursão explícita de filhos do módulo. O host de depuração pode permitir a criação de tipos derivados -- tipos nunca usados dentro do próprio módulo, mas derivados de tipos que são. Por exemplo, se a estrutura MyStruct é definida nos símbolos do módulo, mas o tipo MyStruct ** nunca é usado, o método FindTypeByName pode legitimamente retornar um símbolo de tipo para MyStruct ** apesar desse nome de tipo nunca aparecer explicitamente nos símbolos do módulo.

FindSymbolByRVA

O método FindSymbolByRVA encontrará um único símbolo correspondente no endereço virtual relativo fornecido dentro do módulo. Se não houver um único símbolo no RVA fornecido (por exemplo: há várias correspondências), um erro será retornado por este método. Observe que esse método prefere retornar um símbolo privado em vez de um símbolo na tabela publics.

FindSymbolByName

O método FindSymbolByName encontrará um único símbolo global do nome próprio dentro do módulo. Se não houver um único símbolo correspondente ao nome fornecido, um erro será retornado por esse método. Observe que esse método prefere retornar um símbolo privado em vez de um símbolo na tabela publics.

acesso ao sistema de tipos: IDebugHostType2 / IDebugHostType

Um determinado idioma/tipo nativo é descrito pelas interfaces IDebugHostType2 ou IDebugHostType. Observe que alguns dos métodos nessas interfaces só se aplicam a tipos específicos de tipos. Um determinado símbolo de tipo pode referir-se a um dos seguintes tipos, conforme descrito pela enumeração TypeKind:

Tipo Tipo Descrição
TipoUDT Um tipo definido pelo usuário (uma struct, class, union, etc...). Um objeto de modelo que tem um tipo nativo cujo tipo é TypeUDT tem uma representação canônica de ObjectTargetObject onde o tipo é sempre mantido dentro do IModelObject correspondente.
TypePointer Um ponteiro. Um objeto de modelo que tem um tipo nativo cujo tipo é TypePointer tem uma representação canônica de ObjectIntrínseco onde o valor do ponteiro é zero estendido para VT_UI8 e mantido como dados intrínsecos neste formulário de 64 bits. Qualquer símbolo de tipo de TypePointer tem um tipo base (conforme retornado pelo método GetBaseType) do tipo para o qual o ponteiro aponta.
TypeMemberPointer Um ponteiro para o membro da classe. Um objeto de modelo que tem um tipo nativo cujo tipo é TypeMemberPointer tem uma representação canônica que é intrínseca (o valor é o mesmo que o valor do ponteiro). O significado exato desse valor é específico do host de compilador/depuração.
TypeArray Uma matriz. Um objeto de modelo que tem um tipo nativo cujo tipo é TypeArray tem uma representação canônica de ObjectTargetObject. O endereço base da matriz é a localização do objeto (recuperada através do método GetLocation) e o tipo da matriz é sempre mantido. Qualquer símbolo de tipo de TypeArray tem um tipo base (conforme retornado pelo método GetBaseType) do tipo do qual a matriz é uma matriz.
TypeFunction Uma função.
TypeTypedef Um typedef. Um objeto de modelo que tem um tipo nativo cujo tipo seria TypeTypedef tem uma representação canônica idêntica à representação canônica do tipo final subjacente ao typedef. Isso parece completamente transparente para o usuário final do objeto e as informações de tipo, a menos que os métodos typedef explícitos de IDebugHostType2 sejam utilizados para consultar informações typedef ou haja um modelo de dados explícito registrado em relação ao typedef. Observe que o método GetTypeKind nunca retornará TypeTypedef. Cada método retornará o que o tipo final subjacente ao typedef retornaria. Existem métodos específicos typedef em IDebugHostType2 que podem ser usados para obter as informações específicas typedef.
TypeEnum Um enum. Um objeto de modelo que tem um tipo nativo cujo tipo é TypeEnum tem uma representação canônica de ObjectIntrinsic onde o valor e o tipo do intrínseco é idêntico ao valor de enum.
TipoIntrínseco Um intrínseco (tipo base). Um objeto modelo que tem um tipo nativo cujo tipo é TypeIntrinsic tem uma representação canônica de ObjectIntrinsic. As informações de tipo podem ou não ser mantidas -- particularmente se o tipo subjacente for totalmente descrito pelo tipo de dados variante (VT_*) dos dados intrínsecos armazenados no IModelObject

A interface geral IDebugHostType2 / IDebugHostType é definida da seguinte forma (excluindo os métodos 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étodos gerais IDebugHostType2/IDebugHostType

Os seguintes métodos IDebugHostType são gerais para qualquer tipo, independentemente do tipo retornado do método GetTypeKind:

STDMETHOD(GetTypeKind)(_Out_ TypeKind *kind) PURE;
STDMETHOD(GetSize)(_Out_ ULONG64* size) PURE;
STDMETHOD(GetBaseType)(_Out_ IDebugHostType** baseType) PURE;
STDMETHOD(GetHashCode)(_Out_ ULONG* hashCode) PURE;

GetTypeKind

O método GetTypeKind retorna a que tipo de tipo (ponteiro, matriz, intrínseco, etc...) o símbolo se refere.

GetSize

O método GetSize retorna o tamanho do tipo (como se alguém tivesse feito sizeof(type) em C++).

GetBaseType

Se o tipo for uma derivada de outro tipo único (por exemplo: como MyStruct * é derivado de MyStruct'), o método GetBaseType retorna o tipo base da derivação. Para ponteiros, isso retorna o tipo apontado. Para matrizes, isso retorna o que a matriz é uma matriz. Se o tipo não for um tipo derivado, um erro será retornado.

GetHashCode

O GetHashCode método retorna um código hash de 32 bits para o tipo. Com exceção de uma correspondência global (por exemplo: uma assinatura de tipo equivalente a * que corresponde a tudo se permitido pelo host), qualquer instância de tipo que possa corresponder a uma assinatura de tipo específico deve retornar o mesmo código hash. Esse método é usado em conjunto com assinaturas de tipo para fazer a correspondência entre assinaturas de tipo e instâncias de tipo.

Métodos Intrínsecos IDebugHostType2/IDebugHostType

Os seguintes métodos IDebugHostType são específicos para tipos intrínsecos (ou tipos que contêm dados intrínsecos, como enums):

STDMETHOD(GetIntrinsicType)(_Out_opt_ IntrinsicKind *intrinsicKind, _Out_opt_ VARTYPE *carrierType) PURE;

GetIntrinsicType

O GetIntrinsicType método retorna informações sobre que tipo de intrínseco o tipo é. Dois valores são retornados fora deste método:

  • O tipo intrínseco indica o tipo geral (por exemplo: inteiro, não assinado, ponto flutuante), mas não o tamanho do tipo (por exemplo: 8 bits, 16 bits, 32 bits, 64 bits)
  • O tipo de transportador indica como o tipo intrínseco se encaixa em uma estrutura VARIANT. Esta é uma constante VT_*.

A combinação dos dois valores fornece o conjunto completo de informações sobre o intrínseco.

Métodos Bitfield IDebugHostType2/IDebugHostType

Os seguintes métodos IDebugHostType são específicos para tipos que armazenam dados em campos de bits. As informações sobre o posicionamento do campo de bits dentro de um intrínseco são armazenadas como parte do símbolo de tipo no modelo de dados, em vez de serem um atributo do local.

STDMETHOD(GetBitField)(_Out_ ULONG* lsbOfField, _Out_ ULONG* lengthOfField) PURE;

GetBitField

Se um determinado membro de uma estrutura de dados for um campo de bits (por exemplo: ULONG MyBits:8), as informações de tipo para o campo carregam consigo informações sobre o posicionamento do campo de bits. O método GetBitField pode ser usado para recuperar essas informações. Este método falhará em qualquer tipo que não seja um bitfield. Esta é a única razão pela qual o método falhará. Simplesmente chamar esse método e olhar para o sucesso/falha é suficiente para distinguir um campo bit de um campo não-bit. Se um determinado tipo for um bitfield, as posições do campo são definidas pelo conjunto meio aberto (lsbOfField + lengthOfField : lsbOfField]

Métodos relacionados IDebugHostType2/IDebugHostType Pointer

Os seguintes métodos IDebugHostType são específicos para tipos de ponteiro. Esses são tipos em que GetTypeKind retorna TypePointer ou TypeMemberPointer':

STDMETHOD(GetPointerKind)(_Out_ PointerKind* pointerKind) PURE;
STDMETHOD(GetMemberType)(_Out_ IDebugHostType** memberType) PURE;

GetPointerKind

Para tipos que são ponteiros, o GetPointerKind método retorna o tipo de ponteiro. Isso é definido pela enumeração PointerKind.

GetMemberType

Para tipos que são ponteiro para membro (conforme indicado por um tipo de tipo de TypeMemberPointer), o método GetMemberType retorna a classe da qual o ponteiro é um ponteiro para membro.

Métodos relacionados IDebugHostType2/IDebugHostType Array

Matrizes são tipos em que GetTypeKind retorna TypeArray. Observe que as matrizes conforme definidas pelo sistema de tipo do host de depuração não são as mesmas que as matrizes unidimensionais unidimensionais, baseadas em índice zero e lineares compactadas que C utiliza. As matrizes de estilo C se encaixam na definição, mas o escopo geral de uma matriz é mais amplo em IDebugHostType. Uma matriz no host de depuração pode ser multidimensional e cada dimensão dentro da matriz é definida por um descritor conhecido como ArrayDimensionEste descritor tem os seguintes campos:

Campo Significado
Limite inferior O índice base da matriz como um valor de 64 bits assinado. Para uma matriz de estilo C, isso sempre será zero. Não tem de ser. Uma dimensão individual de uma matriz pode ser considerada como começando em qualquer índice de 64 bits, mesmo um negativo.
Duração O comprimento da dimensão da matriz como um valor de 64 bits não assinado. Os índices da matriz abrangem o conjunto meio aberto [LowerBound, LowerBound + Length).
Passo Define a passada da dimensão da matriz. Para um aumento de um (de N para N + 1) no índice dessa dimensão, isso indica quantos bytes avançar na memória. Para uma matriz de estilo C, esse seria o tamanho de cada elemento da matriz. Não precisa ser. O preenchimento entre elementos pode ser expresso como uma passada maior do que o tamanho de cada elemento individual. Para matrizes multidimensionais, esse valor indicaria como mover uma dimensão inteira para frente. Considere uma matriz M x N. Isso pode ser descrito na forma de linha principal como duas dimensões:
{ [LowerBound: 0, Length: M, Stride: N \* sizeof(element)], [LowerBound: 0, Length: N, Stride: sizeof(element)]} 

ou pode ser alternativamente descrito na forma de coluna maior como duas dimensões:

{ [LowerBound: 0, Length: M, Stride: sizeof(element)], [LowerBound: 0, Length: N, Stride: M \* sizeof(element)]} 

O conceito ArrayDimension permite esse grau de flexibilidade.

Os seguintes métodos IDebugHostType são específicos para tipos de matriz.

STDMETHOD(GetArrayDimensionality)(\_Out_ ULONG64\* arrayDimensionality) PURE; 
STDMETHOD(GetArrayDimensions)(\_In_ ULONG64 dimensions, \_Out_writes_(dimensions) ArrayDimension \*pDimensions) PURE;

GetArrayDimensionality

O método GetArrayDimensionality retorna o número de dimensões nas quais a matriz está indexada. Para matrizes de estilo C, o valor retornado aqui sempre será 1.

GetArrayDimensions

O GetArrayDimensions método retorna um conjunto de descritores, um para cada dimensão da matriz, conforme indicado pelo GetArrayDimensionality método. Cada descritor é uma estrutura ArrayDimension que descreve o índice inicial, o comprimento e a passada para a frente de cada dimensão da matriz. Isso permite descrições de construções de matriz significativamente mais poderosas do que as permitidas no sistema do tipo C.

Para matrizes de estilo C, uma única dimensão de matriz é retornada aqui com valores que são sempre:

  • Limite inferior = 0
  • Comprimento = ARRAYSIZE(matriz)
  • Stride = sizeof(elementType)

IDebugHostType2/IDebugHostType Function Métodos relacionados

Os tipos que indicam que são tipos de função através de um tipo de TypeFunction suportam os seguintes métodos em IDebugHostType e IDebugHostType2.

//
// IDebugHostType:
//
STDMETHOD(GetFunctionCallingConvention)(_Out_ CallingConventionKind* conventionKind) PURE;
STDMETHOD(GetFunctionReturnType)(_COM_Outptr_ IDebugHostType** returnType) PURE;
STDMETHOD(GetFunctionParameterTypeCount)(_Out_ ULONG64* count) PURE;
STDMETHOD(GetFunctionParameterTypeAt)(_In_ ULONG64 i, _Out_ IDebugHostType** parameterType) PURE;
//
// IDebugHostType2:
//
STDMETHOD(GetFunctionVarArgsKind)(_Out_ VarArgsKind* varArgsKind) PURE;

GetFunctionCallingConvention

O método GetFunctionCallingConvention retorna a convenção de chamada da função. Tal é retornado como um membro da enumeração CallingConventionKind.

GetFunctionReturnType

O GetFunctionReturnType método retorna o tipo de retorno da função.

GetFunctionParameterTypeCount

O GetFunctionParameterTypeCount método retorna o número de argumentos que a função toma. Observe que o marcador de argumento de variável baseado em reticências C/C++ não é considerado nessa contagem. A presença de tal deve ser detetada através do método GetFunctionVarArgsKind. Isso incluirá apenas argumentos antes das reticências.

GetFunctionParameterTypeAt

O GetFunctionParameterTypeAt método retorna o tipo do i-ésimo argumento para a função.

O GetFunctionVarArgsKind método retorna se uma determinada função utiliza uma lista de argumentos variáveis e, em caso afirmativo, que estilo de argumentos de variável ela utiliza. Tal é definido por um membro da enumeração VarArgsKind definida da seguinte forma:

Enumerante Significado
VarArgsNona A função não aceita argumentos variáveis.
VarArgsCStyle A função é uma função varargs estilo C (returnType(arg1, arg2, ...)). O número de argumentos relatados pela função não inclui o argumento de reticências. Qualquer passagem de argumento variável ocorre após o número de argumentos retornados pelo método GetFunctionParameterTypeCount.

IDebugHostType2 GetFunctionVarArgsKind

O GetFunctionVarArgsKind método retorna se uma determinada função utiliza uma lista de argumentos variáveis e, em caso afirmativo, que estilo de argumentos de variável ela utiliza. Tal é definido por um membro da enumeração VarArgsKind definida da seguinte forma:

Métodos relacionados IDebugHostType2/IDebugHostType Typedef

Qualquer tipo que seja um typedef se comportará como se o tipo fosse o tipo final subjacente ao typedef. Isso significa que métodos como GetTypeKind não indicarão que o tipo é um typedef. Da mesma forma, GetBaseType não retornará o tipo ao qual a definição se refere. Em vez disso, indicarão que se comportam como se tivessem sido chamados na definição final subjacente ao typedef. A título de exemplo:

typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;

Um IDebugHostType para 'PMYSTRUCT ou PTRMYSTRUCT relatará as seguintes informações:

  • O GetTypeKind método retornará TypePointer. O tipo subjacente final MYSTRUCT * é realmente um ponteiro.
  • O método 'GetBaseType retornará um tipo para MYSTRUCT. O tipo subjacente de MYSTRUCT * é MYSTRUCT.

A única diferença aqui é como os métodos específicos typedef em IDebugHostType2 se comportam. Esses métodos são:

STDMETHOD(IsTypedef)(_Out_ bool* isTypedef) PURE;
STDMETHOD(GetTypedefBaseType)(_Out_ IDebugHostType2** baseType) PURE;
STDMETHOD(GetTypedefFinalBaseType)(_Out_ IDebugHostType2** finalBaseType) PURE;

Neste exemplo:

  • O método IsTypedef retornará true para PMYSTRUCT e PTRMYSTRUCT
  • O método GetTypedefBaseType retornará MYSTRUCT * para PMYSTRUCT e PMYSTRUCT para PTRMYSTRUCT
  • O GetTypedefFinalBaseType método retornará MYSTRUCT * para ambos os tipos

IsTypedef

O método IsTypedef é o único método capaz de ver se um tipo é um typedef. O método GetTypeKind se comportará como se fosse chamado no tipo subjacente.

GetTypedefBaseType

O GetTypedefBaseType método retornará qual a definição imediata do typedef. Nos exemplos descritos na documentação:

typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;

este método retornará MYSTRUCT * para PMYSTRUCT e PMYSTRUCT para PTRMYSTRUCT.

GetTypedefFinalBaseType

O método GetTypedefFinalBaseType retornará o tipo final para o qual o typedef é uma definição. Se o typedef for uma definição de outro typedef, este continuará a seguir a cadeia de definição até atingir um tipo que não é um typedef e esse tipo será devolvido. Nos exemplos descritos na documentação:

typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;

este método retornará MYSTRUCT * quando chamado em PMYSTRUCT ou PTRMYSTRUCT.

Métodos de criação de tipo 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;

valores de símbolo constante: IDebugHostConstant

Para locais onde valores constantes estão presentes em informações simbólicas (onde um determinado valor é um símbolo que pode ou não ser um valor constante), a interface IDebugHostConstant expressa a noção de tal constante. Isso geralmente é usado em lugares como argumentos de modelo, onde um determinado argumento é normalmente um tipo, mas pode ser um argumento de modelo não-tipo (por exemplo: uma constante).

A interface IDebugHostConstant é definida da seguinte forma (ignorando métodos genéricos implementados por IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostConstant, IDebugHostSymbol)
{
    STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}

GetValue

O GetValue método retorna o valor da constante empacotada em um VARIANT. É importante observar que o método GetType em IDebugHostSymbol pode retornar um símbolo de tipo específico para a constante. Nesses casos, não há garantia de que o empacotamento do valor constante, conforme definido pelo símbolo de tipo, seja o mesmo que o empacotamento retornado pelo método GetValue aqui.

Acesso de Membro de Dados: IDebugHostField

A classe IDebugHostField representa um símbolo que é um membro de dados de uma classe, estrutura, união ou outra construção de tipo. Não representam dados livres (por exemplo: dados globais). A interface é definida da seguinte forma (ignorando métodos genéricos para IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostField, IDebugHostSymbol)
{
    STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
    STDMETHOD(GetOffset)(_Out_ ULONG64* offset) PURE;
    STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
    STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}

GetLocationKind

O GetLocationKind método retorna em que tipo de local o símbolo está de acordo com a enumeração LocationKind. Essa enumeração pode ser um dos seguintes valores:

Enumerante Significado
LocalizaçãoMembro O campo é um membro de dados regular de uma classe, estrutura, união ou outra construção de tipo. Ele tem um deslocamento que é relativo ao endereço base da construção de tipo que contém. Esse endereço base é normalmente representado pelo ponteiro this. O deslocamento do campo pode ser recuperado através do método GetOffset. Os métodos GetLocation e GetValue falharão para um campo que é LocationMember.
LocalizaçãoStatic O campo é estático e tem seu próprio endereço. O método GetLocation retornará o local abstrato (por exemplo: endereço) do campo estático. Os métodos GetOffset e GetValue falharão para um campo que é LocationStatic.
LocalizaçãoConstant O campo é uma constante e tem um valor. O GetValue método retornará o valor da constante. Os métodos GetOffset e GetLocation falharão para um campo que é LocationConstant
LocalizaçãoNenhum O campo não tem localização. Pode ter sido otimizado pelo compilador ou pode ser um campo estático que é declarado, mas nunca definido. Independentemente de como tal campo surgiu, ele não tem presença física ou valor. Está apenas nos símbolos. Todos os métodos de aquisição (GetOffset, GetLocation e GetValue) falharão para um campo que é LocationNone.

GetOffset

Para campos que têm um deslocamento (por exemplo: campos cujo tipo de local indica LocationMember), o método GetOffset retornará o deslocamento do endereço base do tipo que contém (o ponteiro this) para os dados do próprio campo. Esses deslocamentos são sempre expressos como valores de 64 bits não assinados. Se o campo fornecido não tiver um local que seja um deslocamento do endereço base do tipo que contém, o método GetOffset falhará.

GetLocation

Para campos que têm um endereço independentemente da instância de tipo particular (por exemplo: campos cujo tipo de localização indica LocationStatic), o método GetLocation retornará o local abstrato (endereço) do campo. Se o campo fornecido não tiver um local estático, o método GetLocation falhará.

GetValue

Para campos que têm um valor constante definido dentro das informações simbólicas (por exemplo: campos cujo tipo de localização indica LocationConstant), o método GetValue retornará o valor constante do campo. Se o campo fornecido não tiver um valor constante, o método GetValue falhará.

Acesso gratuito a dados: IDebugHostData

Os dados em módulos que não são membros de outro tipo são representados pela interface IDebugHostData. Essa interface é definida da seguinte forma (ignorando métodos genéricos para IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostData, IDebugHostSymbol)
{
    STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
    STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
    STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}

Todos esses métodos são semanticamente equivalentes aos seus homólogos em IDebugHostField. A única diferença é que o método GetLocationKind nunca retornará LocationMember para dados gratuitos.

GetLocationKind

O GetLocationKind método retorna em que tipo de local o símbolo está de acordo com a enumeração LocationKind. A descrição dessa enumeração pode ser encontrada na documentação de IDebugHostField.

GetLocation

Para dados que têm um endereço, o método GetLocation retornará o local abstrato (endereço) do campo. Se os dados fornecidos não tiverem um local estático, o método GetLocation falhará.

GetValue

Para dados que têm um valor constante definido dentro das informações simbólicas (por exemplo: dados cujo tipo de localização indica LocationConstant), o método GetValue retornará o valor constante do campo. Se os dados fornecidos não tiverem um valor constante, o método GetValue falhará.

Classes Base: IDebugHostBaseClass

A hierarquia de herança de um determinado tipo é expressa através de filhos de um símbolo de tipo. Se um determinado tipo derivar (herança) de um ou mais tipos, haverá um ou mais filhos SymbolBaseClass do símbolo de tipo para o tipo. Cada um desses símbolos SymbolBaseClass representa herança imediata de um tipo específico. O nome da classe base é tanto o nome do símbolo SymbolBaseClass quanto o do símbolo de tipo para a classe base. O método GetType no símbolo SymbolBaseClass pode ser usado para obter o símbolo de tipo para a própria classe base. A hierarquia de herança completa pode ser percorrida explorando recursivamente os símbolos filho SymbolBaseClass. Cada um desses símbolos de classe base é expresso pela interface IDebugHostBaseClass que é definida da seguinte forma (ignorando métodos genéricos para IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostBaseClass, IDebugHostSymbol)
{
    STDMETHOD(GetOffset)(_Out_ ULONG64* offset) PURE;
}

GetOffset

O método GetOffset retorna o deslocamento da classe base do endereço base da classe derivada. Esse deslocamento pode ser zero ou pode ser um valor positivo de 64 bits não assinado.

Símbolos públicos: IDebugHostPublic

Símbolos públicos representam coisas na tabela pública dentro de um arquivo de símbolos. São, na verdade, endereços de exportação. Não há nenhuma informação de tipo associada a um símbolo público - apenas um endereço. A menos que um símbolo público seja explicitamente solicitado pelo chamador, o host de depuração prefere retornar símbolos privados para cada consulta. Um símbolo público é expresso pela interface IDebugHostPublic que é definida da seguinte forma (ignorando métodos que são genéricos para IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostPublic, IDebugHostSymbol)
{
    STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
    STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
}

Todos esses métodos são semanticamente equivalentes aos seus homólogos em IDebugHostField. A única diferença é que o método GetLocationKind nunca retornará LocationMember ou LocationConstant para esses símbolos.

GetLocationKind

O GetLocationKind método retorna em que tipo de local o símbolo está de acordo com a enumeração LocationKind. A descrição dessa enumeração pode ser encontrada na documentação de IDebugHostField.

GetLocation

Para dados que têm um endereço, o método GetLocation retornará o local abstrato (endereço) do campo. Se o público dado não tiver um local estático, o método GetLocation falhará.

Assinaturas de módulo e correspondência de versão: IDebugHostModuleSignature

As assinaturas de módulo representam um meio de verificar se um determinado módulo atende a um conjunto de critérios em relação à nomeação e controle de versão. Uma assinatura de módulo é criada por meio do método CreateModuleSignature em IDebugHostSymbols. Ele pode corresponder ao nome do módulo e um intervalo opcional de números de versão para o módulo. Depois que essa assinatura é criada, o cliente recebe uma interface IDebugHostModuleSignature que é definida da seguinte maneira:

DECLARE_INTERFACE_(IDebugHostModuleSignature, IUnknown)
{
    STDMETHOD(IsMatch)(_In_ IDebugHostModule* pModule, _Out_ bool* isMatch) PURE;
}

IsMatch

O método IsMatch compara um módulo específico (conforme dado por um símbolo IDebugHostModule) com uma assinatura, comparando o nome e a versão do módulo com o nome e o intervalo de versões indicados na assinatura. É retornada uma indicação de se o símbolo do módulo fornecido corresponde à assinatura.

Assinaturas de tipo e correspondência de tipo: IDebugHostTypeSignature

As assinaturas de tipo representam um meio de verificar se uma determinada instância de tipo atende a um conjunto de critérios sobre o nome do tipo, os argumentos genéricos para o tipo e o módulo no qual o tipo está localizado. Uma assinatura de tipo é criada por meio do método CreateTypeSignature em IDebugHostSymbols. Depois que essa assinatura é criada, o cliente recebe uma interface IDebugHostTypeSignature que é definida da seguinte maneira:

DECLARE_INTERFACE_(IDebugHostTypeSignature, IUnknown)
{
    STDMETHOD(GetHashCode)(_Out_ ULONG* hashCode) PURE;
    STDMETHOD(IsMatch)(_In_ IDebugHostType* type, _Out_ bool* isMatch, _COM_Outptr_opt_ IDebugHostSymbolEnumerator** wildcardMatches) PURE;
    STDMETHOD(CompareAgainst)(_In_ IDebugHostTypeSignature* typeSignature, _Out_ SignatureComparison* result) PURE;
}

GetHashCode

O GetHashCode método retorna um código hash de 32 bits para a assinatura de tipo. O host de depuração garante que haja sincronização na implementação entre o código hash retornado para instâncias de tipo e o código hash retornado para assinaturas de tipo. Com exceção de uma correspondência global, se uma instância de tipo for capaz de corresponder a uma assinatura de tipo, ambas terão o mesmo código hash de 32 bits. Isso permite uma comparação rápida inicial e correspondência entre uma instância de tipo e uma infinidade de assinaturas de tipo registradas com o gerenciador de modelo de dados.

IsMatch

O método IsMatch retorna uma indicação de se uma instância de tipo específica corresponde aos critérios especificados na assinatura de tipo. Se isso acontecer, uma indicação disso será retornada, bem como um enumerador que indicará todas as partes específicas da ocorrência de tipo (como símbolos) que corresponderam a curingas na assinatura de tipo.

CompareAgainst

O método CompareAgainst compara a assinatura de tipo com outra assinatura de tipo e retorna como as duas assinaturas se comparam. O resultado da comparação que é retornado é um membro da enumeração SignatureComparison que é definida da seguinte maneira:

Enumerante Significado
Não relacionado Não há relação entre as duas assinaturas ou tipos que estão sendo comparados.
Ambíguo Uma assinatura ou tipo compara ambíguamente com a outra. Para duas assinaturas de tipo, isso significa que há instâncias de tipo potenciais que podem corresponder igualmente bem a qualquer assinatura. Como exemplo, as duas assinaturas de tipo mostradas abaixo são ambíguas. Assinatura 1: std::pair<*, int> Assinatura 2: std::pair<int,*> porque a instância de tipo std::pair<int, int> corresponde igualmente bem a qualquer uma delas (ambas têm uma correspondência concreta e uma correspondência curinga).
Menos específico Uma assinatura ou tipo é menos específico do que o outro. Muitas vezes, isso significa que a assinatura menos específica tem um curinga, onde a mais específica tem um tipo concreto. Como exemplo, a primeira assinatura abaixo é menos específica do que a segunda. Assinatura 1: std::pair<*, int> Assinatura 2: std::pair<int, int> porque tem um curinga (o *) onde o segundo tem um tipo concreto (int).
MaisEspecífico Uma assinatura ou tipo é mais específico do que o outro. Muitas vezes, isso significa que a assinatura mais específica tem um tipo concreto, onde a menos específica tem um curinga. Como exemplo, a primeira assinatura abaixo é mais específica do que a segunda. Assinatura 1: std::pair<int, int> Assinatura 2: std::pair<*, int> porque tem um tipo concreto (int) onde o segundo tem um curinga (o *).
Idêntico As duas assinaturas ou tipos são idênticos.

Ver também

Este tópico faz parte de uma série que descreve as interfaces acessíveis a partir de C++, como usá-las para criar uma extensão de depurador baseada em C++ e como fazer uso de outras construções de modelo de dados (por exemplo: JavaScript ou NatVis) a partir de uma extensão de modelo de dados C++.

Visão geral do Depurador Data Model C++

Depurador Data Model C++ Objects

Depurador Data Model C++ Interfaces adicionais

Depurador Data Model C++ Conceitos

Depurador Data Model C++ Scripting