从头开始使用WinDbg 第一部分

 

从头开始使用WinDbg 第一部分

基本配置:

1)  sos.dll 拷贝到WinDbg的安装目录,确保你拷贝的这个dll和你想要研究问题的程序的.net 版本一致。如果你同时在.net1.1 .net2.0下,你可以把sos.dll 重命名为 sos11.dll sos20.dll 或者把它们放在不同的目录下面。

2)  创建一个文件夹,用来放置你的符号文件,例如:“C:\symbols”

3)  打开WinDbg,打开配置符号文件路径的对话框

4)  输入路径,并且下载符号文件的路径,当你的本地没有符号文件的时候,它就需要去服务器上下载。结构如下:

srv*[cache path]*[symbols path]

I'd recommend the following path:

srv*c:\symbols\public*http://msdl.microsoft.com/download/symbols

相信你已经设置好,下面开始了。

 

很有用的命令:

我会使用一个从IIS6上取来的dump文件来演示一些很有用的命令。

第一件事要做的就是加载SOS,这个命令是 .load [extension filename] 这个结构很简单。load 前面有一个 . ”。

.load sos

 

你现在已经有了一个很酷的带有SOS扩展的命令提示工具。扩展命令都是以 !”前置的,因此如果你想运行一个帮助命令:

!help

如果你刚好有两个扩展,而且分别有个命令,它们的名字是一样的,你可以这样来分开它们:

![extension name].[command]

!sos.help

现在你知道了如何来运行命令,那么运行help来看看,下面是给你的结果:

0:000> !help

-------------------------------------------------------------------------------

SOS is a debugger extension DLL designed to aid in the debugging of managed

programs. Functions are listed by category, then roughly in order of

importance. Shortcut names for popular functions are listed in parenthesis.

Type "!help " for detailed info on that function.

 

Object Inspection                  Examining code and stacks

-----------------------------      -----------------------------

DumpObj (do)                       Threads

DumpArray (da)                     CLRStack

DumpStackObjects (dso)             IP2MD

DumpHeap                           U

DumpVC                             DumpStack

GCRoot                             EEStack

ObjSize                            GCInfo

FinalizeQueue                      EHInfo

PrintException (pe)                COMState

TraverseHeap                       BPMD

 

Examining CLR data structures      Diagnostic Utilities

-----------------------------      -----------------------------

DumpDomain                         VerifyHeap

EEHeap                             DumpLog

Name2EE                            FindAppDomain

SyncBlk                            SaveModule

DumpMT                             GCHandles

DumpClass                          GCHandleLeaks

DumpMD                             VMMap

Token2EE                           VMStat

EEVersion                          ProcInfo

DumpModule                         StopOnException (soe)

ThreadPool                         MinidumpMode

DumpAssembly                      

DumpMethodSig                      Other

DumpRuntimeTypes                   -----------------------------

DumpSig                            FAQ

RCWCleanupList

DumpIL

更多的信息你可以查看帮助,输入 !help [name of command]

 

.time

这个不是SOS扩展命令,因为明显它不是一个以“!”开头的命令。Time 这个命令会显示和时间有关系的信息。例如:系统启动到现在的时间(uptime)、进程启动到现在的时间,和在用户和核心模式下的时间总和。

0:000> .time

Debug session time: Tue Oct 23 08:38:35.000 2007 (GMT+1)

System Uptime: 4 days 17:48:01.906

Process Uptime: 0 days 0:24:37.000

  Kernel time: 0 days 0:04:23.000

  User time: 0 days 0:03:28.000

你可以看到系统已经启动有4天多了,进程已经运行了24½ 分钟。消耗的cpu时间总计是8分钟。这样我们可以得到一个cpu使用率的大概是32.5%

 

!threadpool

我们可以使用这个命令完整的找出在dump文件在创建的时候得多少的cpu 使用率。并能得到一些很有用的信息,比如队列中的工作请求数目,完整端口线程数目和计时器的数目。

0:000> !threadpool

CPU utilization 100%

Worker Thread: Total: 5 Running: 4 Idle: 1 MaxLimit: 200 MinLimit: 2

Work Request in Queue: 16

Unknown Function: 6a2d945d  Context: 023ede30

Unknown Function: 6a2d945d  Context: 023ee1e8

AsyncTimerCallbackCompletion TimerInfo@11b53760

Unknown Function: 6a2d945d  Context: 023ee3a8

Unknown Function: 6a2d945d  Context: 023e3040

Unknown Function: 6a2d945d  Context: 023ee178

Unknown Function: 6a2d945d  Context: 023edfb0

AsyncTimerCallbackCompletion TimerInfo@11b36428

AsyncTimerCallbackCompletion TimerInfo@11b53868

Unknown Function: 6a2d945d  Context: 023ee060

Unknown Function: 6a2d945d  Context: 023ee290

