[翻译+补充]WinDbg托管程序调试扩展与调试思路

452 阅读4分钟

[翻译+补充]WinDbg托管程序调试扩展与调试思路

在《.Net高级调试》中作者介绍了sos和sosex两种调试工具,最近在查如何实现结构类型的变量显示时,发现了些花里胡哨的WinDbg扩展。主要翻译自nuggets/README.md at main · gabrielweyer/nuggets (github.com),其中环境的配置部分在另一篇中已经记录就不再翻译了。看完以后排查问题就不要只知道sos和sosex扩展了。

推荐扩展简介

SOS

最有名的WinDbg扩展,介绍的比较多不再展开。

SOSEX

作者:Steve Johnson的杰作.(顺便吐槽一句老爷子会在StackOverflow亲自推销他写的这个,例如

下载:

拷贝x64 / x86 DLLs 到指定路径:

  • C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\winext
  • C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\winext

如果没有,则查找 windbg.exe (where.exe /R C:\ windbg.exe).

加载

.load sosex

注意:

  • 实际上可以不拷贝直接指定路径加载.load c:\sosex.dll

  • 商店版本不需要拷贝路径。

MEX

官方使用的加强版sos,作用类似于sosex,参考。Windbg程序调试系列1-Mex扩展使用总结 - Eric zhou - 博客园 (cnblogs.com)

下载: MEX.

加载

.load mex

NetExt

可以方便的调试http request, wcf services等等。

参考官方Github文档博客园

下载: NetExt.

加载

.load netext

CMKD

看文档主要和非托管相关。

下载:

官方地址.

加载

.load cmkd

tracer

(这个没懂干啥的)

下载:

官方地址.

加载

.load tracer

常用命令列表

  • 普通调试进程的命令 (e.g.: k)
  • 点命令控制调试器 (e.g.: .sympath)
  • 扩展命令(e.g.: !handle)

WinDbg 命令

:star2: 获取最近异常:

!analyze -v

显示进程信息块 (PEB) - 包括环境变量和命令行

!peb

(F5) - 继续执行命令:

g

Objects per generation(这里没懂):

!FinalizeQueue

进制转换(看起来毫不需要)

0:000> ?12c0
Evaluate expression: 4800 = 00000000`000012c0

List of drivers:(这个命令也没懂,看起来是列出模块的意思)

lm t.lon

补充几个常用的

显示指定位置内存
dd <memory address>
dp <memory address> l1
// dp以指针显示 
// dd以双字(4字节)显示 
// l1表示只长度1

其他参考【调试技术】windbg帮助文档 (keenjin.github.io)

快捷键

  • 中断当前操作: Ctrl + Break key
  • 焦点到输入框: ALT + 1

Session settings

在合适的地方增加超链接命令,不用手打了 (新版本默认了)::

.prefer_dml 1

SOS 命令

:star2: 列出所有SOS命令(或参考SOS.dll官方命令列表

!sos.help

:star2: 列出类的所有方法

!DumpMT -md <MethodTable address>

SOSEX 命令

:star2: 列出所有SOSEX 命令

!sosex.help

:turtle: 创建堆的索引使得查找更快(build heap index):

!sosex.bhi

列出终结者队列的内容:

!sosex.finq

Freachable queue(遍历终结者队列?):

!sosex.frq

检测死锁:

!sosex.dlk

查看每一个托管线程正在等待什么 (如果有的话):

!sosex.mwaits

显示对象的字段, 可选递归:

!sosex.mdt address

设置托管代码断点

!sosex.mbp File.cs 13

MEX 命令

列出MEX 命令

!mex.help

:star2: ASP.NET: 列出请求的简要历史和正在执行的请求

!mex.aspxpagesext

托管内存相关

获取当前托管堆上的所有对象. 大对象在列表底部:

!dumpheap -stat

获取指定类型的对象:

!dumpheap -type Full.Namespace.Type

查看对象为什么存活:

!sosex.mroot <address>

查看托管堆:

!eeheap -gc

非托管内存相关

按类型统计内存:

!address -summary

异常相关

获取堆上的所有异常:

!dumpheap -type Exception -stat

查找指定异常:

!dumpheap -type System.Threading.ThreadAbortException

通过地址打印异常:

!pe 0x01c601ac

查看转储文件中所有异常:

!mex.dumpallexceptions
# 如果你想偷懒 则
!mex.dae
# 如果你想指定名称
!dumpheap -type Exception -stat

线程相关

:star2: 列出当前所有线程和他们进行的工作。

!mex.mthreads

!sos.threads

第一栏是线程ID,可以被我们用于后面的所有命令中 。

查看托管线程的堆栈:

~142e !sos.CLRStack

查看非托管线程的堆栈:

~142k

切换到线程:

~142s

:star2: :turtle: 根据堆栈分组线程

!mex.us

这个命令很好的区分了执行不同内容的线程 (执行相同的内容意味着他们能被相同的原因阻塞).

代码相关

反汇编:

!U \d <address>

交替显示反汇编和IL代码:

!sosex.mu <address>

锁相关

0:000> !syncblk
Index         SyncBlock MonitorHeld Recursion Owning Thread Info          SyncBlock Owner
   52 20ee3118          229         2 20fc6ba0 9628  42   0a13ee8c System.Object
# Abbreviated

第三栏 (MonitorHeld)指示了多少线程正在尝试获取相同的锁. 在本例中是 (229 - 1) / 2 = 114. 你可以从 so answer了解更多.

概念

参考

资料