Úvod k objektům ladění časového cestování

logo pro ladění časových cest s hodinami.

Tato část popisuje, jak pomocí datového modelu dotazovat časové stopy cestování. Může to být užitečný nástroj pro zodpovězení otázek, jako jsou ty, které se týkají kódu zachyceného v trasování časového cestování.

  • Jaké výjimky jsou v záznamu trasování?
  • V jakém okamžiku se v trasování nahrál konkrétní modul kódu?
  • Kdy bylo vlákno vytvořeno nebo ukončeno v záznamu?
  • Jaké jsou nejdéle běžící vlákna v trasování?

Existují rozšíření TTD, která přidávají data do relace a procesu objekty datového modelu. Objekty datového modelu TTD jsou přístupné prostřednictvím příkazu dx (Display Debugger Object Model Expression), windows modelu WinDbg, JavaScript a C++. Rozšíření TTD se automaticky načítají při ladění časové stopy.

Procesní objekty

Primární objekty přidané do Process objektů lze najít v oboru názvů TTD v rámci jakéhokoli objektu Process. Například @$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

Obecné informace o práci s dotazy LINQ a objekty ladicího programu naleznete v tématu Použití LINQ S objekty ladicího programu.

Vlastnosti

Objekt Popis
Životnost Objekt oblasti TTD popisující životnost celého trasování.
Vlákna Obsahuje kolekci objektů vlákna TTD, jeden pro každé vlákno po celou dobu životnosti trasování.
Události Obsahuje kolekci objektů událostí TTD, jeden pro každou událost ve sledu.

Metody

Metoda Popis
SetPosition() Vezme celé číslo v rozsahu 0 až 100 nebo řetězec ve formátu N:N jako vstup a přeskočí trasování do daného umístění. Další informace najdete na !tt.

Objekty relace

Primární objekty přidané do objektů Session lze najít v oboru názvů TTD od jakéhokoli objektu Session. Například @$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)

Poznámka:

Existují některé objekty a metody přidané TTDAnalyze, které se používají pro interní funkce rozšíření. Ne všechny obory názvů jsou zdokumentované a aktuální obory názvů se budou v průběhu času vyvíjet.

Metody

Metoda Popis
Data.Heap() Kolekce objektů haldy, které byly přiděleny během trasování. Všimněte si, že se jedná o funkci, která provádí výpočty, takže spuštění nějakou dobu trvá.
Calls() Vrátí kolekci objektů volání, které odpovídají vstupnímu řetězci. Vstupní řetězec může obsahovat zástupné znaky. Všimněte si, že se jedná o funkci, která provádí výpočty, takže spuštění nějakou dobu trvá.
Memory() Jedná se o metodu, která přebírá parametry beginAddress, endAddress a dataAccessMask a vrací kolekci paměťových objektů. Všimněte si, že se jedná o funkci, která provádí výpočty, takže spuštění nějakou dobu trvá.

Řazení výstupu dotazu

Pomocí metody OrderBy() seřaďte řádky vrácené z dotazu podle jednoho nebo více sloupců. Tento příklad seřadí podle TimeStart ve vzestupném pořadí.

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
...        

K zobrazení další hloubky objektů datového modelu se používá možnost -r2 rekurzní úroveň. Další informace o možnostech příkazu dx naleznete v tématu dx (Display Debugger Object Model Expression).

Tento příklad seřadí podle TimeStartu v sestupném pořadí.

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    

Určení prvků v dotazu

Pokud chcete vybrat konkrétní prvek, můžete k dotazu připojit řadu kvalifikátorů. Dotaz například zobrazí první volání, které obsahuje "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

Filtrování v dotazu

Pomocí metody Select() vyberte sloupce, které chcete zobrazit a upravit zobrazovaný název sloupce.

Tento příklad vrátí řádky, kde ReturnValue není nula a vybere zobrazení sloupců TimeStart a ReturnValue s vlastními zobrazovanými názvy Time a Error.

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]

Seskupení

Pomocí metody GroupBy() seskupte data vrácená dotazem k provedení analýzy pomocí strukturovaných výsledků. Tento příklad seskupí časová umístění podle čísla chyby.

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]           
...

Přiřazení výsledku dotazu k proměnné

Tato syntaxe slouží k přiřazení výsledku dotazu k proměnné dx @$var = <expression>

Tento příklad přiřadí výsledky dotazu myResults.

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

Pomocí příkazu dx zobrazte nově vytvořenou proměnnou pomocí možnosti -g mřížky. Další informace o možnostech příkazu dx naleznete v tématu dx (Display Debugger Object Model Expression).

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     =

Příklady

Dotazování na výjimky

Tento dotaz LINQ používá TTD. Objekt události k zobrazení všech výjimek v trasování.

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

Dotazování na konkrétní volání rozhraní API

Použijte objekt TTD.Calls pro dotazování na konkrétní volání API. V tomto příkladu došlo k chybě při volání user32! MessageBoxW, rozhraní API systému Windows pro zobrazení pole zprávy. Zobrazíme seznam všech volání MessageBoxW , pořadí podle počátečního času funkce a pak vyberte poslední volání.

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

