• Windbg CLR基础小测 《第六篇》


      首先写一段代码如下:

    namespace ConsoleApplication3
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello, Windbg!");
    
                Console.ReadKey();
            }
        }
    }

      在Debug目录中启动该程序,然后在Debug中附加该进程。

    0:007> .load C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/sos.dll
    0:007> !dumpdomain
    *** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:WindowsMicrosoft.NETFrameworkv4.0.30319clr.dll - 
    PDB symbol for clr.dll not loaded
    --------------------------------------
    System Domain:      7106e898
    LowFrequencyHeap:   7106ebbc
    HighFrequencyHeap:  7106ec04
    StubHeap:           7106ec4c
    Stage:              OPEN
    Name:               None
    --------------------------------------
    Shared Domain:      7106e4f0
    LowFrequencyHeap:   7106ebbc
    HighFrequencyHeap:  7106ec04
    StubHeap:           7106ec4c
    Stage:              OPEN
    Name:               None
    Assembly:           0051a1b8 [C:WindowsMicrosoft.NetassemblyGAC_32mscorlibv4.0_4.0.0.0__b77a5c561934e089mscorlib.dll]
    ClassLoader:        00501660
      Module Name
    697e1000    C:WindowsMicrosoft.NetassemblyGAC_32mscorlibv4.0_4.0.0.0__b77a5c561934e089mscorlib.dll
    
    --------------------------------------
    Domain 1:           004e78a8
    LowFrequencyHeap:   004e7cfc
    HighFrequencyHeap:  004e7d44
    StubHeap:           004e7d8c
    Stage:              OPEN
    SecurityDescriptor: 004e9388
    Name:               ConsoleApplication3.exe
    Assembly:           0051a1b8 [C:WindowsMicrosoft.NetassemblyGAC_32mscorlibv4.0_4.0.0.0__b77a5c561934e089mscorlib.dll]
    ClassLoader:        00501660
    SecurityDescriptor: 0051a130
      Module Name
    697e1000    C:WindowsMicrosoft.NetassemblyGAC_32mscorlibv4.0_4.0.0.0__b77a5c561934e089mscorlib.dll
    
    Assembly:           00521db8 [C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe]
    ClassLoader:        005016c8
    SecurityDescriptor: 00521d30
      Module Name
    00212eac    C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe

      从上面的输出结果中,有如下发现:

    1. .Net app默认情况下,会有三个AppDomain,其中分别是System Domain,Shared Domain和应用程序自己的Application Domain(就是上面的Domain1);
    2. 一个domain内包含一个或若干个Assembly;

     如果仅仅只是想查看一个domain,则可以使用如下命令,其输出结果与上面的结果一致:

    0:007> !dumpdomain 004e78a8
    --------------------------------------
    Domain 1:           004e78a8
    LowFrequencyHeap:   004e7cfc
    HighFrequencyHeap:  004e7d44
    StubHeap:           004e7d8c
    Stage:              OPEN
    SecurityDescriptor: 004e9388
    Name:               ConsoleApplication3.exe
    Assembly:           0051a1b8 [C:WindowsMicrosoft.NetassemblyGAC_32mscorlibv4.0_4.0.0.0__b77a5c561934e089mscorlib.dll]
    ClassLoader:        00501660
    SecurityDescriptor: 0051a130
      Module Name
    697e1000    C:WindowsMicrosoft.NetassemblyGAC_32mscorlibv4.0_4.0.0.0__b77a5c561934e089mscorlib.dll
    
    Assembly:           00521db8 [C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe]
    ClassLoader:        005016c8
    SecurityDescriptor: 00521d30
      Module Name
    00212eac    C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe

      在上面的app domain中,我们可以看到包含了2个assembly,分别是mscorlib.dll和ConsoleApplication3.exe。

      都有1个module。这里我们看ConsoleApplication3.exe。

      看assembly信息,命令使用:!dumpassembly <assembly address>,我们执行:!dumpassembly <00212eac> 这个地址就在appdomain命令返回的程序集路径的左边。

    0:007> !dumpassembly 00521db8
    Parent Domain:      004e78a8
    Name:               C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe
    ClassLoader:        005016c8
      Module Name
    00212eac    C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe

      注意:

    1. assembly包含了指向domain的信息,上面的004e78a8;
    2. assembly包含了一个或者若干个module;

      这里只有一个module,我们继续看module里面包含啥。

      命令!dumpmodule有一个有用的开关,是-mt <mt address>,我们跑一下看看:!dumpmodule -mt 1caa50

    0:007> !dumpmodule -mt 00212eac
    Name:       C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe
    Attributes: PEFile 
    Assembly:   00521db8
    LoaderHeap:              00000000
    TypeDefToMethodTableMap: 00210038
    TypeRefToMethodTableMap: 00210044
    MethodDefToDescMap:      00210098
    FieldDefToDescMap:       002100a4
    MemberRefToDescMap:      002100a8
    FileReferencesMap:       002100fc
    AssemblyReferencesMap:   00210100
    MetaData start address:  012a206c (1628 bytes)
    
    Types defined in this module
    
          MT  TypeDef Name
    ------------------------------------------------------------------------------
    002137c0 0x02000002 ConsoleApplication3.Program
    
    Types referenced in this module
    
          MT    TypeRef Name
    ------------------------------------------------------------------------------
    69bb25e8 0x02000001 System.Object
    69bb869c 0x02000013 System.Console

      我们能发现两个重要的东西:

    1. 这个module里面包含的types,这里是我们的程序主入口点:ConsoleApplication3.Program;
    2. 这个module引用的types,这里是object和Console;

      看上面的ConsoleApplication3.Program,这个type对应的MethodTable地址是:002137c0。我们可以继续看这个MethodTable包含啥东西:

    0:007> !dumpmt 00212eac
    00212eac is not a MethodTable
    0:007> !dumpmt 002137c0
    EEClass:         0021125c
    Module:          00212eac
    Name:            ConsoleApplication3.Program
    mdToken:         02000002
    File:            C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe
    BaseSize:        0xc
    ComponentSize:   0x0
    Slots in VTable: 6
    Number of IFaces in IFaceMap: 0

      这里有一些重要的东西可以看:

    1. EEClass,可以通过!dumpclass <class address>来查看这个class的信息。如:!dumpclass 0021125c;
    2. 包含了Module和name等信息;
    3. 包含了Method Description 信息;
    4. VTable里面的slots一共6个;

      MethodTable只是一个入口表,它实际指向了一堆Method Description,那么我们可以用!dumpmt继续来查看,只不过参数要修改一下:!dumpmt -md 002137c0

    0:007> !dumpmt 002137c0
    EEClass:         0021125c
    Module:          00212eac
    Name:            ConsoleApplication3.Program
    mdToken:         02000002
    File:            C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe
    BaseSize:        0xc
    ComponentSize:   0x0
    Slots in VTable: 6
    Number of IFaces in IFaceMap: 0
    0:007> !dumpmt -md 00212eac
    00212eac is not a MethodTable
    0:007> !dumpmt -md 00212eac
    00212eac is not a MethodTable
    0:007> !dumpmt -md 00212eac
    00212eac is not a MethodTable
    0:007> !dumpmt -md 00212eac
    00212eac is not a MethodTable
    0:007> !dumpmt -md 002137c0
    EEClass:         0021125c
    Module:          00212eac
    Name:            ConsoleApplication3.Program
    mdToken:         02000002
    File:            C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe
    BaseSize:        0xc
    ComponentSize:   0x0
    Slots in VTable: 6
    Number of IFaces in IFaceMap: 0
    --------------------------------------
    MethodDesc Table
       Entry MethodDe    JIT Name
    69accd88 697e60bc PreJIT System.Object.ToString()
    69ac6a90 697e60c4 PreJIT System.Object.Equals(System.Object)
    69ac6660 697e60e4 PreJIT System.Object.GetHashCode()
    69b467c0 697e60f8 PreJIT System.Object.Finalize()
    0021c015 002137b8   NONE ConsoleApplication3.Program..ctor()
    00480050 002137ac    JIT ConsoleApplication3.Program.Main(System.String[])

      加了-md之后多出来了6个method description的信息,这就是那个Slots in VTable:6里面的6

      对于每个方法,上表有一列JIT指明了CLR是否已经对该方法进行了编译动作。上面有一个方法是JIT过了,是那个Main函数,另外的4个CLR已经预先做了JIT(为什么?想想GAC和NGEN.EXE)。那么对于具体的方法是否做过了JIT,我们可以用命令:!dumpmd来看,比如看上面的Main方法,那么!dumpmd 002137c0

    0:007> !dumpmt 002137c0
    EEClass:         0021125c
    Module:          00212eac
    Name:            ConsoleApplication3.Program
    mdToken:         02000002
    File:            C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe
    BaseSize:        0xc
    ComponentSize:   0x0
    Slots in VTable: 6
    Number of IFaces in IFaceMap: 0
    0:007> !dumpmt -md 00212eac
    00212eac is not a MethodTable
    0:007> !dumpmt -md 00212eac
    00212eac is not a MethodTable
    0:007> !dumpmt -md 00212eac
    00212eac is not a MethodTable
    0:007> !dumpmt -md 00212eac
    00212eac is not a MethodTable
    0:007> !dumpmt -md 002137c0
    EEClass:         0021125c
    Module:          00212eac
    Name:            ConsoleApplication3.Program
    mdToken:         02000002
    File:            C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe
    BaseSize:        0xc
    ComponentSize:   0x0
    Slots in VTable: 6
    Number of IFaces in IFaceMap: 0
    --------------------------------------
    MethodDesc Table
       Entry MethodDe    JIT Name
    69accd88 697e60bc PreJIT System.Object.ToString()
    69ac6a90 697e60c4 PreJIT System.Object.Equals(System.Object)
    69ac6660 697e60e4 PreJIT System.Object.GetHashCode()
    69b467c0 697e60f8 PreJIT System.Object.Finalize()
    0021c015 002137b8   NONE ConsoleApplication3.Program..ctor()
    00480050 002137ac    JIT ConsoleApplication3.Program.Main(System.String[])
    0:007> !dumpmd 00480050
    00480050 is not a MethodDesc
    0:007> !dumpmd 00480050
    00480050 is not a MethodDesc
    0:007> !dumpmd 002137ac
    Method Name:  ConsoleApplication3.Program.Main(System.String[])
    Class:        0021125c
    MethodTable:  002137c0
    mdToken:      06000001
    Module:       00212eac
    IsJitted:     yes
    CodeAddr:     00480050
    Transparency: Critical

      上面最重要的结果就是有一个IsJitted的标志,这里是yes,表明它已经被compile过了,对于compile之后的native code,我们就可以用命令!u <m_codeoril>来观察。下命令:!u 00480050

    0:007> !u 00480050
    Normal JIT generated code
    ConsoleApplication3.Program.Main(System.String[])
    Begin 00480050, size 32
    *** WARNING: Unable to verify checksum for C:UsersChenZhuoDocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3inDebugConsoleApplication3.exe
    
    C:UsersChenZhuodocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3Program.cs @ 14:
    >>> 00480050 55              push    ebp
    00480051 8bec            mov     ebp,esp
    00480053 83ec10          sub     esp,10h
    00480056 894dfc          mov     dword ptr [ebp-4],ecx
    00480059 833d7831210000  cmp     dword ptr ds:[213178h],0
    00480060 7405            je      00480067
    00480062 e8dcc98470      call    clr!GetHistoryFileDirectory+0x8b758 (70ccca43) (JitHelp: CORINFO_HELP_DBG_IS_JUST_MY_CODE)
    00480067 90              nop
    
    C:UsersChenZhuodocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3Program.cs @ 15:
    00480068 8b0d7021eb02    mov     ecx,dword ptr ds:[2EB2170h] ("Hello, Windbg!")
    *** WARNING: Unable to verify checksum for C:WindowsassemblyNativeImages_v4.0.30319_32mscorlib45c9588954c3662d542b53f4462268bmscorlib.ni.dll
    0048006e e885796569      call    mscorlib_ni+0x2f79f8 (69ad79f8) (System.Console.WriteLine(System.String), mdToken: 06000995)
    00480073 90              nop
    
    C:UsersChenZhuodocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3Program.cs @ 17:
    00480074 8d4df0          lea     ecx,[ebp-10h]
    00480077 e82460d369      call    mscorlib_ni+0x9d60a0 (6a1b60a0) (System.Console.ReadKey(), mdToken: 06000974)
    0048007c 90              nop
    
    C:UsersChenZhuodocumentsvisual studio 2010ProjectsConsoleApplication3ConsoleApplication3Program.cs @ 18:
    0048007d 90              nop
    0048007e 8be5            mov     esp,ebp
    00480080 5d              pop     ebp
    00480081 c3              ret

      见到源代码了,字符串都看到了。

      如果我们想看看StreamReader里面有哪些方法,应该用什么命令呢?

      命令:!name2ee mscorlib_ni!System.IO.StreamReader.ReadBuffer

    0:007> !name2ee mscorlib_ni!System.IO.StreamReader.ReadBuffer
    Module:      697e1000
    Assembly:    mscorlib.dll
    Token:       06004733
    MethodDesc:  6985f3dc
    Name:        System.IO.StreamReader.ReadBuffer()
    JITTED Code Address: 69b18020
    -----------------------
    Token:       0600473f
    MethodDesc:  6985f460
    Name:        System.IO.StreamReader.ReadBuffer(Char[], Int32, Int32, Boolean ByRef)
    JITTED Code Address: 69b763d0

      拿到了Method Description的地址后执行:!dumpmd 6985f3dc

    0:007> !dumpmd 6985f3dc
    Method Name:  System.IO.StreamReader.ReadBuffer()
    Class:        6983e558
    MethodTable:  69ba8fd0
    mdToken:      06004733
    Module:       697e1000
    IsJitted:     yes
    CodeAddr:     69b18020
    Transparency: Transparent

      再执行!dumpmt -md 69ba8fd0,就可以得到这个class的所有method信息

    0:007> !dumpmt -md 69ba8fd0
    EEClass:         6983e558
    Module:          697e1000
    Name:            System.IO.StreamReader
    mdToken:         02000789
    File:            C:WindowsMicrosoft.NetassemblyGAC_32mscorlibv4.0_4.0.0.0__b77a5c561934e089mscorlib.dll
    BaseSize:        0x40
    ComponentSize:   0x0
    Slots in VTable: 69
    Number of IFaces in IFaceMap: 1
    --------------------------------------
    MethodDesc Table
       Entry MethodDe    JIT Name
    69accd88 697e60bc PreJIT System.Object.ToString()
    69ac6a90 697e60c4 PreJIT System.Object.Equals(System.Object)
    69ac6660 697e60e4 PreJIT System.Object.GetHashCode()
    69b467c0 697e60f8 PreJIT System.Object.Finalize()
    69b7f310 69872554 PreJIT System.MarshalByRefObject.GetLifetimeService()
    69aafd70 6987255c PreJIT System.MarshalByRefObject.InitializeLifetimeService()
    69b6fdbc 69872564 PreJIT System.MarshalByRefObject.CreateObjRef(System.Type)
    69b1bbe0 6985f360 PreJIT System.IO.StreamReader.Close()
    69b4ea80 6985ce74 PreJIT System.IO.TextReader.Dispose()
    69b17a80 6985f368 PreJIT System.IO.StreamReader.Dispose(Boolean)  ... ...省略一部分
  • 相关阅读:
    MSP430:实时时钟-DS1302
    STM32: TIMER门控模式控制PWM输出长度
    LVM磁盘管理
    python的面向对象,类,以及类的使用
    pymysql模块
    paramiko模块
    正则表达式和re模块
    python3的soker模块实现功能
    根据生日测星座
    多进程,进程池,协程
  • 原文地址:https://www.cnblogs.com/kissdodog/p/3732423.html
Copyright © 2020-2023  润新知