您的位置:首页 > 其它

《WinDbg 命令三部曲:(二)WinDbg SOS 扩展命令手册》

2017-11-07 20:34 381 查看
对象审查命令
命令描述
!DumpObj (do)
!DumpObj               显示指定地址的对象的信息。



!DumpObj -nofields 在显示结果中不显示字段信息,这对类似 String 类型等非常有用



!DumpArray (da)
!DumpArray                 检查数组对象元素



!DumpArray -start        可选项,只支持一维数组,从指定索引处开始显示数组元素

!DumpArray -length      可选项,只支持一维数组,指定显示元素的数量

!DumpArray -details      可选项,通过使用 !DumpObj 和 !DumpVC 来打印更多详细信息

!DumpArray -nofields    可选项,仅在 -details 选项使用时有效,不显示对象的字段信息



!DumpStackObjects (dso)
!DumpStackObjects            显示当前调用栈上的所有托管对象的信息,可配合 k 或 CLRStack 命令使用

!DumpStackObjects -verify  将对非静态类中的所有字段进行检查



!DumpHeap
!DumpHeap 将遍历 GC 堆对对象进行分析。通过指定不同的选项,可以查看特定的类型、数组和锁。

                  如果不加任何选项,该命令的输出首先为堆中对象的列表,然后是包含已发现类型的列表、大小和数量的报表。



其中 “Free” 对象代表的是垃圾回收器可以使用的区域。如果此区域的大小超过30%则可能意味着出现了堆碎片。

这通常是由于某些对象被持有了较长时间,并且结合了大量高频率的内存分配。

!DumpHeap 会针对此情况提供一个关于堆碎片化的警告。



-stat              限定输出为类型统计分析的汇总

-strings          限定输出为字符串类型的统计分析汇总

-short            限定输出仅为对象的地址,这将为串行化命令调试带来便利

-min <size>    忽略尺寸小于给定的 bytes 值的对象

-max <size>   忽略尺寸大于给定的 bytes 值的对象

-live               仅输出仍然存活的对象

-dead             仅输出已死亡的对象 (这些对象将在下一个 Full GC 中被回收)

-thinlock         ThinLocks 的报告 (参考 !SyncBlk)

-startAtLowerBound              强制堆指向可使用的地址的低地址边界

-mt <MethodTable address>  仅列出包含 MethodTable 的对象

-type <partial type name>     仅列出对象类型字符串中包含给定子字符串的对象

start               从给定地址处开始列出对象

end                 从给定地址处停止检索

start/end 的参数可以通过 !EEHeap -gc 命令来获取。例如,下面的图中显示列出大对象堆中的对象。



!DumpVC
!DumpVC <MethodTable address> <Address>  

检查值类型对象的字段,在 C# 中指的是 struct,存活于栈中或者被装箱为 Object 后存放在 GC 堆中。

需要为 SOS 提供值对象的方法表地址,因为值对象与一级对象不同,一级对象的第一个字段即为方法表。



!GCRoot
!GCRoot [-nostacks] <Object address>  查询一个对象的所有引用根。

对象的引用根可能存在于如下位置:
栈上
包含在 GC 句柄中
准备被终结的对象中
在上述三点中的对象的成员中

在查询引用根时,首先在栈上查询,然后是句柄表,最后是对象终结器中的队列中的可达对象。

注:!GCRoot 不会栈上的对象根进行有效性校验。可以使用 !CLRStack 或 !U 来检查对象是否仍在被使用。

-nostacks   限定仅在句柄表和终结器队列中查找。



!ObjSize
!ObjSize [<Object address>]  

如果不加参数,!ObjSize 将列出托管线程中所有对象的尺寸。

同时,也会列出进程中的所有 GC 句柄,和句柄指向对象的大小。

在计算对象的尺寸时,!ObjSize 将计算对象及其所有子对象的大小。



!FinalizeQueue
!FinalizeQueue [-detail] | [-allReady] [-short]

!FinalizeQueue   列出所有注册为终结化的对象。



GC 堆是按照代来划分,此处同样列出每代中将被终结的对象的数量。

上图中显示了只有 0 代堆中包含了注册终结对象。"(0015bc90->0015bca0)" 提示了对象指针的内存查询区域。



-allReady   指定此选项后,将列出所有准备终结化的对象,无论其是否被标注为在当前轮 GC 还是下一轮 GC。

                那些已经不在 "Ready for finalization" 列表中的对象则已经失去了引用根。

                这个选项可能会有些开销,因为其会验证是否终结化队列中的对象是否仍然存在引用根。

-short       限定输出仅为对象的地址。

                如果与 -allReady 选项同时使用,则将列出所有存在终结器中并且不再是引用根的对象。

                如果单独使用,则将列出 "Ready for finalization" 队列中的所有对象。

