• Windbg在Managed App中设置函数断点的几种方法


    本文介绍两种使用Windbg在Managed App中设置断点的方法。一种是在live Debug的时候,attach到了Process之后。另外一种是动态调试的时候,如何给几个模块的特定方法下一个断点。    

             使用Windbg在Native Code里面下断点是比较方便的,bp加上一个内存地址就可以做到。但是在托管的时候给一个方法下一个断点稍微有点麻烦。因为Windbg是一个native Debugger,而Managed App在没有Jited的时候,是没有生成Native Code的。每个方法在第一次调用之后,才生成了native code。当然,这里不说ngen。

            

             还是先给个小程序做小白鼠:

             class Program

        {

            static void Main(string[] args)

            {

                System.Console.WriteLine("Show Params in Windbg");

                Program p = new Program();

     

                p.ShowParams(123456, "TestParams", 'L');

     

                System.Console.ReadLine();

            }

            public void ShowParams(int a, string b ,char c)

            {

            }

    }

             

              在使用live Debug的时候,设置一个没有本地代码的方法断点不是很麻烦,首先:

     

              0:000> !name2ee *!FounctionParams.Program

    Module: 790c2000 (mscorlib.dll)

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

    Module: 00a82c3c (FounctionParams.exe)

    Token: 0x02000002

    MethodTable: 00a83038

    EEClass: 00a811d8

    Name: FounctionParams.Program

     

    得到了MethodTable的地址了,然后:

             
    0:000> !dumpmt -md 00a83038

    EEClass: 00a811d8

    Module: 00a82c3c

    Name: FounctionParams.Program

    mdToken: 02000002 (E:"myProject"FounctionParams"FounctionParams"bin"Debug"FounctionParams.exe)

    BaseSize: 0xc

    ComponentSize: 0x0

    Number of IFaces in IFaceMap: 0

    Slots in VTable: 7

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

    MethodDesc Table

       Entry MethodDesc      JIT Name

    79371278   7914b928   PreJIT System.Object.ToString()

    7936b3b0   7914b930   PreJIT System.Object.Equals(System.Object)

    7936b3d0   7914b948   PreJIT System.Object.GetHashCode()

    793624d0   7914b950   PreJIT System.Object.Finalize()

    00db0070   00a83020      JIT FounctionParams.Program.Main(System.String[])

    00db0110   00a83028      JIT FounctionParams.Program.ShowParams

    (Int32, System.String, Char)

    00db00e0   00a83030      JIT FounctionParams.Program..ctor()

     

    这里,得到了这个方法的MethodDesc的地址之后,继续:

    0:000> !dumpmd 00a83028     

    Method Name: FounctionParams.Program.ShowParams(Int32, System.String, Char)

    Class: 00a811d8

    MethodTable: 00a83038

    mdToken: 06000002

    Module: 00a82c3c

    IsJitted: yes

    m_CodeOrIL: 00db0110

     

    可以看到,已经JIT过了,生成了本地的代码。列个时候,就有很多选择了,顺便看看native code:

    0:000> !u 00db0110

    Normal JIT generated code

    FounctionParams.Program.ShowParams(Int32, System.String, Char)

    Begin 00db0110, size 20

    >>> 00db0110 83ec08          sub     esp,8

    00db0113 890c24          mov     dword ptr [esp],ecx

    00db0116 89542404        mov     dword ptr [esp+4],edx

    00db011a 833d082ea80000 cmp     dword ptr ds:[0A82E08h],0

    00db0121 7405            je      00db0128

    00db0123 e81f823779      call    mscorwks!JIT_DbgIsJustMyCode (7a128347)

    00db0128 90              nop

    00db0129 90              nop

    00db012a 83c408          add     esp,8

    00db012d c20800          ret     8

     

    感觉和方法本身的代码不是很像,不过也就是他了,这个时候下断点可以有很多选择:

    在地址上面下断点:

    0:000> bp 00db0110

    用BPMD命令在这个方法的MethodDesc上面下断点:

    0:000> !bpmd -md 00a83028     

    MethodDesc = 00a83028

    Setting breakpoint: bp 00DB0110 [FounctionParams.Program.ShowParams(Int32, System.String, Char)]

     

    That will work。

     

    如果是动态调试下面,该如何做呢?这个比较麻烦点:

    使用Windbg的Open Executable File菜单,打开上面编写的测试的引用程序:

    0:000> sxe ld:mscorjit

    0:000> g

    ModLoad: 79060000 790b6000   C:"WINDOWS"Microsoft.NET"Framework"v2.0.50727"mscorjit.dll

    eax=00000000 ebx=00000000 ecx=00d90000 edx=7c90eb94 esi=00000000 edi=00000000

    eip=7c90eb94 esp=0012e554 ebp=0012e648 iopl=0 nv up ei ng nz ac pe nc

    cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000296

    ntdll!KiFastSystemCallRet:

    7c90eb94 c3              ret

     

    接着查看线程:

     

    0:000> !threads

    ThreadCount: 2

    UnstartedThread: 0

    BackgroundThread: 1

    PendingThread: 0

    DeadThread: 0

    Hosted Runtime: no

     

    Hosted Runtime: no

                                          PreEmptive   GC Alloc          

           ID       Context       Domain   Count APT Exception

       0    1   013f16d0:013f1fe8 0015c410    2 MTA

       2    2   00000000:00000000 0015c410     0 MTA (Finalizer)

     

    接着就查看这个domain:

     

    0:000> !dumpdomain 0015c410    

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

    Domain 1: 0015c410

    LowFrequencyHeap: 0015c434

    HighFrequencyHeap: 0015c48c

    StubHeap: 0015c4e4

    Stage: OPEN

    SecurityDescriptor: 0015d740

    Name: FounctionParams.exe

    Assembly: 0019f408

    [C:"WINDOWS"assembly"GAC_32"mscorlib"2.0.0.0__b77a5c561934e089"mscorlib.dll]

    ClassLoader: 0019f4a0

    SecurityDescriptor: 0019be58

     Module Name

    790c2000

    C:"WINDOWS"assembly"GAC_32"mscorlib"2.0.0.0__b77a5c561934e089"mscorlib.dll

     

    Assembly: 001a6b90

    [E:"myProject"FounctionParams"FounctionParams"bin"Debug"FounctionParams.exe]

    ClassLoader: 001a7270

    SecurityDescriptor: 001a6a58

     Module Name

    00a82c3c

    E:"myProject"FounctionParams"FounctionParams"bin"Debug"FounctionParams.exe

     

    然后查看module的信息:

     

    0:000> !dumpmodule -mt 00a82c3c

    Name: E:"myProject"FounctionParams"FounctionParams"bin"Debug"FounctionParams.exe

    Attributes: PEFile

    Assembly: 001a6b90

    LoaderHeap: 00000000

    TypeDefToMethodTableMap: 00a80038

    TypeRefToMethodTableMap: 00a80040

    MethodDefToDescMap: 00a8008c

    FieldDefToDescMap: 00a8009c

    MemberRefToDescMap: 00a800a0

    FileReferencesMap: 00a800ec

    AssemblyReferencesMap: 00a800f0

    MetaData start address: 00402094 (1580 bytes)

     

    Types defined in this module

     

          MT    TypeDef Name

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

    00a83038 0x02000002 FounctionParams.Program

     

    Types referenced in this module

     

          MT    TypeRef Name

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

    790fd0f0 0x01000001 System.Object

     

    恩,找到MT的地址了:

     

    0:000> !dumpmt -md 00a83038

    EEClass: 00a811d8

    Module: 00a82c3c

    Name: FounctionParams.Program

    mdToken: 02000002 (E:"myProject"FounctionParams"FounctionParams"bin"Debug"FounctionParams.exe)

    BaseSize: 0xc

    ComponentSize: 0x0

    Number of IFaces in IFaceMap: 0

    Slots in VTable: 7

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

    MethodDesc Table

       Entry MethodDesc      JIT Name

    79371278   7914b928  PreJIT System.Object.ToString()

    7936b3b0   7914b930   PreJIT System.Object.Equals(System.Object)

    7936b3d0   7914b948   PreJIT System.Object.GetHashCode()

    793624d0   7914b950   PreJIT System.Object.Finalize()

    00a8c011   00a83020     NONE FounctionParams.Program.Main(System.String[])

    00a8c015   00a83028     NONE FounctionParams.Program.ShowParams

    (Int32, System.String, Char)

    00a8c019   00a83030     NONE FounctionParams.Program..ctor()

     

    恩,这个时候还没有被JIT,正好可以在这个地方下一个断点,当执行到这个方法的时候就触发断点:

    0:000> !bpmd -md 00a83028    

    MethodDesc = 00a83028    

    Adding pending breakpoints...

     

    恩,到这个地方,就给这个managed的方法,而且是没jited的给加上了一个断点。恩,两种不同的情况下下断点的方法。

  • 相关阅读:
    SpringBoot:Web开发
    java @Value注解 和 @Data注解
    携程 Apollo 配置中心传统 .NET 项目集成实践
    Spring Boot 整合 JPA 使用多个数据源
    ibatis 核心原理解析!
    Spring Boot 面试,一个问题就干趴下了!
    在Docker中部署Spring Boot项目
    REDIS缓存穿透,缓存击穿,缓存雪崩原因+解决方案
    超全详解Java开发环境搭建
    SpringBoot入门(一):从HelloWorld开始
  • 原文地址:https://www.cnblogs.com/gxh973121/p/16310578.html
Copyright © 2020-2023  润新知