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


!tt (путешествие по времени)

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

Расширение отладчика !tt (путешествие по времени), позволяющее перемещаться вперед и назад во времени.

Навигационные команды !tt

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

!tt [position]

Параметры

позиция

Укажите позицию времени в любом из следующих форматов для перемещения в этот момент времени.

  • Если {position} является десятичным числом от 0 до 100, он перемещается примерно на этот процент в трассировку. Рассмотрим пример.

    • !tt 0 — перемещение во времени к началу трассировки
    • !tt 50 — путешествие во времени на середину трассировки
    • !tt 100 — путешествие во времени до конца трассировки
  • Если {position} является числом с плавающей запятой от 0 до 100, оно перемещается примерно на этот процент вдоль трассы. Рассмотрим пример.

    • !tt 0.00 — время перемещения к началу трассировки
    • !tt 50.1 — путешествие во времени чуть более чем наполовину по временной шкале
    • !tt 99.9 — путешествие во времени почти до конца следа
  • Если {position} имеет значение #:#, где # является шестнадцатеричными числами, он перемещается в эту позицию. Если число после : опущено, значение по умолчанию равно нулю.

    • !tt 1A0: — время поездки на позицию 1A0:0
    • !tt 1A0:0 — путешествие во времени к позиции 1A0:0
    • !tt 1A0:12F - Время путешествия по позиции 1A0:12F

    Примечание.

    Трассировки используют двухчастную позицию инструкции, которая ссылается на конкретную позицию в трассировке, например 12:0. или 15:7. Два элемента — шестнадцатеричные числа, определенные как описано здесь.

    xx:yy

    xx - первый элемент — это номер последовательности, соответствующий событию последовательности.

    y — второй элемент — это число шагов, которое соответствует примерно числу инструкций с момента события последовательности.

Команды останова !tt

Прерывание регистрации

!tt br[-] <register> [<value>]

Эта команда перейдет к предыдущей или следующей позиции, где указанный регистр изменил значения (или, если задано <value>, принимает указанное значение) в текущем потоке.

Примеры:

!tt br rbx 0x12345678 — найдите следующую позицию в текущем потоке, который устанавливает rbx в 0x12345678.

!tt br- ebx — найти предыдущую позицию в текущем потоке, установившую rbx в его текущее значение.

0:000> !tt br- ebx

Setting position: 2C8:0
(3b24.2d98): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 2C8:0
ntdll!LdrInitializeThunk:
00007ff9`999e3dd0 4053            push    rbx
  • Команда register watchpoint поддерживает все поддерживаемые архитектуры Windows, такие как x64 и ARM64.
  • Точка отслеживания ограничена только регистрами общего назначения и XMM-регистрами.
  • Точка отслеживания регистра реализуется с помощью алгоритма, медленного по сравнению с обычной скоростью воспроизведения трассировки. Поиск можно отменить с помощью CTRL+C.

Разрыв доступа

!tt ba[-] <rwe> <address> <size> [<address> <size> …]

Эта команда перейдет к предыдущей или следующей позиции, где один из указанных диапазонов памяти обращается к указанному способу: "R" предназначен для чтения памяти, "W" предназначен для записи памяти, а "E" предназначен для выполнения. Одновременно можно указать более одной опции, т. е. «RW». Это аналогично команде отладчика ba (break on Access).

Примеры. !tt ba- rw 0x12345678 0x4000 Найдите предыдущую позицию, которая считывается из диапазона памяти. (0x12345678 – 0x12345678 + 0x4000). !tt ba e 0x7fffe0001234 0x30000 — найдите следующую позицию, которая выполняется из указанного диапазона. Представьте себе, что адрес и диапазон представляют собой диапазон ntdll.dll. Эта команда найдет следующую позицию, в которой ntdll.dll вводится.

  • Адреса и размеры должны быть предоставлены в виде чисел. Символы не поддерживаются.

Прерывание в модуле

Используйте метод навигации с помощью функции прерывания для перемещения вперед или назад на уровне модуля.

!tt bm[-] [<module> ...]

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

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

При использовании этой команды для перемещения по трассировке, поиск в обратном направлении значительно медленнее, чем поиск вперед.

Примеры вариантов использования

Ниже приведены два примера вариантов использования.

Вариант использования 1. Перемещение вперед или назад, пока вы не находитесь в другом модуле в текущем потоке. В этом случае TTD перемещается из dwmcore в модули ucrtbase, идущие вперед, а затем перемещается назад к ntdll.

Пример трассировки начинается с исключения в модуле dwmcore.

Setting position: 1C46AE:0
(a54.c98): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 1C46AE:0
dwmcore!wil_atomic_uint32_compare_exchange_relaxed+0xc [inlined in dwmcore!wil_details_FeatureReporting_RecordUsageInCache+0x124]:
00007ffa`441e16a0 f0450fb102      lock cmpxchg dword ptr [r10],r8d ds:00007ffa`444b0450=00000003

Выполните командлет !tt bm commmand. Поскольку модуль не указан, перейдите к следующей точке выполнения за пределами текущего выполняемого модуля — ucrtbase.

0:001> !tt bm
Replaying - Currently at 1D1BEE:0 (  2.95%)
Setting position: 1C46AF:61
(a54.c98): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 1C46AF:61
ucrtbase!_finite:
00007ffa`4ac3c080 48b9ffffffffffffff7f mov rcx,7FFFFFFFFFFFFFFFh

