다음을 통해 공유


시간 이동 디버깅 개체 소개

시계가 있는 시간 이동 디버깅 로고입니다.

이 섹션에서는 데이터 모델을 사용하여 시간 이동 추적을 쿼리하는 방법을 설명합니다. 이 도구는 시간 이동 추적에서 캡처되는 코드와 같은 질문에 대답하는 강력한 도구가 될 수 있습니다.

  • 추적에 있는 예외는 무엇인가요?
  • 추적에서 특정 코드 모듈이 로드된 시점은 어느 시점인가요?
  • 추적에서 스레드를 만들거나 종료한 시기는 언제인가요?
  • 추적에서 가장 오래 실행되는 스레드는 무엇인가요?

세션프로세스 데이터 모델 개체에 데이터를 추가하는 TTD 확장이 있습니다. TTD 데이터 모델 개체는 dx(디버거 개체 모델 식 표시) 명령, WinDbg의 모델 창, JavaScript 및 C++를 통해 액세스할 수 있습니다. TTD 확장은 시간 이동 추적을 디버깅할 때 자동으로 로드됩니다.

프로세스 개체

Process 개체에 추가된 기본 개체는 Process 개체의 TTD 네임스페이스에서 찾을 수 있습니다. 예들 들어 @$curprocess.TTD입니다.

:000> dx @$curprocess.TTD
@$curprocess.TTD                
    Threads         
    Events          
    Lifetime         : [26:0, 464232:0]
    SetPosition      [Sets the debugger to point to the given position on this process.]

LINQ 쿼리 및 디버거 개체 작업에 대한 일반적인 내용은 디버거 개체와 함께 LINQ 사용을 참조 하세요.

속성

Object 설명
수명 전체 추적의 수명을 설명하는 TTD 범위 개체입니다.
스레드 추적 수 명 동안 모든 스레드에 대해 하나씩 TTD 스레드 개체의 컬렉션을 포함합니다.
이벤트 추적의 모든 이벤트에 대해 하나씩 TTD 이벤트 개체컬렉션을 포함합니다.

메서드

메서드 설명
SetPosition() 0에서 100 사이의 정수 또는 N:N 형식의 문자열을 입력으로 사용하고 추적을 해당 위치로 이동합니다. 자세한 내용은 !tt를 참조하세요.

세션 개체

Session 개체에 추가된 기본 개체는 모든 Session 개체의 TTD 네임스페이스에서 찾을 수 있습니다. 예들 들어 @$cursession.TTD입니다.

0:000> dx @$cursession.TTD
@$cursession.TTD                 : [object Object]
    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"])]
    DefaultParameterCount : 0x4
    AsyncQueryEnabled : false
    Resources       
    Data             : Normalized data sources based on the contents of the time travel trace
    Utility          : Methods that can be useful when analyzing time travel traces

참고 항목

확장의 내부 함수에 사용되는 일부 개체 및 메서드가 TTDAnalyze에서 추가되었습니다. 모든 네임스페이스가 문서화되는 것은 아니며, 현재 네임스페이스는 시간이 지남에 따라 진화합니다.

메서드

메서드 설명
Data.Heap() 추적 중에 할당된 힙 개체의 컬렉션입니다. 계산을 수행하는 함수이므로 실행하는 데 시간이 걸립니다.
Calls() 입력 문자열과 일치하는 호출 개체의 컬렉션을 반환합니다 . 입력 문자열은 wild카드s를 포함할 수 있습니다. 계산을 수행하는 함수이므로 실행하는 데 시간이 걸립니다.
Memory() 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)                
    [0xb]           
        EventType        : Call
        ThreadId         : 0x3a10
        UniqueThreadId   : 0x2
        TimeStart        : 39:2DC [Time Travel]
        TimeEnd          : 39:2DF [Time Travel]
        Function         : UnknownOrMissingSymbols
        FunctionAddress  : 0x7561ccc0
        ReturnAddress    : 0x7593d24c
        ReturnValue      : 0x0
        Parameters      
    [0xe]           
        EventType        : Call
        ThreadId         : 0x3a10
        UniqueThreadId   : 0x2
        TimeStart        : AF:36 [Time Travel]
        TimeEnd          : AF:39 [Time Travel]
        Function         : UnknownOrMissingSymbols
        FunctionAddress  : 0x7561ccc0
        ReturnAddress    : 0x4723ef
        ReturnValue      : 0x0
        Parameters  

데이터 모델 개체의 추가 깊이를 표시하기 위해 -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        : Call
    ThreadId         : 0x3a10
    UniqueThreadId   : 0x2
    TimeStart        : 77A:9 [Time Travel]
    TimeEnd          : 77A:C [Time Travel]
    Function         : UnknownOrMissingSymbols
    FunctionAddress  : 0x7561ccc0
    ReturnAddress    : 0x6cf12406
    ReturnValue      : 0x0
    Parameters    

