Интерфейсы C++ модели данных отладчика

В этом разделе содержатся общие сведения об использовании интерфейсов C++ модели данных отладчика для расширения и настройки возможностей отладчика.

Интерфейсы узла модели данных отладчика C++

Узел модели данных отладчика

Модель данных отладчика предназначена для создания компонентной системы, которая может размещаться в различных контекстах. Обычно модель данных размещается в контексте приложения отладчика. Чтобы быть хостом модели данных, необходимо реализовать ряд интерфейсов для предоставления основных аспектов отладчика: его целевой объект, его пространства памяти, его вычислитель, его символьная система и система типов и т. д. Хотя эти интерфейсы реализуются любым приложением, желающим разместить модель данных, они используются как основной моделью данных, так и любым расширением, которое взаимодействует с моделью данных.

Набор основных интерфейсов:

Имя_интерфейса Описание
IDebugHost Основной интерфейс для узла отладки.
IDebugHostStatus Интерфейс, позволяющий клиенту запрашивать состояние узла.
IDebugHostContext Абстракция контекста в узле (например, определенный целевой объект, определенный процесс, определенное адресное пространство и т. д.).
IDebugHostErrorSink Интерфейс, реализованный вызывающими абонентами для получения ошибок из определенных частей узла и модели данных.
IDebugHostEvaluator / IDebugHostEvaluator2 Средство оценки выражений узла отладки.
IDebugHostExtensibility Интерфейс для расширения возможностей узла или его частей (например, вычислителя выражений).

Системные и символьные интерфейсы типов:

InterfaceName Описание
IDebugHostSymbols Основной интерфейс, предоставляющий доступ к символам и их разрешение
IDebugHostSymbol / IDebugHostSymbol2 Представляет один символ любого типа. Конкретный символ является производным от этого интерфейса.
IDebugHostModule Представляет модуль, загруженный в процесс. Это своего рода символ.
IDebugHostType / IDebugHostType2 Представляет собственный тип или тип языка.
IDebugHostConstant Представляет константу в символьных данных (например, нетипичный аргумент шаблона в C++).
IDebugHostField Представляет поле в структуре или классе.
IDebugHostData Представляет данные в модуле (если бы они находились в структуре или классе, это был бы IDebugHostField)
IDebugHostBaseClass Представляет базовый класс.
IDebugHostPublic Представляет символ в таблице publics PDB. С ним не связаны сведения о типе. Это имя и адрес.
IDebugHostModuleSignature Представляет сигнатуру модуля — определение, которое будет соответствовать набору модулей по имени и(или) версии.
IDebugHostTypeSignature Представляет сигнатуру типа — определение, которое будет соответствовать набору типов по модулю и(или) имени.

Интерфейс основного узла: IDebugHost

Интерфейс IDebugHost является основным интерфейсом любого узла модели данных. Он определяется следующим образом:

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

GetHostDefinedInterface

Метод GetHostDefinedInterface возвращает main частного интерфейса узла, если таковой существует для данного узла. Для средств отладки для Windows здесь возвращается интерфейс IDebugClient (приведение к IUnknown).

GetCurrentContext

Метод GetCurrentContext возвращает интерфейс, который представляет текущее состояние узла отладчика. Точное значение этого параметра остается за узлом, но обычно оно включает такие элементы, как сеанс, процесс и адресное пространство, активное в пользовательском интерфейсе узла отладки. Возвращаемый объект контекста в значительной степени непрозрачн для вызывающего объекта, но он является важным объектом для передачи между вызовами узла отладки. Если вызывающий объект, например, считывает память, важно знать, из какого процесса и адресного пространства считывается память. Это понятие инкапсулируется в понятие объекта контекста, возвращаемого этим методом.

GetDefaultMetadata

Метод GetDefaultMetadata возвращает хранилище метаданных по умолчанию, которое может использоваться для определенных операций (например, преобразования строк), если явные метаданные не были переданы. Это позволяет узлу отладки иметь некоторый контроль над способом представления некоторых данных. Например, метаданные по умолчанию могут содержать ключ PreferredRadix, позволяющий узлу указать, должны ли порядковые номера отображаться в десятичном или шестнадцатеричном формате, если не указано иное.

Обратите внимание, что значения свойств в хранилище метаданных по умолчанию должны разрешаться вручную и передавать объект, для которого запрашиваются метаданные по умолчанию. Метод GetKey следует использовать вместо GetKeyValue.

Интерфейс состояния: IDebugHostStatus

Интерфейс IDebugHostStatus позволяет клиенту модели данных или узлу отладки запрашивать определенные аспекты состояния узла отладки. Интерфейс определяется следующим образом:

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

PollUserInterrupt

Метод PollUserInterrupt используется для проверки того, запросил ли пользователь узла отладки прерывание текущей операции. Метод доступа к свойству в модели данных может, например, вызывать произвольный код (например, метод JavaScript). Этот код может занять произвольное время. Чтобы обеспечить реагирование узла отладки, любой такой код, который может занять произвольное количество времени, должен проверка для запроса прерывания с помощью вызова этого метода. Если значение interruptRequested возвращается как true, вызывающий объект должен немедленно прервать и вернуть результат E_ABORT.

Контекстный интерфейс: IDebugHostContext

Контекст является одним из наиболее важных аспектов модели данных и базового узла отладки. При удержании объекта важно знать, откуда он пришел: в каком процессе он находится, с каким адресным пространством он связан. Знание этих сведений позволяет правильно интерпретировать такие вещи, как значения указателя. Объект типа IDebugHostContext должен передаваться многим методам на узле отладки. Этот интерфейс можно получить несколькими способами:

  • Получение текущего контекста отладчика: вызов метода GetCurrentContext объекта IDebugHost
  • Получение контекста объекта: вызов метода GetContext объекта IModelObject
  • Получение контекста символа: вызов метода GetContext объекта IDebugHostSymbol

Кроме того, существуют два значения, которые имеют особое значение в контексте интерфейса IDebugHostContext, который возвращается или передается в модель данных или метод узла отладки:

nullptr: указывает на отсутствие контекста. Вполне допустимо, чтобы некоторые объекты не имели контекста. Объект Отладчика в корневом пространстве имен модели данных не ссылается ни на что из определенного процесса или адресного пространства. Он не имеет контекста.

USE_CURRENT_HOST_CONTEXT: значение sentinel, указывающее, что следует использовать текущий контекст пользовательского интерфейса узла отладки. Это значение никогда не будет возвращено с узла отладки. Однако он может быть передан любому методу узла отладки, который принимает входные данные IDebugHostContext вместо явного вызова метода GetCurrentContext iDebugHost. Обратите внимание, что явная передача USE_CURRENT_HOST_CONTEXT часто более эффективна, чем явное получение текущего контекста.

Контексты контекста узла в значительной степени непрозрачны для вызывающего объекта. Единственная операция, которую вызывающий объект за пределами основного узла отладки может выполнить с контекстом узла, — сравнить его с другим контекстом узла.

Интерфейс IDebugHostContext определяется следующим образом:

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

IsEqualTo

Метод IsEqualTo сравнивает контекст узла с другим контекстом узла. Если два контекста эквивалентны, возвращается указание на это. Обратите внимание, что это сравнение не является эквивалентностью интерфейса. Это сравнивает базовое непрозрачные содержимое самого контекста.

Приемник ошибок: IDebugHostErrorSink

IDebugHostErrorSink — это средство, с помощью которого клиент может получать уведомления об ошибках, возникающих во время определенных операций, и маршрутизировать эти ошибки при необходимости. Интерфейс определяется следующим образом:

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

ReportError

Метод ReportError — это обратный вызов в приемнике ошибок, который уведомляет его об ошибке и позволяет приемнику направлять ошибку в любой подходящий пользовательский интерфейс или механизм.

Средство оценки узла: IDebugHostEvaluator / IDebugHostEvaluator2

Одной из наиболее важных функций, которые узел отладки предоставляет клиентам, является доступ к средству оценки выражений на основе языка. Интерфейсы IDebugHostEvaluator и IDebugHostEvaluator2 позволяют получить доступ к этой функции с узла отладки.

Интерфейсы определяются следующим образом:

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

EvaluateExpression

Метод EvaluateExpression позволяет запрашивать узел отладки для вычисления выражения языка (например, C++) и возвращать результирующее значение вычисления этого выражения в виде IModelObject. Этот конкретный вариант метода допускает только языковые конструкции. Любые дополнительные функциональные возможности, представленные в средстве оценки выражений узла отладки, отсутствующего в языке (например, методы запроса LINQ), отключены для оценки.

EvaluateExtendedExpression

Метод EvaluateExtendedExpression аналогичен методу EvaluateExpression, за исключением того, что он включает дополнительные функции, не относящиеся к языку, которые конкретный узел отладки выбирает для добавления в средство оценки выражений. Например, для средств отладки для Windows это позволяет использовать анонимные типы, запросы LINQ, квалификаторы модулей, описатели формата и другие функции, отличные от C/C++.

IDebugHostEvaluator2

AssignTo

Метод AssignTo выполняет назначение в соответствии с семантикой отлаживаемого языка.

Интерфейс расширяемости узла: IDebugHostExtensibility

Некоторые функциональные возможности узла отладки при необходимости подвержены расширяемости. Сюда может, например, входить средство оценки выражений. Интерфейс IDebugHostExtensibility — это средство, с помощью которого осуществляется доступ к этим точкам расширяемости. Интерфейс определяется следующим образом:

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

CreateFunctionAlias

Метод CreateFunctionAlias создает "псевдоним функции", "быстрый псевдоним" для метода, реализованного в некотором расширении. Значение этого псевдонима зависит от узла. Он может расширить вычислитель выражений узла с помощью функции или выполнить что-то совершенно другое.

DestroyFunctionAlias

Метод DestroyFunctionAlias отменяет предыдущий вызов метода CreateFunctionAlias. Функция больше не будет доступна под именем быстрого псевдонима.

Доступ к модели данных

Во-первых, API расширяемости модели данных предназначены для нейтрального приложения (как правило, отладчика), которое выступает в качестве узла модели данных. Теоретически любое приложение может разместить модель данных, предоставив набор интерфейсов API узла, которые предоставляют систему типов целевых объектов отладки приложения и набор проецируемых объектов в пространство имен модели данных о целевых объектах, процессах, потоках и т. д. находятся в этих целевых объектах отладки.

Хотя API-интерфейсы модели данных , которые начинают IDataModel, IDebugHost и ответвление IModelObject, предназначены для переноса, они не определяют, что такое "расширение отладчика". Сегодня компонент, который хочет расширить средства отладки для Windows и модуль, который он предоставляет, должен написать расширение обработчика, чтобы получить доступ к модели данных. Это расширение обработчика должно быть только расширением подсистемы в такой степени, как это механизм загрузки и начальной загрузки для расширения. Таким образом, минимальная реализация обеспечит:

  • DebugExtensionInitialize: метод, который использует созданный IDebugClient для получения доступа к модели данных и настраивает манипуляции с объектной моделью.
  • DebugExtensionUninitialize: метод, который отменяет манипуляции объектной модели, выполненные в DebugExtensionInitialize.
  • DebugExtensionCanUnload: метод, который возвращает возможность выгрузки расширения. Если в расширении по-прежнему имеются динамические COM-объекты, оно должно указывать на это. Это эквивалент отладчика DllCanUnloadNow COM. Если возвращается S_FALSE указание на невозможность выгрузки, отладчик может запросить его позже, чтобы узнать, является ли выгрузка безопасной, или он может повторно инициализировать расширение, вызвав DebugExtensionInitialize еще раз. Расширение должно быть готово к обработке обоих путей.
  • DebugExtensionUnload: метод, который выполняет любую окончательную очистку, необходимую непосредственно перед выгрузкой библиотеки DLL.

Интерфейс моста: IHostDataModelAccess

Как уже упоминалось, при вызове DebugExtensionInitialize он создает клиент отладки и получает доступ к модели данных. Такой доступ обеспечивается мостом между устаревшими интерфейсами IDebug* средств отладки для Windows и моделью данных. Этот интерфейс моста имеет тип IHostDataModelAccess и определяется следующим образом:

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

GetDataModel

Метод GetDataModel — это метод в интерфейсе моста, который предоставляет доступ к обеим сторонам модели данных. Узел отладки (нижний край отладчика) выражается возвращенным интерфейсом IDebugHost Компонент main модели данных — диспетчер модели данных выражается возвращенным интерфейсом IDataModelManager.

Системные интерфейсы модели данных отладчика

Узел модели данных