Одношаговая обработка с этого места позволила TTD правильно найти границу модуля.

0:001> t-
Time Travel Position: 1C46AF:60
dwmcore!CBaseExpression::IsExpressionValueValid+0x50:
00007ffa`44124b40 48ff15f9db2700  call    qword ptr [dwmcore!_imp__finite (00007ffa`443a2740)] ds:00007ffa`443a2740={ucrtbase!_finite (00007ffa`4ac3c080)}

(a54.c98): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 1C46AE:0
dwmcore!wil_atomic_uint32_compare_exchange_relaxed+0xc [inlined in dwmcore!wil_details_FeatureReporting_RecordUsageInCache+0x124]:
00007ffa`441e16a0 f0450fb102      lock cmpxchg dword ptr [r10],r8d ds:00007ffa`444b0450=00000003

Выполните поиск назад до ближайшей границы модуля.

0:001> !tt bm-
Setting position: 1C46AD:2B1
(a54.c98): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 1C46AD:2B1
ntdll!LdrpDispatchUserCallTarget+0x3b:
00007ffa`4d27f24b 48ffe0          jmp     rax {dwmcore!CKeyframeAnimation::CalculateValueWorker (00007ffa`441264e0)}

Затем перейдите с границы модуля к следующему модулю.

0:001> t
Time Travel Position: 1C46AD:2B2
dwmcore!CKeyframeAnimation::CalculateValueWorker:
00007ffa`441264e0 48895c2408      mov     qword ptr [rsp+8],rbx ss:0000004e`5151f4d0=0000000000000000
Вариант использования 2. Перемещение вперед, пока не будет введен модуль. В этом примере ntdll.
0:001> !tt bm ntdll
Replaying - Currently at 1CBF15:0 (  1.66%)
Setting position: 1C46B0:97
(a54.c98): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 1C46B0:97
ntdll!LdrpDispatchUserCallTarget:
00007ffa`4d27f210 4c8b1db1c11000  mov     r11,qword ptr [ntdll!LdrSystemDllInitBlock+0xb8 (00007ffa`4d38b3c8)] ds:00007ffa`4d38b3c8=00007df503990000

Можно использовать !tt bm- <module> для поиска назад.

Модель данных — NextModuleAccess и PrevModuleAccess

Используйте команду dx (выражение объектной модели отладчика) и объекты модели данных NextModuleAccess и PrevModuleAccess, чтобы получить доступ к тем же функциям, которые доступны в команде !tt.

Перейдите к следующей границе доступа к модулю.

0:001> dx @$curprocess.TTD.NextModuleAccess()
Replaying - Currently at 1D1BEE:0 (  2.95%)
@$curprocess.TTD.NextModuleAccess() : [UTID 3] Execute [1C46AE:0] -> [1C46AF:61] ucrtbase 0x7ffa4ac3c080
    Position         : 1C46AF:61
    OriginalPosition : 1C46AE:0
    UniqueThreadId   : 0x3
    AccessType       : Execute
    Address          : 0x7ffa4ac3c080
    ModuleName       : ucrtbase

Перемещайтесь назад к следующей предыдущей границе доступа.

0:001> dx @$curprocess.TTD.PrevModuleAccess()
@$curprocess.TTD.PrevModuleAccess() : [UTID 3] Execute [1C46AE:0] -> [1C46AD:2B1] ntdll 0x7ffa4d27f24b
    Position         : 1C46AD:2B1
    OriginalPosition : 1C46AE:0
    UniqueThreadId   : 0x3
    AccessType       : Execute
    Address          : 0x7ffa4d27f24b
    ModuleName       : ntdll

Перейдите к следующей границе доступа модуля ntdll .

0:001> dx @$curprocess.TTD.NextModuleAccess("ntdll")
Replaying - Currently at 1CBF15:0 (  1.66%)
@$curprocess.TTD.NextModuleAccess("ntdll") : [UTID 3] Execute [1C46AE:0] -> [1C46B0:97] ntdll 0x7ffa4d27f210
    Position         : 1C46B0:97
    OriginalPosition : 1C46AE:0
    UniqueThreadId   : 0x3
    AccessType       : Execute
    Address          : 0x7ffa4d27f210
    ModuleName       : ntdll

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

Доступ к функциональности прерывания при доступе к памяти можно получить с помощью команды dx (выражение объектной модели отладчика), окон моделей данных отладчиков, JavaScript и C++. Общие сведения о работе с запросами LINQ и объектами отладчика см. в разделе "Использование LINQ С объектами отладчика".

TTD.PrevRegisterWrite

dx @$curthread.TTD.PrevRegisterWrite("<reg>" [, <value>])

Этот метод выполняет поиск предыдущей позиции, в которой указанный регистр изменил значения (или, если <value> задано, принимает указанное значение) в текущем потоке. Это аналогично приведенной !tt br- выше команде, за исключением того, что она не автоматически переходит к позиции. Вместо этого он возвращает такие сведения, как показано ниже.

0:000> dx @$curthread.TTD.PrevRegisterWrite("rbx")

@$curthread.TTD.PrevRegisterWrite("rbx")                 : [UTID 2] rbx [2C8:0] 0x0 -> [2C8:0] 0x0
    Register         : rbx
    Position         : 2C8:0 [Time Travel]
    Value            : 0x0
    OriginalPosition : 2C8:0 [Time Travel]
    OriginalValue    : 0x0
    UniqueThreadId   : 0x2

Аналогичным образом можно использовать @$curthread. TTD. NextRegisterWrite(...) для поиска следующего изменения регистра.

0:000> dx @$curthread.TTD.NextRegisterWrite("rbx")

@$curthread.TTD.NextRegisterWrite("rbx")                 : [UTID 2] rbx [2C8:1] 0x0 -> [2C8:2] 0x963127f5a0
    Register         : rbx
    Position         : 2C8:2 [Time Travel]
    Value            : 0x963127f5a0
    OriginalPosition : 2C8:1 [Time Travel]
    OriginalValue    : 0x0
    UniqueThreadId   : 0x2

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

0:000> dx -s @$create("Debugger.Models.TTD.Position", 712, 0).SeekTo()
(3b24.2d98): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 2C8:0

TTD. PrevMemoryAccess

dx @$curprocess.TTD.PrevMemoryAccess("<rwe>", <address>, <size> [, <address>, <size> …])

Этот метод ищет предыдущую позицию, где доступ к одному из указанных диапазонов памяти осуществляется указанным способом. Это аналогично приведенной выше команде !tt ba-, за исключением того, что она не автоматически переходит к позиции. Вместо этого он возвращает такие сведения, как показано ниже.

@$curprocess.TTD.PrevMemoryAccess("w", 0x01a16a939820, 0x10) : [UTID 3] Write 0x1a16a939828 4 bytes [1C46AE:0] -> [1C4575:0]
   Position         : 1C4575:0
   OriginalPosition : 1C46AE:0
   UniqueThreadId   : 0x3
   Address          : 0x1a16a939828
   Size             : 0x4
   AccessType       : Write

Аналогичным образом можно использовать @$curprocess.TTD.NextMemoryAccess(…) для поиска следующего доступа к памяти.

0:000> dx @$curprocess.TTD.NextMemoryAccess("r", 0x00007ff9`95420000, 0xFF)

@$curprocess.TTD.NextMemoryAccess("r", 0x00007ff9`95420000, 0xFF)                 : [UTID 2] Read 0x7ff995420000 2 bytes [2C8:0] -> [66C:10A2]
    Position         : 66C:10A2 [Time Travel]
    OriginalPosition : 2C8:0 [Time Travel]
    UniqueThreadId   : 0x2
    Address          : 0x7ff995420000
    Size             : 0x2
    AccessType       : Read

!tt DLL

ttdext.dll

Дополнительные сведения

Это расширение работает только с трассировками перемещения по времени. Дополнительные сведения о путешествии по времени см. в разделе "Отладка временных путешествий" — обзор.

См. также

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