对于一般的程序不需要使用WinDBG工具去调试,使用MDBG就OK

使用WinDBG + SOS调试.Net程序的一般步骤

2009-03-28

1. 加载进程和SOS扩展:

a. F6或者使用菜单Files –> Attach to a process…来Attach一个托管进程

b.使用命令.loadby sos mscorwks来加载SOS扩展(注意:.Net1.1时代的SOS扩展已经自带于下载安装的WinDBG中,从.Net2.0以后,SOS扩展已经自带到.Net框架中:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\SOS.dll,为了不至于引起混淆,最好的方法就是使用前面的loadby调试器元命令来让WinDBG自己决定加载什么版本的SOS。 mscorwks表示.Net框架的工作站版本,现在我们安装的.Net Framework都是该版本)

c.加载SOS后,使用命令.chain来查看调试链中是否已经成功包含SOS扩展,如下图的WinDBG输出就表示已经成功的加载了SOS:

2. 查看进程加载的模块并加载调试符号:

Attach到进程并顺利加载SOS扩展后,我们可以使用lm命令来查看当前进程已经加载的模块,WinDBG会列出一个模块加载列表,这个列表非常有用,我们后面设置断点,查看方法表和IL以及汇编代码都需要使用到相应的Module Name。另外对于我们常用的情况:调试IISHost的进程,由于进程的名字都是w3wp,我们需要区分出哪个进程才是我们想要调试的Application,这个时候我们就可以通过lm命令列出的加载模块列表来判断:

接下来我们就可以根据Module Name来给对应的Module加载调试符号库,由于在使用WinDBG进行调试的时候大多数时候我们都会查看汇编代码,所以加载调试符号对于辅助我们更好的看懂汇编代码和相关的变量命名是必须的,WinDBG默认会帮我们加载相关Module的调试符号,我们也可以使用ld [ModuleName]来显示的加载某一个Module的调试符号,例如ld BasicDebugDemo指定加载BasicDebugDemo这个Module的调试符号。

3. 准备就绪,开始调试:

经过1,2两个步骤的准备,我们的调试环境已经准备好了,接下来就可以开始调试了,下面介绍一些重要的和常用的调试命令:

1) 根据调试符号库的信息查看类或者方法在.Net执行引擎中的具体元信息,包括类的方法表地址,类在运行时的元信息(父类元信息地址,虚方法表地址等很多有用信息),这些信息是我们接下来调试的基础!使用命令!name2ee [ModuleName] [ClassName or MehodName]来进行查看,例如:!name2ee BasicDebugDemo BasicDebugDemo.Program

我们也可以使用!name2ee命令直接查看某个类方法的元信息:

2) 有了上面得到的一个类的方法表的入口地址后,我们就可以使用!dumpmt [-md] [MethodTabel Address]来查看这个类中每一个方法的具体运行时信息(加带md选项表示我们要查询每一个方法声明的入口地址),例如我们利用上面得到的00993030这个地址,!dumpmt –md 00993030

3) 另外我们通过上面的!name2ee命令除了拿到MehodTable的地址外,还拿到了Program这个Class的运行时元信息地址EEClass Address,所以我们可以通过!dumpclass [Class Address]来查看这个类中的具体内容(比如其中的静态变量的地址等):

4) 上面提到了一个很重要的信息MehodDesc,得到这个MethodDesc有什么用呢?首先我们可以使用!dumpil [MethodDesc]来查看其编译后的IL代码:

5) 另外如果这个方法已经被JIT了,那么我们调用!dumpmd [MethodDesc]会得到下面的信息:

接下来我们就可以使用!u [LocalCodeAddr]来查看生成的本地汇编代码:

6) 上面能获取的元信息我们基本上都获取了,有了这些元信息(主要是代码地址信息)我们要下断点就很简单了,我们有很多种方式来给我们的代码的指定位置加上断点P

a.首先如果调试符号加载成功的话,我们可以直接使用很直观的原始方法命名来给指定的方法入口处加上断点:!bpmd [ModuleName] [MethodName],例如!bpmd BasicDebugDemo BasicDebugDemo.Program.CreateFooObject

b.如果我们有MethodDesc,也可以直接使用!bpmd -md [MethodDesc]来给方法入口处加上断点,例如!bpmd -md 0099301c

c.我们上面看到了本地汇编代码,所以我们也可以使用bp [CodeAddr]来给某个方法内部的某行代码加上断点。

d.我们可以使用bl命令来列出所有已加载的断点,也可以使用bc [BreakPoint ID]命令来删除指定ID的断点(用bl命令列出的断点列表种有各个断点的ID),或者使用bc *来删除所有的断点。

e.断点加载成功后,WinDBG会给出类似下面这样的提示:

Found 1 methods...

MethodDesc = 00993028

Adding pending breakpoints...

f.当我们的断点命中后,我们仍然可以像普通调试一样来使用F10 Step Out单步执行,使用F11来Step Into单步执行。注意:这里的单步执行,都是指单步汇编代码,而不是我们所写的代码。

7) 在命中断点后我们就可以通过查看类命令来查看栈和堆中的变量的值以及当前的调用堆栈:

a.使用!clrstack可以查看当前的条用堆栈,使用!clrstack –l可以查看当前调用堆栈以及其上的局部变量和值,使用!clrstack –p可以查看当前调用堆栈上的参数变量以及值,使用!clrstack –a可以查看当前堆栈上所有局部变量和参数变量以及值(格式为StackAddress =  StackValue)。!clrstack命令只会显示托管代码的调用堆栈,如果想查看完整的调用堆栈可以使用!dumpstack命令:

b.使用!dso命令可以查看堆栈上的所有对象

c.使用!do [ObjectAddress]查看指定对象的具体内容:

8) 除了通过堆栈查看栈上的变量外,我们还可以直接通过!dumpheap来查看目前堆中的所有对象,但是由于一般情况下堆中存在的变量会非常的多(包含.Net框架里的很多预定义对象),所以直接使用!dumpheap得到的结果一般我们很难查看。大多数情况下,我们需要查看的是堆中指定类型的对象,所以我们可以使用!dumpheap –type [ClassName]来查看指定类型的对象:

9)如何检查内存泄漏?WinDBG SOS中有一个很有用的命令!GCRoot [ObjectAddress]可以帮助我们查看指定对象的引用情况,这个信息可以很好的帮助我们分析那些本应该没有引用但却一直还存在有效引用的对象,由此发现我们代码中潜在的内存泄漏,同时我们也可以观察到哪些对象是目前没有引用了,但是GC还没有回收的:

4. 总结:

1) WinDBG不是专门用于调试.Net程序的工具,它更偏向于底层,可用于内核和驱动调试。进行普通的.Net程序调试还是使用微软专为.Net开发的调试工具MDBG更方便一些。但是WinDBG能看到更多的底层信息,对于某些特别疑难的问题调试有所帮助,例如内存泄漏等问题。

2) SOS扩展命令中最有用的命令是!help命令J,使用该命令可以列出所有可用的SOS扩展命令列表,使用!help [SOSCommandName]可以查看每一个具体扩展命名的详细使用说明,例如!help dumpheap就可以查看!dumpheap这个扩展命名的具体使用方法。多多利用!help命名可以很快上手SOS。

3) WinDBG本身的资料可以参考 张银奎 先生的《软件调试》一书,另外在互联网上也有非常多的WinDBG资料。

转载于:https://www.cnblogs.com/mashuping/archive/2009/03/28/1424187.html

