windbg分析dump操作流程

1、加载pdb:
.reload /i /f

2、查看pdb是否加载成功:
lm

3、自动分析指令(通常分析出的是主线程的堆栈)
!analyze -v

此时通过分析出的堆栈去找有无kernel32!UnhandledExceptionFilter信息
如果有,则此堆栈(主线程堆栈)为异常堆栈;
如果没有,则需查看所有线程堆栈:


4、查看所有线程堆栈:

~*kb

同理去找有无kernel32!UnhandledExceptionFilter信息堆栈

如果有,则此堆栈为异常堆栈;

windbg分析dump操作流程_第1张图片
图示异常出现在3号线程中

注:如果查看到的堆栈都是显示如下的信息:

windbg分析dump操作流程_第2张图片
则表明需要将windbg切换到32位模式,才能分析,指令如下:

  • .load wow64exts
  • !sw

5、找到异常堆栈分析,切换到异常堆栈的线程ID;
   查看该线程(3号线程)的堆栈:
eg:
0:000> ~3s


6、dd [Args to Child的第一个参数(该例子中是0329e7b0)] (指令是d, 第二个d表示是DWORD:双字,表示4字节数据格式)
   第一个参数指向了_EXCEPTION_POINTERS结构体

注:_EXCEPTION_POINTERS的定义如下:

typedef struct _EXCEPTION_POINTERS {
    PEXCEPTION_RECORD ExceptionRecord;
    PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;


eg:
0:003> dd 0329e7b0
00000000`0329e7b0  0329f3f0 00000000 0329ef00 00000000
00000000`0329e7c0  76f60000 00000000 0329f3f0 00000000
00000000`0329e7d0  00000000 00000000 76f8c541 00000000
00000000`0329e7e0  0329a000 00000000 76f89d2d 00000000
00000000`0329e7f0  032a0000 00000000 0329f830 00000000
00000000`0329e800  0329f830 00000000 770a2dd0 00000000
00000000`0329e810  0329e8b0 00000000 76f791cf 00000000
00000000`0329e820  032a0000 00000000 76f4dda0 00000000


7、.cxr [dd结果的第二个参数,此例中为0329ef00]  -重建堆栈(查看结构体中的PCONTEXT成员)
windbg分析dump操作流程_第3张图片

可以看到他的错误堆栈信息和windows捕捉到的是一致的


8、.exr [dd结果的第一个参数,此例中为0329f3f0] (查看结构体中的 PEXCEPTION_RECORD成员)
windbg分析dump操作流程_第4张图片




9、kv 查看程序崩溃前调用的最后堆栈信息 【需执行完上述8步后】
windbg分析dump操作流程_第5张图片


如果在上述第四步后仍未发现没有任何异常错误堆栈信息,此时有可能是线程之间死锁了
可通过以下指令查看
5、!locks 【需加载相应的windows pdb文件】

windbg分析dump操作流程_第6张图片


6、然后通过死锁的线程id:7d8去 ~*kb里面寻找该线程的堆栈


除了上述的UnhandledExceptionFilter异常和死锁的现象,还有一种_except_handler异常的情况,其处理流程和UnhandledExceptionFilter类似,具体如下:

_except_handler函数的情况


1.有些情况下堆栈中没有UnhandledExceptionFilter,而只有_except_handler函数,这个是SEH异常处理函数。函数原型:EXCEPTION_DISPOSITION __cdecl _except_handler( 
                         struct _EXCEPTION_RECORD *ExceptionRecord,
                         void * EstablisherFrame,
                         struct _CONTEXT *ContextRecord,
                         void * DispatcherContext); 
这个函数的第一个参数是一个指向 EXCEPTION_RECORD 结构的指针。这个结构在WINNT.H中定义,如下所示: 
typedef struct _EXCEPTION_RECORD {
   DWORD ExceptionCode;
   DWORD ExceptionFlags;
   struct _EXCEPTION_RECORD *ExceptionRecord;
   PVOID ExceptionAddress;
   DWORD NumberParameters;
   DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD; 
_except_handler 函数的第二个参数是一个指向establisher帧结构的指针。
_except_handler 回调函数的第三个参数是一个指向 CONTEXT 结构的指针。
typedef struct _CONTEXT
{
    DWORD ContextFlags;
    DWORD Dr0;
    DWORD Dr1;
    DWORD Dr2;
    DWORD Dr3;
    DWORD Dr6;
    DWORD Dr7;
    FLOATING_SAVE_AREA FloatSave;
    DWORD SegGs;
    DWORD SegFs;
    DWORD SegEs;
    DWORD SegDs;
    DWORD Edi;
    DWORD Esi;
    DWORD Ebx;
    DWORD Edx;
    DWORD Ecx;
    DWORD Eax;
    DWORD Ebp;
    DWORD Eip;
    DWORD SegCs;
    DWORD EFlags;
    DWORD Esp;
    DWORD SegSs;
} CONTEXT; 
_except_handler 回调函数的第四个参数被称为DispatcherContext。


2.分析dump文件时,在命令提示符处键入 ~*kb 要列出所有进程中线程。


3.标识进行函数调用的线程 Kernel32!_except_handler。 它看起来类似于以下内容:
   9  Id: 918.117c Suspend: 2 Teb: 7ffd8000 Unfrozen
ChildEBP RetAddr  Args to Child            
085df400 7c9232a8 085df4ec 085dffdc 085df50c kernel32!_except_handler3+0x61
085df424 7c92327a 085df4ec 085dffdc 085df50c ntdll!ExecuteHandler2+0x26
085df4d4 7c92e48a 00000000 085df50c 085df4ec ntdll!ExecuteHandler+0x24

4.切换到该线程 (在此示例中,线程是"~ 9s")。

5.Kernel32! !_except_handler第一个参数 dword 值表示异常记录。 若要获取有关异常的类型的信息,请在命令提示符处运行以下:
 .exr first DWORD from step 5
0:009> .exr 085df4ec
ExceptionAddress: 7c812afb (kernel32!RaiseException+0x00000053)  
ExceptionCode: e06d7363 (C++ EH exception) 
ExceptionFlags: 00000001
NumberParameters: 3  
Parameter[0]: 19930520  
Parameter[1]: 085df874  
Parameter[2]: 006c010c

6.Kernel32! !_except_handler第三个参数 dword 值是上下文记录。 要获取的上下文信息,请在命令提示符处运行以下: 
.cxr second DWORD from step 6
0:009> .cxr 085df50c
eax=085df7dc ebx=00005d34 ecx=00000000 edx=01240608 esi=085df864 edi=00100000eip=7c812afb esp=085df7d8 ebp=085df82c iopl=0         nv up ei pl nz na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206kernel32!RaiseException+0x53:7c812afb 5e              pop     esi

 7.运行 kv 命令以获得实际的异常的调用堆栈。 这可以帮助您识别可能不具有被正确处理过程中的实际问题 
0:009> kv
ChildEBP RetAddr  Args to Child          
WARNING: Stack unwind information not available. Following frames may be wrong.
09a8fa2c 780119ab 09a8fad4 00000000 09a8faa8 MSVCRT!strnicmp+0x92
09a8fa40 7801197c 09a8fad4 00000000 6d7044fd MSVCRT!stricmp+0x3c
09a8fa80 6e5a6ef6 09a8fad4 2193d68d 00e5e298 MSVCRT!stricmp+0xd


参考博文:

WinDbg 查找问题异常堆栈,堆栈跟踪UnhandledExceptionFilter
17.windbg-!cs、~~[TID](经典死锁)

注:切换当前的线程:
~0s  切换到0号线程
~3s  切换到3号线程





你可能感兴趣的:(Coder,Life)