Unknown Function: 6a2d945d  Context: 023eded0

Unknown Function: 6a2d945d  Context: 023edd88

Unknown Function: 6a2d945d  Context: 023ede98

Unknown Function: 6a2d945d  Context: 023ee258

Unknown Function: 6a2d945d  Context: 023edfe8

--------------------------------------

Number of Timers: 9

--------------------------------------

Completion Port Thread:Total: 3 Free: 3 MaxFree: 4 CurrentLimit: 2 MaxLimit: 200 MinLimit: 2

所以我们看见现在的cpu使用率是100%,然后我们再看下一个命令。

 

!runaway

这是一个很好的命令,将会列出所有运行中的线程和cpu使用时间,这个是解决高cpu占用率很有用的一个命令。

0:000> !runaway

User Mode Time

  Thread       Time

  25:1a94      0 days 0:00:39.937

  16:1bc0      0 days 0:00:38.390

  50:1e8c      0 days 0:00:08.859

  52:1e40      0 days 0:00:08.687

  20:1c2c      0 days 0:00:08.234

  51:1340      0 days 0:00:08.171

  21:1bcc      0 days 0:00:06.953

  26:13ec      0 days 0:00:06.671

  44:131c      0 days 0:00:03.906

  22:d8c       0 days 0:00:03.375

  33:78c       0 days 0:00:02.656

你会看到这个总的时间和上面那个从.time命令中得到的cpu 利用(cpu utilization)的时间不一样,那是因为进程被重用了和回收了。这意味着总的cpu使用时间被若干个页面请求线程分割了。

 

!threads

要得到更多的运行线程信息,我们可以运行这个命令,这个会列出所有当前应用程序域下的托管线程。输出类似如下:

0:000> !threads

ThreadCount: 48

UnstartedThread: 0

BackgroundThread: 29

PendingThread: 0

DeadThread: 19

Hosted Runtime: no

                                      PreEmptive   GC Alloc           Lock

       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception

  16    1 1bc0 001fccd0   1808220 Enabled  00000000:00000000 0019daf0     0 Ukn (Threadpool Worker)

  22    2  d8c 002016f0      b220 Enabled  00000000:00000000 0019daf0     0 MTA (Finalizer)

  14    4  4ac 00242e58   880a220 Enabled  00000000:00000000 0019daf0     0 MTA (Threadpool Completion Port)

  23    5 14a4 11b39f18    80a220 Enabled  00000000:00000000 0019daf0     0 MTA (Threadpool Completion Port)

  24    6 1d2c 11b41ad8      1220 Enabled  00000000:00000000 0019daf0     0 Ukn

  25    7 1a94 11b46c70   180b220 Enabled  27240c98:27241fd8 11b42540     1 MTA (Threadpool Worker)

  26    9 13ec 12ce2888   200b220 Enabled  2a9f1434:2a9f33c0 11b42540     0 MTA

  27    a 190c 12d85eb8   200b220 Enabled  00000000:00000000 11b42540     0 MTA

  29    b 1f5c 13df6a50   200b220 Enabled  2ab1da6c:2ab1f1c0 11b42540     0 MTA

那些ID XXXX 的线程是已经结束的,正在等待被回收。我们可以看见 一个 finalizer”的线程的ID号是22。因此当如果我们运行 !runaway 命令看到一个不正常的活动的编号是22,那我们现在知道是finalizer 的问题。

 

切换到某一个指定的进程

我们使用 ~[number of thread]s ,所以如果要转到50号进程,按下面的方法:

0:000> ~50s

如果我们能切换到50号进程,那我们有很多其他有用的命令。

 

!clrstack

这个命令列出当前进程的调用堆栈。 -p”开关量可以提供参数和局部变量的信息。

0:050> !clrstack

OS Thread Id: 0x1e8c (50)

ESP       EIP    

17a9e750 7d61c828

[NDirectMethodFrameSlim: 17a9e750]

 System.DirectoryServices.Protocols.Wldap32.ldap_bind_s(IntPtr, System.String,

System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX, System.DirectoryServices.Protocols.BindMethod)

17a9e768 14df70f9

System.DirectoryServices.Protocols.LdapConnection.BindHelper(System.Net.NetworkCredential, Boolean)

17a9e794 14df6de0 System.DirectoryServices.Protocols.LdapConnection.Bind()

17a9e79c 14df59e9

System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(System.DirectoryServices.Protocols.DirectoryRequest, Int32 ByRef)

17a9e8b8 14df56e8

System.DirectoryServices.Protocols.LdapConnection.SendRequest(System.DirectoryServices.Protocols.DirectoryRequest, System.TimeSpan)

17a9e8bc 14df5657 [InlinedCallFrame: 17a9e8bc]

从下读到上,我们可以看到 调用了LdapConnectionSendRequest方法,该方法又调用了SendRequestHelper,这样一层一层的。

