您的位置:首页 > 其它

用WINDBG查看托管堆栈函数参数的值

2009-09-09 17:48 405 查看
我们在使用WINDBG 做LIVE debug时,经常需要在想停下来的函数上打个断点(打断点的方法我就不在这里说了,可以参看我以前的一些windbg随笔),然后用!clrstack -p 来看看调用堆栈和调用参数。但是如果函数的参数中如有泛型参数的时候,这种方法就有问题了。clrstack 的结果大致如下:

0:004> !clrstack -p
OS Thread Id: 0x1728 (4)
ESP EIP
0129e310 04f8d240 SystemService.CreateTCX12A.CreateTCSerials(ServiceInterface.Serials)
PARAMETERS:
this = 0x014e0088
sourceSerials = 0x0142accc

0129e314 04f8d21c SystemService.PreDataHandle.GetTCSerials(ServiceInterface.Serials)
PARAMETERS:
this = 0x014e0158
sourceSerials = 0x0142accc

0129e328 04f8d120 SystemService.WorkSheet.PreDataHandle()
PARAMETERS:
this = 0x014dfed0
。。。。。。
在我们可以很清楚的看到CreateTCSerials函数的参数,sourceSerials ,然后用!do 0x0142accc 指令看到参数的全貌。这是不包含泛型参数的函数堆栈信息。那么如果参数有泛型呢,那就不一样了。接下来用个例子来讲述。我有我的函数原型为:
public List<Serials> CalculateDISerials(List<Serials> SourceSerials, string CriterionSerialsName)
我在CalculateDISerials函数上打了一个断点,然后断下来后,我查看了一下堆栈信息,如下

0:009> !clrstack -p
OS Thread Id: 0xe34 (9)
ESP EIP
0391ec84 04f88647 SystemService.MainServiceProcess.CalculateDISerials(System.Collections.Generic.List`1<ServiceInterface.Serials>, System.String)
PARAMETERS:
this = 0x013165e4

0391ecd0 04f885ee SystemService.MainService.CalculateDISerials(System.Collections.Generic.List`1<ServiceInterface.Serials>, System.String)
PARAMETERS:
this = 0x01409c60

我很惊奇的发现,只要是泛型的参数这里就看不到了。那么怎么办呢?
我们知道C++和C#,在编译时,会默认把第一个this指针作为函数的第一个参数,同时在函数压栈时,参数是从左边到右,或者从右到左边依次入栈。函数的第一个参数地址入栈时,是被压入到ECX寄存器上,第二个参数是EDX寄存器上。那么我们找第一个参数和第二个参数的地址就容易了是吧。
0:009> !do edx
Name: System.Collections.Generic.List`1[[ServiceInterface.Serials, ServiceInterface]]
MethodTable: 03d64d04
EEClass: 7912f680
Size: 24(0x18) bytes
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
MT Field Offset Type VT Attr Value Name
7912d8f8 40009c7 4 System.Object[] 0 instance 01370164 _items
79102290 40009c8 c System.Int32 1 instance 20 _size
79102290 40009c9 10 System.Int32 1 instance 20 _version
790fd0f0 40009ca 8 System.Object 0 instance 00000000 _syncRoot
7912d8f8 40009cb 0 System.Object[] 0 shared static _emptyArray

ok,我们就很容易找到第一个参数的。那么如果要找接下来的参数怎么办呢?

0:009> ? edx
Evaluate expression: 20381948 = 013700fc
我们看到EDX的地址为013700fc

0:009> !dso
OS Thread Id: 0xe34 (9)
ESP/REG Object Name
ebx 013700fc System.Collections.Generic.List`1[[ServiceInterface.Serials, ServiceInterface]]
ecx 01315f74 SystemService.MainServiceProcess
edx 013700fc System.Collections.Generic.List`1[[ServiceInterface.Serials, ServiceInterface]]
0391eccc 0136f9cc System.String 工业增加值(当期)
0391ecd0 014182fc SystemService.MainService

我们看到EDX 的下一个地址 是 0136f9cc。
0136f9cc 就是第二个参数的地址了。值都已经显示出来了,就不用Do了。如果为多个参数,那就依次类推了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: