Closed Symbai closed 4 years ago
I don't know of a direct way to get this.
You can subscribe to the jit events stream and find that information in the relevant event. Note in principle a method's code may be split into two parts (though this does not happen in core, currently).
This isn't a codegen issue so will reclassify.
Do you know of an indirect way to get this? I wouldn't mind about an unsafe way as I'm already using unsafe code to read the method table. I'm fine with something that works most of the time, hasn't to be deal with all situations like code split into two parts.
From what I've seen most code on github dealing with this problem are using clrmd to obtain the end address(es) which I cannot use in my scenario. Clrmd is also calling native code, so I have no idea how it's getting this information but it somehow can.
Here's an example of using eventing. I don't know of an unsafe way.
If you run the above, you get data like:
Address Size Info Name
0x00007FFC0C080A50 000179 jitted tier0 System.Runtime.Intrinsics.Vector128.CreateScalarUnsafe
0x00007FFC0C080B20 000037 jitted tier0 System.Runtime.Intrinsics.Vector128.AsInt64
0x00007FFC0C080F70 000093 jitted fullopts dynamicClass.IL_STUB_ReversePInvoke
0x00007FFC0C081650 000011 jitted tier0 System.Runtime.Intrinsics.X86.Popcnt.get_IsSupported
0x00007FFC0C082F00 000192 jitted tier1 System.SpanHelpers.SequenceCompareTo
0x00007FFC0C083D30 000377 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C083EF0 000166 jitted fullopts dynamicClass.IL_STUB_WinRTtoCLR
0x00007FFC0C083FC0 000237 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C0840E0 000445 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C0846F0 000057 jitted minopts JitEventSample.F
Copying here in case that useful gist gets lost 😄
Note with this you can play around with the various config settings and build options and start to see the impact they have on the code the jit generates.
For "minopts" and "Tier0" codegen will be the same, and "fullopts" and "Tier1" codegen will be similar (though not always the same).
Note some methods are never optimized when jitting (like .cctors) because they are only ever called once.
C:\bugs\r36751>dotnet run
F(33) = 1089
Address Size Info Name
0x00007FFC0C070630 000179 jitted tier0 System.Runtime.Intrinsics.Vector128.CreateScalarUnsafe
0x00007FFC0C070700 000037 jitted tier0 System.Runtime.Intrinsics.Vector128.AsInt64
0x00007FFC0C070F50 000377 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C071110 000166 jitted fullopts dynamicClass.IL_STUB_WinRTtoCLR
0x00007FFC0C0711E0 000237 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C071300 000055 jitted minopts JitEventSample.F
0x00007FFC0C071B20 001769 jitted minopts JitEventListener.OnEventWritten
0x00007FFC0C073490 000038 jitted minopts JitEventListener..cctor
0x00007FFC0C073B00 000221 jitted fullopts dynamicClass.IL_STUB_PInvoke
0x00007FFC0C073C10 000169 jitted fullopts dynamicClass.IL_STUB_PInvoke
C:\bugs\r36751>dotnet run -c Release
F(33) = 1089
Address Size Info Name
0x00007FFC0C0605D0 000179 jitted tier0 System.Runtime.Intrinsics.Vector128.CreateScalarUnsafe
0x00007FFC0C0606A0 000037 jitted tier0 System.Runtime.Intrinsics.Vector128.AsInt64
0x00007FFC0C060EF0 000377 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C0610B0 000166 jitted fullopts dynamicClass.IL_STUB_WinRTtoCLR
0x00007FFC0C061180 000237 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C0612A0 000016 jitted tier0 JitEventSample.F
0x00007FFC0C062CE0 001130 jitted fullopts JitEventListener.OnEventWritten
0x00007FFC0C063190 000013 jitted tier0 JitEventListener..cctor
0x00007FFC0C0637F0 000221 jitted fullopts dynamicClass.IL_STUB_PInvoke
0x00007FFC0C063900 000169 jitted fullopts dynamicClass.IL_STUB_PInvoke
C:\bugs\r36751>set complus_tc_quickjitforloops=1
C:\bugs\r36751>dotnet run -c Release
F(33) = 1089
Address Size Info Name
0x00007FFC0C051660 000179 jitted tier0 System.Runtime.Intrinsics.Vector128.CreateScalarUnsafe
0x00007FFC0C051730 000037 jitted tier0 System.Runtime.Intrinsics.Vector128.AsInt64
0x00007FFC0C051F80 000377 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C052140 000166 jitted fullopts dynamicClass.IL_STUB_WinRTtoCLR
0x00007FFC0C052210 000237 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C052330 000016 jitted tier0 JitEventSample.F
0x00007FFC0C052E20 001256 jitted tier0 JitEventListener.OnEventWritten
0x00007FFC0C053750 000013 jitted tier0 JitEventListener..cctor
0x00007FFC0C0545E0 000221 jitted fullopts dynamicClass.IL_STUB_PInvoke
0x00007FFC0C0546F0 000169 jitted fullopts dynamicClass.IL_STUB_PInvoke
C:\bugs\r36751>set complus_tieredcompilation=0
C:\bugs\r36751>dotnet run -c Release
F(33) = 1089
Address Size Info Name
0x00007FFC0C0803F0 000069 jitted fullopts System.Runtime.Intrinsics.Vector128.CreateScalarUnsafe
0x00007FFC0C080450 000015 jitted fullopts System.Runtime.Intrinsics.Vector128.AsInt64
0x00007FFC0C080880 000377 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C080A40 000166 jitted fullopts dynamicClass.IL_STUB_WinRTtoCLR
0x00007FFC0C080B10 000237 jitted fullopts dynamicClass.IL_STUB_CLRtoWinRT
0x00007FFC0C080C30 000006 jitted fullopts JitEventSample.F
0x00007FFC0C082350 001130 jitted fullopts JitEventListener.OnEventWritten
0x00007FFC0C082C00 000013 jitted minopts JitEventListener..cctor
0x00007FFC0C082E50 000221 jitted fullopts dynamicClass.IL_STUB_PInvoke
0x00007FFC0C082F60 000169 jitted fullopts dynamicClass.IL_STUB_PInvoke
I hooked up iced to disassemble the jitted code and was amused to see it disassembling itself:
;; 0x00007FFC01C07B30 000241 jitted tier0 Iced.Intel.DecoderInternal.OpCodeHandler_Gb_Eb.Decode
00007FFC01C07B30 55 push rbp
00007FFC01C07B31 4883EC30 sub rsp,30h
00007FFC01C07B35 488D6C2430 lea rbp,[rsp+30h]
00007FFC01C07B3A 33C0 xor eax,eax
00007FFC01C07B3C 488945F8 mov [rbp-8],rax
00007FFC01C07B40 8945F4 mov [rbp-0Ch],eax
00007FFC01C07B43 48894D10 mov [rbp+10h],rcx
Seems like question has been answered so I'll go ahead and close this for now. @Symbai feel free to reopen if you that was not the case.
Using
System.Reflection.MethodInfo.MethodHandle.GetFunctionPointer()
we're able to obtain the memory address of the beginning of a managed method when its jitted. Now how do I get the size of this method (i.e. the end address)?