Модель данных отладчика разработана как компонентная система, которая может размещаться в различных контекстах. Как правило, модель данных размещается в контексте приложения отладчика. Чтобы быть ведущим объектом модели данных, необходимо реализовать ряд интерфейсов для предоставления основных аспектов отладчика: его целевого объекта, пространств памяти, вычислителя, системы символов и типов и т. д. Хотя эти интерфейсы реализуются любым приложением, желающим разместить модель данных, они используются как основной моделью данных, так и любым расширением, которое взаимодействует с моделью данных.

Системный и символьный интерфейсы типов:

Имя_интерфейса Описание
IDebugHostSymbols Основной интерфейс, обеспечивающий доступ к символам и разрешение символов
IDebugHostSymbol / IDebugHostSymbol2 Представляет один символ любого вида. Конкретный символ является производным от этого интерфейса.
IDebugHostModule Представляет модуль, загруженный в процесс. Это своего рода символ.
IDebugHostType / IDebugHostType2 Представляет собственный/языковой тип.
IDebugHostConstant Представляет константу в символьной информации (например, нетипичный аргумент шаблона в C++).
IDebugHostField Представляет поле в структуре или классе.
IDebugHostData Представляет данные в модуле (если бы они находились в структуре или классе, это было бы IDebugHostField)
IDebugHostBaseClass Представляет базовый класс.
IDebugHostPublic Представляет символ в общедоступной таблице PDB. С ним не связаны сведения о типе. Это имя и адрес.
IDebugHostModuleSignature Представляет сигнатуру модуля — определение, которое будет соответствовать набору модулей по имени и /или версии.
IDebugHostTypeSignature Представляет сигнатуру типа — определение, которое будет соответствовать набору типов по модулю и/или имени.

Другие основные интерфейсы:

Имя_интерфейса Описание
IDebugHost Основной интерфейс для узла отладки.
IDebugHostStatus Интерфейс, позволяющий клиенту запрашивать состояние узла.
IDebugHostContext Абстракция контекста в узле (например, конкретный целевой объект, определенный процесс, определенное адресное пространство и т. д.).
IDebugHostErrorSink Интерфейс, реализованный вызывающими абонентами для получения ошибок из определенных частей узла и модели данных.
IDebugHostEvaluator / IDebugHostEvaluator2 Средство оценки выражений узла отладки.
IDebugHostExtensibility Интерфейс для расширения возможностей узла или его частей (например, средства оценки выражений).

Основной символьный интерфейс: IDebugHostSymbols

Интерфейс IDebugHostSymbols — это main отправная точка для доступа к символам в целевом объекте отладки. Этот интерфейс можно запрашивать из экземпляра IDebugHost и определяется следующим образом:

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

CreateModuleSignature

Метод CreateModuleSignature создает сигнатуру, которую можно использовать для сопоставления набора конкретных модулей по имени и при необходимости по версии. В сигнатуре модуля есть три компонента:

  • Имя: соответствующий модуль должен иметь имя, которое является точным совпадением без учета регистра с именем в сигнатуре
  • Минимальная версия. Если указано, соответствующий модуль должен иметь минимальную версию, которая не ниже этой версии. Версии указываются в формате "A.B.C.D", при этом каждая последующая часть менее важна, чем предыдущие. Только первый сегмент является обязательным.
  • Максимальная версия: если указано, соответствующий модуль должен иметь максимальную версию, которая не выше этой версии. Версии указываются в формате "A.B.C.D", при этом каждая последующая часть менее важна, чем предыдущие. Только первый сегмент является обязательным.

CreateTypeSignature

Метод CreateTypeSignature создает сигнатуру, которую можно использовать для сопоставления набора конкретных типов, содержащих имя модуля и типа. Формат строки сигнатуры имени типа зависит от отлаживаемого языка (и узла отладки). Для C/C++ строка подписи эквивалентна спецификации типа NatVis. То есть строка подписи — это имя типа, в котором для аргументов шаблона разрешены подстановочные знаки (указанные как *).

CreateTypeSignatureForModuleRange

Метод CreateTypeSignatureForModuleRange создает сигнатуру, которую можно использовать для сопоставления набора конкретных типов по подписи модуля и имени типа. Это похоже на метод CreateTypeSignature, за исключением того, что вместо передачи определенного модуля для сопоставления с подписью вызывающий объект передает аргументы, необходимые для создания подписи модуля (как если бы подпись модуля была создана с помощью метода CreateModuleSignature).

EnumerateModules

Метод EnumerateModules создает перечислитель, который перечисляет каждый модуль, доступный в определенном контексте узла. Этот контекст узла может инкапсулировать контекст процесса или инкапсулировать что-то вроде ядра Windows.

FindModuleByName

Метод FindModuleByName будет просматривать заданный контекст узла и находить модуль с указанным именем и возвращать ему интерфейс. Можно искать модуль по имени с расширением файла или без него.

FindModuleByLocation

Метод FindModuleByLocation просматривает заданный контекст узла и определяет, какой модуль содержит адрес, заданный указанным расположением. Затем он вернет интерфейс в такой модуль.

GetMostDerivedObject

GetMostDerivedObject будет использовать систему типов отладчика для определения типа среды выполнения объекта из его статического типа. Для выполнения этого анализа этот метод будет использовать только символьные сведения и эвристические данные, доступные на уровне системы типов. Такие сведения могут включать C++ RTTI (сведения о типах времени выполнения) или анализ формы таблиц виртуальных функций объекта. Он не включает такие элементы, как предпочтительная концепция типа среды выполнения в IModelObject. Если анализу не удается найти тип среды выполнения или не удается найти тип среды выполнения, отличный от статического типа, переданного в метод, расположение и тип входных данных могут быть переданы. По этим причинам метод не завершится ошибкой.

Основной интерфейс отдельных символов: IDebugHostSymbol

Каждый символ, который может быть возвращен из узла модели данных, будет каким-то образом производным от IDebugHostSymbol. Это основной интерфейс, который реализует каждый символ независимо от типа символа. В зависимости от типа символа данный символ может реализовать набор других интерфейсов, возвращающих атрибуты, более уникальные для определенного типа символа, представленного этим интерфейсом. Интерфейс IDebugHostSymbol2/IDebugHostSymbol определяется следующим образом:

DECLARE_INTERFACE_(IDebugHostSymbol2, IDebugHostSymbol)
{
    // 
    // IDebugHostSymbol:
    //
    STDMETHOD(GetContext)(_COM_Outptr_ IDebugHostContext** context) PURE;
    STDMETHOD(EnumerateChildren)(_In_ SymbolKind kind, _In_opt_z_ PCWSTR name, _Out_ IDebugHostSymbolEnumerator **ppEnum) PURE;
    STDMETHOD(GetSymbolKind)(_Out_ SymbolKind *kind) PURE;
    STDMETHOD(GetName)(_Out_ BSTR* symbolName) PURE;
    STDMETHOD(GetType)(_Out_ IDebugHostType** type) PURE;
    STDMETHOD(GetContainingModule)(_Out_ IDebugHostModule **containingModule) PURE;
    STDMETHOD(CompareAgainst)(_In_ IDebugHostSymbol *pComparisonSymbol, _In_ ULONG comparisonFlags, _Out_ bool *pMatches) PURE;
    //
    // IDebugHostSymbol2
    //
    STDMETHOD(EnumerateChildrenEx)(_In_ SymbolKind kind, _In_opt_z_ PCWSTR name, _In_opt_ SymbolSearchInfo* searchInfo, _Out_ IDebugHostSymbolEnumerator **ppEnum) PURE;
}

Очень важно отметить, что этот интерфейс представляет множество типов символов, разделенных перечислением SymbolKind, которое имеет следующие значения:

Enumarant Значение
Символ Неопределенный тип символа
SymbolModule Символ является модулем, и его можно запросить для IDebugHostModule.
SymbolType Символ является типом, и его можно запросить для IDebugHostType.
SymbolField Символ является полем (элементом данных в структуре или классе) и может запрашиваться для IDebugHostField.
SymbolConstant Символ является постоянным значением, и его можно запросить для IDebugHostConstant.
SymbolData Символ — это данные, которые не являются членом структуры или класса и могут запрашивать данные для IDebugHostData.
SymbolBaseClass Символ является базовым классом, который можно запрашивать для IDebugHostBaseClass.
SymbolPublic Символ является записью в общедоступной таблице модуля (без сведений о типе) и может запрашивать IDebugHostPublic.
SymbolFunction Символ является функцией и может запрашивать IDebugHostData.

GetContext

Метод GetContext возвращает контекст, в котором символ является допустимым. Хотя он будет представлять такие элементы, как целевой объект отладки и пространство процессов или адресов, в котором существует символ, он может быть не столь специфичен, как контекст, полученный из других средств (например, из IModelObject).

EnumerateChildren

Метод EnumerateChildren возвращает перечислитель, который перечисляет все дочерние элементы данного символа. Например, для типа C++ базовые классы, поля, функции-члены и т. п. считаются дочерними элементами символа типа.

Интерфейс модуля: IDebugHostModule

Представление отладчика о модуле, загружаемом в пределах определенного адресного пространства, представлено в модели данных двумя различными способами: на системном уровне типа через интерфейс IDebugHostModule. Здесь модуль является символом, а основные атрибуты модуля — вызовы метода интерфейса Projected на уровне модели данных через модель данных Debugger.Models.Module. Это расширяемая инкапсуляция типа системного представления модуля IDebugHostModule.

Интерфейс IDebugHostModule определяется следующим образом (игнорируются методы, которые являются универсальными для IDebugHostSymbol):

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

GetImageName

Метод GetImageName возвращает имя образа модуля. В зависимости от значения аргумента allowPath возвращаемое имя образа может содержать полный путь к изображению.

GetBaseLocation

Метод GetBaseLocation возвращает базовый адрес нагрузки модуля в виде структуры расположения. Возвращаемая структура расположения для модуля обычно ссылается на виртуальный адрес.

GetVersion

Метод GetVersion возвращает сведения о версии модуля (при условии, что такие сведения можно успешно считывать из заголовков). Если запрашивается заданная версия (с помощью указателя вывода, отличного от nullptr), и она не может быть прочитана, из вызова метода будет возвращен соответствующий код ошибки.

FindTypeByName

Метод FindTypeByName находит тип, определенный в модуле именем типа, и возвращает для него символ типа. Этот метод может возвращать допустимый тип IDebugHostType, который никогда не будет возвращен посредством явной рекурсии дочерних элементов модуля. Узел отладки может разрешить создание производных типов — типов, которые никогда не использовались в самом модуле, но являются производными от типов. Например, если структура MyStruct определена в символах модуля, но тип MyStruct ** никогда не используется, метод FindTypeByName может вернуть символ типа для MyStruct **, несмотря на то, что имя типа никогда явно не отображается в символах модуля.

FindSymbolByRVA

Метод FindSymbolByRVA найдет один соответствующий символ по заданному относительному виртуальному адресу в модуле. Если в предоставленном RVA нет одного символа (например, имеется несколько совпадений), этот метод возвращает ошибку. Обратите внимание, что этот метод предпочтет возвращать закрытый символ, а не символ в общедоступной таблице.

FindSymbolByName

Метод FindSymbolByName найдет в модуле один глобальный символ заданного имени. Если нет ни одного символа, соответствующего заданному имени, этот метод возвращает ошибку. Обратите внимание, что этот метод предпочитает возвращать закрытый символ, а не символ в таблице publics.

Доступ к системе типов: IDebugHostType2 / IDebugHostType

Данный язык или собственный тип описывается интерфейсами IDebugHostType2 или IDebugHostType. Обратите внимание, что некоторые методы в этих интерфейсах применяются только для определенных типов. Данный символ типа может ссылаться на один из следующих типов, как описано в перечислении TypeKind:

