分类 调试 下的文章

支持的同事反应,前端某用户使用系统时,在登录页面点击输入文本框,会崩溃。抓取到一个dmp文件

打开Windbg 加载该dmp

Windows 10 Version 18362 MP (12 procs) Free x86 compatible
Product: WinNt, suite: SingleUserTS Personal
18362.239.x86fre.19h1_release_svc_prod1.190628-1641
Machine Name:
Debug session time: Thu Jul  2 16:24:57.000 2020 (UTC + 8:00)
System Uptime: 3 days 1:03:52.119
Process Uptime: 0 days 0:09:18.000
................................................................
................................................................
................................................................
....................................................
Loading unloaded module list
.........................
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(3cc0.435c): Access violation - code c0000005 (first/second chance not available)
For analysis of this file, run !analyze -v
eax=00000000 ebx=00000000 ecx=00000000 edx=00d7025c esi=00000003 edi=00000003
eip=771823dc esp=0fd6e7c8 ebp=0fd6e958 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00200202
ntdll!NtWaitForMultipleObjects+0xc:
771823dc c21400          ret     14h
根据加载信息可知,在id=435c的线程发生了内存访问违例。

加载完后,windbg自动切换到了异常线程

输入kv查看当前栈

0:011> kv
 # ChildEBP RetAddr  Args to Child              
00 0fd6e7c4 7660c843 00000003 0fd6e9f8 00000001 ntdll!NtWaitForMultipleObjects+0xc (FPO: [5,0,0])
01 0fd6e958 7660c6f8 00000003 0fd6e9f8 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x133 (FPO: [SEH])
02 0fd6e974 76765ba7 00000003 0fd6e9f8 00000000 KERNELBASE!WaitForMultipleObjects+0x18 (FPO: [Non-Fpo])
03 0fd6ea20 767657d8 00000000 00000000 0fd6eb14 kernel32!WerpReportFaultInternal+0x3b7 (FPO: [Non-Fpo])
04 0fd6ea3c 7673c229 0fd6eae4 766abb8b 0fd6eb14 kernel32!WerpReportFault+0x9d (FPO: [Non-Fpo])
05 0fd6ea44 766abb8b 0fd6eb14 00000001 0934db8a kernel32!BasepReportFault+0x19 (FPO: [Non-Fpo])
06 0fd6eae4 771b29b8 0fd6eb14 771863d2 0fd6f828 KERNELBASE!UnhandledExceptionFilter+0x29b (FPO: [Non-Fpo])
07 0fd6f828 77177bf4 ffffffff 77198ff2 00000000 ntdll!__RtlUserThreadStart+0x3adc3
08 0fd6f838 00000000 0142d370 0f4953c8 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])
输入dd 0fd6eb14

0:011> dd 0fd6eb14
0fd6eb14  0fd6ec54 0fd6eca4772163b8 00000001
0fd6eb24  772163a8 0011dae0 0fd6eb4c 7718a060
0fd6eb34  77233360 77183f60 0fd6ec54 0fd6f818
0fd6eb44  0fd6eca4 0fd6ebdc 0fd6eb70 77198e72
0fd6eb54  0fd6ec54 0fd6f818 0fd6eca4 0fd6ebdc
0fd6eb64  0fd6f818 77198e90 0fd6f818 0fd6ec3c
0fd6eb74  77198e44 0fd6ec54 0fd6f818 0fd6eca4
0fd6eb84  0fd6ebdc 7718a040 0fd6f818 0fd6ec54

输入exr 0fd6ec54查看异常记录信息
0:011> .exr 0fd6ec54
ExceptionAddress: 3913910d (freeime!ImeToAsciiEx+0x00000ebd)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000000
   Parameter[1]: 00000008
Attempt to read from address 00000008
可知,在模块freeimeImeToAsciiEx的偏移0x00000ebd处内存访问违例

