Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Débogage temporel (TTD) permet aux utilisateurs d’enregistrer des traces, qui sont des enregistrements de l’exécution d’un programme. Les chronologies sont une représentation visuelle des événements qui se produisent pendant l’exécution. Ces événements peuvent être des emplacements de points d’arrêt, de lectures/écritures de mémoire, d’appels de fonction et de retours et d’exceptions.
Utilisez la fenêtre Chronologies pour afficher les événements importants, comprendre leur position relative et accéder facilement à leur emplacement dans votre fichier de trace TTD. Utilisez plusieurs chronologies pour explorer visuellement les événements dans la trace de voyage de temps et découvrir la corrélation des événements.
La fenêtre Chronologie s’affiche lorsque vous ouvrez un fichier de trace TTD. Il affiche les événements clés sans avoir à créer manuellement des requêtes de modèle de données. En même temps, tous les objets de voyage de temps sont disponibles pour permettre des requêtes de données plus complexes.
Pour plus d’informations sur la création et l’utilisation des fichiers de trace de voyage temporel, consultez Time Travel Debugging : Vue d'ensemble.
Types de chronologies
La fenêtre Chronologies affiche les événements dans les chronologies suivantes :
- Exceptions : vous pouvez filtrer sur un code d’exception spécifique.
- Points d’arrêt : vous pouvez voir quand les points d’arrêt sont atteints sur une chronologie.
- Accès à la mémoire : vous pouvez lire, écrire et exécuter entre deux adresses mémoire.
-
Appels de fonction : vous pouvez effectuer une recherche sous la forme .
module!function
Pointez sur chaque événement pour afficher plus d’informations dans une info-bulle. La sélection d’un événement exécute la requête pour l’événement et affiche plus d’informations. Le double-clic d’un événement amène à cet emplacement dans le fichier de traçage TTD.
Exceptions
Lorsque vous chargez un fichier de trace et que la chronologie est active, elle affiche automatiquement toutes les exceptions dans l’enregistrement.
Lorsque vous pointez sur un point d’arrêt, des informations telles que le type d’exception et le code d’exception s’affichent.
Vous pouvez filtrer davantage sur un code d’exception spécifique à l’aide du champ de code d’exception facultatif.
Vous pouvez également ajouter une nouvelle chronologie pour un type d’exception spécifique.
Points d’arrêt
Après avoir ajouté un point d’arrêt, les positions de la chronologie vous indiquent quand ce point d’arrêt est atteint. Par exemple, vous pouvez utiliser la commande bp Set Breakpoint. Lorsque vous pointez sur un point d’arrêt, l’adresse et le pointeur d’instruction associés au point d’arrêt s’affichent.
Lorsque le point d’arrêt est effacé, la chronologie du point d’arrêt associée est automatiquement supprimée.
Appels de fonction
Vous pouvez voir les positions des appels de fonction sur la chronologie. Pour effectuer cette étape, fournissez la recherche sous la forme .module!function par exemple TimelineTestCode!multiplyTwo. Vous pouvez également spécifier des caractères génériques, par exemple TimelineTestCode!m*.
Lorsque vous pointez sur un appel de fonction, le nom de la fonction, les paramètres d’entrée, leurs valeurs et la valeur de retour s’affichent. Cet exemple montre la mémoire tampon et la taille, car elles sont les paramètres pour DisplayGreeting!GetCppConGreeting.
Accès à la mémoire
Utilisez la chronologie des accès à la mémoire pour voir quand une plage spécifique de mémoire a été lue ou écrite, ou où l’exécution du code a eu lieu. Les adresses de démarrage et d’arrêt sont utilisées pour définir une plage entre deux adresses mémoire.
Lorsque vous pointez sur un élément d’accès à la mémoire, la valeur et le pointeur d’instruction s’affichent.
Utiliser des chronologies
Une ligne grise verticale suit le curseur lorsque vous pointez sur la chronologie. La ligne bleue verticale indique la position actuelle dans la trace.
Sélectionnez les icônes de loupe pour effectuer un zoom avant et arrière sur la chronologie.
Dans la zone de contrôle de chronologie supérieure, utilisez le rectangle pour faire défiler l’affichage de la chronologie. Faites glisser les délimiteurs externes du rectangle pour redimensionner l’affichage chronologie actuel.
Mouvements de la souris
Pour effectuer un zoom avant et arrière, sélectionnez Ctrl et utilisez la roulette de défilement.
Pour faire un panoramique de côté à côté, maintenez la touche Maj et utilisez la roulette de défilement.
Techniques de débogage de chronogramme
Pour illustrer les techniques de chronologie de débogage, le guide de débogage Time Travel est ici réutilisé. Cette démonstration suppose que vous avez terminé les deux premières étapes pour générer l’exemple de code et créer l’enregistrement TTD à l’aide des deux premières étapes décrites ici.
- Section 1 : Générer l’exemple de code
- Section 2 : Enregistrer une trace de l’exemple DisplayGreeting
Dans ce scénario, la première étape consiste à rechercher l’exception dans la trace de voyage dans le temps. Double-cliquez sur la seule exception que vous voyez dans la chronologie.
Dans la fenêtre Commande , vous pouvez voir que la commande suivante a été émise lorsque vous avez sélectionné l’exception.
(2dcc.6600): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: CC:0
@$curprocess.TTD.Events.Where(t => t.Type == "Exception")[0x0].Position.SeekTo()
Sélectionnez Afficher>les registres pour afficher les registres à ce stade dans la chronologie pour commencer votre investigation.
Dans la sortie de commande, la pile (esp) et le pointeur de base (ebp) pointent vers différentes adresses. Cette différence peut indiquer une altération de la pile. Il est possible qu'une fonction ait terminé son exécution puis ait endommagé la pile. Pour valider ce problème, retournez à un moment avant que l'état du processeur soit corrompu et vérifiez si vous pouvez déterminer quand l'altération de la pile s'est produite.
À mesure que vous effectuez ce processus, examinez les valeurs des variables locales et de la pile :
- Sélectionnez Afficher>les variables locales pour afficher les valeurs locales.
- Sélectionnez Vue>Pile pour voir la pile d’exécution de code.
Au moment de l’échec, dans la trace, il est courant d’arriver quelques étapes après la véritable cause dans le code de traitement des erreurs. Avec le voyage dans le temps, vous pouvez revenir en arrière une instruction à la fois pour localiser la véritable cause racine.
Dans le ruban Accueil , utilisez la commande Step Into Back pour revenir à trois instructions. À mesure que vous effectuez ce processus, continuez à examiner les fenêtres Stack, Locals et Registers.
La fenêtre commande affiche la position de voyage dans le temps et les registres à mesure que vous revenez en arrière de trois instructions.
0:000> t-
Time Travel Position: CB:41
eax=00000000 ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=00540020 esp=003cf7d0 ebp=00520055 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
00540020 ?? ???
0:000> t-
Time Travel Position: CB:40
eax=00000000 ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=00061767 esp=003cf7cc ebp=00520055 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
DisplayGreeting!main+0x57:
00061767 c3 ret
0:000> t-
Time Travel Position: CB:3A
eax=0000004c ebx=00564000 ecx=c0d21d62 edx=7a1e4a6c esi=00061299 edi=00061299
eip=0006175f esp=003cf718 ebp=003cf7c8 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
DisplayGreeting!main+0x4f:
0006175f 33c0 xor eax,eax
À ce stade de la trace, votre pile et votre pointeur de base ont des valeurs qui sont plus logiques. Il semble que vous vous rapprochez du point dans le code où l’altération s’est produite.
esp=003cf718 ebp=003cf7c8
La fenêtre Locals contient des valeurs de votre application cible. La fenêtre Code source met en surbrillance la ligne de code prête à être exécutée dans votre code source à ce stade de la trace.
Pour examiner plus en détail, ouvrez une fenêtre Mémoire pour afficher le contenu près de l’adresse mémoire du pointeur de pile (esp). Dans cet exemple, il a la valeur 003cf7c8. Sélectionnez Mémoire>Texte>ASCII pour afficher le texte ASCII stocké à cette adresse.
Chronologie de l’accès à la mémoire
Une fois qu’un emplacement de mémoire intéressant est identifié, utilisez cette valeur pour ajouter une chronologie d’accès à la mémoire. Sélectionnez + Ajouter une chronologie et renseignez l’adresse de départ. Examinez 4 octets de sorte que lorsque vous les ajoutez à la valeur de d'adresse de début003cf7c8, vous avez une valeur de d'adresse de fin003cf7cb. La valeur par défaut consiste à examiner toutes les écritures de mémoire, mais vous pouvez également examiner uniquement les écritures ou l’exécution du code à cette adresse.
Vous pouvez maintenant parcourir la chronologie en sens inverse pour examiner à quel moment dans cette trace de voyage dans le temps cet emplacement mémoire a été modifié, pour voir ce que cela révèle. Lorsque vous sélectionnez cette position dans la chronologie, vous pouvez voir que les valeurs locales sont différentes pour la chaîne copiée. La valeur de destination semble incomplète, comme si la longueur de votre chaîne n’est pas correcte.
Chronologie des points d’arrêt
L’utilisation de points d’arrêt est une approche courante pour suspendre l’exécution du code à un événement d’intérêt. Avec TTD, vous pouvez définir un point d’arrêt et revenir en arrière jusqu’à ce que ce point d’arrêt soit atteint après l’enregistrement de la trace. La possibilité d’examiner l’état du processus une fois qu’un problème se produit, afin de déterminer le meilleur emplacement pour un point d’arrêt, active davantage de flux de travail de débogage uniques au TTD.
Pour explorer une autre technique de débogage de chronologie, sélectionnez l’exception dans la chronologie et revenez à nouveau trois étapes en arrière à l’aide de la commande Retour en arrière sur le ruban Accueil.
Dans ce petit exemple, il est facile d’examiner le code. Si vous avez des centaines de lignes de code et des dizaines de sous-routines, utilisez les techniques décrites ici pour réduire le temps nécessaire pour localiser le problème.
Comme mentionné précédemment, le pointeur de base (esp) pointe vers le texte de votre message au lieu de pointer vers une instruction.
Utilisez la commande ba pour définir un point d’arrêt sur l’accès à la mémoire. Vous définissez un point d’arrêt d’écriture w - pour voir quand cette zone de mémoire est écrite.
0:000> ba w4 003cf7c8
Bien que vous utilisiez un simple point d'arrêt d'accès mémoire, vous pouvez créer des points d'arrêt sous forme d'instructions conditionnelles plus complexes. Pour plus d’informations, consultez bp, bu, bm (Définir le point d’arrêt).
Dans le menu Accueil , sélectionnez Revenir en arrière jusqu’à ce que le point d’arrêt soit atteint.
À ce stade, vous pouvez examiner la pile des programmes pour voir quel code est actif.
Étant donné qu'il est peu probable que la fonction Microsoft fournie par wscpy_s() ait un bogue de code de ce type, recherchez plus loin dans la stack. La pile montre qu'Greeting!main appelle Greeting!GetCppConGreeting. Dans votre petit exemple de code, vous pouvez ouvrir le code à ce stade et trouver l’erreur facilement. Toutefois, pour illustrer les techniques que vous pouvez utiliser avec un programme plus volumineux et plus complexe, vous ajoutez une chronologie des appels de fonction.
Chronologie des appels de fonction
Sélectionnez + Ajouter une chronologie et saisissez DisplayGreeting!GetCppConGreeting dans le champ chaîne de recherche de fonction.
Les cases d’emplacement de début et d’emplacement de fin indiquent le début et la fin d’un appel de fonction dans la trace.
Vous pouvez utiliser le dx commande pour afficher l’objet d’appel de fonction et voir les champs TimeStart et TimeEnd associés, qui correspondent à l’emplacement de début et de fin de l’appel de fonction.
dx @$cursession.TTD.Calls("DisplayGreeting!GetCppConGreeting")[0x0]
EventType : 0x0
ThreadId : 0x6600
UniqueThreadId : 0x2
TimeStart : 6D:BD [Time Travel]
SystemTimeStart : Thursday, October 31, 2019 23:36:05
TimeEnd : 6D:742 [Time Travel]
SystemTimeEnd : Thursday, October 31, 2019 23:36:05
Function : DisplayGreeting!GetCppConGreeting
FunctionAddress : 0x615a0
ReturnAddress : 0x61746
Parameters
Vous devez sélectionner l’une des cases Emplacement de début ou Emplacement de fin , ou les deux cases à cocher Emplacement de début et Emplacement de fin .
Votre code n’est pas récursif ou réinitif, il est donc facile de localiser sur la chronologie lorsque la GetCppConGreeting méthode est appelée. L’appel à GetCppConGreeting se produit également en même temps que votre point d’arrêt et l’événement d’accès à la mémoire que vous avez défini. Il semble donc que vous avez ciblé une zone spécifique du code pour examiner attentivement la cause première de l’incident de l’application.
Explorer l’exécution du code en affichant plusieurs chronologies
Bien que notre exemple de code soit petit, la technique d’utilisation de plusieurs chronologies permet l’exploration visuelle d’une trace de voyage de temps. Vous pouvez consulter le fichier de trace pour poser des questions, telles que « Quand une zone de mémoire est accessible avant qu’un point d’arrêt soit atteint ? ».
La possibilité d’afficher davantage de corrélations et de trouver des éléments inattendus différencie l’outil de chronologie de l’interaction avec la trace de trajet du temps à l’aide de commandes de ligne de commande.
Marqueurs de chronologie
Marquez les positions temporelles importantes dans WinDbg au lieu de copier et coller manuellement la position dans Notepad. Les signets facilitent l’affichage en un clin d’œil des positions différentes dans la trace par rapport à d’autres événements et pour les annoter.
Vous pouvez fournir un nom descriptif pour les marque-pages.
Sélectionnez Afficher> lachronologie pour ouvrir la fenêtre Chronologie afin de pouvoir accéder à la chronologie des signets. Lorsque vous pointez sur un signet, le nom du signet s’affiche.
Cliquez avec le bouton droit sur le signet pour atteindre la position du signet, renommez le signet ou supprimez-le.
Remarque
La fonctionnalité de signet n’est pas disponible dans la version 1.2402.24001.0 de WinDbg.