stand on the shoulders of giants

Windbg+SOS 分析托管程序

转载Juqiang的Basic Windbg系列

代码: 

代码
using System;
using System.Collections;
using System.Text;

namespace SOSBasics
{
    
class Program
    {
        
static void Main(string[] args)
        {
            MatrixWorld matrix 
= new MatrixWorld();
            Console.WriteLine(matrix);
            Console.WriteLine(
"=========================================================");
            Console.WriteLine(
"到命令行下面,然后切换到windbg目录,执行adplus -hang -pn cosoleTry.exe -o c:\\dumps");
            Console.ReadLine();
        }
    }

    
public class MatrixWorld
    {
        
private int generation;
        
private double gold;
        
private string name;
        
private DateTime age;
        
private Hashtable systemKey;
        
private string[] leaders;
        
private object previousOne;

        
private Zion zion;

        
public MatrixWorld()
        {
            
this.generation = 6;
            
this.gold = 123456789;
            
this.name = "The Matrix";
            
this.age = new DateTime(209911);
            
this.systemKey = new Hashtable();

            
this.systemKey.Add("Oracle""会变脸的老女人");
            
this.systemKey.Add("Architect""很帅的酷老头儿,应该去演Gandalf");
            
this.systemKey.Add("Smith""徒为别人做嫁衣");

            
this.leaders = new string[] { "第一代""第二代""第三代""第四代""第五代""NEO""那个印度小女孩" };
            
this.previousOne = "NEO的前身,不知道是谁";

            
this.zion = new Zion();
            
this.zion.One = "NEO";
        }

        
public int Generation { get { return this.generation; } }
        
public double Gold { get { return this.gold; } set { this.gold = value; } }
        
public string Name { get { return this.name; } }
        
public DateTime Age { get { return this.age; } }
        
public Hashtable SystemKey { get { return this.systemKey; } }
        
public string[] Leaders { get { return this.leaders; } }
        
public object PreviousOne { get { return this.previousOne; } }
        
public Zion Zion { get { return this.zion; } }

        
public override string ToString()
        {
            System.Text.StringBuilder sb 
= new StringBuilder(1024);

            sb.Append(
this.name); sb.Append(" time is "); sb.Append(this.age); sb.Append(System.Environment.NewLine);
            sb.Append(
"Gold: "); sb.Append(this.gold); sb.Append(System.Environment.NewLine);
            sb.Append(
"All key items in "); sb.Append(this.name); sb.Append(" listed here"); sb.Append(System.Environment.NewLine);

            IEnumerator ite 
= this.systemKey.Keys.GetEnumerator();
            
while (ite.MoveNext())
            {
                sb.Append(
"\t");
                sb.Append(ite.Current.ToString());
                sb.Append(
"");
                sb.Append(
this.systemKey[ite.Current]);
                sb.Append(System.Environment.NewLine);
            }

            sb.Append(
"历代救世主名单");
            sb.Append(System.Environment.NewLine);
            
foreach (string leader in this.leaders)
            {
                sb.Append(leader);
                sb.Append(System.Environment.NewLine);
            }

            sb.Append(System.Environment.NewLine);
            sb.Append(
"其中,上一代救世主:");
            sb.Append(
this.previousOne);

            sb.Append(System.Environment.NewLine);
            sb.Append(
"ZION的资料是:");
            sb.Append(
this.zion);

            
return sb.ToString();
        }
    }

    
public class Zion
    {
        
private string one;

        
public string One
        {
            
get { return this.one; }
            
set { this.one = value; }
        }

        
public override string ToString()
        {
            
return this.one;
        }
    }
}

 

1. 打开Dump文件, windbg打开,Ctrl+D

2. ~ 列出所有线程 ~2s 进入第二个线程

3. kb 列出当前线程CallStack (非托管)

4. ~*kb 列出所有线程的callstack (非托管)

5. 装载SOS 命令 .load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll

