wenmo8 发布的文章

简介

!runaway扩展显示有关每个线程使用的时间的信息。

使用形式

!runaway [Flags]

参数

  • Flags
    指定要显示的信息类型。 标志可以是以下位的任意组合。 默认值为 0x1。
    位 0 (0x1)
    使调试器以显示每个线程使用的用户时间量。

    位 1 (0x2)
    使调试器以显示每个线程使用的内核时间量。

    位 2 (0x4)
    使调试器以显示每个线程创建以来已经过去的时间量。

支持环境

Windows 2000

Uext.dll Ntsdexts.dll

Windows XP 及更高版本

Uext.dll Ntsdexts.dll

说明

这个扩展是一种快速的方法,可以找出哪些线程正在失控地旋转或占用太多的CPU时间。显示标识每个线程由调试器的内部线程编号和线程 ID 以十六进制格式。 调试器 Id 也会显示。
下面是一个例子:

0:001> !runaway 7

 User Mode Time
 Thread       Time
 0:55c        0:00:00.0093
 1:1a4        0:00:00.0000

 Kernel Mode Time
 Thread       Time
 0:55c        0:00:00.0140
 1:1a4        0:00:00.0000

 Elapsed Time
 Thread       Time
 0:55c        0:00:43.0533
 1:1a4        0:00:25.0876

 

大家都知道,在调试托管代码时,一定会加载到sos/clr/mscorwks/mscordacwks这些动态库,才能够很好的完成我们的调试工作,那么他们的版本对应关系是怎样的呢,特别是clr.dll/mscorwks.dll有什么关系呢?

clr是通用语言运行时库,对应的就是clr.dll/mscorwks.dll,在clr发展过程中,文件名发生了变化,他们的版本对应关系如下:

.NET framework 版本CLR 版本CLR 文件名
1.1 1.1 mscorwks.dll
2.0 2.0 mscorwks.dll
3.0 2.0 mscorwks.dll
3.5 2.0 mscorwks.dll
4.0 4.0 clr.dll
4.5 4.0 clr.dll

我们在进行托管代码调试时,还会使用到sos.dll和mscordacwks.dll这两个动态库:

  • SOS.dll
    SOS 调试扩展 (SOS.dll) 通过提供有关内部公共语言运行时 (CLR) 环境的信息,帮助你在 Visual Studio 和 Windows 调试器 (WinDbg.exe) 中调试托管程序。
  • mscordacwks.dll
    这是进行调试的数据访问组件 (DAC)。SOS和CLR调试器使用 Data Access Component (DAC)来实现进程外调试,DAC原则上可以视做CLR执行引擎的子集。它能用在转储文件上,甚至是在CLR未安装的机器上面工作,其实现主要包括一组宏和模板,结合执行引擎代码的条件编译。当编译runtime时,clr.dll和mscordacwks.dll同时生成。为了检索对象,DAC可以读取其内存,获取mscordacwks中VM代码的输入。 然后,它可以在宿主机中运行相应的函数来计算有关托管结构所需的信息,并将最终结果返回给调试器。
    请注意。DAC需要读取对象进程的内存。调试进程和调试对象进程是独立的,地址空间也是独立的。因此需要清楚的区分对象内存和宿主(调试器)内存。在宿主进程中使用目标地址结果无法预料,通常情况下是错误的结果。当使用DAC检索目标内存时,在正确的地址空间中使用目标地址时十分重要的,此外,有时目标地址严格用作数据,在这种情况下,使用主机地址同样不正确,比如,要显示一个托管函数的信息,可能需要列出开始的地址,地址大小。当在VM文件夹下编辑DAC可能运行的代码时,需要正确的选择宿主地址或者目标进程地址。

请注意  对于所有版本的.NET Framework 中,该 DAC 的文件名是 mscordacwks.dll,,SOS 调试扩展的文件名为 sos.dll。

若要验证 mscordacwks.dll 版本与应用程序使用的 clr 的版本相匹配,请输入以下命令以显示有关已加载的 CLR 模块信息之一:

  • lmv mclr (适用于 CLR 版本 4.0)
  • lmv mscorwks (适用于版本 1.0 或 2.0 CLR)

简介

sx*命令控制调试器在正在调试的应用程序中发生异常或发生某些事件时采取的操作。

使用形式

sx

sx{e|d|i|n} [-c "Cmd1"] [-c2 "Cmd2"] [-h] {Exception|Event|*}

sx- [-c "Cmd1"] [-c2 "Cmd2"] {Exception|Event|*}

sxr

参数

  • -c " Cmd1 "
    指定在发生异常或事件时执行的命令。 当处理此异常的第一次机会发生时,无论此异常是否中断调试器,都将执行此命令。 必须将Cmd1字符串用引号引起来。 此字符串可以包含用分号分隔的多个命令。 -C 和带引号的命令字符串之间的空格是可选的。
  • -c2 " Cmd2 "
    指定在发生异常或事件并且在第一次机会未处理时执行的命令。 当第二次处理此异常时,会执行此命令,无论此异常是否中断调试器。 必须将Cmd2字符串用引号引起来。 此字符串可以包含用分号分隔的多个命令。 -C2 和带引号的命令字符串之间的空格是可选的。
  • -h
    更改指定事件的处理状态,而不是其中断状态。 如果事件cchcbpecssec,则无需使用 -h选项。
  • Exception
    以当前基数指定命令作用于的异常号。
  • Event
    指定命令所作用的事件。这些事件用简短的缩写来表示。
  • *
    影响所有未以其他方式显式命名为sx的异常。

