Поделиться через


Введение в объекты отладки с путешествием во времени

Логотип отладки путешествия во времени с изображением часов.

В этом разделе описывается, как использовать модель данных для запроса трассировок перемещения по времени. Это может быть полезным инструментом для ответов на такие вопросы о коде, который был зафиксирован в трассировке времени.

  • Какие исключения содержатся в трассировке?
  • В какой момент в процессе трассировки был загружен определенный модуль кода?
  • Когда были созданы или завершены потоки в трассировке?
  • Что такое самые длительные потоки в трассировке?

Существуют расширения TTD, добавляющие данные в объекты модели сеансов и обработки данных. К объектам модели данных TTD можно получить доступ с помощью команды dx (выражение объектной модели отладчика), окон моделей WinDbg, JavaScript и C++. Расширения TTD автоматически загружаются при отладке трассировки перемещения по времени.

Объекты обработки

Основные объекты, добавленные в объекты Process , можно найти в пространстве имен TTD вне любого объекта Process . Например, @$curprocess.TTD.

0:000> dx @$curprocess.TTD
@$curprocess.TTD                
    Index           
    Threads         
    Events          
    DebugOutput     
    Lifetime         : [2C8:0, 16EC:98A]
    DefaultMemoryPolicy : InFragmentAggressive
    SetPosition      [Sets the debugger to point to the given position on this process.]
    GatherMemoryUse  [0]
    RecordClients   
    PrevMemoryAccess [(accessMask, address, size [, address, size, ...]) - Find the previous matching memory access before current position.]
    NextMemoryAccess [(accessMask, address, size [, address, size, ...]) - Find the next matching memory access after current position.]
    Recorder

Общие сведения о работе с запросами LINQ и объектами отладчика см. в разделе "Использование LINQ С объектами отладчика".

Свойства

Объект Описание
Срок службы Объект диапазона TTD, описывающий время существования всей трассировки.
Потоки Содержит коллекцию объектов потоков TTD, по одному для каждого потока в течение всего времени существования трассировки.
События Содержит коллекцию объектов событий TTD, по одному для каждого события в трассировке.

Методы

Метод Описание
SetPosition() Принимает целое число от 0 до 100 или строку в формате N:N в качестве входных данных и переходит по трассировке в это место. Дополнительные сведения см. в разделе !tt .

Объекты сеанса

Основные объекты, добавленные в объекты сеанса, можно найти в пространстве имен TTD вне любого объекта Session. Например, @$cursession.TTD.

0:000> dx @$cursession.TTD
@$cursession.TTD                
    Calls            [Returns call information from the trace for the specified set of methods: TTD.Calls("module!method1", "module!method2", ...) For example: dx @$cursession.TTD.Calls("user32!SendMessageA")]
    Memory           [Returns memory access information for specified address range: TTD.Memory(startAddress, endAddress [, "rwec"])]
    MemoryForPositionRange [Returns memory access information for specified address range and position range: TTD.MemoryForPositionRange(startAddress, endAddress [, "rwec"], minPosition, maxPosition)]
    PinObjectPosition [Pins an object to the given time position: TTD.PinObjectPosition(obj, pos)]
    AsyncQueryEnabled : false
    RichQueryTypesEnabled : true
    DefaultParameterCount : 0x4
    Data             : Normalized data sources based on the contents of the time travel trace
    Utility          : Methods that can be useful when analyzing time travel traces
    Analyzers        : Methods that perform code analysis on the time travel trace
    Bookmarks        : Bookmark collection
    Checkers         : Checkers (scripts for detection of common issues recorded in a time travel trace)

Примечание.

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

Методы

Метод Description
Data.Heap() Коллекция объектов кучи, выделенных во время трассировки. Обратите внимание, что это функция, которая выполняет вычисления, поэтому требуется некоторое время для выполнения.
Вызовы() Возвращает коллекцию вызовов объектов , соответствующих входной строке. Входная строка может содержать подстановочные знаки. Обратите внимание, что это функция, которая выполняет вычисления, поэтому требуется некоторое время для выполнения.
Память() Это метод, который принимает beginAddress, endAddress и параметры dataAccessMask и возвращает коллекцию объектов памяти. Обратите внимание, что это функция, которая выполняет вычисления, поэтому требуется некоторое время для выполнения.

