diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs index 7846e4c5aa3fe4..15d701c9077f2a 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs @@ -61,7 +61,20 @@ private TargetPointer GetILExtentStart(out uint codeSize) { ILoader loader = _target.Contracts.Loader; Contracts.ModuleHandle moduleHandle = loader.GetModuleHandleFromModulePtr(_module); - TargetPointer ilHeader = loader.GetILHeader(moduleHandle, _token); + TargetPointer ilHeader = TargetPointer.Null; + TargetPointer methodDesc = TryResolveMethodDesc(); + if (methodDesc != TargetPointer.Null && _target.Contracts.TryGetContract(out ICodeVersions codeVersions)) + { + ILCodeVersionHandle activeVersion = codeVersions.GetActiveILCodeVersion(methodDesc); + if (activeVersion.IsValid && codeVersions.GetSource(activeVersion) == CodeVersionSource.EnC) + { + ilHeader = codeVersions.GetIL(activeVersion); + } + } + + if (ilHeader == TargetPointer.Null) + ilHeader = loader.GetILHeader(moduleHandle, _token); + if (ilHeader == TargetPointer.Null) { codeSize = 0; diff --git a/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs b/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs index 03f203e6a1743b..622182ea7db2b2 100644 --- a/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs @@ -241,6 +241,11 @@ public void MethodDefinitionsByAddress(MockTarget.Architecture arch) loader.Setup(l => l.GetILAddr(new TargetPointer(PeAssemblyAddress), 0x20)).Returns(new TargetPointer(SecondHeaderAddress)); loader.Setup(l => l.GetILHeader(module, FirstToken)).Returns(new TargetPointer(FirstHeaderAddress)); loader.Setup(l => l.GetILHeader(module, SecondToken)).Returns(new TargetPointer(SecondHeaderAddress)); + loader.Setup(l => l.GetModuleLookupMapElement( + module, + ModuleLookupMapKind.MethodDefToDesc, + It.IsAny(), + out It.Ref.IsAny)).Returns(TargetPointer.Null); Mock ecmaMetadata = new(MockBehavior.Strict); ecmaMetadata.Setup(e => e.GetMetadata(module)).Returns(reader); @@ -360,6 +365,11 @@ public void MethodDefinitionWithoutIL(MockTarget.Architecture arch) Mock loader = new(MockBehavior.Strict); loader.Setup(l => l.GetModuleHandleFromModulePtr(new TargetPointer(ModuleAddress))).Returns(module); loader.Setup(l => l.GetILHeader(module, Token)).Returns(TargetPointer.Null); + loader.Setup(l => l.GetModuleLookupMapElement( + module, + ModuleLookupMapKind.MethodDefToDesc, + Token, + out It.Ref.IsAny)).Returns(TargetPointer.Null); TestPlaceholderTarget.Builder builder = new(arch); builder.AddMockContract(loader.Object); IXCLRDataMethodDefinition method = new ClrDataMethodDefinition( @@ -376,6 +386,63 @@ public void MethodDefinitionWithoutIL(MockTarget.Architecture arch) Assert.Equal(CorDbgHResults.E_UNEXPECTED, method.GetRepresentativeEntryAddress(&address)); } + [Theory] + [ClassData(typeof(MockTarget.StdArch))] + public void MethodDefinitionUsesActiveEnCIL(MockTarget.Architecture arch) + { + const ulong ModuleAddress = 0x2000; + const ulong DefaultHeaderAddress = 0x3000; + const ulong EnCHeaderAddress = 0x4000; + const ulong MethodDescAddress = 0x5000; + const uint Token = 0x06000001; + const byte TinyFormat = 0x2; + const int DefaultCodeSize = 1; + const int EnCCodeSize = 3; + + ModuleHandle module = new(new TargetPointer(ModuleAddress)); + Mock loader = new(MockBehavior.Strict); + loader.Setup(l => l.GetModuleHandleFromModulePtr(new TargetPointer(ModuleAddress))).Returns(module); + loader.Setup(l => l.GetModuleLookupMapElement( + module, + ModuleLookupMapKind.MethodDefToDesc, + Token, + out It.Ref.IsAny)).Returns(new TargetPointer(MethodDescAddress)); + loader.Setup(l => l.GetILHeader(module, Token)).Returns(new TargetPointer(DefaultHeaderAddress)); + + ILCodeVersionHandle activeVersion = ILCodeVersionHandle.CreateExplicit(new TargetPointer(0x7000)); + Mock codeVersions = new(MockBehavior.Strict); + codeVersions.Setup(c => c.GetActiveILCodeVersion(new TargetPointer(MethodDescAddress))).Returns(activeVersion); + codeVersions.Setup(c => c.GetSource(activeVersion)).Returns(CodeVersionSource.EnC); + codeVersions.Setup(c => c.GetIL(activeVersion)).Returns(new TargetPointer(EnCHeaderAddress)); + + TestPlaceholderTarget.Builder builder = new(arch); + builder.AddMockContract(loader.Object); + builder.AddMockContract(codeVersions.Object); + builder.MemoryBuilder.AddHeapFragment(new MockMemorySpace.HeapFragment + { + Address = DefaultHeaderAddress, + Data = [(byte)((DefaultCodeSize << 2) | TinyFormat), 0], + Name = nameof(DefaultHeaderAddress), + }); + builder.MemoryBuilder.AddHeapFragment(new MockMemorySpace.HeapFragment + { + Address = EnCHeaderAddress, + Data = [(byte)((EnCCodeSize << 2) | TinyFormat), 0, 0, 0], + Name = nameof(EnCHeaderAddress), + }); + + IXCLRDataMethodDefinition method = new ClrDataMethodDefinition( + builder.Build(), + new TargetPointer(ModuleAddress), + Token, + legacyImpl: null); + + AssertMethodDefinitionExtent( + method, + EnCHeaderAddress + sizeof(byte), + EnCHeaderAddress + sizeof(byte) + EnCCodeSize - 1); + } + private static void AssertMethodDefinitionExtent( IXCLRDataMethodDefinition method, ClrDataAddress expectedStart,