输入lmDvmfreeime查看freeime模块信息
0:011> lmDvmfreeime
Browse full module list
start    end        module name
39110000 391ce000   freeime    (export symbols)       freeime.ime
    Loaded symbol image file: freeime.ime
    Image path: C:\Windows\System32\freeime.ime
    Image name: freeime.ime
    Browse all global symbols  functions  data
    Timestamp:        Fri Dec 30 19:40:06 2011 (4EFDA316)
    CheckSum:         000AE352
    ImageSize:        000BE000
    File version:     7.1.5.0
    Product version:  7.1.5.0
    File flags:       8 (Mask 3F) Private
    File OS:          40000 NT Base
    File type:        3.B Driver
    File date:        00000000.00000000
    Translations:     0804.04b0
    Information from resource tables:
        CompanyName:      极点五笔工作室
        ProductName:      极点五笔  纪念版
        InternalName:     极点五笔 纪念版
        OriginalFilename: freeime.ime
        ProductVersion:   7.1.5.0
        FileVersion:      7.1.5.0
        FileDescription:  极点五笔 纪念版
        LegalCopyright:   Copyright (C) 极点五笔工作室 2001-2011

可知这个模块是输入法的动态库

输入.cxr 0fd6eca4;kv查看异常栈

0:011> .cxr 0fd6eca4;kv
eax=00000000 ebx=0f352248 ecx=00000000 edx=00d7025c esi=45fd57e0 edi=00000000
eip=3913910d esp=0fd6f184 ebp=0f2b8ea8 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00210246
freeime!ImeToAsciiEx+0xebd:
3913910d 8b5808          mov     ebx,dword ptr [eax+8] ds:002b:00000008=????????

  *** Stack trace for last set context - .thread/.cxr resets it
 # ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0fd6f1c8 7628e5e3 00000000 00000001 0fd6f30c freeime!ImeToAsciiEx+0xebd
01 00000000 00000000 00000000 00000000 00000000 user32!CallNextHookEx+0x93 (FPO: [Non-Fpo])
可知是用户在点击文本输入框时,输入法模块下钩子发生了冲突,我们既无法修改输入法,也无法修改浏览器,后台也来不急修改,只好远程用户机帮他先卸载输入法看看。
当远程后,发现用户机上有多个输入法,很可能是在装不明软件时,顺带装上的,把用户机器上不用的输入法都卸载了,就正常了。

 

问题的引出

我在调试某个崩溃问题时,要跟踪clr的栈,于是,我先执行了指令.loadby sos clrjit,没有报错,然后我又执行!clrstack,结果却有如下输出:
0:000:x86> !clrstack
CLRDLL: Consider using ".cordll -lp <path>" command to specify .NET runtime directory.
Failed to load data access DLL, 0x80004005
Verify that 1) you have a recent build of the debugger (6.2.14 or newer)
            2) the file mscordacwks.dll that matches your version of clr.dll is
                in the version directory or on the symbol path
            3) or, if you are debugging a dump file, verify that the file
                mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path.
            4) you are debugging on supported cross platform architecture as
                the dump file. For example, an ARM dump file must be debugged
                on an X86 or an ARM machine; an AMD64 dump file must be
                debugged on an AMD64 machine.

You can also run the debugger command .cordll to control the debugger's
load of mscordacwks.dll.  .cordll -ve -u -l will do a verbose reload.
If that succeeds, the SOS command should work on retry.

If you are debugging a minidump, you need to make sure that your executable
path is pointing to clr.dll as well.
也就是说执行失败了,看不了栈,根据输出建议执行.cordll -ve -u -l,有如下输出
0:000:x86> .cordll -ve -u -l
CLRDLL: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll:4.8.4042.00 f:8
doesn't match desired version 4.7.3132.00 f:8
CLRDLL: Unable to find mscordacwks_x86_x86_4.7.3132.00.dll by mscorwks search
CLRDLL: Unable to find 'mscordacwks_x86_x86_4.7.3132.00.dll' on the path
CLRDLL: Unable to get version info for 'f:\debug_symbol\symbols32\clr.dll\5B5543296ee000\mscordacwks_x86_x86_4.7.3132.00.dll', Win32 error 0n87
Cannot Automatically load SOS
CLRDLL: ERROR: Unable to load DLL mscordacwks_x86_x86_4.7.3132.00.dll, Win32 error 0n87
CLRDLL: Consider using ".cordll -lp <path>" command to specify .NET runtime directory.
CLR DLL status: ERROR: Unable to load DLL mscordacwks_x86_x86_4.7.3132.00.dll, Win32 error 0n87
傻子都知道发生了什么问题,就是没有“mscordacwks_x86_x86_4.7.3132.00.dll”和"SOS_x86_x86_4.7.3132.00.dll",由于我机子是联网的,也配好了windows符号服务器,应该说在上面的过程中应该已经下载下来了,现在没有,只能是到出问题的机器上考这两个文件了。

