WinDbg 调试.net程序

WinDbg支持以下三种类型的命令:

·        常规命令,用来调试进程

·        点命令,用来控制调试器

·        扩展命令,可以添加叫WinDbg的自定义命令,一般由扩展dll提供这些命令

PDB文件

PDB文件是由链接器产生的程序数据库文件。私有PDB文件包含私有和公有符号,源代码行,类型,本地和全局变量信息。公有PDB文件不包含类型,本地变量和源代码行信息,且只包含共有成员的调试信息。

Dump文件

利用Dump工具,你可以获得进程的快照信息。一个mini-dump包含当前进程的所有线程,线程栈信息和已加载模块信息。一个full-dump包括更多信息,如堆信息。

使用WinDbg调试

1.       启动WinDbg

要用WinDbg(x86)调式32位程序,用WinDbg(x64)调试64位程序。

2.       使用帮助

任何时候都可以使用!help命令来获取帮助,查看命令的使用方法。

3.       设置SymbolFile Path,指定了符号库,我们才能看到详细的类型信息

SRV*c:\symbols*http://msdl.microsoft.com/download/symbols

WinDbg会将微软的符号库下载指定的本地目录中,以上设置可以使用以下命令来实现:

.symfixc:\symbols,此命令表示要连接到Microsoft服务器下载调试符号文件,符号文件将被下载到c:\symbols目录中。

还可以使用.sympath命令来显示当前的符号路径设置。

4.       重新加载符号

如果进入调试之后才指定的符号路径,需要使用命令来重新加载符号

.reload

5.       加载调试扩展

调试扩展定义了很多命令来调试.net程序。使用调式非托管代码的命令来调试.net程序是非常困难的。下面的命令加载了用于调试.net程序的sos模块。

a.      对于.Net Runtime 2.0

.loadby sos mscorwks

b.     对于.Net Runtime 4.0

.loadby sos clr

sos是一个dll,定义了很多针对.net assembly的调试命令,sos.dll针对不同的runtime有不同的版本。如果使用.load命令,需要为sos.dll指定完整路径。如果使用.loadby命令,则表示要在mscorwks.dll和clr.dll的同一目录下查找sos。对于.net程序,基本上都会加载mscorwks.dll(2.0)和clr.dll(4.0)。

6.       查看线程

a.      包括托管线程和非托管线程

~

b.     查看托管线程

!threads

c.      显示有关托管线程池的信息,包括队列中工作请求的数目、完成端口线程的数目和计时器的数目。

!ThreadPool

d.     切换线程(中间的数字表示线程号)

~0s

e.     查看线程栈, 仅提供托管代码的堆栈跟踪。

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

-p 选项显示托管函数的参数。

-l 选项将显示有关帧中的局部变量的信息。 若SOSdebugging extension 未能检索本地名称,因此,本地名称的输出格式<local address>= <value>。

-a (all) 选项是一个表示 -l 和 -p 的组合的快捷方式。

-n 选项禁止显示源文件名和行号。

在基于x64 和IA-64 的平台上,SOS调试扩展不显示过渡帧。

f.       查看线程栈,只能正常显示非托管部分

k

g.      显示线程栈全部信息,包括托管和非托管部分

!dumpstack [-EE] [-n] [top stack [bottom stack]]

-EE 选项使DumpStack 命令仅显示托管函数。 使用top 和bottom 参数可限制x86 平台上显示的堆栈帧。

-n 选项禁止显示源文件名和行号。 如果调试器已指定选项

显示所有线程栈信息

h.     对一个进程中的所有线程运行 DumpStack 命令

!EEStack [-short] [-EE]

将-EE 选项直接传递给DumpStack 命令。-short 参数将输出限制为以下类型的线程:

·        已获取锁的线程。

·        己停止运行以允许垃圾回收的线程。

·        当前在托管代码中的线程。

i.     显示所有线程的堆栈

~*e !clrstack

j.       显示在当前堆栈的边界内找到的所有托管对象

!dumpstackobjects [-verify] [top stack [bottom stack]] 或 !dso

7.       查看堆中的所有对象信息,包括类型信息,个数,大小等

!dumpheap –stat

