使用 Windows Debugger 调试托管代码

使用 Windows Debugger 调试托管代码

https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugging-managed-code

您可以使用 Windows debugger ( WinDbg、CDB 和 NTSD ) 来调试包含托管代码的目标应用程序。为了调试托管代码,你必须加载 SOS 调试扩展 (sos.dll) 和数据访问组件 ( mscordacwks.dll )。

Windows 调试器是与 Visual Studio 调试器分开的。关于更详细的在 Windows 调试器与 Visual Studio 调试器之间的区别,请参考:Windows Debugger

托管代码入门

托管代码是与 Microsoft .NET 公共语言运行 (CLR) 时一起执行的。在托管代码应用程序中,编译器生成的二进制代码是微软中间语言 (MSIL),它是平台无关的。

当托管代码执行的时候,运行时生成平台特定的原生代码。从 MSIL 生成原生代码的过程被称为即时编译 (JIT)。在即时编译器将特定方法的 MSIL 编译之后,方法的原生代码保留在内存中。对该方法的随后无论何时的调用,都会执行原生代码,JIT 编译器将不再参与。

你可以使用多种编译器来构建托管代码。特别是,Microsoft Visual Studio 可以从多种不同的语言,例如 C#、VB、JScript 和支持托管扩展的 C++ 来构建托管代码。

CLR 并不是伴随着 .NET Framework 的升级而升级。例如,版本 2.0、3.0 和 3.5 的 .NET Framework 都使用 2.0 版本的 CLR。下表展示了每种 .NET Framework 所使用的版本和 CLR 文件名。

.NET FrameworkCLR versionCLR 文件名
1.11.1mscorwks.dll
2.02.0mscorwks.dll
3.02.0mscorwks.dll
3.52.0mscorwks.dll
4.04.0clr.dll
4.54.0clr.dll

调试托管代码

为了调试托管代码,调试器必须加载下面两个组件:

  1. 数据访问组件 (DAC) (mscordacwks.dll)
  2. SOS 调试扩展 (sos.dll)

注意:对于所有版本的 .NET Framework 来说,DAC 的文件名都是 mscordacwks.dll,而 SOS 调试扩展的文件名则是 sos.dll

获得 SOS 调试扩展 (sos.dll)

SOS 调试扩展 (sos.dll) 文件并不包含在当前版本的 Windows 调试工具中。

对于 .NET Framework 2.0 和以后的版本,sos.dll 包含在 .NET Framework 的安装中。

对于 .NET Framework 1.x 版本,sos.dll 不包含在 .NET Framework 的安装中。为了获得 .NET Framework 1.x 对应的 sos.dll,请下载 32 位版本的 Windows 7 调试工具 Windows 版本。

Windows 7 调试工具 Windows 版包含在 Windows SDK 的 Windows 7 版本中,可以从下面两个位置获得:

如果你运行在 64 位的 Windows 下,使用 该 ISO,以便指定你希望 32 位版本的 SDK,sos.dll 仅仅包含在 32 位版本的 Windows 7 调试工具中。

加载 mscordacwks.dll 和 sos.dll ( 现场调试 )

假设调试器和被调试的应用程序运行在同一台机器上。而应用程序所使用的 .NET Framework 也被安装在该计算机上,可以被调试器所使用。

调试器必须加载与托管代码应用程序所使用的 CLR 相同版本的 DAC。平台也必须匹配 ( 32 位或者 64 位 )。DAC (mscordacwks.dll) 来自 .NET Framework。为了加载正确的 DAC 版本,将调试器挂接到托管代码应用程序上,然后输入如下命令

.cordll -ve -u -l

输出应该与下面内容类似:

CLRDLL: Loaded DLL C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscordacwks.dll
CLR DLL status: Loaded DLL C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscordacwks.dll

为了验证 mscordacwks.dll 的版本匹配应用程序所使用的版本,输入下面命令之一来显示当前加载的 CLR 模块。

  • lmv mclr (for version 4.0 of the CLR)
  • lmv mscorwks (for version 1.0 or 2.0 of the CLR)

输出应该类似下面:

start             end                 module name
000007ff`26710000 000007ff`2706e000   clr        (deferred)             
    Image path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
...

我机器上使用的另一个示例输出

0:000> lmv mclr
Browse full module list
start    end        module name
73db0000 74521000   clr        (deferred)             
    Image path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
    Image name: clr.dll
    Browse all global symbols  functions  data
    Timestamp:        Sat Apr  2 00:08:10 2022 (6247236A)
    CheckSum:         00778D86
    ImageSize:        00771000
    File version:     4.7.3946.0
    Product version:  4.0.30319.0
    File flags:       8 (Mask 3F) Private
    File OS:          4 Unknown Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0409.04b0
    Information from resource tables:
        CompanyName:      Microsoft Corporation
        ProductName:      Microsoft® .NET Framework
        InternalName:     clr.dll
        OriginalFilename: clr.dll
        ProductVersion:   4.7.3946.0
        FileVersion:      4.7.3946.0 built by: NET472REL1LAST_B
        PrivateBuild:     DDBLD305B
        FileDescription:  Microsoft .NET Runtime Common Language Runtime - WorkStation
        LegalCopyright:   © Microsoft Corporation.  All rights reserved.
        Comments:         Flavor=Retail

在前面的示例中,注意到 CLR (clr.dll) 的版本匹配 DAC (mscordacwks.dll) 的版本 : v4.0.30319。同时注意到它们的组件都是 64 位。

当你使用 .cordll 来加载 DAC 的时候,SOS 调试扩展 (sos.dll) 可能已经自动加载了。如果 sos.dll 没有自动加载,你可以使用下面的命令之一来加载:

  • .loadby sos clr (for version 4.0 of the CLR)
  • .loadby sos mscorwks (for version 1.0 or 2.0 of the CLR)

除了使用 .loadby,你还可以使用 .load。例如,加载 4.0 版的 64 位 CLR,你可以使用如下命令:

.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll

在上面的输出中,注意 SOS 调试扩展 (sos.dll) 的版本匹配 CLR 的版本和 DAC 的版本:v4.0.30319。还要注意到所有的组件都是 64 位的。

加载 mscordacwoks.dll 和 sos.dll (dump 文件)

假设你使用调试器打开一个 dump 文件 (托管代码应用程序),它在其它计算机上被创建出来。

调试器必须加载该运行在其它计算机上的托管代码应用程序相同版本的 CLR 的 相同版本的 DAC。平台位数必须匹配 ( 32 位或者 64 位 ).

DAC ( mscordacwks.dll ) 来自 .NET Framework,但是我们假设你并没有正确版本的 .NET Framework 安装在运行调试器的计算机上。你可以有如下选择:

  • 从符号服务器加载 DAC。例如,你可以包含 Microsoft 的公共符号服务器到你的符号路径中
  • 安装正确版本的 .NET Framework 到运行调试器的计算机上
  • 从创建该 dump 文件的人那里获得正确版本的 mscordacwks.dll ( 在其它计算机上 ),然后手工复制到运行调试器的计算机上。

这里说明一下 Microsoft 的符号服务器。

输入下面的命令

.sympath+ srv\* (Add symbol server to symbol path.)
!sym noisy
.cordll -ve -u -l

输入类似下面内容:

CLRDLL: Unable to get version info for 'C:\Windows\Microsoft.NET
   \Framework64\v4.0.30319\mscordacwks.dll', Win32 error 0n87

SYMSRV:  C:\ProgramData\dbg\sym\mscordacwks_AMD64_AMD64_4.0.30319.18010.dll
   \5038768C95e000\mscordacwks_AMD64_AMD64_4.0.30319.18010.dll not found

SYMSRV:  mscordacwks_AMD64_AMD64_4.0.30319.18010.dll from 
   https://msdl.microsoft.com/download/symbols: 570542 bytes - copied         
...
SYMSRV:  C:\ProgramData\dbg\sym\SOS_AMD64_AMD64_4.0.30319.18010.dll
   \5038768C95e000\SOS_AMD64_AMD64_4.0.30319.18010.dll not found