Тип типа Описание
TypeUDT Определяемый пользователем тип (структуру, класс, объединение и т. д.). Объект модели, имеющий собственный тип TypeUDT, имеет каноническое представление ObjectTargetObject, где тип всегда хранится внутри соответствующего объекта IModelObject.
TypePointer Указатель. Объект модели, имеющий собственный тип TypePointer, имеет каноническое представление ObjectIntrinsic, где значение указателя равно нулю, расширено до VT_UI8 и хранится как встроенные данные в этой 64-разрядной форме. Любой символ типа TypePointer имеет базовый тип (возвращаемый методом GetBaseType) типа, на который указывает указатель.
TypeMemberPointer Указатель на член класса. Объект модели, имеющий собственный тип TypeMemberPointer, имеет каноническое представление, которое является встроенным (значение совпадает со значением указателя). Точное значение этого значения зависит от узла компилятора или отладки.
TypeArray Массив объектов . Объект модели, имеющий собственный тип TypeArray, имеет каноническое представление ObjectTargetObject. Базовым адресом массива является расположение объекта (извлекается с помощью метода GetLocation), а тип массива всегда сохраняется. Любой символ типа TypeArray имеет базовый тип (возвращаемый методом GetBaseType) типа, массивом которого является массив.
TypeFunction Функция.
TypeTypedef Определение типа. Объект модели, имеющий собственный тип, тип которого в противном случае был бы TypeTypedef, имеет каноническое представление, идентичное каноническому представлению конечного типа, лежащего в основе typedef. Это выглядит полностью прозрачным для конечного пользователя объекта и сведений о типе, если только явные методы определения типа IDebugHostType2 не используются для запроса сведений о определении типа или нет явной модели данных, зарегистрированной для определения типа. Обратите внимание, что метод GetTypeKind никогда не возвращает TypeTypedef. Каждый метод возвращает то, что будет возвращать окончательный тип, лежащий в основе typedef. В IDebugHostType2 существуют методы typedef, которые можно использовать для получения сведений о определении типа.
TypeEnum Перечисление. Объект модели, имеющий собственный тип TypeEnum, имеет каноническое представление ObjectIntrinsic, где значение и тип встроенного объекта идентичны значению перечисления.
TypeIntrinsic Встроенный (базовый тип). Объект модели, имеющий собственный тип TypeIntrinsic, имеет каноническое представление ObjectIntrinsic. Сведения о типе могут храниться или не храниться, особенно если базовый тип полностью описан типом данных variant (VT_*) встроенных данных, хранящихся в IModelObject.

Общий интерфейс IDebugHostType2/IDebugHostType определяется следующим образом (за исключением методов IDebugHostSymbol):

DECLARE_INTERFACE_(IDebugHostType2, IDebugHostType)
{
    //
    // IDebugHostType:
    //
    STDMETHOD(GetTypeKind)(_Out_ TypeKind *kind) PURE;
    STDMETHOD(GetSize)(_Out_ ULONG64* size) PURE;
    STDMETHOD(GetBaseType)(_Out_ IDebugHostType** baseType) PURE;
    STDMETHOD(GetHashCode)(_Out_ ULONG* hashCode) PURE;
    STDMETHOD(GetIntrinsicType)(_Out_opt_ IntrinsicKind *intrinsicKind, _Out_opt_ VARTYPE *carrierType) PURE;
    STDMETHOD(GetBitField)(_Out_ ULONG* lsbOfField, _Out_ ULONG* lengthOfField) PURE;
    STDMETHOD(GetPointerKind)(_Out_ PointerKind* pointerKind) PURE;
    STDMETHOD(GetMemberType)(_Out_ IDebugHostType** memberType) PURE;
    STDMETHOD(CreatePointerTo)(_In_ PointerKind kind, _COM_Outptr_ IDebugHostType** newType) PURE;
    STDMETHOD(GetArrayDimensionality)(_Out_ ULONG64* arrayDimensionality) PURE;
    STDMETHOD(GetArrayDimensions)(_In_ ULONG64 dimensions, _Out_writes_(dimensions) ArrayDimension *pDimensions) PURE;
    STDMETHOD(CreateArrayOf)(_In_ ULONG64 dimensions, _In_reads_(dimensions) ArrayDimension *pDimensions, _COM_Outptr_ IDebugHostType** newType) PURE;
    STDMETHOD(GetFunctionCallingConvention)(_Out_ CallingConventionKind* conventionKind) PURE;
    STDMETHOD(GetFunctionReturnType)(_COM_Outptr_ IDebugHostType** returnType) PURE;
    STDMETHOD(GetFunctionParameterTypeCount)(_Out_ ULONG64* count) PURE;
    STDMETHOD(GetFunctionParameterTypeAt)(_In_ ULONG64 i, _Out_ IDebugHostType** parameterType) PURE;
    STDMETHOD(IsGeneric)(_Out_ bool* isGeneric) PURE;
    STDMETHOD(GetGenericArgumentCount)(_Out_ ULONG64* argCount) PURE;
    STDMETHOD(GetGenericArgumentAt)(_In_ ULONG64 i, _Out_ IDebugHostSymbol** argument) PURE;
    //
    // IDebugHostType2:
    //
    STDMETHOD(IsTypedef)(_Out_ bool* isTypedef) PURE;
    STDMETHOD(GetTypedefBaseType)(_Out_ IDebugHostType2** baseType) PURE;
    STDMETHOD(GetTypedefFinalBaseType)(_Out_ IDebugHostType2** finalBaseType) PURE;
    STDMETHOD(GetFunctionVarArgsKind)(_Out_ VarArgsKind* varArgsKind) PURE;
}

Общие методы IDebugHostType2/IDebugHostType

Следующие методы IDebugHostType являются общими для любого типа независимо от типа, возвращаемого методом GetTypeKind:

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

GetTypeKind

Метод GetTypeKind возвращает тип типа (указатель, массив, встроенный и т. д.), на который ссылается символ.

GetSize

Метод GetSize возвращает размер типа (как если бы вы сделали sizeof(type) в C++).

GetBaseType

Если тип является производным от другого отдельного типа (например, myStruct * является производным от MyStruct), метод GetBaseType возвращает базовый тип производной части. Для указателей возвращается тип, на который указывает. Для массивов возвращается то, что массив является массивом. Если тип не является производным типом, возвращается ошибка.

GetHashCode

Метод GetHashCode возвращает 32-разрядный хэш-код для типа . За исключением глобального соответствия (например, сигнатуры типа, эквивалентной *, которая соответствует всем, если это разрешено узлом), любой экземпляр типа, который может соответствовать определенной сигнатуре типа, должен возвращать тот же хэш-код. Этот метод используется в сочетании с сигнатурами типов, чтобы сопоставить сигнатуры типов экземплярам типа.

Встроенные методы IDebugHostType2/IDebugHostType

Следующие методы IDebugHostType относятся к встроенным типам (или типам, которые содержат встроенные данные, такие как перечисления):

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

GetIntrinsicType

Метод GetIntrinsicType возвращает сведения о том, какой тип является встроенным типом. Из этого метода возвращаются два значения:

  • Встроенный тип указывает общий тип (например, целое число, без знака, с плавающей запятой), но не размер типа (например, 8 бит, 16 бит, 32 бит, 64 бит).
  • Тип носителя указывает, как встроенный тип упаковывается в структуру VARIANT. Это константа VT_*.

Сочетание этих двух значений предоставляет полный набор сведений о встроенной функции .

Битовые методы IDebugHostType2/IDebugHostType

Следующие методы IDebugHostType относятся к типам, которые хранят данные в битовых полях. Сведения о размещении битовых полей внутри встроенной функции хранятся как часть символа типа в модели данных, а не как атрибут расположения.

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

