windbg笔记
数据结构
Module
EEClass
MD(Method Desc)
MT(Method desc Table)
Object
基本命令
- ~*e!clrstack
查看所有持有和等待锁的线程(的下一条要执行的代码)
- k
观察非托管堆栈
- x <模块名>!*<函数名>*
查看符号
- lm -f
显示已经载入的模块及其完整路径
- sxe <异常类型号>
发生指定异常时中断
元命令
- .hh <命令名>
打开帮助文档,并显示其命令的文档索引
- .logopen /t/u <日志文件路径>
创建日志文件,将在windbg所有的输出同时写入此文件
- .chain
显示已经载入的扩展模块与扩展模块搜索路径链
- .loadby <要加载的模块名> <已经加载的模块名>
.Net 3.5版本及以下:.loadby sos mscorwks
.Net 4.0:.loadby sos clr
silverlight:.loadby sos coreclr
- .dump /ma <full dmp文件路径>
- .unload
- .unloadall
- .help
- .time
看进程运行了多长时间
- vertarget
查看操作系统的信息
sos.dll扩展模块命令
- !help
- !dumpstackobjects
显示当前堆栈上的所有托管对象,包括本地变量与参数
- !threadpool
查看线程池的运行情况
- !runaway
查看线程运行了多长时间
- !gchandles
查看gc handle的统计情况
- ~<线程序号> s
切换到指定线程
- !clrstack
显示当前线程的托管堆栈(能显示其代码行),使用p参数显示传入参数,使用l参数显示局部变量,使用a参数显示两者
- !dumpstack
同时显示托管堆栈与非托管堆栈
- !ip2md <代码地址>
获取代码地址处的MethodTable结构。!clrstack命令结果的IP列即为代码地址。
- !DumpVC <MethodTable address> <address>
显示指定类实例的指定成员的值
- !eeheap -gc
查看托管堆的总信息
- !dumpheap -min 200 -stat
获取占用堆内存的各对象的统计信息
- !dumpheap -type Byte[] -min 200
查看各Byte数组占用堆内存的详细信息
- !dumpheap -mt <MethodTable地址>
显示托管堆中指定的MethodTable结构的那些对象的信息
- !gcroot <对象地址>
看对象引用关系
- !do <对象地址>
查看对象的详细信息
- !da <对象地址>
获取数据对象的详细信息
- !dso (DumpStackObjects)
查看当前堆栈的所有对象
- !objsize
查看对象的大小
- !FinalizeQueue
查看终结对象队列
- !analyze -v
分析挂掉线程的详细情形,错误原因
- !threads
看所有的线程统计情况,包括崩溃后各线程抛出的异常。第1列为WinDbg内置线程号(可使用“~<内置线程号>s”功能切换堆栈),第2列为托管线程号,第3列为系统线程号
- !syncblk
查看哪些线程拿到了锁
- !pe
获取当前堆栈抛出的异常信息
- !pe <异常类型的对象的地址>
格式化打印输出指定Exception对象的信息
- !eestack -short -ee
显示所有感兴趣的(持有锁的、被劫持以执行一个垃圾收集操作、正在托管代码中执行)托管线程的堆栈
- !bpmd <模块名> <命名空间名.类名.方法名>
在指定的方法处下断点。之后可以使用:
!clrstack -a:查看当前的堆栈(带参数信息)
g:继续执行至下一个断点
- !name2ee <模块名> <类型名或方法名>
显示指定模块中指定类型或方法的 MethodTable 结构和 EEClass 结构
- !soe -create system.Exception -1
当程序出现system.Exception后, 断下来
psscor.dll扩展模块命令
可从DebugDiag的安装目录获取psscor2.dll、psscor4.dll
- !printDateTime
- !convertVTDateToDate
- !convertTicksToDate
- !printIPAdress
- !dumpXmlDocument
- !dumpCollection
- !dumpThreadConfig
- !dumpField
获取类的字段值
- !dumpDataTables
获取所有DataTable实例
- !dumpColumnNames
获取指定DataTable的所有列名
- !aspxpages
- !dumpASPNETCache
- !dumpHttpRuntime
- !dumpRequestQueues
- !dumpRequestTable
- !dumpHistoryTable
- !dumpBuckets
- !GetWorkItems
解决mscordacwks.dll版本错误的问题
- 使用.cordll命令查看需要的版本
- 在本地建目录A,并将其路径加入windbg的符号搜索目录路径链的链首
- 从运行调试目标应用程序的机器上拷贝以下正确版本的DLL至目录A:
- mscordacwks.dll(在客户端机通过.cordll命令获取其路径):改成指定的文件名,然后后用.cordll -ve -u -l重新载入。
- SOS.dll:使用.load进行载入。
另外若要使用VS调试dmp文件,那将mscordbi.dll文件拷贝至应用程序所在目录,以防止出现异常。
备注
- 若表现为界面死掉,就直接找UI线程(STA线程就一个)
- 堆栈分为本地堆栈与托管堆栈,线程号也有本地线程号与托管线程号
- 在64位的winodws上使用任务管理器获取的dmp为64位,即使跑的是32位的应用程序,所以得使用windbg、adplus、debugdiag获取
- 32位应用程序的dmp使用32位的windbg进行分析,64位应用程序的dmp使用64位的windbg
- 符号文件路径:C:\Users\Administrator\Desktop\ConsoleApplication1t;SRV*C:\symbolscache*http://msdl.microsoft.com/download/symbols
- 使用VS分析.dmp文件时,注意另创建系统符号文件缓存目录,否则下载过来的符号文件默认存储在临时目录可能会被删除。
- 使用!Threads可查看所有线程以及其类型,除了手动创建Thread的类型为MTA外,使用ThreadPool,Timer,Task创建的线程的类型皆为(Threadpool Worker)
- (堆)内存碎片可通过!dumpheap <起始地址(任意一块free的地址)> <前面的地址>+<空间差>查看是由于什么对象造成的碎片
- 使用WinDbg打开dmp文件后直接运行“!analyze -v”,WinDbg会自动载入sos.dll。
- 若要使用WinDbg为Windows Api下断点,必须先载入其符号文件(如user32.pdb,可以将其直接指向到vs所使用的符号文件目录),可使用“x user!*”查看符号文件中所有的函数,并且注意下断点时一定要写上符号文件名
- 句柄(IntPtr)是指针的指针,保存着目标对象的内存地址,可使用dd命令查看(取前4个字节表示的第一个地址)
- System.Threading.Thread对象的ManagedThreadId在线程消亡后是可以被重新使用的,所以当检查到SynchronizationContext中的托管线程号指向到一个线程,并不表示SynchronizationContext一定是此线程创建的。
参考
PSSCor2: Object Inspection Commands, Part 1
PSSCor2: Object Inspection Commands, Part 2
Debugging Tools for Windows: The psscor2 Managed Code Debugger Extension
SOS.dll(SOS 调试扩展)
SOS.dll (SOS Debugging Extension)