惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tenable Blog
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
H
Help Net Security
F
Fortinet All Blogs
MyScale Blog
MyScale Blog
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 司徒正美
量子位
N
Netflix TechBlog - Medium
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
Recorded Future
Recorded Future
博客园 - 三生石上(FineUI控件)
Vercel News
Vercel News
aimingoo的专栏
aimingoo的专栏
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
Scott Helme
Scott Helme
The Last Watchdog
The Last Watchdog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
IT之家
IT之家
AI
AI
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
U
Unit 42
V2EX - 技术
V2EX - 技术
MongoDB | Blog
MongoDB | Blog
Schneier on Security
Schneier on Security
博客园 - Franky
H
Heimdal Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Jina AI
Jina AI
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
N
News | PayPal Newsroom
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
Hacker News - Newest:
Hacker News - Newest: "LLM"
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
雷峰网
雷峰网

博客园 - -==NoWay.==-

[转载]使用C#的BitmapData The Open Source iPhone Apps List 一个自动更新的简单实现(通过反射解耦) - -==NoWay.==- - 博客园 Lambda印象 获取系统信息 魔兽、星际和红警的比较 迟到 年华 一款简单却很非脑力的小游戏 Implementing Virtual Mode with Just-In-Time Data Loading in the Windows Forms DataGridView Control 只因女婿是VB程序员,刚见面就被未来岳父轰出家门 About System.Reflection.Emit InitialInstanceActivator AsyncCallback The Windows Control 为开通http://beta.zooomr.com/的Pro帐户用的 AsyncCallback The Windows Control 标准代码页列表 winmine cheat Read MP3 Header Info
使用WinDBG + SOS调试.Net程序的一般步骤
-==NoWay.==- · 2009-04-13 · via 博客园 - -==NoWay.==-
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资料。