microsoft / clrmd

Microsoft.Diagnostics.Runtime is a set of APIs for introspecting processes and dumps.
MIT License
1.05k stars 255 forks source link

ILOffsetMap points to QuickJitted assembly code even after method has been Tier-1 compiled (.NET 7+) #1171

Closed anderspedersen closed 1 year ago

anderspedersen commented 1 year ago

I am trying to read the machine code of a method using the method described here: https://github.com/microsoft/dotnet-samples/blob/bd22ceaf81cccf8587f26efcd3de5a21411f2df2/Microsoft.Diagnostics.Runtime/CLRMD/docs/MachineCode.md

In .NET 6 this works perfectly, but in .NET 7 & .NET 8 preview it does not work for methods that have been Tier-1 compiled. In that case ClrmdMethod.NativeCode will correctly point to the start of the Tier-1 compiled machine code, but ClrmdMethod.ILOffsetMap will point to the QuickJitted machine code.

clrmdmethod

NativeCode is 00007ffa3f1e4360 & ILOffsetMap begins at 00007ffa3f1e4160. As can be seen using Windbg/SOS the value in NativeCode points to OptimizedTier1 machine code, while the value in ILOffsetMap points to QuickJitted machine code.

windbg
leculver commented 1 year ago

Unfortunately, it looks like there is no runtime API for getting the IL to Native map from tiered JIT'ed code. At least, not in the API that ClrMD uses.

ClrMD calls into IXClrDataModule::GetILAddressMap, this is implemented in debug\daccess\task.cpp. The inner call that does this work is GetMethodNativeMap which does take the native address location, but we always pass 0 in GetILAddressMap because the shape of that COM API doesn't take in the native address value.

That means this would be a dotnet/runtime feature and not a ClrMD feature. Feel free to create a dotnet/runtime feature request for this. Without that feature I have to close this "Not Planned". I may end up marking the IL to Native map obsolete in the future since it's not supported for tiered JIT.

I believe ICorDebug will be the only place to get the correct IL to Native map, but I haven't investigated it there.