.NET 调试入门(三)常用的命令

windbg ANSI Command Tree 1.0
title {"Crash Dump Analysis Checklist"}
body
{"Crash Dump Analysis Checklist"}
{"General"}
  {"Versions and locations"} {"version"}
  {"Set longer stack trace"} {".kframes 100"}
{"Application crash or hang"}
  {"Default analysis (crash)"} {"!analyze -v"}
  {"Default analysis (hang)"} {"!analyze -v -hang"}
  {"Switch to x86 architecture"} {".load wow64exts; .effmach x86"}
  {"Critical sections (locked)"} {"!locks"}
  {"Modules"} {"lmv"}
  {"Threads (all)"} {"~*kv 250"}
  {"Threads (unique)"} {"!uniqstack"}
  {"Gflags"} {"!gflag"}
  {"Time consumed by thread"} {"!runaway"}
  {"PEB"} {"!peb"}
  {"TEB"} {"!teb"}
  {"Hooked functions (ntdll)"} {"!chkimg -lo 50 -d !ntdll -v"}
  {"Hooked functions (kernel32)"} {"!chkimg -lo 50 -d !kernel32 -v"}
  {"Hooked functions (user32)"} {"!chkimg -lo 50 -d !user32 -v"}
  {"Hooked functions (ALL)"} {"!for_each_module !chkimg -lo 50 -d !${@#ModuleName} -v"}
  {"Exception handlers"} {"!exchain"}
  {"Computer name"} {"!envvar COMPUTERNAME"}
  {"Stack of exception thread"} {"~#kv 250"}
  {"Stack of current thread"} {"~.kv 250"}
  {"Switch to thread"}
   {"#0"} {"~0s"}
   {"#1"} {"~1s"}
   {"#2"} {"~2s"}
   {"#3"} {"~3s"}
   {"#4"} {"~4s"}
   {"#5"} {"~5s"}
   {"#6"} {"~6s"}
   {"#7"} {"~7s"}
   {"#8"} {"~8s"}
   {"#9"} {"~9s"}
{"System hang"}
  {"Default analysis"} {"!analyze -v -hang"}
  {"ERESOURCE contention"} {"!locks"}
  {"Processes and virtual memory"} {"!vm 4"}
  {"Sorted pool consumption (paged)"} {"!poolused 4"}
  {"Sorted pool consumption (nonpaged)"} {"!poolused 3"}
  {"Waiting threads"} {"!stacks"}
  {"Critical system queues"} {"!exqueue f"}
  {"I/O"} {"!irpfind"}
  {"The list of all thread stack traces"} {"!process 0 ff"}
  {"Critical sections for current process"} {"!ntsdexts.locks"}
  {"Sessions"} {"!session"}
  {"Processes"} {"!process 0 0"}
  {"Running threads"} {"!running"}
  {"Ready threads"} {"!ready"}
  {"DPC queues"} {"!dpcs"}
  {"The list of APCs"} {"!apc"}
  {"Internal queued spinlocks"} {"!qlocks"}
  {"Computer name"} {"dS srv!srvcomputername"}
  {"Switch to processor"}
   {"#0"} {"~0s"}
   {"#1"} {"~1s"}
   {"#2"} {"~2s"}
   {"#3"} {"~3s"}
   {"#4"} {"~4s"}
   {"#5"} {"~5s"}
   {"#6"} {"~6s"}
   {"#7"} {"~7s"}
{"BSOD"}
  {"Default analysis"} {"!analyze -v"}
  {"Processes and virtual memory"} {"!vm 4"}
  {"Bugcheck callback data (prior to Windows XP SP1)"} {"!bugdump"}
  {"Bugcheck secondary callback data"} {".enumtag"}
  {"Computer name"} {"dS srv!srvcomputername"}

 

以上内容另存为.wl 文件就可以放到WinDbg安装目录中,就可以在Windbg命令行中输入.cmdtree **.wl 就可以打开该命令窗口了。


