大佬教程收集整理的这篇文章主要介绍了.NET / Rotor源码研究3 – 调试Rotor托管代码的利器:WinDbg和SOS,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
在动手进一步研究Rotor之前,我们需要首先解决一个问题:用什么调试工具最好? 很有可能你会说,这还不简单,直接用Visual studio不就好了?一般情况下是的,只不过,在这个情况下,Visual studio并非是最好的选择:
1. CLR对代码的编译是动态进行的(其实还有可能是静态的,称之为Prejit或者NGEN,不过可惜Rotor对此不支持),也就是说常规的设置断点的方法并不适用,因为可能这个时候对应的本地代码还没有生成呢
2. CLR是一个复杂的运行时环境/虚拟机。有些时候我们需要获得CLR的一些相关信息,而这个时候Visual studio就显得功能不够强大
你可能会说,那为什么VS可以调试托管代码呢?确实,VS是可以调试托管代码,但是注意我们是调试CLR本身,这个时候VS本身的对托管代码的调试功能会造成不少麻烦,得到一些你所不希望的结果。此外,由于我们是在调试Rotor,这个时候不能直接运行托管代码,而是要在CLIX的支持下运行,这也使得VS的托管代码调试功能无效。
这个时候,相对而言较好的工具是WinDbg+SOS的组合。
WinDbg是微软提供的Windows下面的免费调试器,具有下面特点:
2. 支持GUI(虽然看起来是废话,不过WinDbg也有所谓命令行版本NTSD/CDB/KD,相对于这几个调试器而言WinDbg算是很友好的了)
3. 支持远程调试
6. 非常轻量级,完整地版本仅数十兆(相对于VS而言),如果只需要调试器本身,还可以更小
8. 可扩展
WinDbg可以在下面的地址下载:
32位版本:http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx
64位版本:http://www.microsoft.com/whdc/devtools/debugging/install64bit.mspx
SOS全称是Son of Strike(别问我为什么,我也不知道,这个要问Larry了),是一个WinDbg的Extension,加载之后可以给WinDbg提供一些对托管代码调试的命令。值得一提的是,WinDbg也有有限的对托管代码的支持,只不过功能非常有限,需要SOS的帮助。
SOS在.NET Framework中和Rotor中均有提供,所以本文中对于WinDbg和SOS的描述基本上适用于Rotor和发行版的.NET Framework(而且有可能也将适用于Silverlight)。比如.NET Framework 2.0中的SOS在C:/Windows/Microsoft .NET/v2.0.50727下面,而Rotor的SOs.dll则是在binaries.<flavor>.rotor目录下面(flavor指Build的配置,如cpu,Debug/Release,等等)。
SOS可以做到:
2. 察看CLR的数据结构
3. 察看代码和堆栈
4. 显示各种历史信息
5. 提供各种诊断信息
SOS有如下限制:
1. 不可以在@H_243_29@mscorwks加载之前被使用
2. 无法察看局部对象的名称
3. 以及很多其他的功能
SOS使用方法如下:
1. 使用.loadby / .load 命令加载。但是Rotor下面SOS由于对VC Runtime的依赖会发生Side By Side相关的问题导致无法找到@H_243_29@mSVCR80.dll或者@H_243_29@mSVCR80D.dll。解决方法在文章最后会提到
2. !Help命令可以提供所有命令的列表
4. !Help <command>显示具体Command的帮助
WinDbg+SOS的优势在于:
@H_572_673@1. WinDbg的本地代码(非托管代码)调试功能非常强,甚至比VS还强大,只是需要一些时间习惯2. SOS是调试托管代码必须的,提供一些基本功能如设置对托管代码的断点,显示变量和Stack,等等
3. SOS可以用来查询对CLR内部的状态,如GC,Heap,@H_243_29@methodTable,@H_243_29@methodDesc,@H_243_29@module,Assembly等等各种信息,对于除错和诊断非常有用
由于SOS是在WinDbg进程中加载,而WinDbg的@H_243_29@manifest中并没有VC Runtime调试版的DLL的Side By Side信息,所以加载会失败。解决方法有下面的两种:
@H_377_801@1. Copy相应的的DLL到WinDbg目录或者到Rotor的目录下面。我的VS2005编译出来的SOs.dll依赖于8.0.50727.762版本的@H_243_29@mSVCR80D.dll,因此可以在C:/windows/WinSxS/x86_microsoft.vc80.debugcrt_1fc8b3b9a1e18e3b_8.0 .50727.762_none_24c8a196583ff03b目录下面找到。2. 也可以从WinDbg的@H_243_29@manifest入手解决这个问题。既然WinDbg的@H_243_29@manifest没有@H_243_29@mSVCR80D的相关信息,我们可以手动替WinDbg加上一个,步骤如下:
首先使用@H_243_29@mt.exe将WinDbg的@H_243_29@manifest提取出来,这个@H_243_29@manifest是在WinDbg.exe中作为资源存在的,其ID为1。先打开VS 2005的命令提示符(否则找不到@H_243_29@mt),进入WinDbg所在目录,输入:
@H_103_944@
@H_103_944@@H_956_945@mt.exe -inputresource:windbg.exe;#1 -out:extracted.manifest |
获得了WinDbg的@H_243_29@manifest之后,打开extracted.manifest可以看到下面内容:
@H_103_944@<?xml version="1.0" encoding="UTF-8" standalone="yes"?> @H_103_944@<assembly xmlns="urn:scheR_855_11845@as-microsoft-com:asm.v1" manifestVersion="1.0"> @H_103_944@<assemblyIdentity name="Microsoft.Windows.SdkTools.windbg" processorArchitecture="x86" version="6.7.0.0" type="win32"></assemblyIdentity> @H_103_944@<description>Windows GUI symbolic debugger</description> @H_103_944@<dependency> @H_103_944@ <dependentAssembly> @H_103_944@ <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity> @H_103_944@ </dependentAssembly> @H_103_944@</dependency> @H_103_944@</assembly> |
可以看到里面并没有对于@H_243_29@mSVCR80D.dll的信息,我们可以自己动手加上去:
@H_103_944@<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@H_103_944@<assembly xmlns="urn:scheR_855_11845@as-microsoft-com:asm.v1" manifestVersion="1.0">
@H_103_944@<assemblyIdentity name="Microsoft.Windows.SdkTools.windbg" processorArchitecture="x86" version="6.7.0.0" type="win32"></assemblyIdentity>
@H_103_944@<description>Windows GUI symbolic debugger</description>
@H_103_944@<dependency>
@H_103_944@ <dependentAssembly>
@H_103_944@ <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
@H_103_944@ </dependentAssembly>
@H_103_944@</dependency>
@H_103_944@<dependency>
@H_103_944@ <dependentAssembly>
@H_103_944@ <assemblyIdentity type="win32" name="Microsoft.VC80.DebugCRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
@H_103_944@ </dependentAssembly>
@H_103_944@</dependency>
@H_103_944@
@H_103_944@</assembly> |
其中深红色的为添加的内容,意思是该EXE依赖于@H_243_29@microsoft.VC80.DebugCRT这个DLL,version 8.0.50727.762,architecture为x86,public key token为1fc8b3b9a1e8e3b。Windows会自动根据这个信息找到对应的@H_243_29@mSVCR80D.dll。
下面我们可以动手修改WinDbg了,建议动手之前WinDbg之前请先备份WinDbg。准备好了之后键入:
@H_103_944@
@H_103_944@@H_956_945@mt.exe -manifest extracted.manifest -outputresource:windbg.exe;#1 @H_103_944@ |
这个命令会将@H_243_29@manifest作为资源重新添加到WinDbg.exe,覆盖原来的@H_243_29@manifest,至此WinDbg已经被我们修改了。验证一下,用WinDbg打开CLIX.exe进行调试,然后键入如下命令:
@H_103_944@
@H_103_944@.loadby sos sscoree @H_103_944@ |
没有看到任何输出,说明加载成功。再输入
@H_103_944@
@H_103_944@!Help @H_103_944@ |
SOS会输出所有命令的列表。
经过修改之后,SOS可以被正常加载了。很遗憾的是,在我后续的对Rotor的实验中,发现Rotor的代码中对SOS的BPMD命令和CLR notification支持存在问题,而BPMD命令正好是SOS的最重要功能之一:设置断点。在我的下一篇文章中,会讲到问题的具体情况以及如何修改Rotor代码来支持CLR Notification和SOS的BPMD命令。在修改了Rotor代码使SOS正常工作之后,再下一篇文章则会以跟踪一个简单的HelloWorld的托管代码程序来揭示Rotor的基本运行机制和原理,敬请关注。
以上是大佬教程为你收集整理的.NET / Rotor源码研究3 – 调试Rotor托管代码的利器:WinDbg和SOS全部内容,希望文章能够帮你解决.NET / Rotor源码研究3 – 调试Rotor托管代码的利器:WinDbg和SOS所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。