共用方式為


!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- 第一個元素是序列號碼,對應至排序事件。

    yy - 第二個元素是步驟計數,其與排序事件之後的指令計數大致對應。

!tt break 命令

在緩存器上中斷

!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
  • 暫存器 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 command。 如未指定模組,請移至目前執行模組 - 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 (Display Debugger Object Model Expression) 命令和 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

使用輸出中的 [Time Travel] 連結,以跳至追蹤記錄中的該位置。

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

其他資訊

此延伸模組僅適用於時間移動追蹤。 如需時間移動的詳細資訊,請參閱 時間旅行偵錯 - 概觀

另請參閱

時間移動偵錯 - 概觀