Сортировка выходных данных запроса

Используйте метод OrderBy() для сортировки строк, возвращаемых из запроса по одному или нескольким столбцам. В этом примере выполняется сортировка по TimeStart в порядке возрастания.

0:000> dx -r2 @$cursession.TTD.Calls("kernelbase!GetLastError").OrderBy(c => c.TimeStart)
@$cursession.TTD.Calls("kernelbase!GetLastError").OrderBy(c => c.TimeStart)                
    [0x0]           
        EventType        : 0x0
        ThreadId         : 0x2d98
        UniqueThreadId   : 0x2
        TimeStart        : 718:7D7 [Time Travel]
        TimeEnd          : 718:7DA [Time Travel]
        Function         : KERNELBASE!GetLastError
        FunctionAddress  : 0x7ff996cf20f0
        ReturnAddress    : 0x7ff99855ac5a
        ReturnValue      : 0x0 [Type: unsigned long]
        Parameters      
        SystemTimeStart  : Friday, January 12, 2024 21:18:40.862
        SystemTimeEnd    : Friday, January 12, 2024 21:18:40.862
    [0x1]           
        EventType        : 0x0
        ThreadId         : 0x2d98
        UniqueThreadId   : 0x2
        TimeStart        : 72D:1B3 [Time Travel]
        TimeEnd          : 72D:1B6 [Time Travel]
        Function         : KERNELBASE!GetLastError
        FunctionAddress  : 0x7ff996cf20f0
        ReturnAddress    : 0x7ff9961538df
        ReturnValue      : 0x57 [Type: unsigned long]
        Parameters      
        SystemTimeStart  : Friday, January 12, 2024 21:18:40.862
        SystemTimeEnd    : Friday, January 12, 2024 21:18:40.862
...        

Для отображения дополнительной глубины объектов модели данных используется параметр уровня рекурсии -r2. Дополнительные сведения о параметрах команды dx см. в разделе dx (Выражение объектной модели отладчика).

В этом примере выполняется сортировка по TimeStart в порядке убывания.

0:000> dx -r2 @$cursession.TTD.Calls("kernelbase!GetLastError").OrderByDescending(c => c.TimeStart)
@$cursession.TTD.Calls("kernelbase!GetLastError").OrderByDescending(c => c.TimeStart)                
    [0x1896]        
        EventType        : Call
        ThreadId         : 0x3a10
        UniqueThreadId   : 0x2
        TimeStart        : 464224:34 [Time Travel]
        TimeEnd          : 464224:37 [Time Travel]
        Function         : UnknownOrMissingSymbols
        FunctionAddress  : 0x7561ccc0
        ReturnAddress    : 0x7594781c
        ReturnValue      : 0x0
        Parameters      
    [0x18a0]        
        EventType        : Call
        ThreadId         : 0x3a10
        UniqueThreadId   : 0x2
        TimeStart        : 464223:21 [Time Travel]
        TimeEnd          : 464223:24 [Time Travel]
        Function         : UnknownOrMissingSymbols
        FunctionAddress  : 0x7561ccc0
        ReturnAddress    : 0x7594781c
        ReturnValue      : 0x0
        Parameters    

Указание элементов в запросе

Чтобы выбрать определенный элемент, можно добавить к запросу различные квалификаторы. Например, в запросе отображается первый вызов, содержащий "kernelbase! GetLastError".

0:000> dx @$cursession.TTD.Calls("kernelbase!GetLastError").First()
@$cursession.TTD.Calls("kernelbase!GetLastError").First()                
    EventType        : 0x0
    ThreadId         : 0x2d98
    UniqueThreadId   : 0x2
    TimeStart        : 718:7D7 [Time Travel]
    TimeEnd          : 718:7DA [Time Travel]
    Function         : KERNELBASE!GetLastError
    FunctionAddress  : 0x7ff996cf20f0
    ReturnAddress    : 0x7ff99855ac5a
    ReturnValue      : 0x0 [Type: unsigned long]
    Parameters      
    SystemTimeStart  : Friday, January 12, 2024 21:18:40.862
    SystemTimeEnd    : Friday, January 12, 2024 21:18:40.862

