Partager via


Introduction aux objets de débogage de voyage dans le temps

Logo de débogage avec voyage dans le temps mettant en vedette une horloge.

Cette section décrit comment utiliser le modèle de données pour interroger les traces de voyage dans le temps. Cela peut être un outil puissant pour répondre à des questions comme celles-ci sur le code capturé dans une trace de voyage dans le temps.

  • Quelles exceptions se trouvent dans la trace ?
  • À quel moment dans la trace un module de code spécifique a-t-il été chargé ?
  • Quand les threads ont-ils été créés/terminés dans la trace ?
  • Quels sont les threads les plus longs dans la trace ?

Il existe des extensions TTD qui ajoutent des données aux objets de modèle de données de session et de processus. Les objets de modèle de données TTD peuvent être accédés via la commande dx (Afficher l’expression du modèle d’objet de débogage), les fenêtres de modèle de WinDbg, JavaScript et C++. Les extensions TTD sont automatiquement chargées lors du débogage d’une trace de voyage dans le temps.

Objets de processus

Les principaux objets ajoutés aux objets de processus peuvent être trouvés dans l’espace de noms TTD de n’importe quel objet de processus. Par exemple : $@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.]

Pour obtenir des informations générales sur le travail avec les requêtes LINQ et les objets de débogage, veuillez consulter la rubrique Utilisation de LINQ avec les objets de débogage.

Propriétés

Object Description
Durée de vie Un objet de plage TTD décrivant la durée de vie de toute la trace.
Threads Contient une collection d’objets de thread TTD, un pour chaque thread tout au long de la durée de vie de la trace.
Événements Contient une collection d’objets d’événement TTD, un pour chaque événement dans la trace.

Méthodes

méthode Description
SetPosition() Prend un entier entre 0 et 100 ou une chaîne sous forme N:N en entrée et saute la trace à cet emplacement. Voir !tt pour plus d’informations.

Objets de session

Les principaux objets ajoutés aux objets de Session peuvent être trouvés dans l’espace de noms TTD de n’importe quel objet de Session. Par exemple, $@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

Remarque

Il existe des objets et des méthodes ajoutés par TTDAnalyze qui sont utilisés pour les fonctions internes de l’extension. Tous les espaces de noms ne sont pas documentés, et les espaces de noms actuels évolueront avec le temps.

Méthodes

méthode Description
Data.Heap() Une collection d’objets de tas qui ont été alloués pendant la trace. Notez qu’il s’agit d’une fonction qui effectue un calcul, elle prend donc un certain temps pour s’exécuter.
Calls() Renvoie une collection d’objets d’appels qui correspondent à la chaîne d’entrée. La chaîne d’entrée peut contenir des caractères génériques. Notez qu’il s’agit d’une fonction qui effectue un calcul, elle prend donc un certain temps pour s’exécuter.
Memory() Il s’agit d’une méthode qui prend beginAddress, endAddress et dataAccessMask comme paramètres et renvoie une collection d’objets mémoire. Notez qu’il s’agit d’une fonction qui effectue un calcul, elle prend donc un certain temps pour s’exécuter.

Tri de la sortie de la requête

Utilisez la méthode OrderBy() pour trier les lignes renvoyées par la requête par une ou plusieurs colonnes. Cet exemple trie par TimeStart par ordre croissant.

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  

Pour afficher une profondeur supplémentaire des objets du modèle de données, l’option de niveau de récursion -r2 est utilisée. Pour plus d’informations sur les options de la commande dx, voir dx (Afficher l’expression du modèle d’objet de débogage).

Cet exemple trie par TimeStart par ordre décroissant.

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    

Spécification des éléments dans une requête

Pour sélectionner un élément spécifique, divers qualificateurs peuvent être ajoutés à la requête. Par exemple, la requête affiche le premier appel qui contient « 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    

Filtrage dans une requête

Utilisez la méthode Select() pour choisir quelles colonnes voir et modifier le nom d’affichage de la colonne.

Cet exemple renvoie les lignes où ReturnValue n’est pas zéro et sélectionne pour afficher les colonnes TimeStart et ReturnValue avec des noms d’affichage personnalisés de Time et 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 })                
    [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]

Regroupement

Utilisez la méthode GroupBy() pour regrouper les données renvoyées par la requête afin de réaliser une analyse à l’aide de résultats structurés. Cet exemple groupe les emplacements temporels par numéro d’erreur.

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

Attribution du résultat d’une requête à une variable

Utilisez cette syntaxe pour attribuer le résultat d’une requête à une variable dx $@var = <expression>.

Cet exemple attribue les résultats d’une requête à myResults.

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

Utilisez la commande dx pour afficher la variable nouvellement créée en utilisant l’option de grille -g. Pour plus d’informations concernant les options de la commande dx, voir dx (Afficher l’expression du modèle d’objet de débogage).

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     =

Exemples

Recherche des exceptions

Cette requête LINQ utilise l’objet TTD.Event pour afficher toutes les exceptions dans la trace.

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

Recherche des appels API spécifiques

Utilisez l’objet TTD.Calls pour interroger des appels API spécifiques. Dans cet exemple, une erreur s’est produite lors de l’appel à user32!MessageBoxW, l’API Windows pour afficher une boîte de dialogue. Nous répertorions tous les appels à MessageBoxW, les trions par l’heure de début de la fonction, puis sélectionnons le dernier appel.

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

