程序发生了崩溃,我抓了一个mini Dump,Mini dump 有一个优势就是很是的小。比full dump 要小不少。 php
0:020> .loadby sos clr //首先加载sos 0:020> !threads The version of SOS does not match the version of CLR you are debugging. Please load the matching version of SOS for the version of CLR you are debugging. CLR Version: 4.0.30319.1008 SOS Version: 4.0.30319.1022 0:020> .cordll -ve -u -l CLRDLL: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscordacwks.dll:4.0.30319.1022 f:8 doesn't match desired version 4.0.30319.1008 f:8 CLRDLL: Loaded DLL c:\symbols\mscordacwks_AMD64_AMD64_4.0.30319.1008.dll\517A18FF965000\mscordacwks_AMD64_AMD64_4.0.30319.1008.dll CLR DLL status: Loaded DLL c:\symbols\mscordacwks_AMD64_AMD64_4.0.30319.1008.dll\517A18FF965000\mscordacwks_AMD64_AMD64_4.0.30319.1008.dll 还有一种错误:
If you are debugging a minidump, you need to make sure that your executable
path is pointing to clr.dll as well.
The version of SOS does not match the version of CLR you are debugging. Please
load the matching version of SOS for the version of CLR you are debugging.
CLR Version: 4.0.30319.1026
SOS Version: 4.0.30319.34209
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. html
.cordll –ve –u –l (小写的L ) 这个命令是控制调试和控制CLR的命令,-ve是显示详细信息,-u 卸载模块,-l (小写的L) 是加载模块,上面这个命令就是卸载CLR 调试模块,而后再加载CLR调试模块,并显示详细信息。 windows
这个命令提示个人mscordacwks.dll 版本不对。而后有提示从 C:\symbols 加载了 mscordacwks_<arch>_<arch>_<version>.dll 这个文件。 缓存
我windbg的符号文件路径的设置是: 数据结构
srv*c:\symbols*http://msdl.microsoft.com/download/symbols
经过windbg的快捷键 Ctrl+S 能够设置符号文件的路径。 架构
虽然看似上面的mscodacwks.dll 加载了,可是运行命令仍是报错: app
0:033> !clrstack The version of SOS does not match the version of CLR you are debugging. Please load the matching version of SOS for the version of CLR you are debugging. CLR Version: 4.0.30319.1008 SOS Version: 4.0.30319.1022 OS Thread Id: 0x6e54 (33) Child SP IP Call Site 000000000540a968 000007fefaab8e4f [PrestubMethodFrame: 000000000540a968] Unknown MethodDesc (Module 000007ff00a613b0, mdToken 060000aa) 000000000540a9d0 000007ff00b829fd Unknown MethodDesc (Module 000007ff00a613b0, mdToken 06000096)
CLR.dll 是一个原生C++ Win32 Native code 编写的托管代码运行时,它是托管代码的运行环境,它从咱们.net编写的生成的dll中抽取IL中间代码和元数据,经过JIT即时编译来生成内存中的原生native Code. Windbg是一个针对原生Native code 的调试器。那在原生调试器和托管代码世界之间,咱们须要一座“桥梁”这就是SOS.dll。可是CLR的内部数据结构多是要不断变化的,这时若是有一个针对调试器的一个抽象层就很是重要,调试器经过一个抽象层来访问CLR的内部数据结构。mscordacwks.dll 就是这样一个抽象层 ( Data-Access-Component (DAC) ),它实现了让调试器SOS.dll 以比较稳定的接口来访问CLR内部不断的数据结构的目的。但CLR和SOS.dll 以及 mscordacwkd.dll 仍是耦合的很是紧密的,以致乎 他们的版本必须一致才能够正常工做。 cors
通常,咱们的机器上安装好.net 运行时后,都有 clr.dll ,sos.dll 和mscordacwk.dll 三个版本一致的dll。 工具
通常在调试dump文件才会出现这类不匹配的错误。由于若是是调试一个活生生的进程,调试器能自动的从.net Framework的安装目录来找到正确的mscordacwks.dll。 网站
能够尝试
!sym noisy //显示详细信息
.symfix+ c:\symbols //强制下载symbols
.reload /f; // Force reloading symbols 强制加载符号文件
.cordll -ve -u –l //从新加载调试DLL,这是加载DLL,不是符号
上面的命令试了后也可能不起做用。
遇到这种问题,你须要到抓取dump文件的机器上,把 mscordacwks.dll 和Sos.dll 拷贝下来,若是是别人传给你dump,则最好让他将这3个文件一块儿拷贝给你。拿到DLL后,确认版本正确后,改成相似一下的名字:
mscordacwks_AMD64_AMD64_4.0.30319.1008.dll
AMD64 这个字符串对应的是CPU架构信息,由于AMD公司先作出64位架构,Intel公司虽然也有本身的64位架构,但好像没有流行开,他仍是沿用了AMD兼容的64位。而这个AMD64的遗留名字就一直使用下来了。
文件重命名后,能够放到windbg的exe目录下,与windbg.exe 同一个目录,也能够放到一个指定的目录下。
而后运行:
.cordll -u -ve -lp c:\clr1008 // C盘有个clr1008文件夹,我从那里加载调试DLL,-lp 指定目录
.cordll -ve -u –l //从默认路径加载调试DLL。
若是遇到以下错误:
CLR DLL status: ERROR: Unable to load DLL mscordacwks_AMD64_x86_4.0.30319.1008.dll,
或者
CLRDLL: ERROR: DLL C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll init failure, Win32 error 0n87 CLR DLL status: ERROR: DLL C:\Windows\Microsoft.NET\Framework\ v4.0.30319\mscordacwks.dll init failure, Win32 error 0n87
说明 32位、64位这个搞错了。
你可能抓了一个32位进程的dump。64位系统上的任务管理器中,32位进程的名字相似:w3wp.exe*32,后面带一个 *32 字样,它们是运行在WoW64模式下的。同时你用了一个64位的windbg调试器在尝试调试这个dump。Dump分析必须3二、64严格区分开,64位系统抓64位进程dump,用64位windbg来分析。64位系统抓32位进程dump,用32位windbg来分析。
还有 第三种方法,本身去获取匹配版本的关键dll。 Mscordacwk 全名是指Ms-core-Data-Access-Component (DAC) -Work.dll,是sos 访问clr数据须要的一个核心dll。
用“sos 4.0.30319.1008 ” 去网上搜索找到对应的 微软补丁包:
例如,我找到了这样一个网站: http://www.mskbfiles.com/sos.dll.php
我要的版本他这里列出来了:
“
Sos.dll version 4.0.30319.1008:
”
点击这个连接进去,找到“下载信息”
“
下载信息
此更新可从 Microsoft 下载中心下载:
http://www.microsoft.com/zh-cn/download/details.aspx?id=39418, 点击这个连接去下载补丁文件
”
个人dump文件是运行在X64系统上的,那我就下载了“NDP40-KB2835393-x64.exe”。
下载这个文件,它是一个子解压的exe文件,能够用 WinRAR 或 7-Zip 打开,打开后在目录里找到 *.msp 结尾的文件,右键菜单继续打开,而后找到 *.cab文件,选中 *.cab 文件,经过右键菜单继续打开,查找里面的 sos_dll_amd64,mscordacwks_dll_am64,clr_dll_amd64文件,把他们导出到普通文件夹下,从新命名为 sos.dll,mscordacwks.dll,clr.dll,而后查看版本是否是 4.0.30319.1008。若是不是这个版本继续在 *cab 里面找dll,应该是能找到正确的文件版本。
我就经过这种方法找到了对应 我须要的三个正确版本的dll文件。把他们放在一个clr1008的文件夹下,而后把clr1008 放与windbg.exe 同一级的目录下。这样加载敲命令就方便多了。
我已经将文件版本保存好后,我从新加载sos.dll
0:033> .load clr1008\sos.dll 0:033> .chain Extension DLL search Path: D:\Users\Downloads\windbg\WINXP;.... //环境变量的 PATH 值 Extension DLL chain: clr1008\sos.dll: image 4.0.30319.1008, API 1.0.0, built Fri Apr 26 14:21:22 2013 [path: D:\Users \Downloads\windbg\clr1008\sos.dll] C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos: [path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll] [path: D:\Users \Downloads\windbg\dbghelp.dll] ....
我如今有2个sos.dll, 我须要把默认路径下的卸载掉
0:033> .unload C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos Unloading C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos extension DLL 0:033> .setdll clr1008\sos.dll
这两个命令的做用是1)卸载dll,2)设置默认dll。
而后加载调试DLL:
0:020> .cordll -u -ve -lp clr1008 CLRDLL: Loaded DLL clr1008\mscordacwks.dll CLR DLL status: Loaded DLL clr1008\mscordacwks.dll
若是没法正确加载PDB文件,就没法正确的显示堆栈Stack信息,问题:
0:024> !clrstack PDB symbol for clr.dll not loaded OS Thread Id: 0x8158 (24) Unable to walk the managed stack. The current thread is likely not a managed thread. You can run !threads to get a list of managed threads in 0:024> kb //stack 信息没法正确显示 RetAddr : Args to Child : Call Site 000007fe`f9b1c841 : 00000000`77359b6e ... : clr+0x1fde45 00000000`77359b6e : 00000000`00000000 ... : clr+0x1c841 000007fe`f9cfba57 : 00000000`02340850 ... : ntdll!RtlLookupFunctionTable+0xaa 00000000`02340850 : 00000001`0000001f ...: clr+0x1fba57 0:024> .exepath+ clr1008 //+ 是表示附加 Executable image search path is: clr1008 Expanded Executable image search path is: clr1008 0:024> .reload //必须Reload .............. 0:024> kb //以后的堆栈信息已经能正确显示了 RetAddr : Args to Child : Call Site 000007fe`f9cfba57 : 00000000`02340850 ... : clr!SVR::gc_heap::mark_object_simple1+0xbd6 000007fe`f9cf9aa9 : 00000000`02340850 ... : clr!SVR::gc_heap::mark_object_simple+0x4d7 000007fe`f9b8cf6e : 00000001`c0e4fbc8 ... : clr!SVR::GCHeap::Promote+0x161 000007fe`f9b8ec95 : 00000000`0475dd90 ... : clr!GcEnumObject+0x37 000007fe`f9b8e585 : ffffffff`00000000 ... : clr!GcInfoDecoder::EnumerateLiveSlots+0x5dd
必须保证exepath指向正确的路径,默认指向的是.net Framework的安装目录,但我如今须要的是1008版本的clr.dl路径,因此须要将exepath 额外加上一个路径。
If you are debugging a minidump, you need to make sure that your executable
path is pointing to clr.dll as well.
在没有将clr1008目录下的clr.dll 加载到exepath时,下面的输出是这样的:
0:000> !EEVersion 4.0.30319.1022 free Workstation mode SOS Version: 4.0.30319.1022 retail build 0:000> lmv m clr start end module name 000007fe`f77f0000 000007fe`f8155000 clr (pdb symbols) c:\symbols\clr.pdb\14AD6AF3D1B64799A5908CBBBA0E9C482\clr.pdb Loaded symbol image file: clr.dll Image path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll Image name: clr.dll Timestamp: Wed Jan 08 14:28:31 2014 (52CCF00F) CheckSum: 0096784D ImageSize: 00965000 File version: 4.0.30319.1022 Product version: 4.0.30319.1022 File flags: 8 (Mask 3F) Private File OS: 4 Unknown Win32 File type: 2.0 Dll File date: 00000000.00000000 Translations: 0409.04b0 CompanyName: Microsoft Corporation ProductName: Microsoft® .NET Framework InternalName: clr.dll OriginalFilename: clr.dll ProductVersion: 4.0.30319.1022 FileVersion: 4.0.30319.1022 (RTMGDR.030319-1000)
在将clr1008目录下的clr.dll 附加到 exepath后,命令输出以下:
0:020> lmv m clr start end module name 000007fe`f9b00000 000007fe`fa465000 clr (pdb symbols) c:\symbols\clr.pdb\118B3CCCBA4A4A709B496CFB294BF5162\clr.pdb Loaded symbol image file: clr.dll Mapped memory image file: clr1008\clr.dll Image path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll Image name: clr.dll Timestamp: Fri Apr 26 14:04:47 2013 (517A18FF) CheckSum: 0095CE19 ImageSize: 00965000 File version: 4.0.30319.1008 Product version: 4.0.30319.1008 File flags: 8 (Mask 3F) Private File OS: 4 Unknown Win32 File type: 2.0 Dll File date: 00000000.00000000 Translations: 0409.04b0 CompanyName: Microsoft Corporation ProductName: Microsoft® .NET Framework InternalName: clr.dll OriginalFilename: clr.dll ProductVersion: 4.0.30319.1008 FileVersion: 4.0.30319.1008 (RTMGDR.030319-1000)
能够看到 pdb 符号文件已经有了,并且有了一个Mapped memory image file: clr1008\clr.dll 这一项。并且个人symbol path下缓存的clr.pdb文件也已经对应到正确的版本了。
额外的:
lm 能够检查你的.net 程序是否运行在 .net 4或.net 2,仍是混合着 4.0 和 2.0, 就是经过 查看输出内容是否 包含 clr, mscorwk, mscorsrv 这些模块,4.0 的核心dll 是clr.dll。2.0 的核心dll是 mscorwks.dll 或者mscorsrv.dll。下面只有clr 模块,说明只工做在.net 4.0下。
0:000> lm start end module name …… 00000000`77530000 00000000`7764f000 kernel32 (pdb symbols) 00000000`77650000 00000000`7774a000 user32 (pdb symbols) 00000000`77750000 00000000`778f9000 ntdll (export symbols) 000007fe`f24e0000 000007fe`f2653000 clrjit (pdb symbols) 000007fe`f77f0000 000007fe`f8155000 clr (pdb symbols)
在这里补充一点:这篇文章是将windbg如何去正确加载 sos.dll,同时有可能须要去正确加载 clr.dll 这个exe 可执行路径。若是使用DebugDiag这类自动化工具,由于自动化工具没有能够配置去哪一个路径加载exe可执行路径。须要在环境变量里设置这些参数:
_NT_EXECUTABLE_IMAGE_PATH = c:\clr1008
例如我这里就设置了这样一个环境变量,让DebugDiag 启动分析时,知道去这里找正确的clr版本。参见:http://msdn.microsoft.com/en-us/library/windows/hardware/hh439335(v=vs.85).aspx
参考资料:
http://stackoverflow.com/questions/23636764/clr-dll-exception-causes-the-iis-crashed
http://voneinem-windbg.blogspot.com/2007/10/failed-to-load-data-access-dll.html