Фильтрация в запросе

Используйте метод Select(), чтобы выбрать столбцы для просмотра и изменения отображаемого имени столбца.

В этом примере возвращаются строки, в которых ReturnValue не равен нулю, и выбираются для отображения столбцы TimeStart и ReturnValue с пользовательскими именами Время и Ошибка.

0:000> dx -r2 @$cursession.TTD.Calls("kernelbase!GetLastError").Where(c => c.ReturnValue != 0).Select(c => new { Time = c.TimeStart, Error = c.ReturnValue })
@$cursession.TTD.Calls("kernelbase!GetLastError").Where(c => c.ReturnValue != 0).Select(c => new { Time = c.TimeStart, Error = c.ReturnValue })                
    [0x1]           
        Time             : 72D:1B3 [Time Travel]
        Error            : 0x57 [Type: unsigned long]
    [0x2]           
        Time             : 72D:1FC [Time Travel]
        Error            : 0x2af9 [Type: unsigned long]
    [0x3]           
        Time             : 72D:26E [Time Travel]
        Error            : 0x2af9 [Type: unsigned long]

Группировка

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

0:000> dx -r2 @$cursession.TTD.Calls("kernelbase!GetLastError").Where(c => c.ReturnValue != 0).Select(c => new { Time = c.TimeStart, Error = c.ReturnValue }).GroupBy(x => x.Error)
@$s = @$cursession.TTD.Calls("kernelbase!GetLastError").Where(c => c.ReturnValue != 0).Select(c => new { Time = c.TimeStart, Error = c.ReturnValue }).GroupBy(x => x.Error)                
    [0x36b7]        
        [0x0]           
        [0x1]           
        [0x2]           
        [0x3]           
        [...]           
    [0x3f0]         
        [0x0]           
        [0x1]           
        [0x2]           
        [0x3]           
...

Назначение результата запроса переменной

Используйте этот синтаксис для назначения результата запроса переменной dx @$var = <expression>

В этом примере результаты запроса назначаются переменной myResults

dx -r2 @$myResults = @$cursession.TTD.Calls("kernelbase!GetLastError").Where(c => c.ReturnValue != 0).Select(c => new { Time = c.TimeStart, Error = c.ReturnValue })

Используйте команду DX, чтобы отобразить только что созданную переменную с помощью параметра сетки -g. Дополнительные сведения о параметрах команды dx см. в разделе dx (Выражение объектной модели отладчика).

0:000> dx -g @$myResults
========================================
=           = (+) Time     = (+) Error =
========================================
= [0x13]    - 3C64A:834    - 0x36b7    =
= [0x1c]    - 3B3E7:D6     - 0x3f0     =
= [0x1d]    - 3C666:857    - 0x36b7    =
= [0x20]    - 3C67E:12D    - 0x2       =
= [0x21]    - 3C6F1:127    - 0x2       =
= [0x23]    - 3A547:D6     - 0x3f0     =
= [0x24]    - 3A59B:D0     - 0x3f0     =

Примеры

Запрос исключений

Этот запрос LINQ использует объект TTD.Event для отображения всех исключений в трассировке.

0:000> dx @$curprocess.TTD.Events.Where(t => t.Type == "Exception").Select(e => e.Exception)
@$curprocess.TTD.Events.Where(t => t.Type == "Exception").Select(e => e.Exception)
    [0x0]            : Exception 0x000006BA of type Software at PC: 0X777F51D0
    [0x1]            : Exception 0x000006BA of type Software at PC: 0X777F51D0
    [0x2]            : Exception 0xE06D7363 of type CPlusPlus at PC: 0X777F51D0

Запросы для конкретных API-вызовов

Используйте объект TTD.Calls для запроса определённых вызовов API. В этом примере произошла ошибка при вызове user32!MessageBoxW, API Windows для отображения окна сообщения. Мы перечисляем все вызовы MessageBoxW, упорядочиваем их по времени начала функции, а затем выбираем последний вызов.

