Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе описано, как использовать интерфейсы C++ модели данных отладчика для расширения и настройки возможностей отладчика.
Интерфейсы узла модели данных C++ отладчика
Узел модели данных отладчика
Модель данных отладчика предназначена для создания компонентной системы, которая может размещаться в различных контекстах. Обычно модель данных размещается в контексте приложения отладчика. Для того чтобы быть узлом модели данных, необходимо реализовать ряд интерфейсов для предоставления основных аспектов отладчика: его целевых пространств, пространств памяти, его вычислителя, его символьной и типной системы и т. д. Хотя эти интерфейсы реализуются любым приложением, желающим разместить модель данных, они используются как основной моделью данных, так и любым расширением, которое взаимодействует с моделью данных.
Набор основных интерфейсов:
Имя интерфейса | Описание |
---|---|
IDebugHost | Основной интерфейс узла отладки. |
IDebugHostStatus | Интерфейс, позволяющий клиенту запрашивать состояние узла. |
IDebugHostContext | Абстракция контекста в узле (например, конкретный целевой объект, определенный процесс, определенное адресное пространство и т. д.) |
IDebugHostErrorSink | Интерфейс, реализованный вызывающими пользователями для получения ошибок из определенных частей хост-модели и модели данных |
IDebugHostEvaluator / IDebugHostEvaluator2 | Средство оценки выражений узла отладки. |
IDebugHostExtensibility | Интерфейс для расширения возможностей узла или частей (например, вычислителя выражений). |
Системные и символьные интерфейсы типов:
InterfaceName | Описание |
---|---|
IDebugHostSymbols | Основной интерфейс, предоставляющий доступ к символам и их разрешение |
IDebugHostSymbol / IDebugHostSymbol2 | Представляет один символ любого вида. Конкретный символ является производным от этого интерфейса. |
IDebugHostModule | Представляет модуль, загруженный в процессе. Это вид символа. |
IDebugHostType / IDebugHostType2 | Представляет собственный или языковой тип. |
IDebugHostConstant | Представляет константу в символьной информации (например, аргумент шаблона нетипа в C++) |
IDebugHostField | Представляет поле в структуре или классе. |
IDebugHostData | Представляет данные в модуле (были ли они в структуре или классе, это будет IDebugHostField) |
IDebugHostBaseClass | Представляет базовый класс. |
IDebugHostPublic | Представляет символ в общедоступной таблице PDB. Это не имеет сведений о типе, связанном с ним. Это имя и адрес. |
IDebugHostModuleSignature | Представляет сигнатуру модуля — определение, которое будет соответствовать набору модулей по имени и(или) версии. |
IDebugHostTypeSignature | Представляет сигнатуру типа — определение, которое будет соответствовать набору типов по модулю и /или имени |
Основной интерфейс узла: IDebugHost
Интерфейс IDebugHost — это основной интерфейс любого узла модели данных. Он определен следующим образом:
DECLARE_INTERFACE_(IDebugHost, IUnknown)
{
STDMETHOD(GetHostDefinedInterface)(_COM_Outptr_ IUnknown** hostUnk) PURE;
STDMETHOD(GetCurrentContext)(_COM_Outptr_ IDebugHostContext** context) PURE;
STDMETHOD(GetDefaultMetadata)(_COM_Outptr_ IKeyStore** defaultMetadataStore) PURE;
}
Метод GetHostDefinedInterface возвращает основной закрытый интерфейс узла, если такой интерфейс существует для данного узла. Для средств отладки для Windows интерфейс, возвращенный здесь, является IDebugClient (приведение к IUnknown).
Метод GetCurrentContext возвращает интерфейс, представляющий текущее состояние узла отладчика. Точное значение этого остается на узле, но обычно включает такие вещи, как сеанс, процесс и адресное пространство, активное в пользовательском интерфейсе узла отладки. Возвращаемый объект контекста в значительной степени непрозрачн для вызывающего объекта, но это важный объект для передачи между вызовами узла отладки. Если вызывающий объект, например, чтение памяти, важно знать, какой процесс и адресное пространство, из которого выполняется чтение памяти. Это понятие инкапсулируется в понятие объекта контекста, возвращаемого этим методом.
Метод GetDefaultMetadata возвращает хранилище метаданных по умолчанию, которое может использоваться для определенных операций (например, преобразования строк) при отсутствии явных метаданных. Это позволяет узлу отладки контролировать способ представления некоторых данных. Например, метаданные по умолчанию могут включать ключ PreferredRadix, что позволяет узлу указывать, следует ли отображать порядковые порядковые номера в десятичном или шестнадцатеричном формате, если не указано в противном случае.
Обратите внимание, что значения свойств в хранилище метаданных по умолчанию должны быть разрешены вручную и должны передавать объект, для которого запрашиваются метаданные по умолчанию. Метод GetKey должен использоваться вместо GetKeyValue.
Интерфейс состояния: IDebugHostStatus
Интерфейс IDebugHostStatus позволяет клиенту модели данных или узлу отладки узнать о некоторых аспектах состояния узла отладки. Интерфейс определяется следующим образом:
DECLARE_INTERFACE_(IDebugHostStatus, IUnknown)
{
STDMETHOD(PollUserInterrupt)(_Out_ bool* interruptRequested) PURE;
}
Метод PollUserInterrupt используется для проверки того, запрашивает ли пользователь узла отладки прерывание текущей операции. Метод доступа к свойствам в модели данных может, например, вызывать произвольный код (например, метод JavaScript). Этот код может занять произвольное время. Чтобы обеспечить скорость реагирования узла отладки, любой такой код, который может занять произвольное время, должен проверять запрос на прерывание с помощью вызова этого метода. Если значение прерывания Возвращается как 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 сравнивает контекст узла с другим контекстом узла. Если два контекста эквивалентны, возвращается указание на это. Обратите внимание, что это сравнение не является эквивалентностью интерфейса. Это сравнивает базовое непрозрачные содержимое самого контекста.
Приемник ошибок: IDebugHostErrorSink
IDebugHostErrorSink — это средство, с помощью которого клиент может получать уведомления об ошибках, возникающих во время определенных операций, и направлять эти ошибки по мере необходимости. Интерфейс определяется следующим образом:
enum ErrorClass
{
ErrorClassWarning,
ErrorClassError
}
DECLARE_INTERFACE_(IDebugHostErrorSink, IUnknown)
{
STDMETHOD(ReportError)(_In_ ErrorClass errClass, _In_ HRESULT hrError, _In_ PCWSTR message) PURE;
}
Метод 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 позволяет запрашивать узел отладки для вычисления выражения языка (например, C++) и возврата результирующего значения вычисления этого выражения в виде IModelObject. Этот конкретный вариант метода допускает только языковые конструкции. Любые дополнительные функциональные возможности, представленные в средстве оценки выражений узла отладки, который не присутствует на языке (например, методы запроса LINQ), отключены для оценки.
Метод EvaluateExtendedExpression аналогичен методу EvaluateExpression, за исключением того, что он возвращает дополнительные функции, отличные от языка, которые конкретный узел отладки выбирает для добавления в его средство оценки выражений. Для средств отладки для Windows, например, это позволяет анонимным типам, запросам LINQ, квалификаторам модулей, описателям формата и другим функциям, отличным от C/C++.
IDebugHostEvaluator2
Метод AssignTo выполняет назначение в соответствии с семантикой отлаживаемого языка.
Интерфейс расширяемости узла: IDebugHostExtensibility
Некоторые функциональные возможности узла отладки при необходимости подвергаются расширяемости. Это может быть, например, средство оценки выражений. Интерфейс IDebugHostExtensibility — это средство, с помощью которого осуществляется доступ к этим точкам расширяемости. Интерфейс определяется следующим образом:
DECLARE_INTERFACE_(IDebugHostExtensibility, IUnknown)
{
STDMETHOD(CreateFunctionAlias)(_In_ PCWSTR aliasName, _In_ IModelObject *functionObject) PURE;
STDMETHOD(DestroyFunctionAlias)(_In_ PCWSTR aliasName) PURE;
}
Метод CreateFunctionAlias создает "псевдоним функции", "быстрый псевдоним" для метода, реализованного в определенном расширении. Значение этого псевдонима — это конкретный узел. Он может расширить средство оценки выражений узла с помощью функции или сделать что-то совершенно другое.
Метод DestroyFunctionAlias отменяет предыдущий вызов метода CreateFunctionAlias. Функция больше не будет доступна под именем быстрого псевдонима.
Доступ к модели данных
В первую очередь API расширяемости модели данных предназначены для нейтрального приложения (обычно отладчика), который выступает в качестве узла модели данных. В теории, любое приложение может размещать модель данных, предоставляя набор API узлов, которые предоставляют систему типов отладочных целевых объектов приложения и набор проецируемых объектов в пространство имен модели данных о целевых объектах, процессах, потоках и т. д. находятся в этих целевых объектах отладки.
Хотя API модели данных , которые начинают IDataModel, IDebugHost и offshoots 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 — это метод интерфейса моста, предоставляющий доступ к обеим сторонам модели данных: узел отладки (нижний край отладчика) выражается возвращаемым интерфейсом IDebugHost основного компонента модели данных — диспетчер модели данных выражается возвращенным интерфейсом IDataModelManager.
Системные интерфейсы модели данных отладчика
Узел модели данных
Модель данных отладчика предназначена для создания компонентной системы, которая может размещаться в различных контекстах. Обычно модель данных размещается в контексте приложения отладчика. Для того чтобы быть узлом модели данных, необходимо реализовать ряд интерфейсов для предоставления основных аспектов отладчика: его целевых пространств, пространств памяти, его вычислителя, его символьной и типной системы и т. д. Хотя эти интерфейсы реализуются любым приложением, желающим разместить модель данных, они используются как основной моделью данных, так и любым расширением, которое взаимодействует с моделью данных.
Системные и символьные интерфейсы типов:
Имя интерфейса | Описание |
---|---|
IDebugHostSymbols | Основной интерфейс, предоставляющий доступ к символам и их разрешение |
IDebugHostSymbol / IDebugHostSymbol2 | Представляет один символ любого вида. Конкретный символ является производным от этого интерфейса. |
IDebugHostModule | Представляет модуль, загруженный в процессе. Это вид символа. |
IDebugHostType / IDebugHostType2 | Представляет собственный или языковой тип. |
IDebugHostConstant | Представляет константу в символьной информации (например, аргумент шаблона нетипа в C++) |
IDebugHostField | Представляет поле в структуре или классе. |
IDebugHostData | Представляет данные в модуле (были ли они в структуре или классе, это будет IDebugHostField) |
IDebugHostBaseClass | Представляет базовый класс. |
IDebugHostPublic | Представляет символ в общедоступной таблице PDB. Это не имеет сведений о типе, связанном с ним. Это имя и адрес. |
IDebugHostModuleSignature | Представляет сигнатуру модуля — определение, которое будет соответствовать набору модулей по имени и(или) версии. |
IDebugHostTypeSignature | Представляет сигнатуру типа — определение, которое будет соответствовать набору типов по модулю и /или имени |
Другие основные интерфейсы:
Имя интерфейса | Описание |
---|---|
IDebugHost | Основной интерфейс узла отладки. |
IDebugHostStatus | Интерфейс, позволяющий клиенту запрашивать состояние узла. |
IDebugHostContext | Абстракция контекста в узле (например, конкретный целевой объект, определенный процесс, определенное адресное пространство и т. д.) |
IDebugHostErrorSink | Интерфейс, реализованный вызывающими пользователями для получения ошибок из определенных частей хост-модели и модели данных |
IDebugHostEvaluator / IDebugHostEvaluator2 | Средство оценки выражений узла отладки. |
IDebugHostExtensibility | Интерфейс для расширения возможностей узла или частей (например, вычислителя выражений). |
Основной символьный интерфейс: IDebugHostSymbols
Интерфейс IDebugHostSymbols — это основная отправная точка для доступа к символам в целевом объекте отладки. Этот интерфейс можно запрашивать из экземпляра IDebugHost и определяется следующим образом:
DECLARE_INTERFACE_(IDebugHostSymbols, IUnknown)
{
STDMETHOD(CreateModuleSignature)(_In_z_ PCWSTR pwszModuleName, _In_opt_z_ PCWSTR pwszMinVersion, _In_opt_z_ PCWSTR pwszMaxVersion, _Out_ IDebugHostModuleSignature** ppModuleSignature) PURE;
STDMETHOD(CreateTypeSignature)(_In_z_ PCWSTR signatureSpecification, _In_opt_ IDebugHostModule* module, _Out_ IDebugHostTypeSignature** typeSignature) PURE;
STDMETHOD(CreateTypeSignatureForModuleRange)(_In_z_ PCWSTR signatureSpecification, _In_z_ PCWSTR moduleName, _In_opt_z_ PCWSTR minVersion, _In_opt_z_ PCWSTR maxVersion, _Out_ IDebugHostTypeSignature** typeSignature) PURE;
STDMETHOD(EnumerateModules)(_In_ IDebugHostContext* context, _COM_Outptr_ IDebugHostSymbolEnumerator** moduleEnum) PURE;
STDMETHOD(FindModuleByName)(_In_ IDebugHostContext* context, _In_z_ PCWSTR moduleName, _COM_Outptr_ IDebugHostModule **module) PURE;
STDMETHOD(FindModuleByLocation)(_In_ IDebugHostContext* context, _In_ Location moduleLocation, _COM_Outptr_ IDebugHostModule **module) PURE;
STDMETHOD(GetMostDerivedObject)(_In_opt_ IDebugHostContext *pContext, _In_ Location location, _In_ IDebugHostType* objectType, _Out_ Location* derivedLocation, _Out_ IDebugHostType** derivedType) PURE;
}
Метод CreateModuleSignature создает сигнатуру, которую можно использовать для сопоставления набора определенных модулей по имени и при необходимости по версии. Существует три компонента в сигнатуре модуля:
- Имя: соответствующий модуль должен иметь имя, которое является точным регистром без учета имени в сигнатуре.
- Минимальная версия: если задано, соответствующий модуль должен иметь минимальную версию, которая не менее высока, как эта версия. Версии указываются в формате A.B.C.D, при этом каждая следующая часть менее важна, чем предыдущий. Только первый сегмент является обязательным.
- Максимальная версия: если задано, соответствующий модуль должен иметь максимальную версию, которая не превышает эту версию. Версии указываются в формате A.B.C.D, при этом каждая следующая часть менее важна, чем предыдущий. Только первый сегмент является обязательным.
Метод CreateTypeSignature создает сигнатуру, которую можно использовать для сопоставления набора конкретных типов, содержащего имя модуля и типа. Формат строки подписи имени типа зависит от отлаживаемого языка (и узла отладки). Для C/C++строка подписи эквивалентна спецификации типа NatVis. То есть строка подписи — это имя типа, в котором для аргументов шаблона разрешены подстановочные знаки (указанные как *).
CreateTypeSignatureForModuleRange
Метод CreateTypeSignatureForModuleRange создает подпись, которую можно использовать для сопоставления набора конкретных типов по сигнатуре модуля и имени типа. Это похоже на метод CreateTypeSignature, за исключением того, что вместо передачи определенного модуля в соответствии с подписью вызывающий объект передает аргументы, необходимые для создания подписи модуля (как если бы подпись модуля была создана с помощью метода CreateModuleSignature).
Метод EnumerateModules создает перечислитель, который перечисляет каждый модуль, доступный в определенном контексте узла. Этот контекст узла может инкапсулировать контекст процесса или инкапсулировать что-то подобное ядро Windows.
Метод FindModuleByName будет просматривать заданный контекст узла и находить модуль с указанным именем и возвращать в него интерфейс. Это законно для поиска модуля по имени или без расширения файла.
Метод FindModuleByLocation будет просматривать заданный контекст узла и определять, какой модуль содержит адрес, заданный указанным расположением. Затем он вернет интерфейс в такой модуль.
GetMostDerivedObject будет использовать систему типов отладчика для определения типа объекта из своего статического типа. Этот метод будет использовать только символьные сведения и эвристики, доступные на уровне системы типов для выполнения этого анализа. Такие сведения могут включать C++ RTTI (сведения о типе времени выполнения) или анализ формы таблиц виртуальных функций объекта. Он не включает такие вещи, как предпочтительное понятие типа среды выполнения в IModelObject. Если анализ не может найти тип среды выполнения или не может найти тип среды выполнения, отличный от статического типа, переданного в метод, то входное расположение и тип могут быть переданы. Метод не завершится ошибкой по этим причинам.
Основной отдельный интерфейс символов: IDebugHostSymbol
Каждый символ, который можно вернуть из узла модели данных, будет производным от IDebugHostSymbol. Это основной интерфейс, реализующий каждый символ независимо от типа символа. В зависимости от типа символа данный символ может реализовать набор других интерфейсов, возвращающих атрибуты более уникальным для определенного типа символа, представленного этим интерфейсом. Интерфейс IDebugHostSymbol2 / IDebugHostSymbol определен следующим образом:
DECLARE_INTERFACE_(IDebugHostSymbol2, IDebugHostSymbol)
{
//
// IDebugHostSymbol:
//
STDMETHOD(GetContext)(_COM_Outptr_ IDebugHostContext** context) PURE;
STDMETHOD(EnumerateChildren)(_In_ SymbolKind kind, _In_opt_z_ PCWSTR name, _Out_ IDebugHostSymbolEnumerator **ppEnum) PURE;
STDMETHOD(GetSymbolKind)(_Out_ SymbolKind *kind) PURE;
STDMETHOD(GetName)(_Out_ BSTR* symbolName) PURE;
STDMETHOD(GetType)(_Out_ IDebugHostType** type) PURE;
STDMETHOD(GetContainingModule)(_Out_ IDebugHostModule **containingModule) PURE;
STDMETHOD(CompareAgainst)(_In_ IDebugHostSymbol *pComparisonSymbol, _In_ ULONG comparisonFlags, _Out_ bool *pMatches) PURE;
//
// IDebugHostSymbol2
//
STDMETHOD(EnumerateChildrenEx)(_In_ SymbolKind kind, _In_opt_z_ PCWSTR name, _In_opt_ SymbolSearchInfo* searchInfo, _Out_ IDebugHostSymbolEnumerator **ppEnum) PURE;
}
Очень важно отметить, что этот интерфейс представляет множество типов символов, разделенных перечислением SymbolKind, которое имеет значения следующим образом:
Энумарант | Значение |
---|---|
Символ | Неопределенный тип символа |
SymbolModule | Символ является модулем и может запрашиваться для IDebugHostModule |
SymbolType | Символ является типом и может запрашиваться для IDebugHostType |
SymbolField | Символ — это поле (член данных в структуре или классе) и может запрашиваться для IDebugHostField |
SymbolConstant | Символ является константным значением и может запрашиваться для IDebugHostConstant |
SymbolData | Символ — это данные, которые не являются членом структуры или класса и запрашиваются для IDebugHostData. |
SymbolBaseClass | Символ является базовым классом и запрашивается для IDebugHostBaseClass |
SymbolPublic | Символ является записью в общедоступной таблице модуля (без сведений о типе) и запрашивается для IDebugHostPublic |
SymbolFunction | Символ является функцией и запрашивается для IDebugHostData |
Метод GetContext возвращает контекст, в котором допустимы символ. Хотя это будет представлять такие вещи, как целевой объект отладки и адресное пространство, в котором существует символ, он может не быть таким конкретным, как контекст, полученный из других средств (например, из IModelObject).
перечисление EnumerateChildren
Метод EnumerateChildren возвращает перечислитель, который перечисляет все дочерние элементы заданного символа. Например, для типа C++ базовые классы, поля, функции-члены и такие же элементы считаются дочерними элементами символа типа.
Интерфейс модуля: IDebugHostModule
Понятие отладчика модуля, загруженного в некоторое адресное пространство, представлено двумя различными способами в модели данных: на уровне системы типа через интерфейс IDebugHostModule. Здесь модуль представляет собой символ и основные атрибуты модуля — это метод интерфейса, вызываемый на уровне модели данных с помощью модели данных Debugger.Models.Module. Это расширяемая инкапсуляция типа системного представления IDebugHostModule модуля.
Интерфейс IDebugHostModule определяется следующим образом (игнорируя методы, которые являются универсальными для IDebugHostSymbol):
DECLARE_INTERFACE_(IDebugHostModule, IDebugHostSymbol)
{
//
// IDebugHostModule:
//
STDMETHOD(GetImageName)(_In_ bool allowPath, _Out_ BSTR* imageName) PURE;
STDMETHOD(GetBaseLocation)(_Out_ Location* moduleBaseLocation) PURE;
STDMETHOD(GetVersion)(_Out_opt_ ULONG64* fileVersion, _Out_opt_ ULONG64* productVersion) PURE;
STDMETHOD(FindTypeByName)(_In_z_ PCWSTR typeName, _Out_ IDebugHostType** type) PURE;
STDMETHOD(FindSymbolByRVA)(_In_ ULONG64 rva, _Out_ IDebugHostSymbol** symbol) PURE;
STDMETHOD(FindSymbolByName)(_In_z_ PCWSTR symbolName, _Out_ IDebugHostSymbol** symbol) PURE;
}
Метод GetImageName возвращает имя образа модуля. В зависимости от значения аргумента allowPath имя возвращаемого изображения может или не включать полный путь к изображению.
Метод GetBaseLocation возвращает базовый адрес загрузки модуля в виде структуры расположения. Возвращаемая структура расположения модуля обычно ссылается на виртуальный адрес.
Метод GetVersion возвращает сведения о версии модуля (предполагая, что такие сведения можно считывать из заголовков). Если указанная версия запрашивается (с помощью указателя вывода, отличного от nullptr), и она не может быть прочитана, соответствующий код ошибки будет возвращен из вызова метода.
Метод FindTypeByName находит тип, определенный в модуле по имени типа, и возвращает для него символ типа. Этот метод может возвращать допустимый идентификатор IDebugHostType, который никогда не будет возвращен с помощью явного рекурсии дочерних элементов модуля. Узел отладки может разрешить создание типов производных типов, которые никогда не используются в самом модуле, а производные от типов. Например, если структура MyStruct определена в символах модуля, но тип MyStruct ** никогда не используется, метод FindTypeByName может законно возвращать символ типа для MyStruct ** несмотря на то, что имя типа никогда явно не отображается в символах модуля.
Метод FindSymbolByRVA найдет один соответствующий символ по указанному относительному виртуальному адресу в модуле. Если в предоставленном RVA нет одного символа (например, несколько совпадений), то ошибка будет возвращена этим методом. Обратите внимание, что этот метод предпочитает возвращать закрытый символ над символом в таблице publics.
Метод FindSymbolByName найдет один глобальный символ заданного имени в модуле. Если нет одного символа, соответствующего заданному имени, ошибка будет возвращена этим методом. Обратите внимание, что этот метод предпочитает возвращать закрытый символ над символом в таблице publics.
Доступ к системе типов: IDebugHostType2 / IDebugHostType
Заданный язык или собственный тип описывается интерфейсами IDebugHostType2 или IDebugHostType. Обратите внимание, что некоторые методы этих интерфейсов применяются только для определенных типов. Указанный символ типа может ссылаться на один из следующих типов, как описано перечислением TypeKind:
Тип типа | Описание |
---|---|
TypeUDT | Определяемый пользователем тип (структуру, класс, объединение и т. д.). Объект модели, имеющий собственный тип, тип которого имеет тип TypeUDT, имеет каноническое представление ObjectTargetObject, где тип всегда хранится внутри соответствующего IModelObject. |
TypePointer | Указатель. Объект модели, который имеет собственный тип, тип TypePointer имеет каноническое представление ObjectIntrinsic, где значение указателя равно нулю до VT_UI8 и хранится как встроенные данные в этой 64-разрядной форме. Любой символ типа TypePointer имеет базовый тип (как возвращается методом GetBaseType) типа, на который указывает указатель. |
TypeMemberPointer | Указатель на член класса. Объект модели, имеющий собственный тип, тип которого — TypeMemberPointer, имеет каноническое представление, которое является встроенным (значение совпадает со значением указателя). Точное значение этого значения — компилятор или отладочный узел. |
TypeArray | Массив. Объект модели, имеющий собственный тип, тип которого — TypeArray, имеет каноническое представление ObjectTargetObject. Базовый адрес массива — это расположение объекта (полученное с помощью метода GetLocation), а тип массива всегда сохраняется. Любой символ типа TypeArray имеет базовый тип (как возвращается методом GetBaseType) типа, который массив является массивом. |
TypeFunction | Функция. |
TypeTypedef | Типдф. Объект модели, имеющий собственный тип, тип которого в противном случае имеет каноническое представление, идентичное каноническому представлению конечного типа, лежащего в основе typedef. Это выглядит полностью прозрачным для конечного пользователя объекта и сведений о типе, если только явные методы typedef IDebugHostType2 не используются для запроса сведений о типдефа или существует явная модель данных, зарегистрированная для typedef. Обратите внимание, что метод GetTypeKind никогда не возвращает TypeTypedef. Каждый метод возвращает конечный тип, базовый возвращаемый типом. Существуют определенные методы для IDebugHostType2, которые можно использовать для получения определенных сведений о типе. |
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 возвращает тип типа (указателя, массива, встроенного и т. д.) символа.
Метод GetSize возвращает размер типа (как если бы он сделал sizeof(type) в C++.
Если тип является производным от другого отдельного типа (например, как MyStruct * является производным от MyStruct'), метод GetBaseType возвращает базовый тип производных. Для указателей возвращается тип, на который указывает тип. Для массивов возвращается то, что массив является массивом. Если тип не является таким производным типом, возвращается ошибка.
Метод GetHashCode возвращает 32-разрядный хэш-код для типа. За исключением глобального совпадения (например, сигнатуры типа, эквивалентной *, которая соответствует всему, если это разрешено узлом), любой экземпляр типа, который может соответствовать определенной сигнатуре типа, должен возвращать тот же хэш-код. Этот метод используется в сочетании с сигнатурами типов, чтобы соответствовать сигнатурам типов с экземплярами типов.
Встроенные методы IDebugHostType2/IDebugHostType
Следующие методы IDebugHostType относятся к встроенным типам (или типам, которые содержат встроенные данные, такие как перечисления):
STDMETHOD(GetIntrinsicType)(_Out_opt_ IntrinsicKind *intrinsicKind, _Out_opt_ VARTYPE *carrierType) PURE;
Метод GetIntrinsicType возвращает сведения о типе встроенного типа. Из этого метода возвращаются два значения:
- Встроенный тип указывает общий тип (например, целое число, без знака, плавающую точку), но не размер типа (например, 8 бит, 16 бит, 32 бит, 64 бита)
- Тип оператора указывает, как встроенные пакеты типа в структуру VARIANT. Это константа VT_*.
Сочетание двух значений предоставляет полный набор сведений о встроенной функции.
Методы IDebugHostType2/IDebugHostType Bitfield
Следующие методы IDebugHostType относятся к типам, которые хранят данные в битовых полях. Сведения о размещении битовых полей внутри внутренней части хранятся как часть символа типа в модели данных, а не атрибут расположения.
STDMETHOD(GetBitField)(_Out_ ULONG* lsbOfField, _Out_ ULONG* lengthOfField) PURE;
Если заданный элемент структуры данных является битовой областью (например, ULONG MyBits:8), сведения о типе поля содержат сведения о размещении битового поля. Метод GetBitField можно использовать для получения этой информации. Этот метод завершится ошибкой в любом типе, который не является битовой. Это единственная причина, по которой метод завершится ошибкой. Просто вызывая этот метод и глядя на успешность или сбой, достаточно для отличия битового поля от небитового поля. Если заданный тип происходит в битовом поле, позиции полей определяются половиной открытого набора (lsbOfField + lengthOfField : lsbOfField: lsbOfField]
Связанные методы IDebugHostType2/IDebugHostType
Следующие методы IDebugHostType относятся к типам указателей. Это типы, в которых GetTypeKind возвращает TypePointer или TypeMemberPointer':
STDMETHOD(GetPointerKind)(_Out_ PointerKind* pointerKind) PURE;
STDMETHOD(GetMemberType)(_Out_ IDebugHostType** memberType) PURE;
Для типов, которые являются указателями, метод GetPointerKind возвращает тип указателя. Это определяется перечислением PointerKind.
Для типов, которые являются указателем на член (как указано типом TypeMemberPointerPointer), метод GetMemberType возвращает класс, указатель которого является указателем на член.
Связанные методы массива IDebugHostType2/IDebugHostType
Массивы — это типы, в которых GetTypeKind возвращает TypeArray. Обратите внимание, что массивы, определенные системой типов узла отладки, не совпадают с одномерными, нулевой базой индексов, упакованными линейными одномерными массивами, которые использует C. Массивы стилей C соответствуют определению, но общая область массива шире в IDebugHostType. Массив в узле отладки может быть многомерным, и каждое измерение в массиве определяется дескриптором, известным как дескриптор ArrayDimensionThis, имеет следующие поля:
Поле | Значение |
---|---|
Нижний трафик | Базовый индекс массива в виде 64-разрядного значения со знаком. Для массива стилей C это всегда будет равно нулю. Это не должно быть. Отдельное измерение массива можно считать начальным в любом 64-разрядном индексе, даже отрицательном. |
Длина | Длина измерения массива в виде 64-разрядного значения без знака. Предикаты массива охватывают половину открытого набора [LowerBound, LowerBound + Length). |
Шаг | Определяет шаг измерения массива. Для увеличения одного (от N до N + 1) в индексе этого измерения это измерение указывает, сколько байтов перемещается вперед в памяти. Для массива стилей C это будет размер каждого элемента массива. Это не обязательно. Заполнение между элементами можно выразить как шаг, превышающий размер каждого отдельного элемента. Для многомерных массивов это значение указывает, как перемещать все измерение вперед. Рассмотрим матрицу M x N. Это может быть описано в основной форме строк как два измерения: |
{ [LowerBound: 0, Length: M, Stride: N \* sizeof(element)], [LowerBound: 0, Length: N, Stride: sizeof(element)]}
или можно также описать в основной форме столбца как два измерения:
{ [LowerBound: 0, Length: M, Stride: sizeof(element)], [LowerBound: 0, Length: N, Stride: M \* sizeof(element)]}
Концепция ArrayDimension позволяет обеспечить эту степень гибкости.
Следующие методы IDebugHostType относятся к типам массивов.
STDMETHOD(GetArrayDimensionality)(\_Out_ ULONG64\* arrayDimensionality) PURE;
STDMETHOD(GetArrayDimensions)(\_In_ ULONG64 dimensions, \_Out_writes_(dimensions) ArrayDimension \*pDimensions) PURE;
Метод GetArrayDimensionality возвращает количество измерений, в которых индексируется массив. Для массивов стилей C возвращаемое здесь значение всегда будет равно 1.
Метод GetArrayDimensions возвращает набор дескрипторов, по одному для каждого измерения массива, как указано методом GetArrayDimensionality. Каждый дескриптор представляет собой структуру ArrayDimension, которая описывает начальный индекс, длину и шаг вперед каждого измерения массива. Это позволяет описаниям значительно более мощных конструкций массивов, чем разрешено в системе типов C.
Для массивов стилей C здесь возвращается одно измерение массива со значениями, которые всегда:
- LowerBound = 0
- Length = ARRAYSIZE(array)
- Stride = sizeof(elementType)
Связанные методы функции IDebugHostType2/IDebugHostType
Типы, указывающие, что они являются типами функций с помощью типа TypeFunction, поддерживают следующие методы в IDebugHostType и IDebugHostType2.
//
// IDebugHostType:
//
STDMETHOD(GetFunctionCallingConvention)(_Out_ CallingConventionKind* conventionKind) PURE;
STDMETHOD(GetFunctionReturnType)(_COM_Outptr_ IDebugHostType** returnType) PURE;
STDMETHOD(GetFunctionParameterTypeCount)(_Out_ ULONG64* count) PURE;
STDMETHOD(GetFunctionParameterTypeAt)(_In_ ULONG64 i, _Out_ IDebugHostType** parameterType) PURE;
//
// IDebugHostType2:
//
STDMETHOD(GetFunctionVarArgsKind)(_Out_ VarArgsKind* varArgsKind) PURE;
Метод GetFunctionCallingConvention возвращает соглашение о вызове функции. Возвращается в качестве члена перечисления CallingConventionKind.
Метод GetFunctionReturnType возвращает возвращаемый тип функции.
Метод GetFunctionParameterTypeCount возвращает количество аргументов, которые принимает функция. Обратите внимание, что маркер аргумента переменной на основе многоточия C/C++ не учитывается в этом подсчете. Наличие такого объекта должно быть обнаружено с помощью метода GetFunctionVarArgsKind. Это будет включать только аргументы перед многоточием.
Метод GetFunctionParameterTypeAt возвращает тип аргумента i-th функции.
Метод GetFunctionVarArgsKind возвращает, использует ли данная функция список аргументов переменной и, если да, какой стиль аргументов переменной он использует. Такой определяется элементом перечисления VarArgsKind, определенным следующим образом:
Перечисление | Значение |
---|---|
VarArgsNone | Функция не принимает аргументы переменной. |
VarArgsCStyle | Функция — это функция varargs в стиле C (returnType(arg1, arg2, ...)). Число аргументов, сообщаемых функцией, не включает аргумент с многоточием. Любой аргумент переменной происходит после числа аргументов, возвращаемых методом GetFunctionParameterTypeCount. |
IDebugHostType2 GetFunctionVarArgsKind
Метод GetFunctionVarArgsKind возвращает, использует ли данная функция список аргументов переменной и, если да, какой стиль аргументов переменной он использует. Такой определяется элементом перечисления VarArgsKind, определенным следующим образом:
Связанные методы IDebugHostType2/IDebugHostType Typedef
Любой тип, являющийся типом, будет вести себя так, как если тип является окончательным типом, базовым типом. Это означает, что такие методы, как GetTypeKind, не указывают, что тип является типом. Аналогичным образом GetBaseType не вернет тип определения, на который ссылается определение. Вместо этого они указывают на поведение, как если бы они были вызваны на окончательное определение, лежащее в основе typedef. В качестве примера:
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
Идентификатор IDebugHostType для PMYSTRUCT или PTRMYSTRUCT будет сообщать следующие сведения:
- Метод GetTypeKind возвращает TypePointer. Последний базовый тип MYSTRUCT * действительно является указателем.
- Метод GetBaseType возвращает тип для MYSTRUCT. Базовый тип MYSTRUCT * — MYSTRUCT.
Единственное различие заключается в том, как работают определенные методы typedef в 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 — единственный метод, способный видеть, является ли тип типом тип. Метод GetTypeKind будет вести себя так, как будто вызывается в базовом типе.
Метод GetTypedefBaseType вернет немедленное определение типа. В примерах, описанных в документации:
typedef MYSTRUCT *PMYSTRUCT;
typedef PMYSTRUCT PTRMYSTRUCT;
этот метод возвращает MYSTRUCT * для PMYSTRUCT и PMYSTRUCT для PTRMYSTRUCT.
Метод GetTypedefFinalBaseType вернет окончательный тип, для который типdef является определением. Если типdef является определением другого типа, оно будет продолжать следовать цепочке определений, пока не достигнет типа, который не является типом, и этот тип будет возвращен. В примерах, описанных в документации:
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 возвращает значение константы, упакованной в 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 возвращает расположение символа в соответствии с перечислением LocationKind. Такое перечисление может быть одним из следующих значений:
Перечисление | Значение |
---|---|
LocationMember | Поле — это обычный элемент данных класса, структуры, объединения или другого типа. Он имеет смещение, которое относительно базового адреса содержащего конструкции типа. Такой базовый адрес обычно представлен этим указателем. Смещение поля можно получить с помощью метода GetOffset. Методы GetLocation и GetValue завершаются ошибкой для поля, которое является LocationMember. |
LocationStatic | Поле является статическим и имеет собственный адрес. Метод GetLocation возвращает абстрактное расположение (например, адрес) статического поля. Методы GetOffset и GetValue завершаются ошибкой для поля, которое является LocationStatic. |
LocationConstant | Поле является константой и имеет значение. Метод GetValue вернет значение константы. Методы GetOffset и GetLocation завершаются ошибкой для поля, которое является LocationConstant |
LocationNone | Поле не имеет расположения. Возможно, он оптимизирован компилятором или может быть статическим полем, которое объявляется, но никогда не определено. Независимо от того, как такое поле пришло, оно не имеет физического присутствия или ценности. Это только в символах. Все методы приобретения (GetOffset, GetLocation и GetValue) завершаются ошибкой для поля, которое является LocationNone. |
Для полей с смещением (например, поля, тип расположения которых указывает LocationMember), метод GetOffset возвращает смещение от базового адреса содержащего типа (этот указатель) к данным для самого поля. Такие смещения всегда выражаются как 64-разрядные значения без знака. Если заданное поле не имеет расположения, которое является смещением от базового адреса содержащего типа, метод GetOffset завершится ошибкой.
Для полей, имеющих адрес независимо от конкретного экземпляра типа (например, поля, тип расположения которого указывает LocationStatic), метод GetLocation вернет абстрактное расположение (адрес) поля. Если заданное поле не имеет статического расположения, метод GetLocation завершится ошибкой.
Для полей, имеющих постоянное значение, определенное в символьных данных (например, поля, тип расположения которых указывает LocationConstant), метод GetValue вернет постоянное значение поля. Если заданное поле не имеет константного значения, метод GetValue завершится ошибкой.
Бесплатный доступ к данным: IDebugHostData
Данные в модулях, которые не являются членом другого типа, представлены интерфейсом IDebugHostData. Этот интерфейс определен следующим образом (игнорируя методы, универсальные для IDebugHostSymbol):
DECLARE_INTERFACE_(IDebugHostData, IDebugHostSymbol)
{
STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
STDMETHOD(GetValue)(_Out_ VARIANT* value) PURE;
}
Все эти методы семантически эквивалентны их аналогам в IDebugHostField. Единственное различие заключается в том, что метод GetLocationKind никогда не возвращает LocationMember для бесплатных данных.
Метод GetLocationKind возвращает расположение символа в соответствии с перечислением LocationKind. Описание этого перечисления можно найти в документации для IDebugHostField.
Для данных, имеющих адрес, метод GetLocation возвращает абстрактное расположение (адрес) поля. Если указанные данные не имеют статического расположения, метод GetLocation завершится ошибкой.
Для datawhich имеет константное значение, определенное в символьной информации (например, данные, тип расположения которых указывает LocationConstant), метод GetValue вернет постоянное значение поля. Если указанные данные не имеют константного значения, метод GetValue завершится ошибкой.
Базовые классы: IDebugHostBaseClass
Иерархия наследования данного типа выражается с помощью дочерних элементов символа типа. Если заданный тип наследуется (наследование мудро) от одного или нескольких типов, для типа будет один или несколько дочерних элементов SymbolBaseClass символа типа. Каждый из этих символов SymbolBaseClass представляет немедленное наследование от определенного типа. Имя базового класса — это имя символа SymbolBaseClass, а также символ типа базового класса. Метод GetType в символе SymbolBaseClass можно использовать для получения символа типа для самого базового класса. Полную иерархию наследования можно пройти путем рекурсивного изучения дочерних символов SymbolBaseClass. Каждый из этих символов базового класса выражается интерфейсом IDebugHostBaseClass, который определяется следующим образом (игнорируя методы, универсальные для IDebugHostSymbol):
DECLARE_INTERFACE_(IDebugHostBaseClass, IDebugHostSymbol)
{
STDMETHOD(GetOffset)(_Out_ ULONG64* offset) PURE;
}
Метод GetOffset возвращает смещение базового класса из базового адреса производного класса. Такое смещение может быть равно нулю или может быть положительным 64-разрядным значением без знака.
Общедоступные символы: IDebugHostPublic
Открытые символы представляют вещи в общедоступной таблице в файле символов. Они, в действительности, являются адресами экспорта. Нет сведений о типе, связанных с открытым символом, — только адресом. Если вызывающий объект явно не запрашивает открытый символ, узел отладки предпочитает возвращать частные символы для каждого запроса. Открытый символ выражается интерфейсом IDebugHostPublic, который определяется следующим образом (игнорируя методы, которые являются универсальными для IDebugHostSymbol):
DECLARE_INTERFACE_(IDebugHostPublic, IDebugHostSymbol)
{
STDMETHOD(GetLocationKind)(_Out_ LocationKind *locationKind) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
}
Все эти методы семантически эквивалентны их аналогам в IDebugHostField. Единственное различие заключается в том, что метод GetLocationKind никогда не возвращает LocationMember или LocationConstant для таких символов.
Метод GetLocationKind возвращает расположение символа в соответствии с перечислением LocationKind. Описание этого перечисления можно найти в документации для IDebugHostField.
Для данных, имеющих адрес, метод GetLocation возвращает абстрактное расположение (адрес) поля. Если заданное общедоступное расположение не имеет статического расположения, метод GetLocation завершится ошибкой.
Подписи модулей и сопоставление версий: IDebugHostModuleSignature
Подписи модулей представляют собой средства проверки соответствия заданного модуля набору критериев для именования и управления версиями. Подпись модуля создается с помощью метода CreateModuleSignature в IDebugHostSymbols. Он может совпадать с именем модуля и необязательным диапазоном номеров версий для модуля. После создания такой подписи клиент получает интерфейс IDebugHostModuleSignature, который определяется следующим образом:
DECLARE_INTERFACE_(IDebugHostModuleSignature, IUnknown)
{
STDMETHOD(IsMatch)(_In_ IDebugHostModule* pModule, _Out_ bool* isMatch) PURE;
}
Метод 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 возвращает 32-разрядный хэш-код для сигнатуры типа. Узел отладки гарантирует синхронизацию между хэш-кодом, возвращенным для экземпляров типов, и хэш-код, возвращаемый для подписей типов. За исключением глобального совпадения, если экземпляр типа может соответствовать сигнатуре типа, оба будут иметь тот же 32-разрядный хэш-код. Это позволяет начальное быстрое сравнение и сопоставление между экземпляром типа и множеством подписей типов, зарегистрированных в диспетчере моделей данных.
Метод IsMatch возвращает значение, указывающее, соответствует ли конкретный экземпляр типа критериям, указанным в сигнатуре типа. Если это делается, возвращается указание этого, а также перечислитель, который будет указывать все определенные части экземпляра типа (как символы), соответствующие подстановочным знакам в сигнатуре типа.
Метод CompareAgainst сравнивает сигнатуру типа с другой сигнатурой типа и возвращает способ сравнения двух подписей. Результат сравнения, возвращаемый, является членом перечисления SignatureComparison, который определяется следующим образом:
Перечисление | Значение |
---|---|
Несвязанные | Связь между двумя сигнатурами или типами не сравнивается. |
Двусмысленный | Одна сигнатура или тип сравнивается неоднозначно с другой. Для двух сигнатур типа это означает, что существуют потенциальные экземпляры типов, которые могут совпадать с любой сигнатурой одинаково хорошо. Например, приведенные ниже сигнатуры двух типов являются неоднозначными. Сигнатура 1. Подпись 2: std::pair<*, int> std::pair<int,*> так как экземпляр std::pair<int, int> типа соответствует одному одинаково хорошо (оба имеют один конкретный и один подстановочный знак). |
LessSpecific | Одна сигнатура или тип меньше, чем другая. Часто это означает, что менее конкретная подпись имеет подстановочный знак, где более конкретный имеет конкретный тип. Например, первая подпись ниже меньше, чем вторая. Сигнатура 1. Подпись 2: std::pair<*, int> std::pair<int, int> поскольку она имеет подстановочный знак (в) * где второй имеет конкретный тип (int). |
MoreSpecific | Одна сигнатура или тип более конкретна, чем другая. Часто это означает, что более конкретная подпись имеет конкретный тип, где менее конкретный имеет подстановочный знак. Например, первая подпись ниже более конкретна, чем вторая. Сигнатура 1: подпись 2: std::pair<int, int> std::pair<*, int> поскольку она имеет конкретный тип (int), где второй имеет подстановочный знак (the * ). |
Идентичный | Две подписи или типы идентичны. |
См. также
Этот раздел является частью серии, в которой описываются интерфейсы, доступные на C++, как использовать их для создания расширения отладчика на основе C++ и использования других конструкций модели данных (например, JavaScript или NatVis) из расширения модели данных C++.
Обзор модели данных отладчика C++
Объекты C++ модели данных отладчика
Дополнительные интерфейсы модели данных отладчика C++
Основные понятия модели данных C++ отладчика
Отладка модели данных C++ с использованием скриптов