两天前,研究控件状态问题是,看到了思归的这篇文章思归的“动态控件的状态问题”的分析,对其中用跟踪TrackViewState用到的工具winDbg比较好奇,经过摸索,现在把实现的步骤列一下:
1安装、部署winDbg、配置SOS,这个网上已经讲得比较多了,这里我就不多说了,列出我参考过的几个链接
Mike Taulty's Blog的
A word for WinDbg A word for WinDbg(2) More on debugging with SOS.DLL - enter Visual Studio 博客园flier的用WinDbg探索CLR世界的一系列文章2调试ASP.Net参考的文章 在托管代码中设置断点(WINDBG) ASP.NET 崩溃-SiteMap中疯狂的循环 用WinDbg动态脱Reflector WinDbg / SOS Cheat Sheet ASP.NET Performance Case Study: Web Service calls taking forever这里也写一下我的步骤,由于我对托管和非托管代码的一些概念都不甚清楚,可能有的命令用的不恰当,但例子确实是工作了,写到这里只是希望抛砖引玉。另外这里的操作是基于asp.net1.1的,我对于调试asp.net2.0步骤还没有理顺,后面我也会把我的一些问题列出,还请高手们不吝赐教。
1.设置path变量
这里是指 我的电脑-〉属性-〉高级-〉环境变量中path的设置,在其后加上sos.dll的路径,注意一定不要将原来的path内容删掉,可能与其他程序关联
我本机上是C:\WINNT_1\Microsoft.NET\Framework\v1.1.4322;
2.打开windbg,选择File->Symbol File Path,这里我写的是
SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols;
c:\winnt_1\symbols;
C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\symbols;
3.按F6或者是File->Attach to a process,选择aspnet_wp进程,注意此时最好保证你的aspx页面尚未执行
4.在命令窗口依次输入.load sos
.loadby sos mscorwks
.chain (查看是否正确load)
本文windbg的命令如果没有声明均为小写,比如name2ee,我在help中查到的是Name2EE,但是我输入的时候不识别
我本机显示
Extension DLL search Path:
C:\Program Files\Debugging Tools for Windows\winext;C:\Program Files\Debugging Tools for Windows\winext\arcade;C:\Program Files\Debugging Tools for Windows\W2KFre;C:\Program Files\Debugging Tools for Windows\pri;C:\Program Files\Debugging Tools for Windows;C:\Program Files\Debugging Tools for Windows\winext\arcade;C:\WINNT_1\system32;C:\WINNT_1;C:\WINNT_1\System32\Wbem;C:\Sybase\dll;C:\Sybase\bin;C:\Program Files\Microsoft SQL Server\80\Tools\BINN;C:\Program Files\Sybase\Sybase Central\win32;C:\Sybase\ASEP;C:\Program Files\ATI Technologies\ATI Control Panel;C:\Program Files\Sybase\SQL Anywhere 7\win32;C:\Program Files\Sybase\Shared\Web Targets;C:\Program Files\Sybase\Shared\PowerBuilder;c:\Program Files\Microsoft SQL Server\90\Tools\binn\;C:\WINNT_1\Microsoft.NET\Framework\v1.1.4322;C:\WINNT_1\Microsoft.NET\Framework\v2.0.50727
Extension DLL chain:
sos: API 1.0.0, built Fri Feb 21 10:47:40 2003
[path: C:\WINNT_1\Microsoft.NET\Framework\v1.1.4322\sos.dll]
C:\WINNT_1\Microsoft.NET\Framework\v2.0.50727\sos.dll: image 2.0.50727.42, API 1.0.0, built Fri Sep 23 15:27:26 2005
[path: C:\WINNT_1\Microsoft.NET\Framework\v2.0.50727\sos.dll]
C:\WINNT_1\Microsoft.NET\Framework\v2.0.50727\sos: image 2.0.50727.42, API 1.0.0, built Fri Sep 23 15:27:26 2005
[path: C:\WINNT_1\Microsoft.NET\Framework\v2.0.50727\sos.dll]
C:\WINNT_1\Microsoft.NET\Framework\v1.1.4322\sos: API 1.0.0, built Fri Feb 21 10:47:40 2003
[path: C:\WINNT_1\Microsoft.NET\Framework\v1.1.4322\sos.dll]
dbghelp: image 6.6.0007.5, API 6.0.6, built Sun Jul 09 04:11:32 2006
[path: C:\Program Files\Debugging Tools for Windows\dbghelp.dll]
ext: image 6.6.0007.5, API 1.0.0, built Sun Jul 09 04:10:52 2006
[path: C:\Program Files\Debugging Tools for Windows\winext\ext.dll]
uext: image 6.6.0007.5, API 1.0.0, built Sun Jul 09 04:11:02 2006
[path: C:\Program Files\Debugging Tools for Windows\winext\uext.dll]
ntsdexts: image 5.00.2195.6618, built Tue Nov 19 08:21:06 2002
[path: C:\Program Files\Debugging Tools for Windows\W2KFre\ntsdexts.dll]
5.再输入!name2ee System.Web.dll System.Web.UI.WebControls.ListItemCollection.TrackViewState
显示
succeeded
Loaded Son of Strike data table version 5 from "C:\WINNT_1\Microsoft.NET\Framework\v1.1.4322\mscorwks.dll"
--------------------------------------
not created yet
-----------------------
表明线程尚未执行
6.运行VS2003 IDE的F5执行aspx页面
7.在windbg的窗口输入g,表示继续调试
显示
0:000> g
ModLoad: 7b0a0000 7b1cc000 c:\winnt_1\assembly\gac\system\1.0.5000.0__b77a5c561934e089\system.dll
ModLoad: 7b490000 7b506000 c:\winnt_1\assembly\gac\system.drawing\1.0.5000.0__b03f5f7f11d50a3a\system.drawing.dll
ModLoad: 7bc10000 7bd5a000 c:\winnt_1\assembly\gac\system.xml\1.0.5000.0__b77a5c561934e089\system.xml.dll
ModLoad: 7a6e0000 7a81e000 c:\winnt_1\assembly\gac\system.data\1.0.5000.0__b77a5c561934e089\system.data.dll
ModLoad: 07a30000 07a6e000 c:\winnt_1\assembly\gac\system.enterpriseservices\1.0.5000.0__b03f5f7f11d50a3a\system.enterpriseservices.dll
ModLoad: 7a2a0000 7a2b2000 c:\winnt_1\assembly\gac\system.web.regularexpressions\1.0.5000.0__b03f5f7f11d50a3a\system.web.regularexpressions.dll
ModLoad: 10a70000 10a75000 c:\winnt_1\assembly\gac\microsoft.visualc\7.0.5000.0__b03f5f7f11d50a3a\microsoft.visualc.dll
ModLoad: 7a000000 7a018000 c:\winnt_1\assembly\gac\system.directoryservices\1.0.5000.0__b03f5f7f11d50a3a\system.directoryservices.dll
ModLoad: 79640000 79692000 c:\winnt_1\assembly\gac\system.runtime.remoting\1.0.5000.0__b77a5c561934e089\system.runtime.remoting.dll
ModLoad: 79550000 79574000 c:\winnt_1\assembly\gac\system.runtime.serialization.formatters.soap\1.0.5000.0__b03f5f7f11d50a3a\system.runtime.serialization.formatters.soap.dll
ModLoad: 53760000 5376a000 c:\winnt_1\assembly\gac\cscompmgd\7.0.5000.0__b03f5f7f11d50a3a\cscompmgd.dll
ModLoad: 79430000 7947c000 C:\WINNT_1\Microsoft.NET\Framework\v1.1.4322\MSCORJIT.DLL
ModLoad: 777e0000 777e7000 C:\WINNT_1\system32\version.dll
ModLoad: 75950000 75956000 C:\WINNT_1\system32\LZ32.DLL
(5a4.224): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=00000101 edx=ffffffff esi=00000000 edi=00000000
eip=77f9193c esp=07f5ffa8 ebp=07f5ffb4 iopl=0 nv up ei ng nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000286
ntdll!DbgBreakPoint:
77f9193c cc int 3
8.此时System.Web.UI.WebControls.ListItemCollection.TrackViewState仍然没有被创建,你可以试着输入!name2ee System.Web.dll System.Web.UI.WebControls.ListItemCollection.TrackViewState查看
9.再次输入g,此时页面全部载入,你可以在浏览器看到页面已经呈现出来了.不过在windbg的窗口可能显示debuggee is busying, 意思是被调试的进程也就是aspnet_wp正忙,这里我们可以不管它,按ctrl+break结束掉,此时System.Web.UI.WebControls.ListItemCollection.TrackViewState已经创建,输入!name2ee System.Web.dll System.Web.UI.WebControls.ListItemCollection.TrackViewState查看
显示
!name2ee System.Web.dll System.Web.UI.WebControls.ListItemCollection.TrackViewState
--------------------------------------
MethodDesc: 82c3fb0
Name: [DEFAULT] [hasThis] Void System.Web.UI.WebControls.ListItemCollection.TrackViewState()
-----------------------
得到MethodDesc: 82c3fb0
10. 接下来输入!dumpmd 82c3fb0 你如果对这些方法不熟悉的可以查阅前面的参考文章或者google一下
显示
Method Name : [DEFAULT] [hasThis] Void System.Web.UI.WebControls.ListItemCollection.TrackViewState()
MethodTable 82c4194
Module: 17f1a8
mdToken: 0600172f (c:\winnt_1\assembly\gac\system.web\1.0.5000.0__b03f5f7f11d50a3a\system.web.dll)
Flags : 80
Method VA : 082af9f8
得到 Method VA : 082af9f8
11.接下来输入
0:010> sxe ld:System.Web.dll 设置模块加载断点
0:010> bp 082af9f8 给得到的Method VA设置断点
12.刷新aspx页面,同时在windbg中输入g继续运行
显示
Breakpoint 0 hit
eax=05707e08 ebx=056f0a9c ecx=05707e08 edx=00000002 esi=05707d28 edi=05707e08
eip=082af9f8 esp=00ebf83c ebp=00ebf84c iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000212
082af9f8 55 push ebp
Breakpoint 0 hit表明运行到断点处
13.输入!clrstack查看
显示
Thread 1
ESP EIP
00ebf83c 082af9f8 [DEFAULT] [hasThis] Void System.Web.UI.WebControls.ListItemCollection.TrackViewState()
at [+0x0] [+0x0]
00ebf840 082af9e5 [DEFAULT] [hasThis] Void System.Web.UI.WebControls.ListControl.TrackViewState()
at [+0x25] [+0x11]
00ebf854 082aea4e [DEFAULT] [hasThis] Void System.Web.UI.Control.InitRecursive(Class System.Web.UI.Control)
at [+0x136] [+0xc5]
00ebf894 0824ec8c [DEFAULT] [hasThis] Void System.Web.UI.Control.AddedControl(Class System.Web.UI.Control,I4)
at [+0xd4] [+0x97]
00ebf8c4 0824eb9b [DEFAULT] [hasThis] Void System.Web.UI.ControlCollection.Add(Class System.Web.UI.Control)
at [+0x113] [+0xb2]
00ebf900 0820067b [DEFAULT] [hasThis] Void DDLViewStateTest.WebForm1.Page_Load(Object,Class System.EventArgs)
at [+0x9b] [+0x46]
至此我们得到了思归在页面中的结果.
几个问题:
1.由于本机是win2000 pro版且asp.net1.1和2.0共存,我的2.0程序通过WebDev.WebServer.exe进程显示,但是我在加载此进程调试是总是不成功,经常显示类似thread not a managed thread
2.关于.loadby sos mscorwks 的确切含义,我在有的文章上看到调用sos.dll 2.0时用到,但好像不太对.我现在的处理是不管在1.0还是2.0都输入这句命令
3.在用!dumpmd <method desc>查看具体的方法描述时,有的时候得到
Method Name : [DEFAULT] [hasThis] Void System.Web.UI.WebControls.ListItemCollection.TrackViewState()
MethodTable 82c4194
Module: 17f1a8
mdToken: 0600172f (c:\winnt_1\assembly\gac\system.web\1.0.5000.0__b03f5f7f11d50a3a\system.web.dll)
Flags : 80
Method VA : 082af9f8
而调试其他代码有时候得到
0:010> !dumpmd 8153e68
Method Name : [DEFAULT] [hasThis] Void System.Web.UI.IStateManager.LoadViewState(Object)
MethodTable 8153ed8
Module: 17f1a8
mdToken: 06000eb7 (c:\winnt_1\assembly\gac\system.web\1.0.5000.0__b03f5f7f11d50a3a\system.web.dll)
Flags : 405
IL RVA : 00000000
0:010> !dumpmd 807b778
Method Name : [DEFAULT] [hasThis] Void CustomComponents.Custom.LoadViewState(Object)
MethodTable 807b7c4
Module: 1c4198
mdToken: 06000021 (c:\winnt_1\microsoft.net\framework\v1.1.4322\temporary asp.net files\viewstatetest\08d00385\afe4cae1\assembly\dl2\76a83f92\304f7da9_925fc701\viewstatetest.dll)
Flags : 0
IL RVA : 00002804
我的理解是Method VA是属于Ngened代码,而IL RVA是属于Jitted代码,因此需要采用另外的设置断点的方法
(1) 查找MethodDesc:
(2) 在该MethodDesc的m_CodeOrIL域(MethodDesc的地址加4)上设置一个内存断点:
例: ba w4 975070+0x04 "bp poi(975070+0x04);g"
上面的断点的意思是在m_CodeOrIL被改变后在m_CodeOrIL中存储的地址上设置代码断点并继续执行。 参考文章在托管代码中设置断点(WINDBG)
但我却没有成功,总是显示
Unable to insert breakpoint 1 at c0000000, Win32 error 998
"内存分配访问无效。"
The breakpoint was set with BP. If you want breakpoints
to track module load/unload state you must use BU.