a.      指定对象类型,如果需要结果准确,需要使用全名称,类型名称是大小写敏感的

!dumpheap -type FlowThrottle –stat

b.     以上命令输出的第一列是mt(method table)信息,表示类型对象的地址。我们可以使用此信息来明确指定我们感兴趣的对象在堆中的信息。

!dumpheap -mt 000007feee769c00  -stat

注意,如果不指定-stat,那么输出每个对象的信息,使用-stat,将会看到统计信息。

c.      使用如下命令只输出对象地址

!dumpheap -mt 000007feee769c00  -short

d.     -short 选项将输出限制为只是每个对象的地址。 这使您方便地以管道方式将输出从该命令转移到另一个调试器命令,以便自动化。

e.     -min 选项忽略小于 size 参数指定的大小(单位为字节)的对象。-max 选项忽略大于size 参数指定的大小(单位为字节)的对象。

8.       显示有关内部公共语言运行时数据结构所使用的进程内存的信息。

EEHeap [-gc][-loader]

-gc 和-loader 选项将此命令的输出限制为垃圾回收器或加载程序数据结构。有关垃圾回收器的信息列出了托管堆中每个段的范围。如果指针落在由-gc 给出的段范围内,则该指针是一个对象指针。

9.       打印对象信息,指定任何有效的对象地址,就能查看该对象的内容

!dumpobj <address>或者 !do<address>

输出的对象信息中有每个属性的地址信息,所以可以继续使用!do命令来打印属性指向的对象信息。

!dumpobj –nofields<address>或者!do <address>

nofields选项指示不要输出对象字段信息,当对象是string类型时,该选项就非常有用。

10.   显示有关指定地址处的值类字段的信息。

DumpVC<MethodTable address> <Address>

MethodTable 参数使DumpVC 命令可以正确解释字段。值类不使用方法表作为它的第一个字段。

11.   输出多个对象信息

.foreach (myobj{!dumpheap -mt 008f4104-short}) {!do ${myobj}}

以上命令指示,对于堆中所有类型为008f4104的对象,依次调用!do命令。

12.   打印数组信息

!dumparray [-start<startIndex>] [-length <length>] [-details] [-nofields] <arrayobject address>或者!da

·        -start 选项指定开始显示元素的起始索引。

·        -length 选项指定要显示的元素数量。

·        -details 选项使用 DumpObj 和 DumpVC 格式显示元素的详细信息。

·        -nofields 选项可阻止显示数组。 此选项只有在指定了-detail 选项之后才可用。

下面的命令显示在地址 00ad28d0 处的数组内容。显示从第二个元素开始,连续显示五个元素。

!dumparray -start2 -length 5 -detail 00ad28d0

13.   输出app domain信息

!dumpdomain

枚举在指定的 AppDomain 对象地址内加载的每个Assembly 对象。若在调用DumpDomain 命令时不提供任何参数,则将列出进程中的所有AppDomain 对象。

14.   输出程序集信息

!dumpassembly

15.   打印方法表

!dumpmt [-MD]<MethodTable address>

显示有关指定地址处的方法表的信息。 指定-MD 选项将显示与对象一起定义的所有方法的列表。每个托管对象都包含一个方法表指针。

16.   打印EEClass结构,其中可以看到类型静态变量信息

!dumpclass<EEClass address>

显示有关与类型关联的 EEClass 结构的信息。DumpClass命令显示静态字段值,但不显示非静态字段值。使用DumpMT、DumpObj,Name2EE 或Token2EE 命令获取EEClass 结构的地址。

17.   显示异常

a.      使调试器在引发指定异常时停止,但在引发其他异常时继续运行。

!StopOnException [-derived] [-create | -create2]<Exception> <Pseudo-register number>

-derived 选项用于捕获指定异常以及从指定异常派生的每个异常。

b.     显示当前活动线程上的最后一个异常

!PrintException [-nested] [-lines] [<Exception objectaddress>] 或 !PE

显示从指定地址处的Exception 类派生的任何对象的字段并设置这些字段的格式。 如果不指定地址,PrintException命令将显示在当前线程上引发的最后一个异常。

-nested 选项显示有关嵌套异常对象的详细信息。

-lines 选项显示源信息(如果可用)。

c.      显示发生在所有线程上的最后的异常

~*e !pe

18.   调试GC相关信息

a.      显示有关对指定地址处的对象的引用(或根)的信息。

!GCRoot [-nostacks] <Object address>

GCRoot 命令将检查整个托管堆和句柄表以查找其他对象内的句柄和堆栈上的句柄。 然后,在每个堆栈中搜索对象的指针,同时还搜索终结器队列。此命令无法确定堆栈根是有效的还是已丢弃。 使用CLRStack 和U 命令可对本地或参数值所属的帧进行反汇编,以便确定堆栈根是否仍在使用中。

-nostacks 选项将搜索限制为垃圾回收器句柄和 Freachable 对象。

b.     显示所有已进行终结注册的对象。

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

-detail 选项显示有关需要清理的任何 SyncBlocks 的额外信息以及有关等待清理的任何RuntimeCallableWrappers (RCW) 的额外信息。 这两种数据结构都由终结器线程在运行时进行缓存和清理。

-allReady 选项显示所有准备终止的对象,无论它们已被垃圾回收标记成这样,还是将被下一个垃圾回收标记。 在“准备终止”列表中的对象为不再为根的可终止对象。 此选项可能耗费大量资源,因为它验证可终止队列中的所有对象是否仍然为根对象。

-short 选项将输出限制为每个对象的地址。 如果与-allReady 一起使用,则将枚举具有不再为根的终结器的所有对象。 如果单独使用,则将列出终结和“准备终结”队列中的所有对象。

19.  设置断点

!bpmdSystem.Windows.Forms.dllSystem.Windows.Forms.MessageBox.Show

第一个参数是dll文件名,第二个是完整的方法名。

20.  查看所有断点列表

bl

21.   释放当前断点, 让程序继续运行。 让程序运行到断点后WinDBG会自动停下来。

g

22.   显示公共语言运行时版本。

!eeversion

23.   清除屏幕信息,该命令还你一个清洁的屏幕

.cls

24.   退出当前调试

q

WinDbg支持以下三种类型的命令:

·        常规命令,用来调试进程

·        点命令,用来控制调试器

·        扩展命令,可以添加叫WinDbg的自定义命令,一般由扩展dll提供这些命令

PDB文件

PDB文件是由链接器产生的程序数据库文件。私有PDB文件包含私有和公有符号,源代码行,类型,本地和全局变量信息。公有PDB文件不包含类型,本地变量和源代码行信息,且只包含共有成员的调试信息。

Dump文件

利用Dump工具,你可以获得进程的快照信息。一个mini-dump包含当前进程的所有线程,线程栈信息和已加载模块信息。一个full-dump包括更多信息,如堆信息。

使用WinDbg调试

1.       启动WinDbg

要用WinDbg(x86)调式32位程序,用WinDbg(x64)调试64位程序。

2.       使用帮助

任何时候都可以使用!help命令来获取帮助,查看命令的使用方法。

3.       设置SymbolFile Path,指定了符号库,我们才能看到详细的类型信息

SRV*c:\symbols*http://msdl.microsoft.com/download/symbols

WinDbg会将微软的符号库下载指定的本地目录中,以上设置可以使用以下命令来实现:

.symfixc:\symbols,此命令表示要连接到Microsoft服务器下载调试符号文件,符号文件将被下载到c:\symbols目录中。

还可以使用.sympath命令来显示当前的符号路径设置。

4.       重新加载符号

如果进入调试之后才指定的符号路径,需要使用命令来重新加载符号

.reload

5.       加载调试扩展

调试扩展定义了很多命令来调试.net程序。使用调式非托管代码的命令来调试.net程序是非常困难的。下面的命令加载了用于调试.net程序的sos模块。

a.      对于.Net Runtime 2.0

.loadby sos mscorwks

b.     对于.Net Runtime 4.0

.loadby sos clr

sos是一个dll,定义了很多针对.net assembly的调试命令,sos.dll针对不同的runtime有不同的版本。如果使用.load命令,需要为sos.dll指定完整路径。如果使用.loadby命令,则表示要在mscorwks.dll和clr.dll的同一目录下查找sos。对于.net程序,基本上都会加载mscorwks.dll(2.0)和clr.dll(4.0)。

