Utilisation de l’extension !analyze
La première étape du débogage d’un ordinateur cible ou d’une application cible bloqué consiste à utiliser la commande !analyze extension. Cette extension effectue une grande quantité d’analyse automatisée. Les résultats de cette analyse sont affichés dans la fenêtre Commande du débogueur.
Vous devez utiliser l’option -v pour un affichage complet des données. Pour plus d’informations sur les autres options, consultez la page de référence !analyser .
Un exemple de mode utilisateur !analyze -v
Dans cet exemple, le débogueur est attaché à une application en mode utilisateur qui a rencontré une exception.
0:000> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
Debugger SolutionDb Connection::Open failed 80004005
Si vous êtes connecté à Internet, le débogueur tente d’accéder à une base de données de solutions d’incident gérées par Microsoft. Dans ce cas, un message d’erreur s’affiche, indiquant que votre ordinateur n’a pas pu accéder à Internet ou que le site web ne fonctionnait pas.
FAULTING_IP:
ntdll!PropertyLengthAsVariant+73
77f97704 cc int 3
Le champ FAULTING_IP affiche le pointeur d’instruction au moment de l’erreur.
EXCEPTION_RECORD: ffffffff -- (.exr ffffffffffffffff)
ExceptionAddress: 77f97704 (ntdll!PropertyLengthAsVariant+0x00000073)
ExceptionCode: 80000003 (Break instruction exception)
ExceptionFlags: 00000000
NumberParameters: 3
Parameter[0]: 00000000
Parameter[1]: 00010101
Parameter[2]: ffffffff
Le champ EXCEPTION_RECORD affiche l’enregistrement d’exception pour ce blocage. Ces informations peuvent également être affichées à l’aide de la commande .exr (Display Exception Record).
BUGCHECK_STR: 80000003
Le champ BUGCHECK_STR affiche le code d’exception. Le nom est un malnomeur : le terme vérification de bogue signifie en fait un plantage en mode noyau. Dans le débogage en mode utilisateur, le code d’exception s’affiche , dans ce cas, 0x80000003.
DEFAULT_BUCKET_ID: APPLICATION_FAULT
Le champ DEFAULT_BUCKET_ID affiche la catégorie générale des échecs auxquels cette défaillance appartient.
PROCESS_NAME: MyApp.exe
Le champ PROCESS_NAME spécifie le nom du processus qui a déclenché l’exception.
LAST_CONTROL_TRANSFER: from 01050963 to 77f97704
Le champ LAST_CONTROL_TRANSFER affiche le dernier appel sur la pile. Dans ce cas, le code à l’adresse 0x01050963 appelé une fonction à 0x77F97704. Vous pouvez utiliser ces adresses avec la commande ln (Lister les symboles les plus proches) pour déterminer les modules et les fonctions dans lesquelles résident ces adresses.
STACK_TEXT:
0006b9dc 01050963 00000000 0006ba04 000603fd ntdll!PropertyLengthAsVariant+0x73
0006b9f0 010509af 00000002 0006ba04 77e1a449 MyApp!FatalErrorBox+0x55 [D:\source_files\MyApp\util.c @ 541]
0006da04 01029f4e 01069850 0000034f 01069828 MyApp!ShowAssert+0x47 [D:\source_files\MyApp\util.c @ 579]
0006db6c 010590c3 000e01ea 0006fee4 0006feec MyApp!SelectColor+0x103 [D:\source_files\MyApp\colors.c @ 849]
0006fe04 77e11d0a 000e01ea 00000111 0000413c MyApp!MainWndProc+0x1322 [D:\source_files\MyApp\MyApp.c @ 1031]
0006fe24 77e11bc8 01057da1 000e01ea 00000111 USER32!UserCallWinProc+0x18
0006feb0 77e172b4 0006fee4 00000001 010518bf USER32!DispatchMessageWorker+0x2d0
0006febc 010518bf 0006fee4 00000000 01057c5d USER32!DispatchMessageA+0xb
0006fec8 01057c5d 0006fee4 77f82b95 77f83920 MyApp!ProcessQCQPMessage+0x3b [D:\source_files\MyApp\util.c @ 2212]
0006ff70 01062cbf 00000001 00683ed8 00682b88 MyApp!main+0x1e6 [D:\source_files\MyApp\MyApp.c @ 263]
0006ffc0 77e9ca90 77f82b95 77f83920 7ffdf000 MyApp!mainCRTStartup+0xff [D:\source_files\MyApp\crtexe.c @ 338]
0006fff0 00000000 01062bc0 00000000 000000c8 KERNEL32!BaseProcessStart+0x3d
Le champ STACK_TEXT affiche une trace de pile du composant défaillant.
FOLLOWUP_IP:
MyApp!FatalErrorBox+55
01050963 5e pop esi
FOLLOWUP_NAME: dbg
SYMBOL_NAME: MyApp!FatalErrorBox+55
MODULE_NAME: MyApp
IMAGE_NAME: MyApp.exe
DEBUG_FLR_IMAGE_TIMESTAMP: 383490a9
Lorsque !analyze détermine l’instruction qui a probablement provoqué l’erreur, elle l’affiche dans le champ FOLLOWUP_IP. Les champs SYMBOL_NAME, MODULE_NAME, IMAGE_NAME et DEBUG_FLR_IMAGE_TIMESTAMP affichent le symbole, le module, le nom de l’image et l’horodatage d’image correspondant à cette instruction.
STACK_COMMAND: .ecxr ; kb
Le champ STACK_COMMAND affiche la commande utilisée pour obtenir le STACK_TEXT. Vous pouvez utiliser cette commande pour répéter cet affichage de trace de pile ou le modifier pour obtenir des informations de pile associées.
BUCKET_ID: 80000003_MyApp!FatalErrorBox+55
Le champ BUCKET_ID affiche la catégorie spécifique d’échecs auxquels appartient l’échec actuel. Cette catégorie aide le débogueur à déterminer les autres informations à afficher dans la sortie d’analyse.
Followup: dbg
---------
Pour plus d’informations sur les champs FOLLOWUP_NAME et suivi, consultez Le champ suivi et le fichier triage.ini.
Il existe une variété d’autres champs qui peuvent apparaître :
Si le contrôle a été transféré vers une adresse non valide, le champ FAULTING_IP contiendra cette adresse non valide. Au lieu du champ FOLLOWUP_IP, le champ FAILED_INSTRUCTION_ADDRESS affiche le code désassemblé de cette adresse, bien que ce désassemblage soit probablement sans signification. Dans ce cas, les champs SYMBOL_NAME, MODULE_NAME, IMAGE_NAME et DEBUG_FLR_IMAGE_TIMESTAMP font référence à l’appelant de cette instruction.
Si le processeur se déclenche mal, vous pouvez voir les champs SINGLE_BIT_ERROR, TWO_BIT_ERROR ou POSSIBLE_INVALID_CONTROL_TRANSFER.
Si l’altération de la mémoire semble avoir eu lieu, le champ CHKIMG_EXTENSION spécifie la commande d’extension !chkimg qui doit être utilisée pour examiner.
Un exemple de noyau !analyze -v
Dans cet exemple, le débogueur est attaché à un ordinateur qui vient de se bloquer.
kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pagable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.
Le premier élément de l’affichage affiche le code de vérification des bogues et des informations sur ce type de vérification de bogue. Certains du texte affiché peuvent ne pas s’appliquer à cette instance spécifique. Pour plus d’informations sur chaque vérification de bogue, consultez la section Informations de référence sur le code de vérification des bogues.
Arguments:
Arg1: 00000004, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: f832035c, address which referenced memory
Les paramètres de vérification des bogues s’affichent ensuite. Chacune d’elles est suivie d’une description. Par exemple, le troisième paramètre est 1 et le commentaire suivant explique que cela indique qu’une opération d’écriture a échoué.
## Debugging Details:
WRITE_ADDRESS: 00000004 Nonpaged pool
CURRENT_IRQL: 2
Les champs suivants varient en fonction de la nature de l’incident. Dans ce cas, nous voyons WRITE_ADDRESS et CURRENT_IRQL champs. Il s’agit simplement de déclarer les informations affichées dans les paramètres de vérification des bogues. En comparant l’instruction « Pool non paginé » au texte de vérification de bogue qui lit « une tentative d’accès à une adresse pagable (ou complètement non valide), nous pouvons voir que l’adresse n’était pas valide. L’adresse non valide dans ce cas était 0x00000004.
FAULTING_IP:
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204 mov [edx+0x4],eax
Le champ FAULTING_IP affiche le pointeur d’instruction au moment de l’erreur.
DEFAULT_BUCKET_ID: DRIVER_FAULT
Le champ DEFAULT_BUCKET_ID affiche la catégorie générale des échecs auxquels cette défaillance appartient.
BUGCHECK_STR: 0xD1
Le champ BUGCHECK_STR affiche le code de vérification des bogues, que nous avons déjà vu. Dans certains cas, des informations de tri supplémentaires sont ajoutées.
TRAP_FRAME: f8950dfc -- (.trap fffffffff8950dfc)
.trap fffffffff8950dfc
ErrCode = 00000002
eax=81cc86dc ebx=81cc80e0 ecx=81e55688 edx=00000000 esi=81cc8028 edi=8052cf3c
eip=f832035c esp=f8950e70 ebp=f8950e90 iopl=0 nv up ei pl nz ac po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010216
USBPORT!USBPORT_BadRequestFlush+7c:
f832035c 894204 mov [edx+0x4],eax ds:0023:00000004=????????
.trap
Resetting default context
Le champ TRAP_FRAME affiche le cadre de piège pour ce blocage. Ces informations peuvent également être affichées à l’aide de la commande .trap (Display Trap Frame).
LAST_CONTROL_TRANSFER: from f83206e0 to f832035c
Le champ LAST_CONTROL_TRANSFER affiche le dernier appel sur la pile. Dans ce cas, le code à l’adresse 0xF83206E0 appelé une fonction à 0xF832035C. Vous pouvez utiliser la commande ln (List Nearest Symbols) pour déterminer le module et la fonction dans lesquelles résident ces adresses.
STACK_TEXT:
f8950e90 f83206e0 024c7262 00000000 f8950edc USBPORT!USBPORT_BadRequestFlush+0x7c
f8950eb0 804f5561 81cc8644 81cc8028 6d9a2f30 USBPORT!USBPORT_DM_TimerDpc+0x10c
f8950fb4 804f5644 6e4be98e 00000000 ffdff000 nt!KiTimerListExpire+0xf3
f8950fe0 8052c47c 8053cf20 00000000 00002e42 nt!KiTimerExpiration+0xb0
f8950ff4 8052c16a efdefd44 00000000 00000000 nt!KiRetireDpcList+0x31
Le champ STACK_TEXT affiche une trace de pile du composant défaillant.
FOLLOWUP_IP:
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204 mov [edx+0x4],eax
Le champ FOLLOWUP_IP affiche le désassemblement de l’instruction qui a probablement provoqué l’erreur.
FOLLOWUP_NAME: usbtri
SYMBOL_NAME: USBPORT!USBPORT_BadRequestFlush+7c
MODULE_NAME: USBPORT
IMAGE_NAME: USBPORT.SYS
DEBUG_FLR_IMAGE_TIMESTAMP: 3b7d868b
Les champs SYMBOL_NAME, MODULE_NAME, IMAGE_NAME et DBG_FLR_IMAGE_TIMESTAMP affichent le symbole, le module, l’image et l’horodatage d’image correspondant à cette instruction (s’il est valide) ou à l’appelant de cette instruction (si ce n’est pas le cas).
STACK_COMMAND: .trap fffffffff8950dfc ; kb
Le champ STACK_COMMAND affiche la commande utilisée pour obtenir le STACK_TEXT. Vous pouvez utiliser cette commande pour répéter cet affichage de trace de pile ou le modifier pour obtenir des informations de pile associées.
BUCKET_ID: 0xD1_W_USBPORT!USBPORT_BadRequestFlush+7c
Le champ BUCKET_ID affiche la catégorie spécifique d’échecs auxquels appartient l’échec actuel. Cette catégorie aide le débogueur à déterminer les autres informations à afficher dans la sortie d’analyse.
Pour plus d’informations sur les champs FOLLOWUP_NAME et suivi, consultez Le champ suivi et le fichier triage.ini.
Il existe une variété d’autres champs qui peuvent apparaître :
Si le contrôle a été transféré vers une adresse non valide, le champ FAULTING_IP contiendra cette adresse non valide. Au lieu du champ FOLLOWUP_IP, le champ FAILED_INSTRUCTION_ADDRESS affiche le code désassemblé de cette adresse, bien que ce désassemblage soit probablement sans signification. Dans ce cas, les champs SYMBOL_NAME, MODULE_NAME, IMAGE_NAME et DBG_FLR_IMAGE_TIMESTAMP font référence à l’appelant de cette instruction.
Si le processeur se déclenche mal, vous pouvez voir les champs SINGLE_BIT_ERROR, TWO_BIT_ERROR ou POSSIBLE_INVALID_CONTROL_TRANSFER.
Si l’altération de la mémoire semble avoir eu lieu, le champ CHKIMG_EXTENSION spécifie la commande d’extension !chkimg qui doit être utilisée pour examiner.
Si une vérification de bogue s’est produite dans le code d’un pilote de périphérique, son nom peut s’afficher dans le champ BUGCHECKING_DRIVER.
Champ suivi et fichier de triage.ini
En mode utilisateur et en mode noyau, le champ Suivi de l’affichage affiche des informations sur le propriétaire du cadre de pile actuel, si cela peut être déterminé. Ces informations sont déterminées de la manière suivante :
Lorsque l’extension !analyze est utilisée, le débogueur commence par le cadre supérieur de la pile et détermine s’il est responsable de l’erreur. Si ce n’est pas le cas, le cadre suivant est analysé. Ce processus se poursuit jusqu’à ce qu’une trame pouvant être en panne soit trouvée.
Le débogueur tente de déterminer le propriétaire du module et de la fonction dans ce frame. Si le propriétaire peut être déterminé, cette trame est considérée comme étant en panne.
Si le propriétaire ne peut pas être déterminé, le débogueur passe au cadre de pile suivant, et ainsi de suite, jusqu’à ce que le propriétaire soit déterminé (ou que la pile est complètement examinée). Le premier cadre dont le propriétaire est trouvé dans cette recherche est considéré comme étant défectueux. Si la pile est épuisée sans aucune information trouvée, aucun champ suivi n’est affiché.
Le propriétaire de l’image en panne s’affiche dans le champ Suivi. Si !analyze -v est utilisé, les champs FOLLOWUP_IP, SYMBOL_NAME, MODULE_NAME, IMAGE_NAME et DBG_FLR_IMAGE_TIMESTAMP font référence à ce cadre.
Pour que le champ Suivi affiche des informations utiles, vous devez d’abord créer un fichier triage.ini contenant les noms des propriétaires de module et de fonction.
Le fichier triage.ini doit identifier les propriétaires de tous les modules susceptibles d’avoir des erreurs. Vous pouvez utiliser une chaîne d’information au lieu d’un propriétaire réel, mais cette chaîne ne peut pas contenir d’espaces. Si vous êtes certain qu’un module ne sera pas défectueux, vous pouvez omettre ce module ou indiquer qu’il doit être ignoré. Il est également possible de spécifier les propriétaires de fonctions individuelles, ce qui donne au processus de triage une granularité encore plus fine.
Pour plus d’informations sur la syntaxe du fichier triage.ini, consultez Spécification des propriétaires de module et de fonction.
Autres techniques !analyser
Si aucun incident ou exception n’a eu lieu, !analyze affiche un texte très court donnant l’état actuel de la cible. Dans certaines situations, vous souhaiterez peut-être forcer l’analyse à se produire comme si un incident s’était produit. Utilisez !analyze -f pour accomplir cette tâche.
En mode utilisateur, si une exception s’est produite, mais que vous pensez que le problème sous-jacent est un thread bloqué, définissez le thread actuel sur le thread que vous examinez, puis utilisez !analyze -hang. Cette extension effectue une analyse de pile de threads pour déterminer si des threads bloquent d’autres threads.
En mode noyau, si une vérification de bogue s’est produite, mais que vous pensez que le problème sous-jacent est un thread suspendu, utilisez !analyze -hang. Cette extension examine les verrous conservés par le système et analyse la chaîne de file d’attente DPC et affiche toutes les indications des threads suspendus. Si vous pensez que le problème est un interblocage de ressources en mode noyau, utilisez l’extension !deadlock ainsi que l’option De détection de blocage du vérificateur de pilote.
Vous pouvez également ignorer automatiquement les problèmes connus. Pour ce faire, vous devez d’abord créer un fichier XML contenant une liste mise en forme des problèmes connus. Utilisez l’extension !analyze -c -load KnownIssuesFile pour charger ce fichier. Ensuite, quand une exception ou un arrêt se produit, utilisez l’extension !analyze -c . Si l’exception correspond à l’un des problèmes connus, la cible reprend l’exécution. Si la cible ne reprend pas l’exécution, vous pouvez utiliser !analyze -v pour déterminer la cause du problème.
Voir aussi
Pour plus d’informations, consultez ces rubriques.
Référence du Code de vérification de bogue
Analyse des dumps de crash à l’aide des débogueurs Windows (WinDbg)