考了这两个文件,按理说我可以放在任何目录,可是我想放载windbg设置的符号目录,于是我将考过来的"mscordacwks.dll"和"SOS.dll"改名为“mscordacwks_x86_x86_4.7.3132.00.dll”和"SOS_x86_x86_4.7.3132.00.dll",然后在windbg设置的符号目录下以这两个文件名新建两个子文件夹,把这两个文件分别考到对应的子文件夹,在次执行.cordll -ve -u -l,跟上次输出一样,我看了下之前Windbg自行下载的其他版本的目录,发现,在还有一级目录,如下:

 

 

也就是说,我也还要需要在建立一级子目录,可是这个目录名称我该用什么呢,瞎折腾一阵,我后来注意到.cordll -ve -u -l的输出有这么一句:

0:000:x86> .cordll -ve -u -l
CLRDLL: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll:4.8.4042.00 f:8
doesn't match desired version 4.7.3132.00 f:8
CLRDLL: Unable to find mscordacwks_x86_x86_4.7.3132.00.dll by mscorwks search
CLRDLL: Unable to find 'mscordacwks_x86_x86_4.7.3132.00.dll' on the path
CLRDLL: Unable to get version info for 'f:\debug_symbol\symbols32\clr.dll\5B5543296ee000\mscordacwks_x86_x86_4.7.3132.00.dll', Win32 error 0n87
Cannot Automatically load SOS
CLRDLL: ERROR: Unable to load DLL mscordacwks_x86_x86_4.7.3132.00.dll, Win32 error 0n87
CLRDLL: Consider using ".cordll -lp <path>" command to specify .NET runtime directory.
CLR DLL status: ERROR: Unable to load DLL mscordacwks_x86_x86_4.7.3132.00.dll, Win32 error 0n87

“CLRDLL: Unable to get version info for 'f:\debug_symbol\symbols32\clr.dll\5B5543296ee000\mscordacwks_x86_x86_4.7.3132.00.dll"这里有个”5B5543296ee000“,于是我也在对应的目录下建立子文件夹”5B5543296ee000“,然后把两个文件考进去,再次执行.cordll -ve -u -l

 0:000:x86> .cordll -ve -u -l
CLRDLL: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll:4.8.4042.00 f:8
doesn't match desired version 4.7.3132.00 f:8
SYMSRV:  BYINDEX: 0x36
         f:\debug_symbol\symbols32
         mscordacwks_x86_x86_4.7.3132.00.dll
         5B5543296ee000
SYMSRV:  PATH: f:\debug_symbol\symbols32\mscordacwks_x86_x86_4.7.3132.00.dll\5B5543296ee000\mscordacwks_x86_x86_4.7.3132.00.dll
SYMSRV:  RESULT: 0x00000000
DBGHELP: f:\debug_symbol\symbols32\mscordacwks_x86_x86_4.7.3132.00.dll\5B5543296ee000\mscordacwks_x86_x86_4.7.3132.00.dll - OK
CLRDLL: Loaded DLL f:\debug_symbol\symbols32\mscordacwks_x86_x86_4.7.3132.00.dll\5B5543296ee000\mscordacwks_x86_x86_4.7.3132.00.dll
SYMSRV:  BYINDEX: 0x37
         f:\debug_symbol\symbols32
         SOS_x86_x86_4.7.3132.00.dll
         5B5543296ee000