0:000> dx @$cursession.TTD.Calls("user32!MessageBoxW").OrderBy(c => c.TimeStart).Last()
@$cursession.TTD.Calls("user32!MessageBoxW").OrderBy(c => c.TimeStart).Last()                
    EventType        : Call
    ThreadId         : 0x3a10
    UniqueThreadId   : 0x2
    TimeStart        : 458310:539 [Time Travel]
    TimeEnd          : 45C648:61 [Time Travel]
    Function         : UnknownOrMissingSymbols
    FunctionAddress  : 0x750823a0
    ReturnAddress    : 0x40cb93
    ReturnValue      : 0x10a7000000000001
    Parameters

Запрос события загрузки определенного модуля

Во-первых, используйте команду lm (список загруженных модулей) для отображения загруженных модулей.

0:000> lm
start    end        module name
012b0000 012cf000   CDog_Console   (deferred)             
11570000 1158c000   VCRUNTIME140D   (deferred)             
11860000 119d1000   ucrtbased   (deferred)             
119e0000 11b63000   TTDRecordCPU   (deferred)             
11b70000 11cb1000   TTDWriter   (deferred)             
73770000 73803000   apphelp    (deferred)             
73ea0000 74062000   KERNELBASE   (deferred)             
75900000 759d0000   KERNEL32   (deferred)             
77070000 771fe000   ntdll      (private pdb symbols)

Затем используйте следующую команду dx, чтобы узнать, какую позицию в трассировке загружен определенный модуль, например ntdll.

dx @$curprocess.TTD.Events.Where(t => t.Type == "ModuleLoaded").Where(t => t.Module.Name.Contains("ntdll.dll")) 
@$curprocess.TTD.Events.Where(t => t.Type == "ModuleLoaded").Where(t => t.Module.Name.Contains("ntdll.dll"))                 
    [0x0]            : Module Loaded at position: A:0 

Этот запрос LINQ отображает события загрузки определенного модуля.

0:000> dx @$curprocess.TTD.Events.Where(t => t.Type == "ModuleUnloaded").Where(t => t.Module.Name.Contains("ntdll.dll")) 
@$curprocess.TTD.Events.Where(t => t.Type == "ModuleUnloaded").Where(t => t.Module.Name.Contains("ntdll.dll"))                 
    [0x0]            : Module Unloaded at position: FFFFFFFFFFFFFFFE:0

Адрес FFFFFFFFFFFFFFFFFE:0 указывает конец трассировки.

Запрос на получение всех проверок ошибок в трассировке

Используйте эту команду для сортировки всех проверок ошибок в трассировке по количеству ошибок.

0:000> dx -g @$cursession.TTD.Calls("kernelbase!GetLastError").Where( x=> x.ReturnValue != 0).GroupBy(x => x.ReturnValue).Select(x => new { ErrorNumber = x.First().ReturnValue, ErrorCount = x.Count()}).OrderByDescending(p => p.ErrorCount),d
==================================================
=                 = (+) ErrorNumber = ErrorCount =
==================================================
= [1008]          - 1008            - 8668       =
= [14007]         - 14007           - 4304       =
= [2]             - 2               - 1710       =
= [6]             - 6               - 1151       =
= [1400]          - 1400            - 385        =
= [87]            - 87              - 383        =

Запрос позиции времени в трассировке при создании потоков

Используйте эту команду dx, чтобы отобразить все события трассировки в формате сетки (-g).