SYMSRV:  SOS_AMD64_AMD64_4.0.30319.18010.dll from 
   https://msdl.microsoft.com/download/symbols: 297048 bytes - copied         
...
Automatically loaded SOS Extension
...

在上面的输出中,你可以看到调试器首先从本地计算机的 C:\Windows\Microsoft.NET 和符号缓存 (C:\ProgramData\dbg\sym) 中加载 mscordacwks.dll 和 sos.dll。当调试器不能在本地计算机上找到正确版本的该文件时,它通过公共符号服务器来获取它。

为了验证 mscordacwks.dll 的版本匹配应用程序所使用的版本,输入下面的命令来显示关于加载的 CLR 模块的信息。

lmv -mclr (for version 4.0 of the CLR)
lmv -mscorwks (for version 1.0 or 2.0 of the CLR)

输入应该类似:

start             end                 module name
000007ff`26710000 000007ff`2706e000   clr        (deferred)             
    Image path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
...

在上面的示例中,注意到 CLR (clr.dll) 的版本匹配 DAC (mscordacwks.dll) 的版本:v4.0.30319。并注意到组件都是 64 位的。

使用 SOS 调试扩展

为了验证调试器扩展已经正确加载,输入 .chain 命令:

0:000> .chain
Extension DLL search Path:
...
Extension DLL chain:
    C:\ProgramData\dbg\sym\SOS_AMD64_AMD64_4.0.30319.18010.dll\...
        ...
    dbghelp: image 6.13.0014.1665, API 6.2.6, built Wed Dec 12 03:02:43 2012

为了测试 SOS 扩展,输入 .help 命令。然后尝试 SOS 扩展所提供的命令之一。例如,你可以尝试 .DumpDomain 或者 .Threads 命令。

备注

有的时候,托管代码加载多于一个版本的 CLR。在这种场景下,你必须指定所加载的 DAC 版本。详细信息请参阅 .cordll

这是一个windows脚本调试器程序。 绿色:只需复制文件到同一目录下就可以了。 纯净:基本不使用注册表,只是在注册文件类型图标和文件关联时才使用了注册表。 无毒:绝对没有任何恶意代码,但是由于程序会自动产生临时的批处理文件,可能会被杀毒软件误报。 注意:如果不能启动,下载vcredist_x86.exe安装VC运行库,然后再试。 已经实现的功能: 设置断点; 在断点命中时在代码编辑器指示哪个断点被命中。 在断点命中时可以观察现场状态【变量、ErrorLevel、当前目录】; 如果批处理没有用Exit退出,那么可以观察到批处理执行完的现场状态; 调试暂停时会自动打开/切换文件并滚动代码窗口,使当前断点可见; 可以预设批处理执行前的环境变量和当前目录。 工程管理,也就是管理批处理文件、断点、观察变量、初始环境变量、初始当前目录、批处理入口文件、批处理文件命令行参数的信息。 支持用户自定义界面,使用标签多文档界面和停靠栏。 双击.bdc文件,会启动windows脚本调试器。 附带使用手册和批处理指南。 准备实现的功能: 在断点命中时修改环境变量或者当前目录; 语法分析【代码着色、语法检查的基础】; 语法检查; 代码着色; 内置命令帮助; 不打算实现的功能: 我感觉批处理编程并不能提供多少智能提示,所以就不做了。 局限性: 代码编辑器暂时不支持中文,这个是最大的限制了,我会在下个版本解决这个问题; 只可以在批处理语句之前加断点,不可以在空行、标签行和右括号)开头的行加断点,不可以在非批处理代码处加断点; 不支持单步调试; 必须在调试之前加断点,在调试之后加的断点,只能在以后的调试会话中起作用。 启动批处理脚本只能接受10个参数,这个限制好像问题不大。 目前可能还有bug。 注意: 不要调试本程序所在目录下的那三个批处理程序,否则会出现无法预料的行为。为了保险,请把他们设为只读隐藏文件。 可以把halt.exe也设为只读隐藏文件。 我会持续改进本程序。 email: cdp97531@sina.com blog: http://hi.baidu.com/chendeping/home
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值