GetBitField

Если данный элемент структуры данных является битовое поле (например, ULONG MyBits:8), сведения о типе поля содержат сведения о расположении битового поля. Для получения этой информации можно использовать метод GetBitField. Этот метод завершится ошибкой для любого типа, не являющегося битовой. Это единственная причина сбоя метода. Простого вызова этого метода и изучения успешного или неудачного достаточно, чтобы отличить битовое поле от небитового поля. Если заданный тип является битовое поле, позиции полей определяются полуоткрытым набором (lsbOfField + lengthOfField : lsbOfField]

Методы, связанные с указателем IDebugHostType2/IDebugHostType

Следующие методы IDebugHostType относятся к типам указателей. Это типы, в которых GetTypeKind возвращает TypePointer или TypeMemberPointer':

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

GetPointerKind

Для типов, являющихся указателями, метод GetPointerKind возвращает тип указателя. Это определяется перечислением PointerKind.

GetMemberType

Для типов, которые являются указателем на член (как указано типом типа TypeMemberPointer), метод GetMemberType возвращает класс, на который указатель является указателем на член.

Методы, связанные с массивом IDebugHostType2/IDebugHostType

Массивы — это типы, в которых GetTypeKind возвращает TypeArray. Обратите внимание, что массивы, определенные системой типов узла отладки, не совпадают с одномерными одномерными массивами, основанными на нулевом индексе, упакованными линейными одномерными массивами, которые использует C. Массивы стилей C соответствуют определению, но общая область массива в IDebugHostType шире. Массив в узле отладки может быть многомерным, и каждое измерение в массиве определяется дескриптором ArrayDimensionЭти дескриптор имеет следующие поля:

Поле Значение
LowerBound Базовый индекс массива в виде 64-разрядного значения со знаком. Для массива стилей C значение всегда будет равно нулю. Это не должно быть. Отдельное измерение массива может начинаться с любого 64-разрядного индекса, даже отрицательного.
Длина Длина измерения массива в виде 64-разрядного значения без знака. Типы массива охватывают половину открытого набора [LowerBound, LowerBound + Length).
Stride Определяет шаг измерения массива. Для увеличения одного (от N до N + 1) в индексе этого измерения это указывает, сколько байтов необходимо переместить вперед в памяти. Для массива стиля C это будет размер каждого элемента массива. Это не обязательно должно быть. Заполнение между элементами может быть выражено как шаг, превышающий размер каждого отдельного элемента. Для многомерных массивов это значение указывает, как переместить все измерение вперед. Рассмотрим матрицу M x N. Это можно описать в виде основной строки как два измерения:
{ [LowerBound: 0, Length: M, Stride: N \* sizeof(element)], [LowerBound: 0, Length: N, Stride: sizeof(element)]} 

Или его можно также описать в виде столбца как два измерения:

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

Концепция ArrayDimension обеспечивает такую степень гибкости.

Следующие методы IDebugHostType относятся к типам массивов.

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

GetArrayDimensionality

Метод GetArrayDimensionality возвращает количество измерений, в которых индексируется массив. Для массивов стилей C возвращаемое здесь значение всегда будет равно 1.

GetArrayDimensions

Метод GetArrayDimensions возвращает набор дескрипторов, по одному для каждого измерения массива, как указано методом GetArrayDimensionality. Каждый дескриптор представляет собой структуру ArrayDimension, которая описывает начальный индекс, длину и шаг вперед каждого измерения массива. Это позволяет опишите значительно более мощные конструкции массива, чем разрешено в системе типов C.

Для массивов в стиле C здесь возвращается одно измерение массива со значениями, которые всегда:

  • LowerBound = 0
  • Length = ARRAYSIZE(array)
  • Stride = sizeof(elementType)

Методы, связанные с функцией IDebugHostType2/IDebugHostType

Типы, указывающие, что они являются типами функций через тип TypeFunction, поддерживают следующие методы в IDebugHostType и IDebugHostType2.

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

GetFunctionCallingConvention

Метод GetFunctionCallingConvention возвращает соглашение о вызовах функции. Возвращается как член перечисления CallingConventionKind.

GetFunctionReturnType

Метод GetFunctionReturnType возвращает тип возвращаемого значения функции.

GetFunctionParameterTypeCount

Метод GetFunctionParameterTypeCount возвращает количество аргументов, которые принимает функция. Обратите внимание, что маркер аргумента переменной на основе многоточия C/C++ не учитывается в этом подсчете. Наличие таких объектов должно быть обнаружено с помощью метода GetFunctionVarArgsKind. Сюда будут входить только аргументы перед многоточием.

GetFunctionParameterTypeAt

Метод GetFunctionParameterTypeAt возвращает функции тип i-го аргумента.

Метод GetFunctionVarArgsKind возвращает, использует ли данная функция список переменных аргументов, и если да, то какой стиль переменных аргументов она использует. Определяется элементом перечисления VarArgsKind, определенным следующим образом:

Перечисление Значение
VarArgsNone Функция не принимает аргументы переменных.
VarArgsCStyle Функция является функцией varargs в стиле C (returnType(arg1, arg2, ...)). Число аргументов, сообщаемых функцией, не включает аргумент с многоточием. Передача любого аргумента переменной происходит после количества аргументов, возвращаемых методом GetFunctionParameterTypeCount.

IDebugHostType2 GetFunctionVarArgsKind

Метод GetFunctionVarArgsKind возвращает, использует ли данная функция список переменных аргументов, и если да, то какой стиль переменных аргументов она использует. Определяется элементом перечисления VarArgsKind, определенным следующим образом:

Методы, связанные с типом IDebugHostType2/IDebugHostType

Любой тип, являющийся определением типа, будет вести себя так, как если бы тип был последним типом, лежащим в основе typedef. Это означает, что такие методы, как GetTypeKind, не будут указывать, что тип является определением типа. Аналогичным образом GetBaseType не возвращает тип, на который ссылается определение. Вместо этого они будут указывать, что они ведут себя так, как если бы они были вызваны для окончательного определения, лежащего в основе определения типа. Например:

typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;

IDebugHostType для PMYSTRUCT или PTRMYSTRUCT будет сообщать следующие сведения:

  • Метод GetTypeKind возвращает TypePointer. Последний базовый тип MYSTRUCT * действительно является указателем.
  • Метод GetBaseType вернет тип для MYSTRUCT. Базовый тип MYSTRUCT * — MYSTRUCT.

