如何使用 windbg 转储 .NET JIT-ed 泛型方法?

How to dump .NET JIT-ed generic method with windbg?

我需要检查 JIT 为具有不同结构参数的泛型方法发出的代码。我阅读了有关 WinDbg 和 SOS.dll 的文章,可以检查非泛型方法。但是对于泛型方法,应该为每个结构类型进行 JIT 编辑,方法 table 中没有 JIT 编辑代码,我在哪里可以找到它?

namespace ConsoleApp1
{
    class Program
    {
        public void Foo<T>(T arg)
        {
            //some code here
        }

        static void Main(string[] args)
        {
            var program = new Program();
            program.Foo("test");
            program.Foo(1.0);
            program.Foo(new Guid());
            program.Foo((byte)1);
            program.Foo((char)1);
            program.Foo(1);
        }
    }
}

WinDbg:

0:006> .loadby sos clr
0:006> !Name2EE ConsoleApp1!ConsoleApp1.Program
Module:      00007ffa3abf4118
Assembly:    ConsoleApp1.exe
Token:       0000000002000002
MethodTable: 00007ffa3abf5a18
EEClass:     00007ffa3abf24b8
Name:        ConsoleApp1.Program

转储方法table

0:006> !DumpMT -md 00007ffa3abf5a18
    EEClass:         00007ffa3abf24b8
    Module:          00007ffa3abf4118
    Name:            ConsoleApp1.Program
    mdToken:         0000000002000002
    File:            D:\repos\ConsoleApp1\ConsoleApp1\bin\Debug\net462\ConsoleApp1.exe
    BaseSize:        0x18
    ComponentSize:   0x0
    Slots in VTable: 7
    Number of IFaces in IFaceMap: 0
    --------------------------------------
    MethodDesc Table
               Entry       MethodDesc    JIT Name
    00007ffa9759c080 00007ffa970f7fb8 PreJIT System.Object.ToString()
    00007ffa97604360 00007ffa970f7fc0 PreJIT System.Object.Equals(System.Object)
    00007ffa97674770 00007ffa970f7fe8 PreJIT System.Object.GetHashCode()
    00007ffa975cf570 00007ffa970f8000 PreJIT System.Object.Finalize()
    00007ffa3ad005c0 00007ffa3abf5a10    JIT ConsoleApp1.Program..ctor()
    00007ffa3ad00078 00007ffa3abf59e0   NONE ConsoleApp1.Program.Foo(!!0) // "base" IL code
    00007ffa3ad00480 00007ffa3abf5a00    JIT ConsoleApp1.Program.Main(System.String[])

而且我没有得到 Foo 的代码

0:006> !U 00007ffa3abf59e0
Not jitted yet

有什么想法吗?

我把你的代码编译成 x86 调试版本。然后我附加到进程并等待它终止。

我发现和你一样的结果:

   Entry MethodDe    JIT Name
[...]
00250038 00204d34   NONE JitExample2.Program.Foo(!!0)

这里说的是NONE,意思是"not jitted".

0:000> !dumpmd  00204d34  
Method Name:  JitExample2.Program.Foo(!!0)
[...]
IsJitted:     no

所以答案似乎得到了证实:它没有抖动。

我不知道有任何官方方法可以获取 jitted 泛型方法列表。但是在 !bpmd 的帮助下,有可能:

0:000> !bpmd JitExample2 JitExample2.Program.Foo
Found 1 methods in module 00204024...
MethodDesc = 00204d34
Setting breakpoint: bp 0025074A [JitExample2.Program.Foo[[System.Char, mscorlib]](Char)]
Setting breakpoint: bp 002506EA [JitExample2.Program.Foo[[System.Byte, mscorlib]](Byte)]
Setting breakpoint: bp 00250687 [JitExample2.Program.Foo[[System.Guid, mscorlib]](System.Guid)]
Setting breakpoint: bp 00250627 [JitExample2.Program.Foo[[System.Double, mscorlib]](Double)]
Setting breakpoint: bp 002505B0 [JitExample2.Program.Foo[[System.__Canon, mscorlib]](System.__Canon)]
Setting breakpoint: bp 002507AA [JitExample2.Program.Foo[[System.Int32, mscorlib]](Int32)]

然后您可以使用 bp 之后的地址来显示 JIT 代码:

0:000> !u 0025074A 
Normal JIT generated code
JitExample2.Program.Foo[[System.Char, mscorlib]](Char)
Begin 00250728, size 4b

C:\Users\For example John\JitExample2\Program.cs @ 8:
00250728 55              push    ebp
00250729 8bec            mov     ebp,esp
0025072b 83ec10          sub     esp,10h
0025072e 33c0            xor     eax,eax
[...]