Dotazování na událost načítání konkrétního modulu

Nejprve pomocí příkazu lm (List Loaded Modules) zobrazte načtené moduly.

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)

Pak pomocí následujícího příkazu dx zjistěte, v jaké pozici trasování byl načten konkrétní modul, například 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 

Tento dotaz LINQ zobrazí události načítání konkrétního modulu.

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

Adresa FFFFFFFFFFFFFFFE:0 označuje konec trasování.

Dotazování na všechny kontroly chyb v trasování

Použijte tento příkaz k řazení kontrol chyb při trasování podle počtu chyb.

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        =

Dotazování na časový okamžik ve stopě, kdy byla vlákna vytvořena

Tento příkaz dx slouží k zobrazení všech událostí v trasování ve formátu mřížky (-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... -                        =
==================================================================================================================================================================================================

Výběrem libovolného sloupce se znaménkem + seřadíte výstup.

Použijte tento dotaz LINQ k zobrazení v mřížkovém formátu, časové pozice v trasovacím záznamu, kdy byly vlákna vytvořena (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]    =
===========================================================================================================

Pomocí tohoto dotazu LINQ můžete zobrazit ve formátu mřížky časové pozice v trasování, kdy byla vlákna ukončena (Typ == "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]    =
===========================================================================================================

Řazení výstupu pro určení nejdéle běžících vláken

Tento dotaz LINQ slouží k zobrazení ve formátu mřížky, přibližných nejdéle běžících vláken v trasování.

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            =
=========================================================

Dotazování na přístup pro čtení k rozsahu paměti

Použijte TTD. Objekt paměti dotaz na dotazování na přístup pro čtení k oblasti paměti.

Blok prostředí vlákna (TEB) je struktura, která obsahuje všechny informace týkající se stavu vlákna, včetně výsledku vráceného funkcí GetLastError(). Tuto datovou strukturu můžete dotazovat spuštěním dx @$teb pro aktuální vlákno. Jedním z členů TEB je proměnná LastErrorValue, velikost 4 bajtů. Pomocí této syntaxe můžeme odkazovat na člena LastErrorValue v TEB. dx &@$teb->LastErrorValue.

Ukázkový dotaz ukazuje, jak najít každou operaci čtení provedenou v této oblasti v paměti, vybrat všechna čtení, ke kterým došlo před vytvořením dialogového okna, a potom seřadit výsledek a najít poslední operaci čtení.

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]     

Pokud v našem trasování došlo k události dialogového okna, můžeme spustit dotaz, abychom našli všechny operace čtení provedené v této oblasti v paměti, vyberte všechna čtení, ke kterým dojde před vytvořením dialogového okna, a pak seřaďte výsledek a vyhledejte poslední operaci čtení. Poté, co se přesunete v čase do tohoto bodu, zavolejte funkci SeekTo() na výsledné časové pozici.


: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

Kurz, jak ladit C++ kód pomocí nahrávky ladění Time Travel Debugging a využití dotazů pro nalezení informací o provádění problematického kódu, naleznete v tématu WinDbg-Samples - Time Travel Debugging a dotazy.

Veškerý kód použitý v testovacím prostředí je k dispozici zde: https://github.com/Microsoft/WinDbg-Samples/tree/master/TTDQueries/app-sample.

Řešení potíží s dotazy TTD

"UnknownOrMissingSymbols" jako názvy funkcí

Rozšíření datového modelu potřebuje úplné informace o symbolech, aby bylo možné zadat názvy funkcí, hodnoty parametrů atd. Pokud nejsou k dispozici úplné informace o symbolech, ladicí program používá jako název funkce "UnknownOrMissingSymbols".

  • Pokud máte soukromé symboly, získáte název funkce a správný seznam parametrů.
  • Pokud máte veřejné symboly, získáte název funkce a výchozí sadu parametrů – čtyři 64bitové inty bez znaménka.
  • Pokud nemáte žádné informace o symbolech pro modul, který dotazujete, použije se jako název "UnknownOrMissingSymbols".

Dotazy TTD pro volání

Může existovat několik důvodů, proč dotaz nic nevrátí při volání na DLL.

  • Syntaxe volání není úplně správná. Zkuste ověřit syntaxi volání pomocí x (Prozkoumat symboly)x <call>. Pokud modul, který vrací x, má název velkými písmeny, použijte ho.
  • Knihovna DLL ještě není načtena a je načtena později při trasování. Chcete-li tento problém obejít, přesuňte se k určitému bodu v čase po načtení knihovny DLL a dotaz znovu zopakujte.
  • Volání je vloženo tak, že jej dotazovací stroj nemůže sledovat.
  • Vzor dotazu používá zástupné řady, které vrací příliš mnoho funkcí. Pokuste se, aby byl vzor dotazu konkrétnější, aby byl počet odpovídajících funkcí dostatečně malý.

Viz také

použití LINQ s objekty ladicího programu

dx (zobrazení výrazu objektového modelu ladicího programu)

ladění časových cest – přehled

Ladění časového cestování - automatizace JavaScriptu