0:000> dx -g @$curprocess.TTD.Events
==================================================================================================================================================================================================
=                                                          = (+) Type            = (+) Position          = (+) Module                                                   = (+) Thread             =
==================================================================================================================================================================================================
= [0x0] : Module Loaded at position: 2:0                   - ModuleLoaded        - 2:0                   - Module C:\Users\USER1\Documents\Visual Studio 2015\Proje... -                        =
= [0x1] : Module Loaded at position: 3:0                   - ModuleLoaded        - 3:0                   - Module C:\WINDOWS\SYSTEM32\VCRUNTIME140D.dll at address 0... -                        =
= [0x2] : Module Loaded at position: 4:0                   - ModuleLoaded        - 4:0                   - Module C:\WINDOWS\SYSTEM32\ucrtbased.dll at address 0X118... -                        =
= [0x3] : Module Loaded at position: 5:0                   - ModuleLoaded        - 5:0                   - Module C:\Users\USER1\AppData\Local\Dbg\UI\Fast.20170907... -                        =
= [0x4] : Module Loaded at position: 6:0                   - ModuleLoaded        - 6:0                   - Module C:\Users\USER1\AppData\Local\Dbg\UI\Fast.20170907... -                        =
= [0x5] : Module Loaded at position: 7:0                   - ModuleLoaded        - 7:0                   - Module C:\WINDOWS\SYSTEM32\apphelp.dll at address 0X73770... -                        =
= [0x6] : Module Loaded at position: 8:0                   - ModuleLoaded        - 8:0                   - Module C:\WINDOWS\System32\KERNELBASE.dll at address 0X73... -                        =
= [0x7] : Module Loaded at position: 9:0                   - ModuleLoaded        - 9:0                   - Module C:\WINDOWS\System32\KERNEL32.DLL at address 0X7590... -                        =
= [0x8] : Module Loaded at position: A:0                   - ModuleLoaded        - A:0                   - Module C:\WINDOWS\SYSTEM32\ntdll.dll at address 0X7707000... -                        =
= [0x9] : Thread created at D:0                            - ThreadCreated       - D:0                   -                                                              - UID: 2, TID: 0x4C2C    =
= [0xa] : Thread terminated at 64:0                        - ThreadTerminated    - 64:0                  -                                                              - UID: 2, TID: 0x4C2C    =
= [0xb] : Thread created at 69:0                           - ThreadCreated       - 69:0                  -                                                              - UID: 3, TID: 0x4CFC    =
= [0xc] : Thread created at 6A:0                           - ThreadCreated       - 6A:0                  -                                                              - UID: 4, TID: 0x27B0    =
= [0xd] : Thread terminated at 89:0                        - ThreadTerminated    - 89:0                  -                                                              - UID: 4, TID: 0x27B0    =
= [0xe] : Thread terminated at 8A:0                        - ThreadTerminated    - 8A:0                  -                                                              - UID: 3, TID: 0x4CFC    =
= [0xf] : Module Unloaded at position: FFFFFFFFFFFFFFFE:0  - ModuleUnloaded      - FFFFFFFFFFFFFFFE:0    - Module C:\Users\USER1\Documents\Visual Studio 2015\Proje... -                        =
= [0x10] : Module Unloaded at position: FFFFFFFFFFFFFFFE:0 - ModuleUnloaded      - FFFFFFFFFFFFFFFE:0    - Module C:\Users\USER1\AppData\Local\Dbg\UI\Fast.20170907... -                        =
= [0x11] : Module Unloaded at position: FFFFFFFFFFFFFFFE:0 - ModuleUnloaded      - FFFFFFFFFFFFFFFE:0    - Module C:\WINDOWS\SYSTEM32\VCRUNTIME140D.dll at address 0... -                        =
= [0x12] : Module Unloaded at position: FFFFFFFFFFFFFFFE:0 - ModuleUnloaded      - FFFFFFFFFFFFFFFE:0    - Module C:\Users\USER1\AppData\Local\Dbg\UI\Fast.20170907... -                        =
= [0x13] : Module Unloaded at position: FFFFFFFFFFFFFFFE:0 - ModuleUnloaded      - FFFFFFFFFFFFFFFE:0    - Module C:\WINDOWS\SYSTEM32\ucrtbased.dll at address 0X118... -                        =
= [0x14] : Module Unloaded at position: FFFFFFFFFFFFFFFE:0 - ModuleUnloaded      - FFFFFFFFFFFFFFFE:0    - Module C:\WINDOWS\SYSTEM32\apphelp.dll at address 0X73770... -                        =
= [0x15] : Module Unloaded at position: FFFFFFFFFFFFFFFE:0 - ModuleUnloaded      - FFFFFFFFFFFFFFFE:0    - Module C:\WINDOWS\System32\KERNELBASE.dll at address 0X73... -                        =
= [0x16] : Module Unloaded at position: FFFFFFFFFFFFFFFE:0 - ModuleUnloaded      - FFFFFFFFFFFFFFFE:0    - Module C:\WINDOWS\System32\KERNEL32.DLL at address 0X7590... -                        =
= [0x17] : Module Unloaded at position: FFFFFFFFFFFFFFFE:0 - ModuleUnloaded      - FFFFFFFFFFFFFFFE:0    - Module C:\WINDOWS\SYSTEM32\ntdll.dll at address 0X7707000... -                        =
==================================================================================================================================================================================================

