From a0eada36cd3b9b6bb5ac2c2b480bb5455a0dc16c Mon Sep 17 00:00:00 2001 From: rcj1 Date: Thu, 16 Jul 2026 12:08:22 -0700 Subject: [PATCH] add the last two location types --- docs/design/datacontracts/DebugInfo.md | 4 + .../Contracts/IDebugInfo.cs | 6 ++ .../Contracts/DebugInfo/DebugInfoHelpers.cs | 19 ++--- .../Dbi/DacDbiImpl.NativeCodeInfo.cs | 16 ++++ .../cdac/tests/UnitTests/DacDbiImplTests.cs | 77 +++++++++++++++++++ 5 files changed, 113 insertions(+), 9 deletions(-) diff --git a/docs/design/datacontracts/DebugInfo.md b/docs/design/datacontracts/DebugInfo.md index fd5539bdd6a5ae..ed1f01f9a1865b 100644 --- a/docs/design/datacontracts/DebugInfo.md +++ b/docs/design/datacontracts/DebugInfo.md @@ -328,6 +328,8 @@ public enum DebugVarLocKind RegisterStack, StackRegister, DoubleStack, + FloatingPointStack, + FixedVarArg, } public readonly struct DebugVarInfo @@ -344,6 +346,8 @@ public readonly struct DebugVarInfo public int StackOffset { get; init; } public uint BaseRegister2 { get; init; } public int StackOffset2 { get; init; } + public uint FloatingPointStackRegister { get; init; } + public uint FixedVarArgOffset { get; init; } public uint CallReturnValueILOffset { get; init; } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugInfo.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugInfo.cs index 7bfcf45c0d000a..f40f8479efb53d 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugInfo.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugInfo.cs @@ -46,6 +46,8 @@ public enum DebugVarLocKind RegisterStack, StackRegister, DoubleStack, + FloatingPointStack, + FixedVarArg, } /// @@ -73,6 +75,10 @@ public readonly struct DebugVarInfo public uint BaseRegister2 { get; init; } /// Second stack offset (RegisterStack). public int StackOffset2 { get; init; } + /// Floating-point stack register number (FloatingPointStack). + public uint FloatingPointStackRegister { get; init; } + /// Offset of a fixed argument in a varargs function (FixedVarArg). + public uint FixedVarArgOffset { get; init; } /// /// For == ICorDebugInfo::CALL_RETURN_ILNUM entries, the IL offset of /// the call site whose return value this entry describes. Zero for all other entries. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/DebugInfo/DebugInfoHelpers.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/DebugInfo/DebugInfoHelpers.cs index 9dc0686c83ccb9..5b52d110947a98 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/DebugInfo/DebugInfoHelpers.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/DebugInfo/DebugInfoHelpers.cs @@ -184,10 +184,16 @@ internal static IEnumerable DoVars(NativeReader nativeReader, bool StartOffset = startOffset, EndOffset = endOffset, VarNumber = varNumber, CallReturnValueILOffset = callReturnValueILOffset, Kind = DebugVarLocKind.DoubleStack, BaseRegister = reader.ReadUInt(), StackOffset = ReadEncodedStackOffset(reader, isX86), }, - // FPSTK and FIXED_VA: consume stream data to keep reader aligned, but no public - // DebugVarLocKind exists for these rarely-used location types. - VarLocType.VLT_FPSTK => ConsumeAndDefault(reader.ReadUInt(), startOffset, endOffset, varNumber, callReturnValueILOffset), - VarLocType.VLT_FIXED_VA => ConsumeAndDefault(reader.ReadUInt(), startOffset, endOffset, varNumber, callReturnValueILOffset), + VarLocType.VLT_FPSTK => new DebugVarInfo + { + StartOffset = startOffset, EndOffset = endOffset, VarNumber = varNumber, CallReturnValueILOffset = callReturnValueILOffset, + Kind = DebugVarLocKind.FloatingPointStack, IsFloatingPoint = true, FloatingPointStackRegister = reader.ReadUInt(), + }, + VarLocType.VLT_FIXED_VA => new DebugVarInfo + { + StartOffset = startOffset, EndOffset = endOffset, VarNumber = varNumber, CallReturnValueILOffset = callReturnValueILOffset, + Kind = DebugVarLocKind.FixedVarArg, FixedVarArgOffset = reader.ReadUInt(), + }, _ => new DebugVarInfo { StartOffset = startOffset, EndOffset = endOffset, VarNumber = varNumber, CallReturnValueILOffset = callReturnValueILOffset, @@ -196,11 +202,6 @@ internal static IEnumerable DoVars(NativeReader nativeReader, bool } } - private static DebugVarInfo ConsumeAndDefault(uint _, uint startOffset, uint endOffset, uint varNumber, uint callReturnValueILOffset) => new() - { - StartOffset = startOffset, EndOffset = endOffset, VarNumber = varNumber, CallReturnValueILOffset = callReturnValueILOffset, - }; - private static int ReadEncodedStackOffset(NibbleReader reader, bool isX86) { int value = reader.ReadInt(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.NativeCodeInfo.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.NativeCodeInfo.cs index b5f9e266d7eee9..3db90d49d72b94 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.NativeCodeInfo.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.NativeCodeInfo.cs @@ -60,6 +60,8 @@ internal static VarLoc ConvertToVarLoc(DebugVarInfo varInfo) (DebugVarLocKind.RegisterStack, _, _) => VarLocType.VLT_REG_STK, (DebugVarLocKind.StackRegister, _, _) => VarLocType.VLT_STK_REG, (DebugVarLocKind.DoubleStack, _, _) => VarLocType.VLT_STK2, + (DebugVarLocKind.FloatingPointStack, _, _) => VarLocType.VLT_FPSTK, + (DebugVarLocKind.FixedVarArg, _, _) => VarLocType.VLT_FIXED_VA, _ => VarLocType.VLT_INVALID, }; @@ -90,6 +92,12 @@ internal static VarLoc ConvertToVarLoc(DebugVarInfo varInfo) loc.vlsBaseReg = varInfo.BaseRegister; loc.vlsOffset = varInfo.StackOffset; break; + case DebugVarLocKind.FloatingPointStack: + loc.vlfReg = varInfo.FloatingPointStackRegister; + break; + case DebugVarLocKind.FixedVarArg: + loc.vlfvOffset = varInfo.FixedVarArgOffset; + break; } return loc; @@ -232,6 +240,14 @@ private static void AssertVarInfosEqual(List cdac, List result = new(DebugInfoHelpers.DoVars(reader, isX86: true)); + + Assert.Collection( + result, + varInfo => + { + Assert.Equal(DebugVarLocKind.FloatingPointStack, varInfo.Kind); + Assert.True(varInfo.IsFloatingPoint); + Assert.Equal(3u, varInfo.FloatingPointStackRegister); + }, + varInfo => + { + Assert.Equal(DebugVarLocKind.FixedVarArg, varInfo.Kind); + Assert.Equal(0x28u, varInfo.FixedVarArgOffset); + }); + } + + private static byte[] EncodeNibbleUInts(params uint[] values) + { + List nibbles = new(); + Span groups = stackalloc byte[11]; + foreach (uint value in values) + { + int groupCount = 0; + uint remaining = value; + do + { + groups[groupCount++] = (byte)(remaining & 7); + remaining >>= 3; + } + while (remaining != 0); + + for (int i = groupCount - 1; i >= 0; i--) + { + byte continuation = i == 0 ? (byte)0 : (byte)8; + nibbles.Add((byte)(groups[i] | continuation)); + } + } + + byte[] bytes = new byte[(nibbles.Count + 1) / 2]; + for (int i = 0; i < nibbles.Count; i++) + bytes[i / 2] |= (byte)(nibbles[i] << (4 * (i & 1))); + return bytes; + } + [Theory] [InlineData(SourceTypes.Default, 0x00u)] [InlineData(SourceTypes.StackEmpty, 0x02u)]