一.问题的现象

程序崩溃的时候有时候会产生dump,或者弹出错误框“×××已停止工作”,这时候用windbg打开dump文件或者attach到进程,查看异常的线程,有时候线程的调用栈已经看不到,如何最大限度的手动恢复栈呢?我也曾经为了解决这个问题查了不少资料,现在也没找到完美的方法,限于自己的知识,只能尽力去恢复。

环境和工具主备

操作系统是windows server 2012(64)64,异常的程序是64位,使用的调试工具windbg也是64位。

三.问题追踪

首先,调用k命令,输出如下:

0:013> kChild-SP          RetAddr           Call Site00000000`3c98db18 00007ffc`749213ed ntdll!ZwWaitForMultipleObjects+0xa00000000`3c98db20 00007ffc`772c8241 KERNELBASE!WaitForMultipleObjectsEx+0xe100000000`3c98de00 00000000`00000000 KERNEL32!WerpReportFaultInternal+0x581

通过这个callstack,我们很难知道异常在哪。
接着,执行!teb指令,查看线程栈的起始位置,输出如下:

0:013> !tebTEB at 00007ff6df4ae000    ExceptionList:        0000000000000000    StackBase:            000000003c990000    StackLimit:           000000003c98d000    SubSystemTib:         0000000000000000    FiberData:            0000000000001e00    ArbitraryUserPointer: 0000000000000000    Self:                 00007ff6df4ae000    EnvironmentPointer:   0000000000000000    ClientId:             000000000000148c . 0000000000001c08    RpcHandle:            0000000000000000    Tls Storage:          0000000000e9acd0    PEB Address:          00007ff6df5f6000    LastErrorValue:       0    LastStatusValue:      c0000017    Count Owned Locks:    0    HardErrorMode:        0

找到线程栈的起始地址和结束地址后,执行命令:

dps 000000003c98d000 000000003c990000

输出的内容如下:

0:013> dps 000000003c98d000 000000003c99000000000000`3c98d000  00000000`0000000000000000`3c98d008  00000000`0000000000000000`3c98d010  00000000`0000000000000000`3c98d018  00007ffc`776bd702 ntdll!EtwEventWriteNoRegistration+0x92...00000000`3c98d0b8  00007ffc`7770be5a ntdll!WaitForWerSvc+0x8a00000000`3c98d0c0  00000000`0000000100000000`3c98d0c8  00007ffc`7770bf20 ntdll!WerpAllocateAndInitializeSid+0xac00000000`3c98d0d0  00000000`0000000000000000`3c98d0d8  00000000`0000000000000000`3c98d0e0  00000000`0048004600000000`3c98d0e8  00007ffc`776d8380 ntdll! ?? ::FNODOBFM::`string'00000000`3c98d0f0  00000000`0000100000000000`3c98d0f8  00007ffc`7770bfa9 ntdll!WerpFreeSid+0x41  ...00000000`3c98ec38  00007ffc`776d262a ntdll!KiUserExceptionDispatcher+0x3a ... 

上面的内容输出很长,内容也很丰富,只列了一部分,执行下面的命令:

你看,这个问题是不是快解决了。至于具体的代码行数,可以根据图中最上面的栈帧,去dps的输出中去查找。

四.其他

在此崩溃的进程中,还有另外的线程也出现了异常,使用同样的方法,可恢复

0:008> !tebTEB at 00007ff6df4b8000    ExceptionList:        0000000000000000    StackBase:            00000000399c0000    StackLimit:           00000000399ba000    SubSystemTib:         0000000000000000    FiberData:            0000000000001e00    ArbitraryUserPointer: 0000000000000000    Self:                 00007ff6df4b8000    EnvironmentPointer:   0000000000000000    ClientId:             000000000000148c . 0000000000001bf4    RpcHandle:            0000000000000000    Tls Storage:          0000000000e9a7f0    PEB Address:          00007ff6df5f6000    LastErrorValue:       8    LastStatusValue:      c0000017    Count Owned Locks:    0    HardErrorMode:        00:008> dps 00000000399ba000 00000000399c000000000000399ba000  0000000000000000...00000000399bdc88  00007ffc776948d7 ntdll!RtlDispatchException+0x197...0:008> k L=00000000399bdc88


当然,使用上面的方法存在一定的运气成分,希望上面的方法对你有用。