Выберите любой из столбцов с знаком +, чтобы отсортировать выходные данные.

Используйте этот запрос LINQ, чтобы отобразить в табличном формате временное положение в трассировке, когда создавались потоки (Type == "ThreadCreated").

dx -g @$curprocess.TTD.Events.Where(t => t.Type == "ThreadCreated").Select(t => t.Thread) 
===========================================================================================================
=                             = (+) UniqueId = (+) Id    = (+) Lifetime                 = (+) ActiveTime  =
===========================================================================================================
= [0x0] : UID: 2, TID: 0x4C2C - 0x2          - 0x4c2c    - [0:0, FFFFFFFFFFFFFFFE:0]    - [D:0, 64:0]     =
= [0x1] : UID: 3, TID: 0x4CFC - 0x3          - 0x4cfc    - [0:0, 8A:0]                  - [69:0, 8A:0]    =
= [0x2] : UID: 4, TID: 0x27B0 - 0x4          - 0x27b0    - [0:0, 89:0]                  - [6A:0, 89:0]    =
===========================================================================================================

Используйте этот запрос LINQ для отображения в табличном формате временных позиций в трассировке при завершении потоков (Type == "ThreadTerminated").

0:000> dx -g @$curprocess.TTD.Events.Where(t => t.Type == "ThreadTerminated").Select(t => t.Thread) 
===========================================================================================================
=                             = (+) UniqueId = (+) Id    = (+) Lifetime                 = (+) ActiveTime  =
===========================================================================================================
= [0x0] : UID: 2, TID: 0x4C2C - 0x2          - 0x4c2c    - [0:0, FFFFFFFFFFFFFFFE:0]    - [D:0, 64:0]     =
= [0x1] : UID: 4, TID: 0x27B0 - 0x4          - 0x27b0    - [0:0, 89:0]                  - [6A:0, 89:0]    =
= [0x2] : UID: 3, TID: 0x4CFC - 0x3          - 0x4cfc    - [0:0, 8A:0]                  - [69:0, 8A:0]    =
===========================================================================================================

Сортировка выходных данных для определения наиболее длительно исполняемых потоков

Используйте этот запрос LINQ для отображения в формате сетки приблизительно самых длительных потоков в трассировке.

0:000> dx -g @$curprocess.TTD.Events.Where(e => e.Type == "ThreadTerminated").Select(e => new { Thread = e.Thread, ActiveTimeLength = e.Thread.ActiveTime.MaxPosition.Sequence - e.Thread.ActiveTime.MinPosition.Sequence }).OrderByDescending(t => t.ActiveTimeLength)
=========================================================
=          = (+) Thread              = ActiveTimeLength =
=========================================================
= [0x0]    - UID: 2, TID: 0x1750     - 0x364030         =
= [0x1]    - UID: 3, TID: 0x420C     - 0x360fd4         =
= [0x2]    - UID: 7, TID: 0x352C     - 0x35da46         =
= [0x3]    - UID: 9, TID: 0x39F4     - 0x34a5b5         =
= [0x4]    - UID: 11, TID: 0x4288    - 0x326199         =
= [0x5]    - UID: 13, TID: 0x21C8    - 0x2fa8d8         =
= [0x6]    - UID: 14, TID: 0x2188    - 0x2a03e3         =
= [0x7]    - UID: 15, TID: 0x40E8    - 0x29e7d0         =
= [0x8]    - UID: 16, TID: 0x124     - 0x299677         =
= [0x9]    - UID: 4, TID: 0x2D74     - 0x250f43         =
= [0xa]    - UID: 5, TID: 0x2DC8     - 0x24f921         =
= [0xb]    - UID: 6, TID: 0x3B1C     - 0x24ec8e         =
= [0xc]    - UID: 10, TID: 0x3808    - 0xf916f          =
= [0xd]    - UID: 12, TID: 0x26B8    - 0x1ed3a          =
= [0xe]    - UID: 17, TID: 0x37D8    - 0xc65            =
= [0xf]    - UID: 8, TID: 0x45F8     - 0x1a2            =
=========================================================

