博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
windbg调试C#代码(一)
阅读量:4345 次
发布时间:2019-06-07

本文共 4844 字,大约阅读时间需要 16 分钟。

用windbg调试C#代码是比较麻烦的,因为windbg是针对OS层级的,而C#被CLR隔了一层,很多原生的命令如查看局部变量dv、查看变量类型dt等在CLR的环境中都不能用了。必须使用针对CLR的扩展命令,比如sos、psscor2中的命令。下面以一个最简单的WPF程序来说明调试的典型步骤,以及典型的坑。

1、用正确版本的windbg、加载正确版本的扩展模块

  1. 把程序跑起来,看任务管理器中是32位 or 64位进程,32-bit用windbg x86、64-bit用windbg x64调试。
  2. 如果是.dump文件,恐怕就要在获取的时候,查看对应进程的信息了。

  3. 判断是.net2.0 or .net4.0的程序:lmvm clr,如果有详细信息,表示是net40的程序。如果为none,则lmvm mscorwks,显示详情则表示是net20的程序。
  4. 根据net20 or net40用.loadby sos clr或.loadby sos mscorwks加载对应的sos版本。当然也可以使用.load [moduleName]直接加载,但要确保版本正确。

  5. 可以用.chain查看已加载的extension,如果没有sos之类的,那么这个扩展下的命令都不可用,比如!DumpDomain 会报“No export NoExist found”。
  6. 不同的扩展可能存在相同的命令,比如sos和psscor2里大部分命令都是同名的,可能参数列表不同。可以用[extension].[command]的方式区分,比如!sos.DumpDomain和!psscor2.DumpDomain。如果不加extensionName,那么会默认使用.chain列表出来的第一个扩展的命令。
  7. 如果加载不成功,可以.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 clrThe 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 Name00252eac    D:\project\TestWindbg_LocalVariables\TestWindbg_LocalVariables\bin\Debug\TestWindbg_LocalVariables.exe!DumpModule -mt [moduleName, such as: 00252eac]      MT  TypeDef Name------------------------------------------------------------------------------00258b6c 0x02000002 TestWindbg_LocalVariables.MainWindow002572b4 0x02000003 TestWindbg_LocalVariables.App!DumpMT -md 00258b6c    Entry MethodDe    JIT Name003e02e8 00258afc    JIT TestWindbg_LocalVariables.MainWindow.Button_Click(System.Object, System.Windows.RoutedEventArgs)!bpmd -md 00258afc    MethodDesc = 00258afcSetting 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 Site003ce5e0 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 0PARAMETERS:  + TestWindbg_LocalVariables.MainWindow this @ 0x268652c  + System.Windows.Controls.Button sender @ 0x269b1d4  + System.Windows.RoutedEventArgs e @ 0x2756720LOCALS:  + int a  = 1  + int b  = 22  + int c  = 0!U /d 003e0326d:\project\TestWindbg_LocalVariables\TestWindbg_LocalVariables\MainWindow.xaml.cs @ 30:003e0318 c745f401000000  mov     dword ptr [ebp-0Ch],1d:\project\TestWindbg_LocalVariables\TestWindbg_LocalVariables\MainWindow.xaml.cs @ 31:003e031f c745f016000000  mov     dword ptr [ebp-10h],16hd:\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],eax003e033a 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=23r eax=19r eax //验证一下是否已修改eax=00000019g!DumpHeap -type System.Windows.Controls.Button      MT    Count    TotalSize Class Name051bc3bc        1          248 System.Windows.Controls.Button!dsoOS Thread Id: 0x310c (0)ESP/REG  Object   Nameebx      0269b1d4 System.Windows.Controls.Button!do -nofields 0269b1d4 Name:        System.Windows.Controls.ButtonMethodTable: 051bc3bcEEClass:     04e39738Size:        248(0xf8) bytesFile:        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、引用

转载于:https://www.cnblogs.com/AlexanderYao/p/4843711.html

你可能感兴趣的文章
ThreadLocal为什么要用WeakReference
查看>>
删除本地文件
查看>>
FOC实现概述
查看>>
base64编码的图片字节流存入html页面中的显示
查看>>
这个大学时代的博客不在维护了,请移步到我的新博客
查看>>
GUI学习之二十一——QSlider、QScroll、QDial学习总结
查看>>
gethostbyname与sockaddr_in的完美组合
查看>>
kibana的query string syntax 笔记
查看>>
旋转变换(一)旋转矩阵
查看>>
thinkphp3.2.3 bug集锦
查看>>
[BZOJ 4010] 菜肴制作
查看>>
C# 创建 读取 更新 XML文件
查看>>
KD树
查看>>
VsVim - Shortcut Key (快捷键)
查看>>
HDU5447 Good Numbers
查看>>
08.CXF发布WebService(Java项目)
查看>>
java-集合框架
查看>>
RTMP
查看>>
求一个数的整数次方
查看>>
点云PCL中小细节
查看>>