diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/DebugExtensions.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/DebugExtensions.cs index b5e348bdbf3d53..50ac0cf9803808 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/DebugExtensions.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/DebugExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; @@ -52,5 +53,35 @@ internal static void ValidateHResult( }; Debug.Assert(match, $"HResult mismatch - cDAC: 0x{unchecked((uint)cdacHr):X8}, DAC: 0x{unchecked((uint)dacHr):X8} ({Path.GetFileName(filePath)}:{lineNumber})"); } + + [Conditional("DEBUG")] + internal static unsafe void ValidateOutputStringBuffer( + char* cdacBuffer, + uint* cdacNeeded, + char[] dacBuffer, + uint dacNeeded, + uint count, + [CallerFilePath] string? filePath = null, + [CallerLineNumber] int lineNumber = 0) + { + string location = $"{Path.GetFileName(filePath)}:{lineNumber}"; + + if (cdacNeeded is not null && *cdacNeeded != dacNeeded) + { + int cdacLen = (int)Math.Min(*cdacNeeded, count); + string cdacStr = cdacBuffer is not null && cdacLen > 0 ? new string(cdacBuffer, 0, cdacLen - 1) : ""; + string dacStr = dacNeeded > 0 ? new string(dacBuffer, 0, (int)dacNeeded - 1) : ""; + Trace.TraceWarning($"Output buffer pNeeded mismatch ({location}) - cDAC: {*cdacNeeded} (\"{cdacStr}\"), DAC: {dacNeeded} (\"{dacStr}\")"); + } + else if (cdacBuffer is not null && dacNeeded > 0 && count >= dacNeeded) + { + var cdacSpan = new ReadOnlySpan(cdacBuffer, (int)dacNeeded - 1); + var dacSpan = new ReadOnlySpan(dacBuffer, 0, (int)dacNeeded - 1); + if (!cdacSpan.SequenceEqual(dacSpan)) + { + Trace.TraceWarning($"Output buffer content mismatch ({location}) - cDAC: \"{new string(cdacBuffer, 0, (int)dacNeeded - 1)}\", DAC: \"{new string(dacBuffer, 0, (int)dacNeeded - 1)}\""); + } + } + } } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs index d67adff3ab3489..1e943235506586 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs @@ -2995,6 +2995,13 @@ int ISOSDacInterface.GetMethodTableName(ClrDataAddress mt, uint count, char* mtN Debug.ValidateHResult(hr, hrLocal); if (hr == HResults.S_OK) { + if (pNeeded != null && *pNeeded != neededLocal) + { + string cdacStr = mtName is not null && count > 0 ? new string(mtName, 0, (int)System.Math.Min(*pNeeded, count) - 1) : ""; + string dacStr = neededLocal > 0 ? new string(mtNameLocal, 0, (int)neededLocal - 1) : ""; + System.Console.Error.WriteLine($"CDAC_MISMATCH GetMethodTableName MT=0x{(ulong)mt:X} pNeeded: cDAC={*pNeeded} DAC={neededLocal} cDAC_name=\"{cdacStr}\" DAC_name=\"{dacStr}\""); + System.Console.Error.Flush(); + } Debug.Assert(pNeeded == null || *pNeeded == neededLocal); Debug.Assert(mtName == null || new ReadOnlySpan(mtNameLocal, 0, (int)neededLocal - 1).SequenceEqual(new string(mtName))); }