From 676c14ba2a0e68c62d2fdce1870fbd2833f6a351 Mon Sep 17 00:00:00 2001 From: rcj1 Date: Mon, 3 Aug 2026 15:24:40 -0700 Subject: [PATCH 1/3] use precise EnC IL --- .../ClrDataMethodDefinition.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) 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 6b7fe626dd424a..8fc45b2992bc66 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs @@ -58,7 +58,22 @@ 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 + && activeVersion.IsExplicit + && codeVersions.GetSource(activeVersion) == CodeVersionSource.EnC) + { + ilHeader = codeVersions.GetIL(activeVersion); + } + } + + if (ilHeader == TargetPointer.Null) + ilHeader = loader.GetILHeader(moduleHandle, _token); + if (ilHeader == TargetPointer.Null) { codeSize = 0; From c6de51cbccc4698c86a2794ef2a6354388047850 Mon Sep 17 00:00:00 2001 From: rcj1 Date: Tue, 4 Aug 2026 10:22:44 -0700 Subject: [PATCH 2/3] fix tests --- .../ClrDataMethodDefinition.cs | 4 +- .../tests/UnitTests/IXCLRDataProcessTests.cs | 71 +++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) 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 8fc45b2992bc66..79835cfc6bc486 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs @@ -63,9 +63,7 @@ private TargetPointer GetILExtentStart(out uint codeSize) if (methodDesc != TargetPointer.Null && _target.Contracts.TryGetContract(out ICodeVersions codeVersions)) { ILCodeVersionHandle activeVersion = codeVersions.GetActiveILCodeVersion(methodDesc); - if (activeVersion.IsValid - && activeVersion.IsExplicit - && codeVersions.GetSource(activeVersion) == CodeVersionSource.EnC) + if (activeVersion.IsValid && codeVersions.GetSource(activeVersion) == CodeVersionSource.EnC) { ilHeader = codeVersions.GetIL(activeVersion); } diff --git a/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs b/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs index 03f203e6a1743b..671dce37dba999 100644 --- a/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs @@ -210,6 +210,7 @@ public void MethodDefinitionsByAddress(MockTarget.Architecture arch) const ulong PeAssemblyAddress = 0x3000; const ulong FirstHeaderAddress = 0x5000; const ulong SecondHeaderAddress = 0x6000; + const ulong MethodDefToDescAddress = 0x7000; const uint FirstToken = 0x06000002; const uint SecondToken = 0x06000003; const byte TinyFormat = 0x2; @@ -241,6 +242,12 @@ 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)); + ModuleLookupTables lookupTables = new() { MethodDefToDesc = new TargetPointer(MethodDefToDescAddress) }; + loader.Setup(l => l.GetLookupTables(module)).Returns(lookupTables); + loader.Setup(l => l.GetModuleLookupMapElement( + lookupTables.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 +367,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.GetLookupTables(module)).Returns(default(ModuleLookupTables)); + loader.Setup(l => l.GetModuleLookupMapElement( + TargetPointer.Null, + Token, + out It.Ref.IsAny)).Returns(TargetPointer.Null); TestPlaceholderTarget.Builder builder = new(arch); builder.AddMockContract(loader.Object); IXCLRDataMethodDefinition method = new ClrDataMethodDefinition( @@ -376,6 +388,65 @@ 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 ulong MethodDefToDescAddress = 0x6000; + const uint Token = 0x06000001; + const byte TinyFormat = 0x2; + const int DefaultCodeSize = 1; + const int EnCCodeSize = 3; + + ModuleHandle module = new(new TargetPointer(ModuleAddress)); + ModuleLookupTables lookupTables = new() { MethodDefToDesc = new TargetPointer(MethodDefToDescAddress) }; + Mock loader = new(MockBehavior.Strict); + loader.Setup(l => l.GetModuleHandleFromModulePtr(new TargetPointer(ModuleAddress))).Returns(module); + loader.Setup(l => l.GetLookupTables(module)).Returns(lookupTables); + loader.Setup(l => l.GetModuleLookupMapElement( + lookupTables.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, From e30d696a17f2adef7b4f4d891175a3037a8f709f Mon Sep 17 00:00:00 2001 From: rcj1 Date: Wed, 5 Aug 2026 13:28:54 -0700 Subject: [PATCH 3/3] fix tests --- .../tests/UnitTests/IXCLRDataProcessTests.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs b/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs index 671dce37dba999..622182ea7db2b2 100644 --- a/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/IXCLRDataProcessTests.cs @@ -210,7 +210,6 @@ public void MethodDefinitionsByAddress(MockTarget.Architecture arch) const ulong PeAssemblyAddress = 0x3000; const ulong FirstHeaderAddress = 0x5000; const ulong SecondHeaderAddress = 0x6000; - const ulong MethodDefToDescAddress = 0x7000; const uint FirstToken = 0x06000002; const uint SecondToken = 0x06000003; const byte TinyFormat = 0x2; @@ -242,10 +241,9 @@ 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)); - ModuleLookupTables lookupTables = new() { MethodDefToDesc = new TargetPointer(MethodDefToDescAddress) }; - loader.Setup(l => l.GetLookupTables(module)).Returns(lookupTables); loader.Setup(l => l.GetModuleLookupMapElement( - lookupTables.MethodDefToDesc, + module, + ModuleLookupMapKind.MethodDefToDesc, It.IsAny(), out It.Ref.IsAny)).Returns(TargetPointer.Null); @@ -367,9 +365,9 @@ 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.GetLookupTables(module)).Returns(default(ModuleLookupTables)); loader.Setup(l => l.GetModuleLookupMapElement( - TargetPointer.Null, + module, + ModuleLookupMapKind.MethodDefToDesc, Token, out It.Ref.IsAny)).Returns(TargetPointer.Null); TestPlaceholderTarget.Builder builder = new(arch); @@ -396,19 +394,17 @@ public void MethodDefinitionUsesActiveEnCIL(MockTarget.Architecture arch) const ulong DefaultHeaderAddress = 0x3000; const ulong EnCHeaderAddress = 0x4000; const ulong MethodDescAddress = 0x5000; - const ulong MethodDefToDescAddress = 0x6000; const uint Token = 0x06000001; const byte TinyFormat = 0x2; const int DefaultCodeSize = 1; const int EnCCodeSize = 3; ModuleHandle module = new(new TargetPointer(ModuleAddress)); - ModuleLookupTables lookupTables = new() { MethodDefToDesc = new TargetPointer(MethodDefToDescAddress) }; Mock loader = new(MockBehavior.Strict); loader.Setup(l => l.GetModuleHandleFromModulePtr(new TargetPointer(ModuleAddress))).Returns(module); - loader.Setup(l => l.GetLookupTables(module)).Returns(lookupTables); loader.Setup(l => l.GetModuleLookupMapElement( - lookupTables.MethodDefToDesc, + module, + ModuleLookupMapKind.MethodDefToDesc, Token, out It.Ref.IsAny)).Returns(new TargetPointer(MethodDescAddress)); loader.Setup(l => l.GetILHeader(module, Token)).Returns(new TargetPointer(DefaultHeaderAddress));