windbg调试C#代码(一)
2015-09-28 12:09
351 查看
用windbg调试C#代码是比较麻烦的,因为windbg是针对OS层级的,而C#被CLR隔了一层,很多原生的命令如查看局部变量dv、查看变量类型dt等在CLR的环境中都不能用了。必须使用针对CLR的扩展命令,比如sos、psscor2中的命令。下面以一个最简单的WPF程序来说明调试的典型步骤,以及典型的坑。
如果是.dump文件,恐怕就要在获取的时候,查看对应进程的信息了。
判断是.net2.0 or .net4.0的程序:lmvm clr,如果有详细信息,表示是net40的程序。如果为none,则lmvm mscorwks,显示详情则表示是net20的程序。
根据net20 or net40用.loadby sos clr或.loadby sos mscorwks加载对应的sos版本。当然也可以使用.load [moduleName]直接加载,但要确保版本正确。
可以用.chain查看已加载的extension,如果没有sos之类的,那么这个扩展下的命令都不可用,比如!DumpDomain 会报“No export NoExist found”。
不同的扩展可能存在相同的命令,比如sos和psscor2里大部分命令都是同名的,可能参数列表不同。可以用[extension].[command]的方式区分,比如!sos.DumpDomain和!psscor2.DumpDomain。如果不加extensionName,那么会默认使用.chain列表出来的第一个扩展的命令。
如果加载不成功,可以.cordll -ve -u -l看到出错的详细信息,一般都是版本没有正确匹配。一般都建议:不论是32位还是64位的进程,都抓32位的dump;具体操作中,由于TaskMgr和ProcExp都存在32位+64位的版本,因此强烈建议只用ProcDump -ma [ProcessName]抓Dump,然后根据Process的32 or 64位,选用Windbg的x86 or x64位。比如,我一个64位的进程,抓了一个64位的dump,.loadby sos clr时报如下错:
2.2、如果是自己写的代码,那就方便了,直接:
可以看出汇编与源码间的对应关系,比如我们想修改c = 25,可以F10到“mov dword ptr [ebp-14h],eax”这一步,如下:
run下去,可以看到MessageBox.Show出来的是25。另外也可以配合!DumpHeap、!DumpStackObjects(dso)、!DumpObj(do)等命令查找感兴趣的对象。最后,多看帮助,windbg的帮助非常详实。多看extension自带的帮助:!sos.help、!help DumpDomain等。
change local stack variable value
1、用正确版本的windbg、加载正确版本的扩展模块
把程序跑起来,看任务管理器中是32位 or 64位进程,32-bit用windbg x86、64-bit用windbg x64调试。如果是.dump文件,恐怕就要在获取的时候,查看对应进程的信息了。
判断是.net2.0 or .net4.0的程序:lmvm clr,如果有详细信息,表示是net40的程序。如果为none,则lmvm mscorwks,显示详情则表示是net20的程序。
根据net20 or net40用.loadby sos clr或.loadby sos mscorwks加载对应的sos版本。当然也可以使用.load [moduleName]直接加载,但要确保版本正确。
可以用.chain查看已加载的extension,如果没有sos之类的,那么这个扩展下的命令都不可用,比如!DumpDomain 会报“No export NoExist found”。
不同的扩展可能存在相同的命令,比如sos和psscor2里大部分命令都是同名的,可能参数列表不同。可以用[extension].[command]的方式区分,比如!sos.DumpDomain和!psscor2.DumpDomain。如果不加extensionName,那么会默认使用.chain列表出来的第一个扩展的命令。
如果加载不成功,可以.cordll -ve -u -l看到出错的详细信息,一般都是版本没有正确匹配。一般都建议:不论是32位还是64位的进程,都抓32位的dump;具体操作中,由于TaskMgr和ProcExp都存在32位+64位的版本,因此强烈建议只用ProcDump -ma [ProcessName]抓Dump,然后根据Process的32 or 64位,选用Windbg的x86 or x64位。比如,我一个64位的进程,抓了一个64位的dump,.loadby sos clr时报如下错:
0:000> .loadby sos clr The call to LoadLibrary(C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos) failed, Win32 error 0n193 “%1 is not a valid Win32 application.” Please check your debugger configuration and/or network access.
2、如何查看元数据,如何在感兴趣的地方下断点
2.1、如果不是自己写的代码,可以用如下命令:!DumpDomain Module Name 00252eac D:\project\TestWindbg_LocalVariables\TestWindbg_LocalVariables\bin\Debug\TestWindbg_LocalVariables.exe !DumpModule -mt [moduleName, such as: 00252eac] MT TypeDef Name ------------------------------------------------------------------------------ 00258b6c 0x02000002 TestWindbg_LocalVariables.MainWindow 002572b4 0x02000003 TestWindbg_LocalVariables.App !DumpMT -md 00258b6c Entry MethodDe JIT Name 003e02e8 00258afc JIT TestWindbg_LocalVariables.MainWindow.Button_Click(System.Object, System.Windows.RoutedEventArgs) !bpmd -md 00258afc MethodDesc = 00258afc Setting breakpoint: bp 003E02E8 [TestWindbg_LocalVariables.MainWindow.Button_Click(System.Object, System.Windows.RoutedEventArgs)]
2.2、如果是自己写的代码,那就方便了,直接:
!bpmd TestWindbg_LocalVariables MainWindow.Button_Click
3、如何查看和修改局部变量
Button_Click里的源码如下:private void Button_Click(object sender, RoutedEventArgs e){ int a = 1; int b = 22; int c = a + b; MessageBox.Show(c.ToString()); } !clrstack -i //能很方便的提供对命令的链接 Child SP IP Call Site 003ce5e0 003e0326 [DEFAULT] [hasThis] Void TestWindbg_LocalVariables.MainWindow.Button_Click(Object,Class System.Windows.RoutedEventArgs) (D:\project\TestWindbg_LocalVariables\TestWindbg_LocalVariables\bin\Debug\TestWindbg_LocalVariables.) !ClrStack -i -a 0 PARAMETERS: + TestWindbg_LocalVariables.MainWindow this @ 0x268652c + System.Windows.Controls.Button sender @ 0x269b1d4 + System.Windows.RoutedEventArgs e @ 0x2756720 LOCALS: + int a = 1 + int b = 22 + int c = 0 !U /d 003e0326 d:\project\TestWindbg_LocalVariables\TestWindbg_LocalVariables\MainWindow.xaml.cs @ 30: 003e0318 c745f401000000 mov dword ptr [ebp-0Ch],1 d:\project\TestWindbg_LocalVariables\TestWindbg_LocalVariables\MainWindow.xaml.cs @ 31: 003e031f c745f016000000 mov dword ptr [ebp-10h],16h d:\project\TestWindbg_LocalVariables\TestWindbg_LocalVariables\MainWindow.xaml.cs @ 32: >>> 003e0326 8b45f4 mov eax,dword ptr [ebp-0Ch] 003e0329 0345f0 add eax,dword ptr [ebp-10h] 003e032c 8945ec mov dword ptr [ebp-14h],eax // F10到这一步,寄存器eax里add的结果,即将被存到c里,修改eax即可 d:\project\TestWindbg_LocalVariables\TestWindbg_LocalVariables\MainWindow.xaml.cs @ 33: 003e032f 8d4dec lea ecx,[ebp-14h] 003e0332 e8e9001355 call mscorlib_ni+0x2e0420 (55510420) (System.Int32.ToString(), mdToken: 06000d5f) 003e0337 8945e4 mov dword ptr [ebp-1Ch],eax 003e033a 8b4de4 mov ecx,dword ptr [ebp-1Ch] 003e033d e862a04005 call PresentationFramework_ni+0x9fa3a4 (057ea3a4) (System.Windows.MessageBox.Show(System.String), mdToken: 06006934) 003e0342 8945e8 mov dword ptr [ebp-18h],eax
可以看出汇编与源码间的对应关系,比如我们想修改c = 25,可以F10到“mov dword ptr [ebp-14h],eax”这一步,如下:
eax=00000017 // 0x17=23 r eax=19 r eax //验证一下是否已修改 eax=00000019 g !DumpHeap -type System.Windows.Controls.Button MT Count TotalSize Class Name 051bc3bc 1 248 System.Windows.Controls.Button !dso OS Thread Id: 0x310c (0) ESP/REG Object Name ebx 0269b1d4 System.Windows.Controls.Button !do -nofields 0269b1d4 Name: System.Windows.Controls.Button MethodTable: 051bc3bc EEClass: 04e39738 Size: 248(0xf8) bytes File: C:\windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework\v4.0_4.0.0.0__31bf3856ad364e35\PresentationFramework.dll
run下去,可以看到MessageBox.Show出来的是25。另外也可以配合!DumpHeap、!DumpStackObjects(dso)、!DumpObj(do)等命令查找感兴趣的对象。最后,多看帮助,windbg的帮助非常详实。多看extension自带的帮助:!sos.help、!help DumpDomain等。
4、如何分析高内存(待续)
5、如何分析高CPU(待续)
6、引用
How can I view the local variables on the evaluation stack when debugging a .NET CLR application?change local stack variable value
相关文章推荐
- 编译生成.NET DLL并调用
- C#操作IIS方法集合
- c#创建ISS站点
- WPF中Style文件的引用——使用xaml代码或者C#代码动态加载
- C# 操作word总结(一)——建立文档和添加页眉页脚
- C#学习之事件
- C# EPL USB 指令打印
- 关于C# 类型转换的问题
- 关于C# 类型转换的问题
- C#中Bitmap类 对图像の操作 可检测图片完整性
- C#多线程编程实例 线程与窗体交互
- c# 快捷键
- C#中跨线程调用windows窗体控件
- C#combox结合存储过程捆绑数据
- C# nullable<T> 用法小结
- 关于C#中关于List.where中过滤条件的使用注意事项
- C# DEV--DateEdit长日期
- C#进阶系列——DDD领域驱动设计初探(四):WCF搭建
- [C#]6.0新特性浅谈
- C#面向对象语言特性