6.       查看线程

a.      包括托管线程和非托管线程

~

b.     查看托管线程

!threads

c.      显示有关托管线程池的信息,包括队列中工作请求的数目、完成端口线程的数目和计时器的数目。

!ThreadPool

d.     切换线程(中间的数字表示线程号)

~0s

e.     查看线程栈, 仅提供托管代码的堆栈跟踪。

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

-p 选项显示托管函数的参数。

-l 选项将显示有关帧中的局部变量的信息。 若SOSdebugging extension 未能检索本地名称,因此,本地名称的输出格式<local address>= <value>。

-a (all) 选项是一个表示 -l 和 -p 的组合的快捷方式。

-n 选项禁止显示源文件名和行号。

在基于x64 和IA-64 的平台上,SOS调试扩展不显示过渡帧。

f.       查看线程栈,只能正常显示非托管部分

k

g.      显示线程栈全部信息,包括托管和非托管部分

!dumpstack [-EE] [-n] [top stack [bottom stack]]

-EE 选项使DumpStack 命令仅显示托管函数。 使用top 和bottom 参数可限制x86 平台上显示的堆栈帧。

-n 选项禁止显示源文件名和行号。 如果调试器已指定选项

显示所有线程栈信息

h.     对一个进程中的所有线程运行 DumpStack 命令

!EEStack [-short] [-EE]

将-EE 选项直接传递给DumpStack 命令。-short 参数将输出限制为以下类型的线程:

·        已获取锁的线程。

·        己停止运行以允许垃圾回收的线程。

·        当前在托管代码中的线程。

i.     显示所有线程的堆栈

~*e !clrstack

j.       显示在当前堆栈的边界内找到的所有托管对象

!dumpstackobjects [-verify] [top stack [bottom stack]] 或 !dso

7.       查看堆中的所有对象信息,包括类型信息,个数,大小等

!dumpheap –stat

a.      指定对象类型,如果需要结果准确,需要使用全名称,类型名称是大小写敏感的

!dumpheap -type FlowThrottle –stat

b.     以上命令输出的第一列是mt(method table)信息,表示类型对象的地址。我们可以使用此信息来明确指定我们感兴趣的对象在堆中的信息。

!dumpheap -mt 000007feee769c00  -stat

注意,如果不指定-stat,那么输出每个对象的信息,使用-stat,将会看到统计信息。

c.      使用如下命令只输出对象地址

!dumpheap -mt 000007feee769c00  -short

d.     -short 选项将输出限制为只是每个对象的地址。 这使您方便地以管道方式将输出从该命令转移到另一个调试器命令,以便自动化。

e.     -min 选项忽略小于 size 参数指定的大小(单位为字节)的对象。-max 选项忽略大于size 参数指定的大小(单位为字节)的对象。

8.       显示有关内部公共语言运行时数据结构所使用的进程内存的信息。

EEHeap [-gc][-loader]

-gc 和-loader 选项将此命令的输出限制为垃圾回收器或加载程序数据结构。有关垃圾回收器的信息列出了托管堆中每个段的范围。如果指针落在由-gc 给出的段范围内,则该指针是一个对象指针。

9.       打印对象信息,指定任何有效的对象地址,就能查看该对象的内容

!dumpobj <address>或者 !do<address>

输出的对象信息中有每个属性的地址信息,所以可以继续使用!do命令来打印属性指向的对象信息。

!dumpobj –nofields<address>或者!do <address>

nofields选项指示不要输出对象字段信息,当对象是string类型时,该选项就非常有用。

10.   显示有关指定地址处的值类字段的信息。

DumpVC<MethodTable address> <Address>

MethodTable 参数使DumpVC 命令可以正确解释字段。值类不使用方法表作为它的第一个字段。

11.   输出多个对象信息

.foreach (myobj{!dumpheap -mt 008f4104-short}) {!do ${myobj}}

以上命令指示,对于堆中所有类型为008f4104的对象,依次调用!do命令。

12.   打印数组信息

!dumparray [-start<startIndex>] [-length <length>] [-details] [-nofields] <arrayobject address>或者!da