-detail       显示额外的信息,例如需要被终结器清理的缓存的数据结构等。
!PrintException (pe)
!PrintException [-nested] [-lines] [<Exception object address>]

!PrintException 将对任意 System.Exception 的衍生对象的字段进行格式化。

                       例如,将对 _stackTrace 字段进行格式化。

                       如果不加任何参数,!PrintException 将查找当前线程上最有一个出现的异常。

                       这与使用 !Threads 中显示的异常是相同的。

-nested 显示嵌套的异常信息。

-lines    显示异常的可用的源信息。
!TraverseHeap
!TraverseHeap [-xml] [-verify] <filename>

!TraverseHeap  将以一种 CLR Profiler 可理解的格式将 GC 堆信息输出到文件。

可以在如下链接下载 CLR Profiler:

http://www.microsoft.com/downloads/details.aspx?FamilyId=86CE6052-D7F4-4AEB-9B7A-94635BEEBDDA&displaylang=en

CLR Profiler 将以图形化的方式来帮助分析应用程序 GC 堆的状态。

-verify  将进行更多合法性检测,可在有任何疑似堆腐化时使用。

-xml     输出格式指定为 XML 格式。



数据结构审查命令
命令描述
!DumpDomain
!DumpDomain [<Domain address>]

在无参数时,!DumpDomain 将列出进程中所有的 AppDomain 。同时也会遍历所有已加载的程序集。

在应用程序的的 AppDomain 之外,还存在另外两个特殊的应用程序域:Shared Domain 和 System Domain。

所列出的任意程序集的指针均可用于 !DumpAssembly 命令。任何 AppDomain 指针均可被使用于 !DumpDomain 命令。



!EEHeap
!EEHeap [-gc] [-loader]  遍历进程内存中的 CLR 数据结构。

!EEHeap -gc



!EEHeap -loader



!Name2EE
!Name2EE <module name> <type or method name>

!Name2EE <module name>!<type or method name>

!Name2EE 用于将给定的类名称转换为 MethodTable 或 EEClass 的地址。或将方法名称转换为 MethodDesc。



!SyncBlk
!SyncBlk [-all | <syncblk number>]

SyncBlock 负责持有一些不是为每个对象都需创建的额外信息,例如 COM Interop 数据、HashCodes、锁信息等。

例如,假设有如下代码:

lock (MyObject)
{
...
}


则将设置 MyObject 为当前线程所拥有。一个 SyncBlock 将会为 MyObject 创建,并且包含线程的宿主信息等。

如果另外一个线程试图执行同样的代码,该线程将不能进入该 Block 中直到上一个线程退出。

这将使 !SyncBlk 在检测托管线程死锁时非常有用途。例如有如下代码情形:

Resource r1 = new Resource();
Resource r2 = new Resource();

lock (r1)
{
lock (r2)
{
...
}
}

lock (r2)
{
lock (r1)
{
...
}
}




通过上面的描述可以了解到,线程 e04 持有着对象 00a7a194,而线程 ab8 持有着对象 00a7a1a4。

再结合调用栈信息可发现死锁。



此处,可通过运行 !U 或 !DumpHeap -ThinLock 获取更多信息。
!DumpMT
!DumpMT [-MD] <MethodTable address>  显示方法表。每个托管对象都在其起始位置包含一个方法表指针。

-MD 显示对象中定义的方法列表。



!DumpClass
!DumpClass <EEClass address> 显示 EEClass 中定义的属性和字段类型。

EEClass 是一种描述对象类型的数据结构。



!Token2EE
!Token2EE <module name> <token>  将 Token 元数据转换为 MethodTable 或 MethodDesc。



!EEVersion
显示 CLR 版本。同时也显示应用程序代码是运行在 "Workstation" 或 "Server" 模式。

类似的功能可以通过命令:"lm v m clr"
!DumpModule
!DumpModule [-mt] <Module address>  通过模块地址获取模块信息。



-mt 显示模块内定义的类型信息。



!ThreadPool
显示线程池的基本信息,包括队列中请求的数量、完成端口线程的数量和计时器的数量。
!DumpAssembly
!DumpAssembly <Assembly address> 显示指定地址程序集的信息。



!DumpSigElem
!DumpSigElem <sigaddr> <moduleaddr>  显示签名对象中的一个指定元素信息。



!DumpRuntimeTypes
!DumpRuntimeTypes  从 GC 堆中寻找 System.RuntimeType 类型的对象,并且打印类型名称和方法表。



!DumpSig
!DumpSig <sigaddr> <moduleaddr>  显示给定地址的方法或字段的签名信息。



!RCWCleanupList
!RCWCleanupList [address]  显示在下一次清理周期内回收的 COM 对象信息。

RuntimeCallableWrapper 是 CLR 内部的数据结构,用于宿主 COM 对象。

通过 System.__ComObject 类向托管代码暴露。

当相应的对象被 GC 回收之后,相关的 COM 对象引用也不在需要,所以相应的 RCW 也需要被清理。



!DumpIL
!DumpIL <Managed DynamicMethod object> | 
              <DynamicMethodDesc pointer> |
              <MethodDesc pointer> |
               /i <IL pointer>

打印托管方法的 IL 代码。在调试 DynamicMethod 时非常有效,但同样适合 non-DynamicMethod。

可以在下列 4 种条件下使用:
如果使用了 System.Reflection.Emit.DynamicMethod 对象,则可将指针作为第一个参数。
如果使用了 DynamicMethodDesc 指针,可以打印相关动态方法的 IL 代码。
如果使用了常规的 MethodDesc,可以将其作为第一个参数来查看 IL 代码。
如果有直接的 IL 指针,则可使用 /i 选项和 IL 地址作为参数。



!DumpRCW
!DumpRCW <RCW address>                 显示 RuntimeCallableWrapper 的信息。
!DumpCCW
!DumpCCW <CCW address or COM IP>  显示 COMCallableWrapper 的信息。
代码堆栈审查命令
命令描述
!Threads
!Threads [-live] [-special]  列出进程中所有的托管线程。

-live        可选项。仅显示活跃的线程。

-special   可选项。显示由 CLR 创建的特殊线程,这些线程有可能不是托管线程。

              例如 GC 线程、调试器线程、终结器线程、应用程序域卸载线程、线程池计时器线程等。

ID 列涵义:
调试器用 ID
CLR 线程 ID
OS 线程 ID



!ThreadState
!ThreadState value   显示线程状态



可能的线程状态包括:
Thread Abort Requested
GC Suspend Pending
User Suspend Pending
Debug Suspend Pending
GC On Transitions
Legal to Join
Yield Requested
Hijacked by the GC
Blocking GC for Stack Overflow
Background
Unstarted
Dead
CLR Owns
CoInitialized
In Single Threaded Apartment
In Multi Threaded Apartment
Reported Dead
Fully initialized
Task Reset
Sync Suspended
Debug Will Sync
Stack Crawl Needed
Suspend Unstarted
Aborted
Thread Pool Worker Thread
Interruptible
Interrupted
Completion Port Thread
Abort Initiated
Finalized
Failed to Start
!IP2MD
!IP2MD <Code address>  根据给定的托管 JITTED 代码,查找相关的 MethodDesc。



上面的例子中,我们通过 Mainy.Main 的返回地址来寻找相关的方法信息。
!U
!U [-gcinfo] [-ehinfo] [-n] <MethodDesc address> | <Code address>

根据给定方法的 MethodDesc 指针,输出反汇编代码。

-gcinfo  同时获得方法的 GCInfo 信息。相关信息可通过 !GCInfo 获得。

-ehinfo  同时获得方法的异常信息。相关信息可通过 !EHInfo 获得。

-n         不显示行号和符号等信息。



!DumpStack
!DumpStack [-EE] [-n] [top stack [bottom stack]]   提供详细甚至过于冗余混淆的调用栈信息。

-EE  仅显示托管函数。

-n    不显示行号或符号信息。



!EEStack
!EEStack [-short] [-EE]  这个命令用于在进程内的所有线程上运行 !DumpStack。

-EE      该选项将直接被传递给 !DumpStack 命令。

-short  尝试仅显示可能感兴趣的线程,包括:
线程获取了一个锁
线程为 "jijacked" 状态,并允许被 GC 回收
线程当前运行至托管代码



!CLRStack
!CLRStack [-a] [-l] [-p] [-n]

!CLRStack [-a] [-l] [-p] [-i] [variable name] [frame]

!CLRStack 试图仅为托管代码提供真实的调用栈信息。

-p    显示托管函数的参数信息。

-l     显示帧内局部变量的信息。

-a    = -p + -l 的组合。

-n    不显示行信息和符号信息。



!GCInfo
!GCInfo (<MethodDesc address> | <Code address>) 用于诊断 JIT 编译器是否存在Bug。



!EHInfo
!EHInfo (<MethodDesc address> | <Code address>)  用于显示 JITTED 方法的异常处理部分。



!BPMD
!BPMD [-nofuturemodule] <module name> <method name> [<il offset>]

!BPMD <source file name>:<line number>

!BPMD -md <MethodDesc>

!BPMD -list

!BPMD -clear <pending breakpoint number>

!BPMD -clearall