WinDBG工具简介(.net大会中张银奎先生介绍)相关推荐

  1. 域渗透提权分析工具 BloodHound 1.3 中的ACL攻击路径介绍

    本文讲的是域渗透提权分析工具 BloodHound 1.3 中的ACL攻击路径介绍, 简介和背景 2014年,Emmanuel Gras和Lucas Bouillot在" 信息通信技术研讨会 ...

  2. 13、域渗透提权分析工具 BloodHound 1.3 中的ACL攻击路径介绍

    简介和背景 2014年,Emmanuel Gras和LucasBouillot在" 信息通信技术研讨会"(Symposiumon Information and Communica ...

  3. Linux 中的 netcat 网络工具简介

    Linux 中的 netcat 网络工具简介 Apr 3, 2020 |  Linux |  linux netcat netcat 是 Linux 系统中的网络工具,其通过 TCP 和 UDP 协议 ...

  4. HttpWatch工具简介及使用技巧

    joan 私は张で QQ:774199038 HttpWatch工具简介及使用技巧(转载) 一 概述: HttpWatch强大的网页数据分析工具.集成在Internet Explorer工具栏.包括网 ...

  5. 专访张银奎:要抓住技术发展趋势,只有不断学习和更新自己?

    如果说软件的执行过程就像是CPU在无数条道路(指令流)间飞奔,那么开发软件的过程就是设计和构建这个交通网络的过程.其基本目标是要让CPU在这个网络中奔跑时可以完成需求(requirement)中所定义 ...

  6. 专访张银奎:要抓住技术发展趋势,只有不断学习和更新自己?...

    如果说软件的执行过程就像是CPU在无数条道路(指令流)间飞奔,那么开发软件的过程就是设计和构建这个交通网络的过程.其基本目标是要让CPU在这个网络中奔跑时可以完成需求(requirement)中所定义 ...

  7. Percona Toolkit工具简介

    系列文章目录 第一章:sql_mode模式 第二章:optimize table.analyze table.alter table.gh-ost 第三章:InnoDB MVCC原理 第四章:sql语 ...

  8. 《python 与数据挖掘 》一 1.2 工具简介

    本节书摘来自华章出版社<python 与数据挖掘 >一书中的第1章,第1.2节,作者张良均 杨海宏 何子健 杨 征,更多章节内容可以访问云栖社区"华章计算机"公众号查看 ...

  9. 【Android 命令行工具】Android 命令行工具简介 ( 官方文档 | SDK 命令行工具 | SDK 构建工具 | SDK 平台工具 | 模拟器工具 | Jetifier 工具 )

    文章目录 一.官方文档 二.Android 命令行工具简介 1.SDK 命令行工具 2.SDK 构建工具 3.SDK 平台工具 4.模拟器工具 5.Jetifier 工具 一.官方文档 Android ...

最新文章

  1. 史上最简单的SpringCloud教程 | 第十二篇: 断路器监控(Hystrix Dashboard)
  2. 在主界面的右下端设置系统时间
  3. P3309-[SDOI2014]向量集【线段树,凸壳】
  4. 【转】设计模式 ( 十七) 状态模式State(对象行为型)
  5. 解决VScode自动保存时在语句后疯狂加分号
  6. 1t硬盘怎么分区最好_win7系统硬盘怎么分区 win7系统硬盘分区步骤【介绍】
  7. 常用API2 正则表达式
  8. 搜索图片及相似度探秘 二
  9. vue ---- webpack中的插件 webpack-dev-server
  10. 使用EasyRecovery简单修复视频
  11. Self Host WebApi服务传输层SSL加密(服务器端+客户端调用)
  12. Redis之Pipeline使用注意事项
  13. EasyCHM - 电子书制作软件
  14. Android Studio制作一个简单的计算器APP
  15. [TravelNotes] CTSC 2017 APIO 2017 THUPC 2017 游记
  16. 为什么电子元器件会老化?像人变老一样吗?
  17. 将 libVLC 视频渲染到 QWidget 中
  18. nmon analyser 使用中报错“宏”不可用的问题及处理
  19. 支付宝花呗提前还款————附操作图片
  20. JavaWeb程序设计———名片管理系统

热门文章

  1. Java转型(向上或向下转型)
  2. golang应用部署
  3. MySQL第3天:MySQL的架构介绍之linux版安装
  4. linux中crontab命令的基本用法
  5. 关于实现udev/mdev自动挂载与卸载
  6. javaweb:servlet
  7. 【前端帮帮忙】第7期 关于节流(throttle)和防抖(debounce)的理解
  8. (转)写的非常好的一个WPF学习之路
  9. linux如何连接移动硬盘
  10. Another app is currently holding the yum lock; waitingn