Recherche de l’événement de chargement d’un module spécifique

Tout d’abord, utilisez la commande lm (List Loaded Modules) pour afficher les modules chargés.

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)

Ensuite, utilisez la commande dx suivante pour voir à quel moment dans la trace un module spécifique a été chargé, comme 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 

Cette requête LINQ affiche l’événement de chargement d’un module particulier.

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

L’adresse de FFFFFFFFFFFFFFFE:0 indique la fin de la trace.

Recherche de toutes les vérifications d’erreur dans la trace

Utilisez cette commande pour trier toutes les vérifications d’erreur dans la trace par nombre d’erreurs.

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        =

Recherche de la position temporelle dans la trace lorsque des threads ont été créés

Utilisez cette commande dx pour afficher tous les événements dans la trace au format grille (-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... -                        =
==================================================================================================================================================================================================

Sélectionnez l’une des colonnes avec un + pour trier la sortie.

Utilisez cette requête LINQ pour afficher au format grille, la position temporelle dans la trace lorsque des threads ont été créés (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]    =
===========================================================================================================

Utilisez cette requête LINQ pour afficher au format grille, les positions temporelles dans la trace lorsque des threads ont été terminés (Type == "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]    =
===========================================================================================================

Tri de la sortie pour déterminer les threads les plus longs

Utilisez cette requête LINQ pour afficher au format grille, les threads approximativement les plus longs dans la trace.

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

Recherche des accès en lecture à une plage de mémoire

Utilisez l’objet TTD.Memory pour rechercher des accès en lecture à une plage de mémoire.

Le bloc d’environnement de thread (TEB) est une structure qui contient toutes les informations concernant l’état d’un thread, y compris le résultat retourné par GetLastError(). Vous pouvez interroger cette structure de données en exécutant dx $@teb pour le thread actuel. L’un des membres de TEB est une variable LastErrorValue, de 4 octets de taille. Nous pouvons faire référence au membre LastErrorValue dans le TEB en utilisant cette syntaxe. dx &$@teb->LastErrorValue.

L’exemple de requête montre comment trouver chaque opération de lecture effectuée dans cette plage en mémoire, sélectionner toutes les lectures qui se produisent avant qu’une boîte de dialogue soit créée, puis trier le résultat pour trouver la dernière opération de lecture.

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]     

Si dans notre trace un événement "dialogue" a eu lieu, nous pouvons exécuter une requête pour trouver chaque opération de lecture effectuée dans cette plage en mémoire, sélectionner toutes les lectures qui se produisent avant la création de la boîte de dialogue, puis trier le résultat pour trouver la dernière opération de lecture. Puis voyagez dans le temps jusqu’à ce point dans le temps en appelant SeekTo() sur la position temporelle résultante.


: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

Labo de requêtes GitHub TTD

Pour un tutoriel sur la façon de déboguer du code C++ en utilisant un enregistrement de débogage de voyage dans le temps en utilisant des requêtes pour trouver des informations sur l’exécution du code problématique en question, voir https://github.com/Microsoft/WinDbg-Samples/blob/master/TTDQueries/tutorial-instructions.md.

Tout le code utilisé dans le laboratoire est disponible ici : https://github.com/Microsoft/WinDbg-Samples/tree/master/TTDQueries/app-sample.

Dépannage des requêtes TTD

« "UnknownOrMissingSymbols » comme noms de fonction

L’extension du modèle de données a besoin d’informations de symboles complètes pour fournir des noms de fonction, des valeurs de paramètres, etc. Lorsque les informations de symboles complètes ne sont pas disponibles, le débogueur utilise « UnknownOrMissingSymbols » comme nom de fonction.

  • Si vous avez des symboles privés, vous obtiendrez le nom de la fonction et la liste correcte des paramètres.
  • Si vous avez des symboles publics, vous obtiendrez le nom de la fonction et un ensemble de paramètres par défaut - quatre entiers non signés de 64 bits.
  • Si vous n’avez aucune information de symbole pour le module que vous interrogez, alors « UnknownOrMissingSymbols » est utilisé comme nom.

Requêtes TTD pour les appels

Il peut y avoir plusieurs raisons pour lesquelles une requête ne renvoie rien pour des appels à une DLL.

  • La syntaxe de l’appel n’est pas tout à fait correcte. Essayez de vérifier la syntaxe de l’appel en utilisant la commande x : "x <call>". Si le nom du module retourné par x est en majuscules, utilisez-le.
  • La DLL n’est pas encore chargée et est chargée plus tard dans la trace. Pour contourner cela, voyagez à un moment où la DLL est chargée et refaites la requête.
  • L’appel est en ligne, ce que le moteur de requête est incapable de suivre.
  • Le motif de requête utilise des caractères génériques qui renvoient trop de fonctions. Essayez de rendre le motif de requête plus spécifique pour que le nombre de fonctions correspondantes soit suffisamment petit.

Voir aussi

Utilisation de LINQ avec les objets du débogueur

dx (Afficher l’expression du modèle d’objet de débogage)

Débogage de voyage dans le temps - Vue d’ensemble

Débogage de voyage dans le temps - Automatisation JavaScript