시간 이동 디버깅 - 추적 재생
이 섹션에서는 시간 이동 추적을 재생하고 정시에 앞뒤로 탐색하는 방법을 설명합니다.
명령 시간 이동 탐색
다음 명령과 함께 후행 빼기 기호를 사용하여 시간을 거슬러 이동합니다.
명령 |
---|
p- (뒤로 단계) |
t- (추적 후면) |
g- (뒤로 이동) |
자세한 내용은 시간 이동 디버깅 - 탐색 명령을 참조하세요.
리본 단추 시간 이동 탐색
또는 리본 단추를 사용하여 추적을 탐색합니다.
TTD 추적 재생 예제
g- 명령을 사용하여 이벤트 또는 TTD 추적의 시작 부분에 도달할 때까지 뒤로 실행합니다. 역방향 실행을 중지할 수 있는 이벤트는 앞으로 실행을 중지하는 것과 동일합니다. 이 예제에서는 추적의 시작에 도달합니다.
0:000> g-
TTD: Start of trace reached.
(3f78.4274): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 29:0
ntdll!ZwTestAlert+0x14:
00007ffc`61f789d4 c3 ret
p(단계) 명령을 사용하여 TTD 추적에서 앞으로 이동합니다.
0:000> p
Time Travel Position: F:1
ntdll!LdrpInitializeProcess+0x1bc5:
7774f828 740b je ntdll!LdrpInitializeProcess+0x1bd2 (7774f835) [br=1]
0:000> p
Time Travel Position: F:2
ntdll!LdrpInitializeProcess+0x1bd2:
7774f835 83bdd0feffff00 cmp dword ptr [ebp-130h],0 ss:002b:010ff454=00000000
0:000> p
Time Travel Position: F:3
ntdll!LdrpInitializeProcess+0x1bd9:
7774f83c 0f8450e8ffff je ntdll!LdrpInitializeProcess+0x42f (7774e092) [br=1]
t(추적) 명령을 사용하여 추적을 탐색할 수도 있습니다.
0:000> t
Time Travel Position: F:4
ntdll!LdrpInitializeProcess+0x42f:
7774e092 33c0 xor eax,eax
0:000> t
Time Travel Position: F:5
ntdll!LdrpInitializeProcess+0x431:
7774e094 e9f5170000 jmp ntdll!LdrpInitializeProcess+0x1c2b (7774f88e)
p- 명령을 사용하여 TTD 추적에서 뒤로 이동합니다.
0:000> p-
Time Travel Position: F:4
ntdll!LdrpInitializeProcess+0x42f:
7774e092 33c0 xor eax,eax
0:000> p-
Time Travel Position: F:3
ntdll!LdrpInitializeProcess+0x1bd9:
7774f83c 0f8450e8ffff je ntdll!LdrpInitializeProcess+0x42f (7774e092) [br=1]
t- 명령을 사용하여 시간을 뒤로 탐색할 수도 있습니다.
!tt 탐색 명령
추적에서 지정된 위치로 건너뛰어 !tt 명령을 사용하여 정시에 앞으로 또는 뒤로 이동합니다.
!tt [위치]
다음 형식 중 어느 형식으로든 시간 위치를 제공하여 해당 시점으로 이동합니다.
[position]가 0에서 100 사이의 10진수인 경우 추적으로 약 해당 백분율로 이동합니다. 예를 들어
!tt 50
추적의 중간으로 이동합니다.{position}이 #:#이면 여기서 #은 16진수 숫자인 경우 해당 위치로 이동합니다. 예를 들어
!tt 1A0:12F
은 추적에서 1A0:12F 위치로 이동합니다.
자세한 내용은 시간 이동 디버깅 - !tt(시간 이동)를 참조하세요.
!위치
를 사용하여 !positions
추적의 위치를 포함하여 모든 활성 스레드를 표시합니다. 자세한 내용은 시간 이동 디버깅 - !위치(시간 이동)를 참조하세요.
0:000> !positions
>*Thread ID=0x1C74 - Position: F:2
Thread ID=0x1750 - Position: A5:0
Thread ID=0x3FFC - Position: 200:0
Thread ID=0x36B8 - Position: 403:0
Thread ID=0x3BC4 - Position: 5F2:0
Thread ID=0x392C - Position: B45:0
Thread ID=0x32B4 - Position: C87:0
Thread ID=0x337C - Position: DF1:0
* indicates an actively running thread
이 예제에서는 현재 위치에 8개의 스레드가 있음을 보여 줍니다. 현재 스레드는 ''>로 표시된 3604입니다.
팁
스레드 및 해당 위치의 현재 목록을 표시하는 또 다른 방법은 데이터 모델 dx 명령을 사용하는 것입니다.
dx -g @$curprocess.Threads.Select(t => new { IsCurrent = t.Id == @$curthread.Id, ThreadId = t.Id, Position = t.TTD.Position })
사용자 모드 ~ (스레드 상태) 명령은 동일한 8개의 스레드를 표시하고 현재 스레드를 '.'로 표시합니다.
0:000> ~
. 0 Id: 954.1c74 Suspend: 4096 Teb: 00fdb000 Unfrozen
1 Id: 954.1750 Suspend: 4096 Teb: 00fea000 Unfrozen
2 Id: 954.3ffc Suspend: 4096 Teb: 00fde000 Unfrozen
3 Id: 954.36b8 Suspend: 4096 Teb: 00fe1000 Unfrozen
4 Id: 954.3bc4 Suspend: 4096 Teb: 00fe4000 Unfrozen
5 Id: 954.392c Suspend: 4096 Teb: 00fed000 Unfrozen
6 Id: 954.32b4 Suspend: 4096 Teb: 00ff0000 Unfrozen
7 Id: 954.337c Suspend: 4096 Teb: 00ff3000 Unfrozen
!positions 명령 출력에서 세 번째 스레드(3FFC) 옆에 있는 링크를 클릭하여 추적의 해당 위치(200:0)로 이동합니다.
0:002> !tt 200:0
Setting position: 200:0
(954.3ffc): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 200:0
ntdll!NtWaitForWorkViaWorkerFactory+0xc:
7775396c c21400 ret 14h
~ (스레드 상태) 명령을 사용하여 이제 세 번째 스레드 3ffc에 위치했는지 확인합니다.
0:002> ~
0 Id: 954.1c74 Suspend: 4096 Teb: 00fdb000 Unfrozen
1 Id: 954.1750 Suspend: 4096 Teb: 00fea000 Unfrozen
. 2 Id: 954.3ffc Suspend: 4096 Teb: 00fde000 Unfrozen
3 Id: 954.36b8 Suspend: 4096 Teb: 00fe1000 Unfrozen
4 Id: 954.3bc4 Suspend: 4096 Teb: 00fe4000 Unfrozen
5 Id: 954.392c Suspend: 4096 Teb: 00fed000 Unfrozen
6 Id: 954.32b4 Suspend: 4096 Teb: 00ff0000 Unfrozen
7 Id: 954.337c Suspend: 4096 Teb: 00ff3000 Unfrozen
참고
~s#(여기서 # 는 스레드 번호)도 지정된 스레드로 전환하지만 추적의 현재 위치는 변경되지 않습니다. !tt를 사용하여 다른 스레드의 위치로 시간 이동하면 메모리에서 읽은 모든 값(및 디버거)이 해당 위치에서 조회됩니다. ~s#으로 스레드를 전환할 때 디버거는 모든 메모리 쿼리에 사용되는 현재 위치를 내부적으로 변경하지 않습니다. 이는 주로 ~ s# 이 디버거의 내부 루프를 다시 설정할 필요가 없도록 이러한 방식으로 작동합니다.
시간 이동 디버깅 확장 명령
및 !positions
!index
명령에 대한 !tt
자세한 내용은 시간 이동 디버깅 - 확장 명령을 참조하세요.