쿼리에서 필터링

Select() 메서드를 사용하여 열 표시 이름을 보고 수정할 열을 선택합니다.

다음은 ReturnValue가 0이 아닌 행을 반환하고 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 })                
    [0x13]          
        Time             : 3C64A:834 [Time Travel]
        Error            : 0x36b7
    [0x1c]          
        Time             : 3B3E7:D6 [Time Travel]
        Error            : 0x3f0
    [0x1d]          
        Time             : 3C666:857 [Time Travel]
        Error            : 0x36b7
    [0x20]          
        Time             : 3C67E:12D [Time Travel]

그룹화

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 grid 옵션을 사용하여 새로 만든 변수를 표시합니다. 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를 사용합니다. 추적의 모든 예외를 표시하는 이벤트 개체 입니다.

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를 사용합니다 . 개체 를 호출하여 특정 API 호출을 쿼리합니다. 이 예제에서는 user32! 메시지 상자를 표시하는 Windows API인 MessageBoxW입니다. 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

FFFFFFFFFFFFFE: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 쿼리를 사용하여 스레드를 만들 때 추적의 시간 위치인 그리드 형식으로 표시합니다(형식 == "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 쿼리를 사용하여 스레드가 종료되었을 때 추적의 시간 위치인 그리드 형식으로 표시합니다(형식 == "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를 사용합니다. 메모리 범위에 대한 읽기 액세스를 쿼리하기 위해 쿼리할 메모리 개체 입니다.

TEB(스레드 환경 블록)는 GetLastError()에서 반환된 결과를 포함하여 스레드 상태에 대한 모든 정보를 포함하는 구조체입니다. 현재 스레드에 대해 실행 dx @$teb 하여 이 데이터 구조를 쿼리할 수 있습니다. TEB의 멤버 중 하나는 LastErrorValue 변수이며 크기는 4바이트입니다. 이 구문을 사용하여 TEB에서 LastErrorValue 멤버를 참조할 수 있습니다. 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]     

추적에서 "dialog" 이벤트가 발생한 경우 쿼리를 실행하여 메모리의 해당 범위에서 수행된 모든 읽기 작업을 찾은 다음, 대화 상자를 만들기 전에 발생하는 모든 읽기를 선택한 다음 결과를 정렬하여 마지막 읽기 작업을 찾을 수 있습니다. 그런 다음 결과 시간 위치에서 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 쿼리 랩

쿼리를 사용하여 시간 이동 디버깅 기록을 사용하여 C++ 코드를 디버그하여 문제의 코드 실행에 대한 정보를 찾는 방법에 대한 자습서는 다음을 참조하세요 https://github.com/Microsoft/WinDbg-Samples/blob/master/TTDQueries/tutorial-instructions.md.

랩에서 사용되는 모든 코드는 다음에서 https://github.com/Microsoft/WinDbg-Samples/tree/master/TTDQueries/app-sample사용할 수 있습니다.

TTD 쿼리 문제 해결

함수 이름으로 "UnknownOrMissingSymbols"

데이터 모델 확장에는 함수 이름, 매개 변수 값 등을 제공하기 위해 전체 기호 정보가 필요합니다. 전체 기호 정보를 사용할 수 없는 경우 디버거는 함수 이름으로 "UnknownOrMissingSymbols"를 사용합니다.

  • 프라이빗 기호가 있는 경우 함수 이름과 올바른 매개 변수 목록을 가져옵니다.
  • 공용 기호가 있는 경우 함수 이름과 기본 매개 변수 집합(서명되지 않은 64비트 int 4개)을 가져옵니다.
  • 쿼리하는 모듈에 대한 기호 정보가 없는 경우 "UnknownOrMissingSymbols"가 이름으로 사용됩니다.

호출에 대한 TTD 쿼리

쿼리가 DLL 호출에 대해 아무것도 반환하지 않는 몇 가지 이유가 있을 수 있습니다.

  • 호출 구문이 적합하지 않습니다. x 명령 "x <call"을 사용하여 호출> 구문을 확인해 보세요. x에서 반환된 모듈 이름이 대문자인 경우 사용합니다.
  • DLL은 아직 로드되지 않았으며 나중에 추적에서 로드됩니다. 이 이동은 DLL이 로드된 후 특정 시점으로 이동하고 쿼리를 다시 실행합니다.
  • 쿼리 엔진이 추적할 수 없는 호출이 인라인 처리됩니다.
  • 쿼리 패턴은 너무 많은 함수를 반환하는 wild카드를 사용합니다. 일치하는 함수 수가 충분히 작도록 쿼리 패턴을 보다 구체적으로 만들려고 합니다.

참고 항목

디버거 개체와 함께 LINQ 사용

dx(디버거 개체 모델 식 표시)

시간 이동 디버깅 - 개요

시간 이동 디버깅 - JavaScript 자동화