SYMSRV:  PATH: f:\debug_symbol\symbols32\SOS_x86_x86_4.7.3132.00.dll\5B5543296ee000\SOS_x86_x86_4.7.3132.00.dll
SYMSRV:  RESULT: 0x00000000
DBGHELP: f:\debug_symbol\symbols32\SOS_x86_x86_4.7.3132.00.dll\5B5543296ee000\SOS_x86_x86_4.7.3132.00.dll - OK
Automatically loaded SOS Extension
CLR DLL status: Loaded DLL f:\debug_symbol\symbols32\mscordacwks_x86_x86_4.7.3132.00.dll\5B5543296ee000\mscordacwks_x86_x86_4.7.3132.00.dll
也就是加载成功了。

问题---“5B5543296ee000”文件夹名称是怎么来的?

加载成功,那么问题也随之而来---““5B5543296ee000”文件夹名称是怎么来的?”。

我注意到前面失败时的输出信息里:

“CLRDLL: Unable to get version info for 'f:\debug_symbol\symbols32\clr.dll\5B5543296ee000\mscordacwks_x86_x86_4.7.3132.00.dll"

对,还是这句话,不过这次的信息的重点不是“5B5543296ee000”,而是上面标粗的"clr.dll"了,它们能放在一起,说明一点:“5B5543296ee000”和“clr.dll”有关。

打开对应目录

查看下这个文件的属性

 处了版本是一样外,没有获得其他信息,后来我想到“5B5543296ee000”是不是跟一些PE信息有关呢?

打开命令行,定位到clr.dll的目录,执行“dumpbin /headers clr.dll

我注意到,在PE的FILE_HEADER里image timestamp的值为0x5B554329,在OPTIONAL HEADER里image size的值是0x6EE000,这两个值拼接在一起就是“5B5543296ee000”。

验证结论

我们上面的结论是对的吗?只能是在找一个相同结论的例子就可以,我找了之前windbg自行下载的

 

拿“”搜索,可以看到

也是这样的存储结构

dumpbin下clr.dll

根据之前的计算方式image timestamp和image size拼接为“5D490E656ef000”,完全正确,说明上面我们得出的结论完全正确

什么是Win32Exception

就是封装了Win32 Error Code的异常。也就是GetLastError返回的值。Win32错误代码在显示时从其数字表示形式转换为系统消息。使用NativeErrorCode访问与此异常关联的错误代码的数字表示形式

继承关系



Object

找到个好东西

为什么要归档

此存档提供帮助,并可能提供对以下问题的答案

  • 是否可以使WinDBG在符号存储中找到mscordacwks.dll?,
  • Windbg需要不同版本的mscordacwks.dll,如何下载mscordacwks和mscorwks的正确版本?,
  • WinDbg要求mscordacwks.dll的特定版本。我在哪能找到这个?,
  • WinDbg x64:无法调试崩溃转储-未能加载数据访问DLL和
  • 在哪里可以找到和下载不同版本的mscorwks.dll和mscordacwks.dll?

下载mscordacwks和SOS

[ICO]NameLast modifiedSize
[DIR] x64/ 2017-11-05 15:32 -
[DIR] x86/ 2017-11-05 15:31 -
[   ] sos.zip 2017-11-05 15:33 124M

MFC里的CMemoryException异常就是表示内存不足的情况。不需要或不可能进一步限定。内存异常由new自动抛出。例如,如果您使用malloc编写自己的内存函数,那么您将负责抛出内存异常。 不要直接使用此构造函数,而是调用全局函数AfxThrowMemoryException。此全局函数在内存不足的情况下可以成功,因为它在先前分配的内存中构造异常对象。

当我们在dum文件分析时,可以看到如下的异常信息:

ExceptionAddress: 768c2552 (KERNELBASE!RaiseException+0x00000062)
ExceptionCode: e06d7363 (C++ EH exception)
ExceptionFlags: 00000001
NumberParameters: 3
Parameter0: 19930520
Parameter1: 0093cb58
Parameter2: 69d9bd10
pExceptionObject: 0093cb58
_s_ThrowInfo : 69d9bd10
Type : class CMemoryException *
Type : class CSimpleException *
Type : class CException *
Type : class CObject *
Type : void *

此时,我们可以用!address -summary来查看进程内存使用情况在佐证