Единственное различие здесь заключается в том, как ведут себя методы определения типа в IDebugHostType2. Ниже приведены следующие методы:

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

В этом примере:

  • Метод IsTypedef возвращает значение true для PMYSTRUCT и PTRMYSTRUCT.
  • Метод GetTypedefBaseType возвращает MYSTRUCT * для PMYSTRUCT и PMYSTRUCT для PTRMYSTRUCT.
  • Метод GetTypedefFinalBaseType возвращает MYSTRUCT * для обоих типов.

IsTypedef

Метод IsTypedef является единственным методом, который может определить, является ли тип typedef. Метод GetTypeKind будет вести себя так, как если бы он был вызван для базового типа.

GetTypedefBaseType

Метод GetTypedefBaseType возвращает то, что непосредственное определение typedef. В примерах, описанных в документации:

typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;

Этот метод возвращает MYSTRUCT * для PMYSTRUCT и PMYSTRUCT для PTRMYSTRUCT.

GetTypedefFinalBaseType

Метод GetTypedefFinalBaseType вернет окончательный тип, для который typedef является определением. Если typedef является определением другого typedef, оно будет продолжать следовать за цепочкой определений, пока не достигнет типа, который не является определением типа, и этот тип не будет возвращен. В примерах, описанных в документации:

typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;

Этот метод возвращает MYSTRUCT * при вызове в PMYSTRUCT или PTRMYSTRUCT.

Методы создания типа IDebugHostType2/IDebugHostType

STDMETHOD(CreatePointerTo)(_In_ PointerKind kind, _COM_Outptr_ IDebugHostType** newType) PURE;
STDMETHOD(CreateArrayOf)(_In_ ULONG64 dimensions, _In_reads_(dimensions) ArrayDimension *pDimensions, _COM_Outptr_ IDebugHostType** newType) PURE;

Постоянные значения символов: IDebugHostConstant

Для расположений, где значения констант присутствуют в символьной информации (где конкретное значение является символом, который может быть постоянным значением или не может быть), интерфейс IDebugHostConstant выражает понятие такой константы. Обычно используется в таких местах, как аргументы шаблона, где заданный аргумент обычно является типом, но вместо этого может быть аргументом шаблона, не являющегося типом (например, константой).

Интерфейс IDebugHostConstant определяется следующим образом (игнорируются универсальные методы, реализованные IDebugHostSymbol):

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

GetValue

Метод GetValue возвращает значение константы, упакованной в VARIANT. Важно отметить, что метод GetType в IDebugHostSymbol может возвращать определенный символ типа для константы. В таких случаях нет никакой гарантии, что упаковка значения константы, определяемого символом типа, совпадает с упаковкой, возвращаемой методом GetValue здесь.

Доступ к элементу данных: IDebugHostField

Класс IDebugHostField представляет символ, который является элементом данных класса, структуры, объединения или другой конструкции типа. Он не представляет свободные данные (например, глобальные данные). Интерфейс определяется следующим образом (игнорируя методы, универсальные для IDebugHostSymbol):

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

GetLocationKind

Метод GetLocationKind возвращает расположение, в каком расположен символ в соответствии с перечислением LocationKind. Такое перечисление может иметь одно из следующих значений:

Перечисление Значение
LocationMember Поле является обычным элементом данных в конструкции класса, структуры, объединения или другого типа. Он имеет смещение относительно базового адреса конструкции содержащего типа. Такой базовый адрес обычно представлен указателем this. Смещение поля можно получить с помощью метода GetOffset. Методы GetLocation и GetValue завершатся ошибкой для поля LocationMember.
LocationStatic Поле является статическим и имеет собственный адрес. Метод GetLocation вернет абстрактное расположение (например, адрес) статического поля. Методы GetOffset и GetValue завершатся ошибкой для поля LocationStatic.
LocationConstant Поле является константой и имеет значение . Метод GetValue возвращает значение константы. Методы GetOffset и GetLocation завершатся ошибкой для поля LocationConstant
LocationNone Поле не имеет расположения. Он может быть оптимизирован компилятором или статическим полем, которое объявлено, но никогда не определено. Независимо от того, как такое поле появилось, оно не имеет физического присутствия или значения. Только в символах. Все методы получения (GetOffset, GetLocation и GetValue) завершатся ошибкой для поля LocationNone.

GetOffset

Для полей, имеющих смещение (например, полей, тип расположения которых указывает LocationMember), метод GetOffset вернет смещение от базового адреса содержащего типа (этот указатель) к данным самого поля. Такие смещения всегда выражаются в виде 64-разрядных значений без знака. Если заданное поле не имеет расположения, которое является смещением от базового адреса содержащего типа, метод GetOffset завершится ошибкой.

GetLocation

Для полей, которые имеют адрес независимо от конкретного экземпляра типа (например, поля, тип расположения которых указывает LocationStatic), метод GetLocation возвращает абстрактное расположение (адрес) поля. Если заданное поле не имеет статического расположения, метод GetLocation завершится ошибкой.

GetValue

Для полей, которые имеют постоянное значение, определенное в символьной информации (например, поля, тип расположения которых указывает LocationConstant), метод GetValue вернет значение константы поля. Если заданное поле не имеет константного значения, метод GetValue завершится ошибкой.

Бесплатный доступ к данным: IDebugHostData

Данные в модулях, которые не являются членами другого типа, представлены интерфейсом IDebugHostData. Этот интерфейс определяется следующим образом (игнорируя методы, универсальные для IDebugHostSymbol):

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

Все эти методы семантически эквивалентны их аналогам в IDebugHostField. Единственное отличие заключается в том, что метод GetLocationKind никогда не возвращает LocationMember для бесплатных данных.

GetLocationKind

Метод GetLocationKind возвращает расположение, в каком расположен символ в соответствии с перечислением LocationKind. Описание этого перечисления можно найти в документации по IDebugHostField.

GetLocation

Для данных с адресом метод GetLocation возвращает абстрактное расположение (адрес) поля. Если указанные данные не имеют статического расположения, метод GetLocation завершится ошибкой.

GetValue

Для данных, которые имеют постоянное значение, определенное в символьной информации (например, данные, тип расположения которых указывает на LocationConstant), метод GetValue вернет постоянное значение поля. Если заданные данные не имеют константного значения, метод GetValue завершится ошибкой.

Базовые классы: IDebugHostBaseClass

