本文概述了从生成进程的内存转储、在一台计算机上运行某个版本的CLR到将转储加载到在另一台计算机上运行的WinDbg所涉及的步骤。在WinDbg中,我们希望加载SOS调试器扩展来查询转储。具体来说,即使WinDbg机器没有安装运行转储进程的机器所安装的CLR版本,SOS也应该加载。
步骤1:生成进程转储
要生成示例转储,请导航到Windows任务管理器,右键单击w3wp.exe(我们知道它正在运行.NET代码),然后选择创建转储文件。对于我们希望基于触发器(如CPU或内存利用率超过某个阈值)生成转储的情况,或者当进程抛出某种类型的异常时,ADPlus、DebugDiag和ProcDump提供了更好的转储捕获方法。
在准备将转储复制到WinDbg机器时,我们必须确定w3wp进程中运行的CLR版本及其位。如果对CLR版本有疑问,我们始终可以检查IIS应用程序池设置,在本例中显示的是.NET Framework v2.0.50727。至于位,Task Manager显示w3wp,没有*32后缀,表示64位进程。另一种方法是,我们可以使用Sysinternals流程资源管理器,查找加载到流程中的dll,这些dll来自C: WindowsMicrosoft.NET子文件夹之一。
在C:WindowsMicrosoft.NETFramework64中,每个x64版本的.NET都显示为一个子文件夹(v2.0.50727、v4.0.30319等)。文件夹名称版本控制方案缺少的是修补程序版本。查看v2.0.50727文件夹中某个dll的属性,我们可以看到w3wp进程中运行的CLR的确切版本实际上是2.0.50727.4253。
有了内存转储和有关在转储进程中运行托管代码的CLR版本和位的知识,我们就可以将转储和辅助文件复制到WinDbg计算机。
步骤2:将转储和.NET CLR dll复制到其他计算机
要使WinDbg能够加载和检查转储,w3wp中运行的CLR的辅助文件必须可用。这些文件与上面确定的修补程序版本和位匹配,可能已经存在于WinDbg计算机上。但是,我们不是假设,而是将所需的两个文件从w3wp机器的.NET Framework文件夹以及转储文件复制到WinDbg机器:
- mscordacwks.dll:用于工作站的Microsoft公共对象运行时数据访问组件(COR是CLR的早期名称)公开了API,WinDbg可以通过这些API访问转储进程的内存,从而访问CLR数据结构。组件实际上是从与正在执行进程内的CLR相同的源代码编译的。在死后调试期间,它充当CLR的替身,在转储中及时冻结。在运行的进程中,查询CLR数据结构不仅意味着读取内存结构,还意味着执行本机代码来解释这些结构。在调试的进程之外运行的数据访问组件也有同样的用途。
- sos.dll:Strike之子的缩写,此库包含WinDbg.NET扩展命令。通过使用mscordacwks.dll(并通过本机检查转储),这些SOS命令查询和解释CLR数据结构,并以可消化的格式呈现这些结构。如果没有mscordacwks.dll和sos.dll,我们将看到CLR数据结构在内存中的分层。
由于CLR内部以及SOS命令可能会随新的运行时版本而更改,因此每个运行时都会附带mscordacwks.dll和SOS.dll的特定版本。因此,从.NET框架文件夹中收集mscordacwks.dll和sos.dll,并与w3wp.dmp一起将这些文件复制到WinDbg计算机上的C: debugw3wp-sp2007文件夹中。
步骤3:首次尝试将w3wp.dmp加载到WinDbg中
打开WinDbg(X64)并转到“文件”菜单,打开崩溃转储。。。并找到C: debugw3wp-sp2007w3wp.dmp。作为响应,WinDbg打印以下输出:
接下来,我们发出命令,设置公共Microsoft符号服务器的符号路径,并为加载到w3wp的模块重新加载符号。然后,基于加载到w3wp中的mscorwks.dll的文件夹位置(版本),我们从同一路径加载SOS。.loadby命令实际上是general.load命令的快捷方式,接受要加载的DLL的路径。引入loadby是因为.NET dll往往有一个很长的路径,因此快捷方式根据加载的mscorwks.dll的位置解析路径。在CLR 4.0及更高版本上,命令为.loadby sos CLR,因为CLR现在位于CLR.dll中:
0:000> .symfix 0:000> .reload ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ . Loading unloaded module list ................ 0:000> .loadby sos mscorwks
另外,最新版本的WinDbg在启动时运行.symfix,从上面的冗余文件中呈现.symfix和.reload命令。从没有任何错误消息来看,SOS似乎已经加载。但我们马上就会看到情况并非如此。
步骤4:第二次尝试将w3wp.dmp加载到WinDbg中
0:000> !CLRStack 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 mscorwks.dll is in the version directory 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 the same architecture as the dump file. For example, an IA64 dump file must be debugged on an IA64 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 mscorwks.dll as well.
另外,请注意上面的HRESULT:0x80004005。WinDbg附带一个命令,用于将HRESULT错误号转换为文本:!error
80004005 解析为错误代码:(HRESULT)0x80004005(21475000037)-未指定的错误。
让我们逐一说明建议的验证步骤:
- 与我们运行的WinDbg 10.0.14321.1024无关。
- WinDbg在C:WindowsMicrosoft.NETFramework64v2.0.50727中查找,但在转储中找不到与CLR版本匹配的mscordacwks.dll版本。请记住,w3wp进程是在v2.0.50727.4253下执行的,但是WinDbg机器上v2.0.50727文件夹中的CLR版本是v2.0.50727.8009。
- 说明如何通过将C:Debugw3wp-sp2007mscordacwks.dll重命名为mscordacwks_AMD64_AMD64_2.0.50727.4253.dll并将C:Debugw3wp-sp2007添加到符号路径来修复CLR版本不匹配问题。
- 这不是问题,因为运行WinDbg和wp3wp的机器的体系结构都是AMD64。如果不确定体系结构,请查看PROCESSOR_architecture环境变量,这两台计算机上的环境变量的值均为AMD64。
根据建议(3),.sympath命令既可以显示当前符号路径,也可以向其附加路径:
0:000> .sympath+ C:Debugw3wp-sp2007 Symbol search path is: srv*;C:Debugw3wp-sp2007 Expanded Symbol search path is: cache*;SRV*https://msdl.microsoft.com/download/symbols;c:debugw3wp-sp2007 ************* Symbol Path validation summary ************** Response Time (ms) Location Deferred srv* OK C:Debugw3wp-sp2007
现在按下面的验证步骤运行.cordell-ve-u-l。
0:000> .cordll -ve -u -l CLRDLL: C:WindowsMicrosoft.NETFramework64v2.0.50727mscordacwks.dll:2.0.50727.8009 f:0 doesn't match desired version 2.0.50727.4253 f:0 CLRDLL: Unable to find '' on the path Cannot Automatically load SOS CLRDLL: Loaded DLL c:debugw3wp-sp2007mscordacwks_AMD64_AMD64_2.0.50727.4253.dll CLR DLL status: Loaded DLL c:debugw3wp-sp2007mscordacwks_AMD64_AMD64_2.0.50727.4253.dll
从输出来看,似乎加载了mscordacwks.dll的正确版本,但sos.dll没有加载。
cordell所做的是搜索dll的位置,包括公共的Microsoft symbol服务器(WinDbg打印/隐藏通过搜索的路径!)!sym noisy/!sym quiet命令)。激活噪音输出,我们可以知道,对于这个版本的CLR,dll不在符号服务器上,并且在最终找到mscordacwks_AMD64_2.0.50727.4253.dll之前,我们看到查找mscordacwks_AMD64_2.0.50727.4253.dll的尝试失败。然后WinDbg开始查找sos_AMD64_AMD64_2.0.50727.4253.dll,但找不到它。输出指示我们应该将sos.dll重命名为sos_AMD64_AMD64_2.0.50727.4253.dll并重新运行.cordll -ve -u -l
.
0:000> .cordll -ve -u -l CLRDLL: C:WindowsMicrosoft.NETFramework64v2.0.50727mscordacwks.dll:2.0.50727.8009 f:0 doesn't match desired version 2.0.50727.4253 f:0 Automatically loaded SOS Extension CLRDLL: Loaded DLL c:debugw3wp-sp2007mscordacwks_AMD64_AMD64_2.0.50727.4253.dll CLR DLL status: Loaded DLL c:debugw3wp-sp2007mscordacwks_AMD64_AMD64_2.0.50727.4253.dll