6. !clrstack 列出托管代码CallStack; 同样~*e!clrstack列出所有线程的callstack

章节1 栈分析

7. !dso(Dump Stack Objects的缩写),这个命令可以把当前上所有的变量都搞出来

8. !do (Dump Object), 查看变量信息 !do + 地址 如果需要查看帮助:!help dumpobj
下面列出的是变量MatrixWorld的所有Field信息

!do 02747724
Name: SOSBasics.MatrixWorld
MethodTable: 00163424
EEClass: 00161490
Size: 48(0x30) bytes
(E:\ProLab\cosoleTry\cosoleTry\bin\x86\Debug\cosoleTry.exe)
Fields:
      MT    Field   Offset                 Type                 VT                  Attr             Value                Name
61f42d34  4000001       20         System.Int32       1             instance        6                         generation
61f14678  4000002        4        System.Double      1             instance  123456789.000000     gold
61f40ae8  4000003        c        System.String        0             instance   02747754                     name
61f18148  4000004       24      System.DateTime   1             instance 02747748                    age
61f4313c  4000005       10 ...ections.Hashtable    0              instance 027479d0                systemKey
61f142b8  4000006       14      System.Object[]     0             instance 02747a98                 leaders
61f40704  4000007       18        System.Object     0             instance 02747904                previousOne
001634b8  4000008       1c       SOSBasics.Zion    0             instance 02747ac4                   zion

The column VT contains the value 1 if the field is a valuetype structure, and 0 if the field contains a pointer to another object. For valuetypes, you can
take the MethodTable pointer in the MT column, and the Value and pass them to the command !DumpVC

可以看出VT列是1的int和double的值直接显示,

9. 特殊的是DateTime类型,需要  !DumpVC + MT + Value