{".NET 常用命令"}
    {"!threads  显示所有线程"} {"!threads"}
    {"!eeheap -gc 查看托管堆的总信息"} {"!eeheap -gc"}
    {"!dumpheap -min 200 -stat 获取占用堆内存的各对象的统计信息"} {"!dumpheap -min 200 -stat"}
    {"!dumpheap -type Byte[] -min 200 看各Byte数组占用堆内存的详细信息"} {""}
    {"!dumpheap  显示托管堆的信息"} {"!dumpheap"}
    {"!gcroot <对象地址> 看对象引用关系"} {""}
    {"!dumpobj(!do) <对象地址> 显示一个对象的内容"} {"!do"}
    {"!dumparray  显示数组"} {"!dumparray"}
    {"!syncblk  查看哪些线程拿到了锁"} {"!syncblk"}
    {"!runaway  显示线程cpu时间"} {"!runaway"}
    {"!threadpool 查看Cpu占用率"} {"!threadpool "}
    {"!runaway 看线程的执行时间"} {"!runaway"}
    {".time看进程运行了多长时间"} {".time"}
    {"!~'*' s切换线程 ‘*’表示那个线程"} {""}
    {"!clrstack  显示调用栈"} {"!clrstack "}
    {"!dso 查看当前堆栈的所有对象"} {"!dso"}
    {"!analyze -v 分析挂掉线程的详细情形,错误原因"} {"!analyze -v"}
    {"~*e!clrstack 查看所有持有和等待锁的线程"} {"~*e!clrstack"}
     {".NET 常用命令"}
  {".load psscor2\amd64\psscor2.dll; load sos.dll"} {".load psscor2\amd64\psscor2.dll"}
  {"!threads  显示所有线程"} {"!threads"}
  {"!eeheap -gc 查看托管堆的总信息"} {"!eeheap -gc"}
  {"!dumpheap -min 200 -stat 获取占用堆内存的各对象的统计信息"} {"!dumpheap -min 200 -stat"}
  {"!dumpheap -type Byte[] -min 200 看各Byte数组占用堆内存的详细信息"} {""}
  {"!dumpheap  显示托管堆的信息"} {"!dumpheap"}
  {"!gcroot <对象地址> 看对象引用关系"} {""}
  {"!dumpobj(!do) <对象地址> 显示一个对象的内容"} {"!do"}
  {"!dumpvc <方法表地址> <值类型地址>; 导出值类型对象"}
  {"!dumparray  显示数组"} {"!dumparray"}
  {"!dumpdomain;  显示所有应用程序域"} {"!dumpdomain"}
  {"!syncblk  查看哪些线程拿到了锁"} {"!syncblk"}
  {"!runaway  显示线程cpu时间"} {"!runaway"}
  {"!threadpool 查看Cpu占用率"} {"!threadpool "}
  {"!runaway 看线程的执行时间"} {"!runaway"}
  {".time看进程运行了多长时间"} {".time"}
  {"!~'*' s切换线程 ‘*’表示那个线程"} {""}
  {"!clrstack  显示调用栈"} {"!clrstack "}
  {"!dso 查看当前堆栈的所有对象"} {"!dso"}
  {"!analyze -v 分析挂掉线程的详细情形,错误原因"} {"!analyze -v"}
  {"~*e!clrstack 查看所有持有和等待锁的线程"} {"~*e!clrstack"}
  {"!eeversion 查看SOS版本"} {"!eeversion"}

 


  !syncblk  查看同步块表的信息
  dd 将内容转储出来(用于查看内存的内容)。
   "dd 值类型数组地址,其结构为:{方法表地址}{数组维度} {数组的内容}" 注:在64位win7系统中,方法表、数组维度的地址的循序是反的,如:f953edc8 000007fe,00000005 00000000 真实的结果是:000007fef9141fb8,0000000000000005
   "dd 引用类型数组地址,其结构为:{方法表地址}{数组维度}{数组元素的方法表}{数组的内容},在64位win7系统中,地址顺序同样是反的。
  du 会把转储出来的内容视为Unicode字符
  da 会把转储出来的内容视为ACSII字符
  dw 会把转储出来的内容视为字(Word)
  db 会把转储出来的内容视为字节值和ACSII字符
  dq 会把转储出来的内容视为四字(quad Word)值
  dds <代码地址> 查看这个地址是什么函数,显示函数名
  lmvm <加载的DLL名,如clr、mscorwks> 显示加载DLL的详细信息
  kb 用于输出异常的调用栈
  !pe <地址>:得到改异常的详细描述,如异常消息等(注:改地址怎么来,1,通过调用kb得到异常的调用栈。2,找到调用栈的“mscorwks!RaiseTheExceptionInternalOnly”异常节点,取他的第一个地址如:
  “000007fe`f9e52460 : 00000000`0268aa30 00000000`00000000 00000000`00000000 00000000`00000001 : mscorwks!RaiseTheExceptionInternalOnly+0x2ff”
  异常地址就是:“0268aa30”
  )
  ~*kn:显示进程中所有线程的回溯,包含栈帧的编号。
  !PrintException <异常地址>
  000007fe`fa822460 : 00000000`0269c330 00000000`00000000 00000000`00000000 00000000`00000001 : mscorwks!RaiseTheExceptionInternalOnly+0x2ff
  异常地址要看RaiseTheExceptionInternalOnly,这个异常地址就为0269c330
  !Threads 可以显示所有托管线程的信息,并能显示出各线程的最后一个异常。包括异常地址
  !threads -live 显示处于活跃状态的线程
  !threads -special:输出进程中所有“特殊的”线程,如,垃圾回收线程,调试器线程,线程池定时线程
  !u <代码地址> 反汇编
  !U <代码地址> 反汇编并带有托管代码
  !ip2md <代码地址>:将托管代码地址转换为一种方法描述符
  SOSEX命令:
  !bpsc  推荐用 !mbp <.CS 文件名> <行号> "设置断点"
  !bpmd <执行的EXE或DLL> <方法名> 在某个方法中设置断点
  !mbm 在IL代码中设置断点
  !mbl 显示所有设置断点列表
  !mbc 从列表中清除指定断点,或清除所有断点
  !mbd 禁用列表中指定断点,或禁用所有断点
  !mbe 启用列表中的指定断点,或启用所有断点
  !mx <查询字符串> :快速找出相应的元数据,如,类型名、方法名
  !mln <地址>:可以识别出该地址上内容相关的托管代码
  !mk:显示托管、非托管代码的栈帧外,还能显示栈帧的编号
  !mdv <栈帧编号> 显示栈帧的局部变量
  !mdv -w:显示所有调用栈 的参数和局部变量。
  !mdt <地址> (显示包括[typename|paramname|localname|mt|addr]) :他可以显示托管代码的局部变量,全局变量,或某个数据类型的信息
  !mdt <地址> -r 递归显示所有嵌套对象的MDT,并输出相应的值
  !dlk :找到那些线程可能发生死锁的过程的详细信息
  !gcgen <托管堆上的对象地址> :显示该对象所属的代
  !dumpgen <第*代>:显示参考中第*代有那些对象
  !strings [-g|-m|-n|-x]:搜索托管堆上的任意字符串
  !strings -m:<查询字符串> 可以用通配符*
  -g:在指定代中搜索
  -n:字符串的最小长度
  -x:字符串的最大长度
  ------------------------------------------------------
  bp <地址>:在非托管代码中设置断点.
  !dumpmt -md <地址>  得到指定方法表的描述符(就是该类有那些方法)
  lm 用来加载完程序的其它模块(相当DLL)
  ln<地址> 查看该地址能否被解析为代码
  .load sosex_64\sosex.dll
  .load psscor2\amd64\psscor2.dll
  .loadby sos.dll mscorwks
  .dump 生成dump文件
  .dump /ma <文件路径>
  ntsd.exe -p <进程ID> 调试一个在运行的进程
  ntsd.exe -g <调试程序路径>   -g表示不希望调试器在初始启用时停止程序的执行。
  ntsd.exe -G <调试程序路径>   -G每当调试目标准备退出时,调试器也将停止执行。
  ntsd.exe -z <dump文件>:调试一个dump文件
  类型句柄指向的是某个类型的方法表
  --------------------------------------------------
  .sympath <符号文件路径>
  .symfix  将符号路径自动设置为Microsoft公用的符号服务器。 加载符号
  .reload  找到进程地址空间所有已加载的模块,并尝试找出各模块相关的符号文件。
  Ctrl+C 中断执行
  g 恢复执行
  p(step)和t(trace) 单步调试
  pc 重复执行所有指令
  pt 会一直执行指令,直到遇到一个ret指令
  ta <address>:执行到address指定的地址,并且将包含被调用函数的单步执行显示出来。
  tc:执行到下一个call指令,并且将包含被调用函数的单步执行显示出来。
  tt:执行到下一个ret指定, 并且将包含被调用函数的单步执行显示出来。
  r 将寄存器转储出来 ->esp、rsp:保存的是当前栈指针
  k[参数]:显示非托管调用栈信息
  kn:显示非托管代码调用栈信息
  !ClrStack :显示托管代码调用栈信息
  !clrstack -l 显示局部变量信息
  !clrstack -p 显示参数信息
  !clrstack -a 合并显示局部变量和参数信息
  !dumpstack: 同时显示托管代码、非托管代码调用栈信息
  !dumpstack -ee:只显示托管代码的调用栈信息
  !eestack:显示所有托管线程的调用栈
  q:结束调度会话并终止调试目标。
  qd(quit and detach):结束调试会话,但让调试目标继续运行。
  .loadby <DLL名字> <模块名字>
  sxe ld <加载的DLL mscorwkds.dll>:当加载完该DLL后,调试器停止等待用户加载其它DLL
  sxe clr 告诉调试器在所有托管异常上都停止执行
  .cordll:在事后调试可能出现mscorwks.dll与mscordacwks.dll的版本不匹配造成不正确调试,可以使用此命令。
  .cordll -lp <mscordacwks.dll 的路径>:-lp 是用于指定mscordacwks.dll的新路径。
  .cordll -u <mscordacwks.dll 的路径>:-lp 是用于卸载mscordacwks.dll。

  !name2ee <模块名字> <类型或方法名> 检查函数是否已经被JIT编译器编译,找出类型、方法的描述符
  !do: dump出引用类型的值。
  !do -nofields 只显示内容不会显字符串类型中的各个域
  !da(!DumpArray)[-start <数组那个索引开始>] [-length<显示数组多少个元素>] [-details] [-nofields] 数据地址
  [-details] 显示数组的详细信息,包括具体值。
  [-nofields] 只显示内容不会显字符串类型中的各个域
  dump 出栈上的对象:
  !DumpStackObjects [-verify] [top stack [bottom stack]]
  -verify 表示对每天托管对象进行一次验证过程
  !dumpheap:dump堆中的所有对象
  !dumpheap -type <类型,包括命名空间> :dump堆中的指定对象
  !dumpheap -mt <方法表地址> :dump堆中的指定对象
  !dumpheap -min <最小内存大小> :dump堆中大于指定内存的对象
  !dumpheap -startAtLowerBound <开始地址> 显示该地址块中有那些对象。
  !dumpheap -thinlock:查看堆上所有瘦锁对象
  !dumpheap -stat 统计堆中各对象的个数,类型于sql中的group by
  !ObjSize <对象的地址> 找到对象的大小
  !eeversion 显示.net 版本和SOS版本信息
  !eeheap -gc: 查看托管堆的总信息,包括各代的起始地址
  !FinalizeQueue:查看进程中可以终结的对象
  !syncblk:它将输出某个线程中所有对象的同步块,查看哪些线程拿到了锁
  如何找出某个对象的同步块索引?
  对象指针指向的是类型句柄域,然后才是实际的对象数据,类型句柄前的4个字节同样是内存布局的一部分,其中包含了对象的对象头。
  如何得到对象头的索引?
  通过dd将对象的地址(指针)减去4个字节即可
  对象头的位掩码如果是“0x08000000”表示一个正在处理一个同步块索引
C:\Users\ADMINI~1\AppData\Local\Temp\MyTools (2).DMP

C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll

C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll

C:\Windows\System32\mscoree.dll

posted @ 2013-06-27 10:10  吉桂昕  阅读(719)  评论(0编辑  收藏  举报