!BPMD 用于提供托管代码的断点支持。
!COMState
显示进程的 COM Apartment Model。
垃圾回收历史审查命令
命令描述
!HistInit
!HistInit 在运行任何 Hist 族命令之前,需要先根据被调试程序的压缩日志中初始化 SOS 结构。



!HistRoot
!HistRoot <root>  显示 promotion 和 relocation 信息。



!HistObj
!HistObj <obj_address>  从日志中检查 GC relocation 链。



!HistObjFind
!HistObjFind <obj_address>  从日志中检索与对象的 relocation 相关的所有信息。



!HistClear
!HistClear  释放用于 Hist 族命令的所有资源。通常无需显式的调用此命令,因为每次 HistInit 会首先清理资源。



诊断工具命令
命令描述
!VerifyHeap
!VerifyHeap 是一个用于检测 GC 堆中是否有腐化迹象的诊断工具。

其以如下的模式逐个的走查对象:





!VerifyObj
!VerifyObj <object address> 是一个用于检查被传递的对象参数是否存在腐化的迹象的诊断工具。



!FindRoots
!FindRoots -gen <N> | -gen any | <object address> 用于查找对象的引用根的诊断工具。



!HeapStat
!HeapStat [-inclUnrooted | -iu]  显示GC堆中每个代的大小和总和,同时显示空闲空间的大小。

-inclUnrooted  报告中包含那些在 GC 堆中已标识为不再引用的托管对象。



!GCWhere
!GCWhere <object address>  显示指定对象在 GC 堆中的位置。



!ListNearObj (lno)
!ListNearObj <object address>  用于显示对象前后的对象的诊断工具。



!GCHandles
!GCHandles [-type handletype] [-stat] [-perdomain]  提供对进程中 GCHandles 的统计分析。

-stat            仅显示统计信息,而不列出句柄和其指向的信息。

-perdomain   根据 AppDomain 来显示统计信息。

-type            句柄类型的过滤。

可用的句柄类型包括:
Pinned
RefCounted
WeakShort
WeakLong
Strong
Variable
AsyncPinned



!GCHandleLeaks
!GCHandleLeaks  帮助检测 GCHandle 泄漏的工具。
!FindAppDomain
!FindAppDomain <Object address>  尝试根据对象查找出 AppDomain。



!SaveModule
!SaveModule <Base address> <Filename>  将内存镜像保存至文件。



!ProcInfo
!ProcInfo [-env] [-time] [-mem]  列出进程中的环境变量,内核 CPU 时间,内存使用率等。
!StopOnException (soe)
!StopOnException [-derived] 
                           [-create | -create2] 
                           <Exception> 
                           [<Pseudo-register number>]

!StopOnException 当需要调试器在遇到特定的托管异常时停止。

例如,当遇到 System.OutOfMemoryException 时停止,而遇到其他异常时继续运行。



!DumpLog
!DumpLog [-addr <addressOfStressLog>] [<Filename>]  允许将 CLR in-memory stress log 日志写入文件。

通过下面注册表内的信息更改 Stress Log 设置:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework:

(DWORD) StressLog = 1

(DWORD) LogFacility = 0xffffffbf 

(DWORD) StressLogSize = 65536

(DWORD) LogLevel = 6

LogFacility 定义:
GC            0x00000001
GCINFO         0x00000002
STUBS          0x00000004
JIT                0x00000008
LOADER        0x00000010
METADATA     0x00000020
SYNC            0x00000040
EEMEM          0x00000080
GCALLOC      0x00000100
CORDB         0x00000200
CLASSLOADER 0x00000400
CORPROF       0x00000800
REMOTING      0x00001000
DBGALLOC     0x00002000
EH                 0x00004000
ENC               0x00008000
ASSERT         0x00010000
VERIFIER        0x00020000
THREADPOOL  0x00040000
GCROOTS       0x00080000
INTEROP         0x00100000
MARSHALER    0x00200000
IJW                0x00400000
ZAP                0x00800000
STARTUP         0x01000000
APPDOMAIN     0x02000000
CODESHARING 0x04000000
STORE             0x08000000
SECURITY        0x10000000
LOCKS             0x20000000
BCL                 0x40000000
!VMMap
!VMMap  遍历虚拟地址空间,列出 Region Protection 类型。



!VMStat
!VMStat  提供虚拟地址空间的综合报告。



!MinidumpMode
!MinidumpMode <0 or 1>

通过 ".dump /m" 或 ".dump" 来获得 CLR 数据的子集,仅适合使用 SOS 的命令的子集,一些 SOS 命令可能失败。

默认值为 0。
!AnalyzeOOM (ao)
!AnalyzeOOM 显示最后一个 OOM 的信息。



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  windbg 调试