!DumpVC 61f18148  02747748
Name: System.DateTime
MethodTable 61f18148
EEClass: 61cf0564
Size: 16(0x10) bytes
(C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
61f193ec  40000f4        0        System.UInt64  1 instance 662065056000000000 dateData
61f42c84  40000f0       30       System.Int32[]  0   shared   static DaysToMonth365
    >> Domain:Value  007567f0:02747950 <<
61f42c84  40000f1       34       System.Int32[]  0   shared   static DaysToMonth366
    >> Domain:Value  007567f0:02747990 <<
61f18148  40000f2       28      System.DateTime  1   shared   static MinValue
    >> Domain:Value  007567f0:02747930 <<
61f18148  40000f3       2c      System.DateTime  1   shared   static MaxValue
    >> Domain:Value  007567f0:02747940 <<

10. 引用类型,!do+地址
11. 殊的对HashTable使用!do
027479d0 得到

!do 027479d0
Name: System.Collections.Hashtable
MethodTable: 61f4313c
EEClass: 61cfe93c
Size: 56(0x38) bytes
(C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
61f43238  400093c        4 ...ashtable+bucket[]  0 instance 02747a08 buckets
61f42d34  400093d       1c         System.Int32  1 instance        3 count
61f42d34  400093e       20         System.Int32  1 instance        1 occupancy
61f42d34  400093f       24         System.Int32  1 instance        7 loadsize
61f3a32c  4000940       28        System.Single  1 instance 0.720000 loadFactor
61f42d34  4000941       2c         System.Int32  1 instance        3 version
61f145b4  4000942       30       System.Boolean  1 instance        0 isWriterInProgress
61f42fb8  4000943        8 ...tions.ICollection  0 instance 0274a87c keys
61f42fb8  4000944        c ...tions.ICollection  0 instance 00000000 values
61f3c8c0  4000945       10 ...IEqualityComparer  0 instance 00000000 _keycomparer
61f40704  4000946       14        System.Object  0 instance 00000000 _syncRoot
61f2eee0  4000947       18 ...SerializationInfo  0 instance 00000000 m_siInfo

Count = 3 表示我们的HashTable有3个元素,
继续对buckets 运行 dd 02747a08 得到
dd 02747a08
02747a08  61f43238 0000000b 00000000 00000000
02747a18  00000000 00000000 00000000 00000000
02747a28  00000000 00000000 00000000 0274777c
02747a38  0274779c e047abd0 00000000 00000000
02747a48  00000000 00000000 00000000 00000000
02747a58  00000000 00000000 00000000 00000000
02747a68  00000000 00000000 00000000 00000000
02747a78  00000000 027477bc 027477e0 62e0f252

第一个0000000b,表明这个hashtable有11个对象。
12. !do -nofields 0274777c 得到HashTable第一个元素的Key,(-nofields不输出fields信息)

13. !do -nofields 0274779c 得到HashTable第一个元素的Value,

14. 对数组,用  !da 02747a98

0:000> !da 02747a98
Name: System.String[]
MethodTable: 61f142b8
EEClass: 61cfda64
Size: 44(0x2c) bytes
Array: Rank 1, Number of elements 7, Type CLASS
Element Methodtable: 61f40ae8
[0] 02747854
[1] 0274786c
[2] 02747884
[3] 0274789c
[4] 027478b4
[5] 027478cc
[6] 027478e4
0:000> !do 02747854

然后对其中任意一个!do 或者直接

15. !da -details 02747a98 列出数组中所有元素的详细信息

16 对自定义类型也是使用!do !do 层层剥皮

章节2 堆分析

17. !eeheap –gc

!eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x027107b4
generation 1 starts at 0x0270100c
generation 2 starts at 0x02701000
ephemeral segment allocation context: none
segment    begin allocated     size
02700000 02701000  0274b4e0 0x0004a4e0(304352)
Large object heap starts at 0x03701000
segment    begin allocated     size
03700000 03701000  03703250 0x00002250(8784)
Total Size   0x4c730(313136)
------------------------------
GC Heap Size   0x4c730(313136)

  GC有三个generation,分别是0、1、2 
  整个gc heap的size是:313136,大概三百多K
  查看抓到的Dump文件,有50M左右,说明大部分都是非托管资源占用的内存。

18.  !dumpheap –stat 把托管堆上所有的东西都扒出来, -stat 按照托管资源的类型group by; 取得帮助
    !help dumpheap

19.  !dumpheap -mt <methodtable>

20. !dumpheap –min 8000 查看所有8000个以上字节的对象

!dumpheap -min 8000
Address       MT     Size
02704b34 61f142b8     8208    
027107c0 61f40ae8    45832    
02720458 61f43558    39684    
027354a8 61f40ae8     9280    
027385b0 61f43558     9012    
0273fb58 61f43558    22920    
total 6 objects
Statistics:
      MT    Count    TotalSize Class Name
61f142b8        1         8208 System.Object[]
61f40ae8        2        55112 System.String
61f43558        3        71616 System.Byte[]
Total 6 objects

一共有6个对象,其中1个object数组,2个字符串,3个byte数组, 其实我们得到的61f40ae8是所有string的table地址,对数组进行查看:

21. !dumpheap -mt 61f40ae8 -min 800 查看字节数超过800的string对象
Address       MT     Size
02701fc4 61f40ae8     2216    
0270286c 61f40ae8     3384    
027107c0 61f40ae8    45832    
027354a8 61f40ae8     9280    
02749478 61f40ae8     2068    
total 5 objects
Statistics:
      MT    Count    TotalSize Class Name
61f40ae8        5        62780 System.String

可以看到一共有5个符合我们要求的string,
运行!do -nofields 02749478可以看到这个string就是我们控制台输出的string,就是我们代码里的stringbuilder变量。
运行!do –nofields  027107c0是一个xml文件,是CLR自己维护的

22. !dumpheap -type String(Hashtable)根据类型查看

posted @ 2010-09-16 16:32  DylanWind  阅读(1056)  评论(0编辑  收藏  举报