·        -start 选项指定开始显示元素的起始索引。

·        -length 选项指定要显示的元素数量。

·        -details 选项使用 DumpObj 和 DumpVC 格式显示元素的详细信息。

·        -nofields 选项可阻止显示数组。 此选项只有在指定了-detail 选项之后才可用。

下面的命令显示在地址 00ad28d0 处的数组内容。显示从第二个元素开始,连续显示五个元素。

!dumparray -start2 -length 5 -detail 00ad28d0

13.   输出app domain信息

!dumpdomain

枚举在指定的 AppDomain 对象地址内加载的每个Assembly 对象。若在调用DumpDomain 命令时不提供任何参数,则将列出进程中的所有AppDomain 对象。

14.   输出程序集信息

!dumpassembly

15.   打印方法表

!dumpmt [-MD]<MethodTable address>

显示有关指定地址处的方法表的信息。 指定-MD 选项将显示与对象一起定义的所有方法的列表。每个托管对象都包含一个方法表指针。

16.   打印EEClass结构,其中可以看到类型静态变量信息

!dumpclass<EEClass address>

显示有关与类型关联的 EEClass 结构的信息。DumpClass命令显示静态字段值,但不显示非静态字段值。使用DumpMT、DumpObj,Name2EE 或Token2EE 命令获取EEClass 结构的地址。

17.   显示异常

a.      使调试器在引发指定异常时停止,但在引发其他异常时继续运行。

!StopOnException [-derived] [-create | -create2]<Exception> <Pseudo-register number>

-derived 选项用于捕获指定异常以及从指定异常派生的每个异常。

b.     显示当前活动线程上的最后一个异常

!PrintException [-nested] [-lines] [<Exception objectaddress>] 或 !PE

显示从指定地址处的Exception 类派生的任何对象的字段并设置这些字段的格式。 如果不指定地址,PrintException命令将显示在当前线程上引发的最后一个异常。

-nested 选项显示有关嵌套异常对象的详细信息。

-lines 选项显示源信息(如果可用)。

c.      显示发生在所有线程上的最后的异常

~*e !pe

18.   调试GC相关信息

a.      显示有关对指定地址处的对象的引用(或根)的信息。

!GCRoot [-nostacks] <Object address>

GCRoot 命令将检查整个托管堆和句柄表以查找其他对象内的句柄和堆栈上的句柄。 然后,在每个堆栈中搜索对象的指针,同时还搜索终结器队列。此命令无法确定堆栈根是有效的还是已丢弃。 使用CLRStack 和U 命令可对本地或参数值所属的帧进行反汇编,以便确定堆栈根是否仍在使用中。

-nostacks 选项将搜索限制为垃圾回收器句柄和 Freachable 对象。

b.     显示所有已进行终结注册的对象。

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

-detail 选项显示有关需要清理的任何 SyncBlocks 的额外信息以及有关等待清理的任何RuntimeCallableWrappers (RCW) 的额外信息。 这两种数据结构都由终结器线程在运行时进行缓存和清理。

-allReady 选项显示所有准备终止的对象,无论它们已被垃圾回收标记成这样,还是将被下一个垃圾回收标记。 在“准备终止”列表中的对象为不再为根的可终止对象。 此选项可能耗费大量资源,因为它验证可终止队列中的所有对象是否仍然为根对象。

-short 选项将输出限制为每个对象的地址。 如果与-allReady 一起使用,则将枚举具有不再为根的终结器的所有对象。 如果单独使用,则将列出终结和“准备终结”队列中的所有对象。

19.  设置断点

!bpmdSystem.Windows.Forms.dllSystem.Windows.Forms.MessageBox.Show

第一个参数是dll文件名,第二个是完整的方法名。

20.  查看所有断点列表

bl

21.   释放当前断点, 让程序继续运行。 让程序运行到断点后WinDBG会自动停下来。

g

22.   显示公共语言运行时版本。

!eeversion

23.   清除屏幕信息,该命令还你一个清洁的屏幕

.cls

24.   退出当前调试

q

上一篇:(IOS)BaiduFM 程序分析


下一篇:java程序练习:猜字母