Windbg是微软开发的免费源码级调试工具。它可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件。在Sharepoint的生产机中,由于失去了Visual Studio的支持,我们只有通过一些外围手段来获取相关信息(如ULS log,数据库的Log文件等等),我们也可以使用Dump文件配合Windbg来介入到生产机的诊断调试。本文主要总结如何引入Windbg到Sharepoint中,不涉及具体的应用。
一、下载 WinDbg
你可以从此处下载WinDbg到你本地的开发机上,请选择正确的下载链接(如:如果你的是x86机器,则你只能下载安装x86的tools,如果你的机器 是Intel 64-bit的处理器,则你只能下载安装X64的tools,如果你选择redistributable version,则会下载所有的三种类型x86,x64 和 Itanium)。 下载完成后,请在你本地的开发机(而不是客户的机器上)安装此工具。
在安装时,有些人为了在后面使用扩展(extension:PssCor2)方便,会把安装目录设定在 d:\debug下,所以你也可以在此处设置此目录。
安装完成后你就可以在开始菜单--->程序中看到"Debugging Tools for Windows (x64)"或"Debugging Tools for Windows (x32)"下的Windbg程序了。
二、安装扩展: PssCor2
接下来是安装extensions for managed code,默认情况下,Windbg是用于调试 unmanaged code的,如果要调试managed code就需要另外安装扩展,此处我们选择PssCor2(以前是用SOS.dll,现在PssCor4也出来了,但是针对不同的.NET Framework版本,当然微软针对.NET Application也专门提供了NET SDK 命令行调试器 MDbg.exe),此扩展可用于诊断managed threads, managed object heap 和CLR stack等等,你可以从此处下载PssCor2 并解压。同样为了使用扩展方便,建议把相应的psscor2.dll拷贝到D:\debug目录下(也就是Windbg.exe存在的目录下)。
三、设置SymbolPath
Symbol文件就是符号文件,如果你想更有效的调试,你需要Symbol文件。有了它,Windbg就可以把你编译后的程序代码翻译成你可以理解的指令。
符号文件可以是老式的COFF格式或者就是PDB格式。PDB就是程序数据库文件并且包含了公有符号。这些调试器内,你可以使用一系列的地址来让调试器寻找已经加载的二进制文件的符号。 操作系统的符号文件一般存储在%SYSTEMDIR%Symbols目录。驱动程序的符号文件(.DBG或.PDB)一般存储在和驱动文件(.sys 文件)相同的目录下。私有符号文件包含的信息包括:函数,局部以及全局变量,以及用来把汇编代码和源代码关联起来的行号信息;对于客户来说,符号文件一半是公有的-这些文件仅仅包括公有成员。
微软提供了一系列的symbols给你的debugger,你可以从此处下载Symbol文件。仍然建议你把Symbol文件下载到目录d:\debug\symbols下,这样可以方便你的使用。
下载完成后,你就需要在Windbg中设置Symbol File Path,如下图:
在输入文本中输入(此处添加到了网络上符号文件的引用)
你也可以使用.sympath命令。使用的命令就是:
当调试器把一个二进制文件(DLL或exe)加载的时候,他会检查它们的相关信息,如文件名,时间戳以及校验值。如果你有符号信息,你就可以在调用栈上看到函数名和他们的参数。如果二进制文件和PDB文件都来自于你自己的应用程序,你就可以看到比如私有函数,局部变量以及类型这类额外的信息。
我们可以把symbols, extensions, dump files都至于同一目录d:\debug下以方便我们的使用。
四、获取Dump
现在转到我们的生产机上,找到我们的Sharepoint运行的进程,方法如此文Sharepoint学习笔记--如何定位网站集所在的w3wp进程 ,
在生产机上打开windows task manager (或Run taskmgr.exe打开task窗口),找到对应进程,创建此进行的Dump,如下图:
创建成功后,系统会告诉你此Dump文件的位置,请把它从问题机上的存储位置拷贝到你本机的某个目录下备用。
五、开始使用WinDbg
现在我们有了dump file来进行调试,在Windbg程序的file菜单下,选择“File / Open Crash Dump”来打开我们的dump 文件,然后你可以看到类似如下的信息
在上述信息中,你可以找到你的dump file的存放路径以及你的symbol search path。在Windbg的最下面是命令窗口,也是我们的主要操作接口。
5.1 List Modules
使用命令lm来查看我们的w3wp进程到底都加载了什么modules.操作如下图
对于SharePoint开发人员,可以通过加载modules来调试诊断诸如feature receivers 和 event handlers 之类的模块,判断它们是否被触发,如果你在此处没有看到它们的相关Assembly被加载进内存,那麽多半是由于configuration设置方面的原因引起的,这样就大大缩小了诊断范围.
5.2 加载 PssCor2
还记得我们前面下载的Extension: PssCor2吗,它用于调试managed code,如果我们要调试w3wp中的Managed Code,我们就需要先加载这个扩展,方法是在Windbg命令行输入
由于我的生产机是64-bit Intel,它所创建的dump是64bit的,所以在此处,我就加载了 AMD64 version 的 PssCor2.dll。如果你是调试基于x86的进程,那么你就需要加载 x86 version 的PssCor2.dll. 为了验证PssCor2.dll成功加载,你可以输入下面的命令
!help
输入结果如下:
*在这里经常会遇到关于 mscordacwks.dll 的问题
也即:源dump文件的mscordacwks.dll文件与调试机上的版本不一致问题而无法使用extension cmd的问题。这是因为我们的问题机与调试机不是同一台机子,所以当我们抓取了问题机器上的managed application的dump文件之后, 而在另外一台机器上对该dump进行分析时。如果问题机器和目标机器的mscordacwks.dll版本不一致,则在使用了上面的Windbg Load 命令加载PssCor2.dll之后目标机器上找不到正确的mscordacwks.dll而导致无法使用debugger extension command.
例如随便键入一个extension command: !Threads
收到的错误信息类似:
用.cordll看一看,feedback如下:
这说明抓取的dump文件所需要的mscordacwks_AMD64_x86_2.0.50727.4963.dll文件找不到。
mscordacwks.dll充当PssCor2.dll的Data Access Component(dac),用于解释.NET程序在内存中的数据结构。每次为.NET Framework打patch,mscordacwks.dll都会更新。
解决方法:很简单,就是把发生问题的客户机上的mscordackws.dll文件copy过来,然后将其rename为其所需要的文件名,并将其放置到适当的search path下。 获取问题的客户机环境中的mscordacwks.dll其位置为
32bit .NET2.0/3.0 | %WINDIR%\Microsoft.NET\Framework\v2.0.50727 |
32bit .NET 4.0 | %WINDIR%\Microsoft.NET\Framework\v4.0.30319 |
64bit .NET 2.0/3.0 | %WINDIR%\Microsoft.NET\Framework64\v2.0.50727 |
64bit .NET 4.0 | %WINDIR%\Microsoft.NET\Framework64\v4.0.30319 |
WinDbg要求把mscordacwks.dll放置在symbol的存储路径或windbg的安装下,而不要和dump文件放在同一路径下。这里即是我们前面提到的 D:\Debug。 然后用.cordll -ve -u -l 可以查看到某个mscordacwks加载成功。
在Windbg下输入命令.cordll -ve -u -l 就会看到
*另一需要注意的问题就是如何处理64位环境中的32位进程
我们的Sharepoint2010网站是运行在64bit的服务器环境中的.
对于IIS7,Sharepoint的Application Pool的 Enable 32-bit Applications 属性决定了这个进程是32位进程还是64位进程。如下图:
对于IIS6,执行32位进程,需要执行 cscript.exe adsutil.vbs set W3SVC/AppPools/Enable32BitAppOnWin64 “true” , 注意,IIS6中所有的Application Pool,要么都执行32位进程,要么都不执行
在客户端问题机上导Dump时,使用Ctrl-Shift-Esc,呼出Task Manager,可以看清导出的进程是32位进程还是64位进程。如图:
在64bit的客户机上如果使用Task Manager的Create Dump File功能生成dump,得到的是64 bit的dump,对于32位进程的64位dump,所有的内存地址都是64位的,PssCor等工具都不能工作。要识别32位进程的64位dump有一个方法:执行kp命令,call stack中显示wow64cpu中的方法,就说明这是32位进程的64位dump。
如何正确的为运行在64为环境中的32位进程生成dump?
方法1:执行32位的task manager C:\Windows\SysWOW64\taskmgr.exe, 用它来生成dump
方法2:在64位环境中安装32位的Debug Diag或32位ADPlus(32位Debugging tools for Windows) 。64 位Debug Diag 1.2 (目前为Beta版)可以生成32位dump。
要debug 32位进程的32位dump,必须使用32位的windbg,调试环境可以是32位,也可以是64位。使用的SOS等插件必须是32位的。
至于64位环境中的64位进程的Dump,请使用64位环境中的64位的windbg打开,如果要进行.NET debug,必须使用64位的SOS或psscor2,sosex等插件
5.3其它常用命令
在解决了mscordacwks.dll版本问题后,我们可以使用Windbg&PssCor2进一步分析我们的程序。
!help命令(前面用过)
最用的命令是!help命令,使用该命令可以列出所有可用的扩展命令列表使用!help [CommandName]可以查看每一个具体扩展命名的详细使用说明。
!aspxpages命令
此命令会显示访问的相关ASPX页面以及每个页面Thread ID,Thread Run time等等信息,通过这些信息可以帮助你了解哪些页面访问速度过慢,以及访问的verb动作等问题。
!threads命令
用于跳转到你指定的thread context去查看它的Stack Information.实现类似于在Visual Studio中,当我们设置了一个断点进行调试时,我们可以查看到call stack的信息,此信息显示了从程序开始执行到我们断点为止时所包含的相关方法链(Method Chain)。
!clrstack命令
使用!clrstack可以查看当前的调用堆栈,使用!clrstack –l可以查看当前调用堆栈以及其上的局部变量和值,使用!clrstack –p可以查看当前调用堆栈上的参数变量以及值,使用!clrstack –a可以查看当前堆栈上所有局部变量和参数变量以及值(格式为StackAddress = StackValue)。!clrstack命令只会显示托管代码的调用堆栈,如果想查看完整的调用堆栈可以使用!dumpstack命令
~* e !clrstack命令
此命令会显示出所有的Thread的CLR Stack信息。显示结果可能会比较长。
当然,Windbg的使用绝非这里提到的这些命令,它常用于解决比较底层的疑难杂症,要掌握Windbg需要对底层的东西有更深的理解,这里只是重点总结了如何在Sharepoint调试中引入它。