0:050> !clrstack -p
OS Thread Id: 0x1e8c (50)
ESP       EIP    
17a9e750 7d61c828 [NDirectMethodFrameSlim: 17a9e750] System.DirectoryServices.Protocols.Wldap32.ldap_bind_s(IntPtr, System.String, System.DirectoryServices.Protocols.SEC_WINNT_AUTH_IDENTITY_EX, System.DirectoryServices.Protocols.BindMethod)
17a9e768 14df70f9 System.DirectoryServices.Protocols.LdapConnection.BindHelper(System.Net.NetworkCredential, Boolean)
    PARAMETERS:
        this = 0x271fdfe0
        newCredential =
        needSetCredential =

17a9e794 14df6de0 System.DirectoryServices.Protocols.LdapConnection.Bind()
    PARAMETERS:
        this =

17a9e79c 14df59e9 System.DirectoryServices.Protocols.LdapConnection.SendRequestHelper(System.DirectoryServices.Protocols.DirectoryRequest, Int32 ByRef)
    PARAMETERS:
        this = 0x271fdfe0
        request = 0x27246e38
        messageID = 0x17a9e8ec

17a9e8b8 14df56e8 System.DirectoryServices.Protocols.LdapConnection.SendRequest(System.DirectoryServices.Protocols.DirectoryRequest, System.TimeSpan)
    PARAMETERS:
        this = 0x271fdfe0
        request = 0x27246e38
        requestTimeout =

17a9e8bc 14df5657 [InlinedCallFrame: 17a9e8bc]

 

我们看看这些参数,比如传递到SendRequest SendRequestHelper DirectoryRequest ,我们要查看它的值,只要把地址记住,然后用下面的命令。

 

!dumpobject (!do)

这是另外一个非常有用的命令,根据地址,可以把一个对象dump出来,把requeset的地址传过去,就可以把这个对象dump出来

0:050> !do 0x27246e38
Name: System.DirectoryServices.Protocols.SearchRequest
MethodTable: 14b394c4
EEClass: 14d97ce0
Size: 52(0x34) bytes
GC Generation: 0
(C:\WINDOWS\assembly\GAC_MSIL\System.DirectoryServices.Protocols\2.0.0.0__b03f5f7f11d50a3a\System.DirectoryServices.Protocols.dll)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
02c39310  4000102        4        System.String  0 instance 00000000 directoryRequestID
14b398bc  4000103        8 ...ControlCollection  0 instance 27246e90 directoryControlCollection
02c39310  4000111        c        System.String  0 instance 27246d00 dn
12579f5c  4000112       10 ....StringCollection  0 instance 27246eb4 directoryAttributes
02c36ca0  4000113       14        System.Object  0 instance 27246ddc directoryFilter
14b39344  4000114       18         System.Int32  1 instance        1 directoryScope
14b393fc  4000115       1c         System.Int32  1 instance        0 directoryRefAlias
0fd3da00  4000116       20         System.Int32  1 instance        0 directorySizeLimit
1202af88  4000117       28      System.TimeSpan  1 instance 27246e60 directoryTimeLimit
120261c8  4000118       24       System.Boolean  1 instance        0 directoryTypesOnly

 

好的,那是什么呢?它是System.DirectoryServices.Protocols.SearchRequest 对象,那就是说它有很多不同的由System.DirectoryServices.Protocols.SearchRequest类定义的属性。可以 查看msdn来知道更多的信息。它包含RequestId, Scope, DistinguishedName等字段。

让我们大胆的猜测 dn 这个东西里面是什么东西。利用27246d00 这个地址,我们来看看

0:050> !do 27246d00

Name: System.String

MethodTable: 02c39310

EEClass: 0fb610ac

Size: 112(0x70) bytes

GC Generation: 0

(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)

String: CN=Dummy,CN=Accounts,CN=useradm,DC=dummy,DC=net

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

0fd3da00  4000096        4         System.Int32  1 instance       48 m_arrayLength

0fd3da00  4000097        8         System.Int32  1 instance       47 m_stringLength

0fb80010  4000098        c          System.Char  1 instance       43 m_firstChar

02c39310  4000099       10        System.String  0   shared   static Empty

    >> Domain:Value  0019daf0:03380310 11b42540:03380310 <<

0fb86d44  400009a       14        System.Char[]  0   shared   static WhitespaceChars

    >> Domain:Value  0019daf0:03380324 11b42540:033855bc <<

确切的说,里面放的是"CN=Dummy,CN=Accounts,CN=useradm,DC=dummy,DC=net",如果你想找出更多的信息,可以继续用 !do 这个命令来检查它们。

下一章,我们继续使用 !do 这些命令来分析dump文件,另外还会介绍更多的命令。

posted @ 2008-01-28 14:21  softfair  阅读(1538)  评论(0编辑  收藏  举报