Иерархия наследования данного типа выражается через дочерние элементы символа типа. Если данный тип является производным (с учетом наследования) от одного или нескольких типов, для этого типа будет один или несколько дочерних элементов SymbolBaseClass символа типа. Каждый из этих символов SymbolBaseClass представляет собой немедленное наследование от определенного типа. Имя базового класса — это имя символа SymbolBaseClass, а также символа типа для базового класса. Метод GetType для символа SymbolBaseClass можно использовать для получения символа типа для самого базового класса. Полную иерархию наследования можно пройти путем рекурсивного изучения дочерних символов SymbolBaseClass. Каждый из этих символов базового класса выражается интерфейсом IDebugHostBaseClass, который определен следующим образом (игнорируя методы, универсальные для IDebugHostSymbol):

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

GetOffset

Метод GetOffset возвращает смещение базового класса от базового адреса производного класса. Такое смещение может быть равно нулю или иметь положительное 64-разрядное значение без знака.

Открытые символы: IDebugHostPublic

Открытые символы представляют элементы в общедоступной таблице в файле символов. Это, по сути, адреса экспорта. Нет сведений о типе, связанных с общедоступным символом, а только адресом. Если вызывающий объект явно не запрашивает открытый символ, узел отладки предпочитает возвращать закрытые символы для каждого запроса. Открытый символ выражается интерфейсом IDebugHostPublic, который определяется следующим образом (игнорируя методы, которые являются универсальными для IDebugHostSymbol):

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

Все эти методы семантически эквивалентны их аналогам в IDebugHostField. Единственное отличие заключается в том, что метод GetLocationKind никогда не возвращает LocationMember или LocationConstant для таких символов.

GetLocationKind

Метод GetLocationKind возвращает расположение, в каком расположен символ в соответствии с перечислением LocationKind. Описание этого перечисления можно найти в документации по IDebugHostField.

GetLocation

Для данных с адресом метод GetLocation возвращает абстрактное расположение (адрес) поля. Если у данного общедоступного объекта нет статического расположения, метод GetLocation завершится ошибкой.

Сигнатуры модулей и сопоставление версий: IDebugHostModuleSignature

Сигнатуры модулей представляют собой средство проверка, соответствует ли данный модуль набору критериев, касающихся именования и управления версиями. Подпись модуля создается с помощью метода CreateModuleSignature в IDebugHostSymbols. Он может совпадать с именем модуля и необязательным диапазоном номеров версий модуля. После создания такой подписи клиент получает интерфейс IDebugHostModuleSignature, который определяется следующим образом:

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

IsMatch

Метод IsMatch сравнивает конкретный модуль (заданный символом IDebugHostModule) с сигнатурой, сравнивая имя и версию модуля с именем и диапазоном версий, указанными в сигнатуре. Возвращается указание на то, соответствует ли данный символ модуля сигнатуре.

Сигнатуры типов и сопоставление типов: IDebugHostTypeSignature

Сигнатуры типов представляют собой средство проверка, соответствует ли данный экземпляр типа набору критериев в отношении имени типа, универсальных аргументов для типа и модуля, в которых находится тип. Подпись типа создается с помощью метода CreateTypeSignature в IDebugHostSymbols. После создания такой подписи клиент получает интерфейс IDebugHostTypeSignature, который определяется следующим образом:

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

GetHashCode

Метод GetHashCode возвращает 32-разрядный хэш-код для сигнатуры типа. Узел отладки гарантирует синхронизацию в реализации между хэш-кодом, возвращенным для экземпляров типа, и хэш-кодом, возвращенным для сигнатур типов. За исключением глобального совпадения, если экземпляр типа может соответствовать сигнатуре типа, оба будут иметь один и тот же 32-разрядный хэш-код. Это позволяет выполнять начальное быстрое сравнение и сопоставление между экземпляром типа и множеством сигнатур типов, зарегистрированных в диспетчере моделей данных.

IsMatch

Метод IsMatch возвращает значение, указывающее, соответствует ли конкретный экземпляр типа критериям, указанным в сигнатуре типа. Если это так, возвращается указание на это, а также перечислитель, который будет указывать все конкретные части экземпляра типа (в виде символов), которые соответствуют подстановочным знакам в сигнатуре типа.

CompareAgainst

Метод CompareAgainst сравнивает сигнатуру типа с другой сигнатурой типа и возвращает способ сравнения двух сигнатур. Возвращаемый результат сравнения является членом перечисления SignatureComparison, которое определяется следующим образом:

Перечисление Значение
Самостоятельный Между двумя сигнатурами или типами, которые сравниваются, связь отсутствует.
Неоднозначно Одна сигнатура или тип сравнивается неоднозначно с другой. Для двух сигнатур типов это означает, что существуют потенциальные экземпляры типов, которые могут одинаково хорошо соответствовать любой из подписей. Например, две сигнатуры типов, показанные ниже, неоднозначны. Сигнатура 1: std::pair<*, int> сигнатура 2: std::pair<int,*> поскольку экземпляр std::pair<int, int> типа соответствует одному из них одинаково хорошо (оба имеют одно конкретное совпадение и одно совпадение с подстановочными знаками).
LessSpecific Одна сигнатура или тип менее специфична, чем другая. Часто это означает, что менее конкретная сигнатура имеет подстановочный знак, где более конкретная имеет конкретный тип. Например, первая сигнатура ниже менее специфична, чем вторая. Сигнатура 1: std::pair<*, int> подпись 2: std::pair<int, int> потому что она имеет подстановочный знак ( *), где вторая имеет конкретный тип (int).
ПодробнееСпецифик Одна сигнатура или тип более специфична, чем другая. Часто это означает, что более конкретная сигнатура имеет конкретный тип, где менее конкретная имеет подстановочный знак. Например, первая сигнатура ниже более конкретна, чем вторая. Сигнатура 1: std::pair<int, int> подпись 2: std::pair<*, int> потому что она имеет конкретный тип (int), где второй имеет подстановочный знак ().*
Идентичные Две сигнатуры или типы идентичны.

См. также

Этот раздел является частью серии, в которой описываются интерфейсы, доступные из C++, способы их использования для создания расширения отладчика на основе C++, а также способы использования других конструкций модели данных (например, JavaScript или NatVis) из расширения модели данных C++.

Общие сведения о модели данных отладчика C++

Интерфейсы C++ модели данных отладчика

Объекты C++ модели данных отладчика

Дополнительные интерфейсы C++ модели данных отладчика

Основные понятия модели данных отладчика C++

Скрипты C++ модели данных отладчика