Запрос доступа на чтение к диапазону памяти

Используйте объект TTD.Memory для запроса доступа на чтение к диапазону памяти.

Блок среды потока (TEB) — это структура, содержащая все сведения о состоянии потока, включая результат, возвращенный GetLastError(). Вы можете запросить эту структуру данных, запустив dx @$teb для текущего потока. Одним из членов TEB является переменная LastErrorValue, размером 4 байта. Мы можем ссылаться на элемент LastErrorValue в TEB с помощью этого синтаксиса. dx &@$teb->LastErrorValue.

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

0:000> dx @$cursession.TTD.Memory(&@$teb->LastErrorValue, &@$teb->LastErrorValue + 0x4, "r")
@$cursession.TTD.Memory(&@$teb->LastErrorValue, &@$teb->LastErrorValue + 0x4, "r")
    [0x0]           
    [0x1]           
    [0x2]           
    [0x3]     

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


:000> dx @$cursession.TTD.Memory(&@$teb->LastErrorValue, &@$teb->LastErrorValue + 0x4, "r").Where(m => m.TimeStart < @$dialog).OrderBy(m => m.TimeStart).Last().TimeEnd.SeekTo()
Setting position: 458300:37
ModLoad: 6cee0000 6cf5b000   C:\WINDOWS\system32\uxtheme.dll
ModLoad: 75250000 752e6000   C:\WINDOWS\System32\OLEAUT32.dll
ModLoad: 76320000 7645d000   C:\WINDOWS\System32\MSCTF.dll
ModLoad: 76cc0000 76cce000   C:\WINDOWS\System32\MSASN1.dll

GitHub TTD Query Lab

Руководство по отладке кода C++ с использованием отладки с временным перемещением и записи с помощью запросов для поиска сведений о выполнении проблемного кода см. в разделе WinDbg-Samples — отладка и запросы.

Весь код, используемый в лаборатории, доступен здесь: https://github.com/Microsoft/WinDbg-Samples/tree/master/TTDQueries/app-sample

Устранение неполадок запросов TTD

"UnknownOrMissingSymbols" в качестве имен функций

Для предоставления имен функций, значений параметров и т. д. для расширения модели данных требуются полные сведения о символах. Если полные сведения о символах недоступны, отладчик использует "UnknownOrMissingSymbols" в качестве имени функции.

  • Если у вас есть закрытые символы, вы получите имя функции и правильный список параметров.
  • Если у вас есть открытые символы, вы получите имя функции и набор параметров по умолчанию — четыре 64-битных беззнаковых целых числа.
  • Если у вас нет сведений о символах для запрашиваемого модуля, в качестве имени используется "UnknownOrMissingSymbols".

Запросы TTD для вызовов

Может быть несколько причин, по которым запрос не возвращает ничего при вызовах к библиотеке DLL.

  • Синтаксис вызова не совсем правильный. Попробуйте проверить синтаксис вызова с помощью x (проверить символы).x <call> Если имя модуля, возвращаемое x, находится в верхнем регистре, используйте это.
  • Библиотека DLL еще не загружена и будет загружена позже в ходе трассировки. Чтобы обойти эту проблему, перейдите к моменту времени после загрузки библиотеки DLL и выполните запрос заново.
  • Вызов встроен, что подсистема запросов не может отследить.
  • Шаблон запроса использует подстановочные знаки, которые возвращают слишком много функций. Попробуйте сделать шаблон запроса более конкретным, чтобы количество сопоставленных функций было достаточно небольшим.

См. также

Использование LINQ С объектами отладчика

dx (выражение объектной модели отладчика)

Отладка временных путешествий — обзор

Отладка перемещения по времени — автоматизация JavaScript