支持环境

模块

用户模式,内核模式

目标

仅限实时调试

适用

全部

说明

sx命令显示当前进程的异常列表和所有非异常事件的列表,并显示每个异常和事件的调试器的默认行为。SXE、SXD、SXN和SXI命令控制每个异常和事件的调试器设置。sxr命令将所有异常和事件筛选器状态重置为默认设置。命令将被清除,中断和继续选项将重置为其默认设置,依此类推。sx-命令不会更改指定异常或事件的处理状态或中断状态。如果希望更改与特定事件关联的第一次机会命令或第二次机会命令,但不希望更改任何其他命令,则可以使用此命令。如果包含-h选项(或者如果指定了CC、HC、BPEC或SSEC事件),则SXE、SXD、SXN和SXI命令控制异常或事件的处理状态。在所有其他情况下,这些命令控制异常或事件的中断状态。
设置中断状态时,这些命令具有以下效果:

CommandStatus nameDescription

sxe

Break

(Enabled)

发生此异常时,目标会在激活任何其他错误处理程序之前立即中断调试器。 这种处理称为第一次机会处理。

sxd

Second chance break

(Disabled)

对于此类型的第一次异常,调试器不会中断(尽管显示了一条消息)。 如果其他错误处理程序未解决此异常,将停止执行,并将目标中断到调试器中。 这种处理称为第二次机会处理。

sxn

Output

(Notify)

发生此异常时,目标应用程序根本不会中断调试器。 但是,会显示一条消息,通知用户此异常。

sxi

Ignore

发生此异常时,目标应用程序根本不会中断调试器,而且不显示任何消息。

设置处理状态时,这些命令具有以下效果:

CommandStatus nameDescription

sxe

Handled

继续执行时,该事件被视为已处理。

sxd,sxn,sxi

Not Handled

继续执行时,该事件被视为未处理。

可以结合使用 -h选项和异常,而不是事件。 将此选项与chbpesse一起使用将分别设置hcbpecssec的处理状态。 如果对任何其他事件使用-h 选项,则该选项不起作用。-c-c2选项与hcbpecssec一起使用时,会将指定的命令分别与chbpesse关联。

在下面的示例中, sxe命令用于将访问冲突事件的中断状态设置为在第一次机会时中断,并设置将在该点执行到r eax的第一条命令。 然后使用sx命令将第一条命令更改为r ebx,而无需更改处理状态。 最后,显示sx输出的一部分,指示访问冲突事件的当前设置:

0:000> sxe -c "r eax" av

0:000> sx- -c "r ebx" av

0:000> sx
 av - Access violation - break - not handled
       Command: "r ebx"

SOS.DLL、SOSEX.DLL这两个就是用来对.NET程序在Windows调试工具中起到翻译作用的调试器扩展。简单讲就是,这两个组件是.NET项目组专门开发出来用来对.NET应用程序进行方便调试用的,当然不用这两个扩展也能调试.NET程序,只不过就会很困难,会被很多细节束缚住。有了这个调试扩展之后,我们就可以让原生Windows调试器正确的翻译出.NET相关概念。

所有对.NET程序发起的调试会话都要经过.NET调试扩展组件进行翻译才行,也就是要使用.NET调试扩展的调试命令来调试.NET程序。上图中,我们如果要想调试.NET程序就需要将.NET调试扩展组件加载到Windows调试工具中去,然后才能方便在Windows调试工具中使用。

还有就是.NET  DAC概念。其实.NET DAC也就是.NET Data Access .NET数据访问层,这个是专门用来提供给SOS.DLL\SOSEXDLL或者其他调试扩展包使用的,所有的调试扩展组件必须通过这个DAC才能访问到.NET运行时的数据,所以在初次使用SOS的时候会经常碰见加载错误的mscordacwks.dll文件,此文件就是DAC的物理文件。

这个文件和SOS扩展文件一样,都有这不同的版本,当加载不同类型的.NET程序时会使用到不同版本的mscordacwks.dll文件,当然大部分情况下此文件时自动加载的,只有出现你分析的文件与生成调试文件的环境不一致时才会出现头疼的问题。

 

 当你知道这个组件是工作于此位置时,当出现跟它相关的错误提示时你就不需要担心了,无非就是文件加载的位置或者版本不匹配而已。

SOS扩展也是可以和VisualStudio进行集成的,这样真的方便了我们调试一些性能要求比较高的程序,当程序运行一段时间后我们用VS附加到进程,然后查看一些重要的对象数据,但是此时我们看不到.NET运行时的一些数据,比如:对象的代龄,托管堆的大小,线程池的任务等。通过集成SOS扩展会让我们对程序的运行时有了一个更加方便的跟踪。

首先对.net工程做如下设置

 

 设置断点,然后在”即时窗口“(调试->窗口->即时)中加载扩展SOS.DLL。

 

这样的便利性大大提高我们在调试程序内存方面、线程方面的好处,我们可以适当的做压力测试,然后Attach process,执行SOS扩展命名来查看内存问题,当需要调试程序逻辑时在单步调式C#代码,一举两得。