From c3905fa8e9e34fb80c3eef90f3851159fd956d48 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 21:30:27 +0000 Subject: [PATCH 1/4] Implement IXCLRDataExceptionState state comparison Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com> --- .../ClrDataExceptionState.cs | 66 +++++++++- .../UnitTests/ClrDataExceptionStateTests.cs | 113 ++++++++++++++++++ 2 files changed, 177 insertions(+), 2 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs index 21469f6b53ffc8..e6d30d718709ce 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs @@ -11,6 +11,8 @@ namespace Microsoft.Diagnostics.DataContractReader.Legacy; [GeneratedComClass] public sealed unsafe partial class ClrDataExceptionState : IXCLRDataExceptionState { + private const uint FirstChance = 0x1; + private readonly Target _target; private readonly TargetPointer _threadAddress; private readonly uint _flags; @@ -213,9 +215,69 @@ int IXCLRDataExceptionState.Request(uint reqCode, uint inBufferSize, byte* inBuf } int IXCLRDataExceptionState.IsSameState(EXCEPTION_RECORD64* exRecord, uint contextSize, byte* cxRecord) - => LegacyFallbackHelper.CanFallback() && _legacyImpl is not null ? _legacyImpl.IsSameState(exRecord, contextSize, cxRecord) : HResults.E_NOTIMPL; + { + int hr = IsSameState2(0, exRecord); +#if DEBUG + if (_legacyImpl is not null) + { + int hrLocal = _legacyImpl.IsSameState(exRecord, contextSize, cxRecord); + Debug.ValidateHResult(hr, hrLocal); + } +#endif + return hr; + } + int IXCLRDataExceptionState.IsSameState2(uint flags, EXCEPTION_RECORD64* exRecord, uint contextSize, byte* cxRecord) - => LegacyFallbackHelper.CanFallback() && _legacyImpl is not null ? _legacyImpl.IsSameState2(flags, exRecord, contextSize, cxRecord) : HResults.E_NOTIMPL; + { + int hr = IsSameState2(flags, exRecord); +#if DEBUG + if (_legacyImpl is not null) + { + int hrLocal = _legacyImpl.IsSameState2(flags, exRecord, contextSize, cxRecord); + Debug.ValidateHResult(hr, hrLocal); + } +#endif + return hr; + } + + private int IsSameState2(uint flags, EXCEPTION_RECORD64* exRecord) + { + if ((flags & ~FirstChance) != 0) + return HResults.E_INVALIDARG; + + int hr = HResults.S_FALSE; + try + { + if ((_flags & (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_PARTIAL) != 0) + { + if ((flags & FirstChance) != 0) + hr = HResults.S_OK; + } + else + { + if (exRecord is null) + throw new NullReferenceException(); + + ThreadData threadData = _target.Contracts.Thread.GetThreadData(_threadAddress); + TargetPointer exceptionAddress = _target.ReadPointer( + threadData.OSExceptionRecord + (ulong)(sizeof(uint) * 2 + _target.PointerSize)); + TargetPointer requestedAddress = new( + _target.PointerSize == sizeof(ulong) + ? exRecord->ExceptionAddress + : (uint)exRecord->ExceptionAddress); + + if (exceptionAddress == requestedAddress) + hr = HResults.S_OK; + } + } + catch (System.Exception ex) + { + hr = ex.HResult; + } + + return hr; + } + int IXCLRDataExceptionState.GetTask(DacComNullableByRef task) { int hr = HResults.S_OK, hrLocal = HResults.S_OK; diff --git a/src/native/managed/cdac/tests/UnitTests/ClrDataExceptionStateTests.cs b/src/native/managed/cdac/tests/UnitTests/ClrDataExceptionStateTests.cs index 015c8ed19f4feb..e47faa0eae7aa9 100644 --- a/src/native/managed/cdac/tests/UnitTests/ClrDataExceptionStateTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/ClrDataExceptionStateTests.cs @@ -128,6 +128,57 @@ private static (int Hr, uint StrLen, char[] Buffer) CallGetString(IXCLRDataExcep return (hr, strLen, buffer); } + private static IXCLRDataExceptionState CreateExceptionStateWithRecord( + MockTarget.Architecture arch, + ulong exceptionAddress) + { + TargetTestHelpers helpers = new(arch); + var targetBuilder = new TestPlaceholderTarget.Builder(arch); + var allocator = targetBuilder.MemoryBuilder.CreateAllocator(0x1_0000, 0x2_0000); + MockMemorySpace.HeapFragment exceptionRecord = + allocator.Allocate((ulong)(sizeof(uint) * 2 + helpers.PointerSize * 2), "ExceptionRecord"); + helpers.WritePointer( + exceptionRecord.Data.AsSpan(sizeof(uint) * 2 + helpers.PointerSize, helpers.PointerSize), + exceptionAddress); + + TargetPointer threadAddress = new(0x1000); + var mockThread = new Mock(); + mockThread.Setup(t => t.GetThreadData(threadAddress)).Returns(new ThreadData( + ThreadAddress: threadAddress, + Id: 1, + OSId: new TargetNUInt(1234), + State: default, + PreemptiveGCDisabled: false, + AllocContextPointer: TargetPointer.Null, + AllocContextLimit: TargetPointer.Null, + Frame: TargetPointer.Null, + FirstNestedException: TargetPointer.Null, + ExposedObjectHandle: TargetPointer.Null, + LastThrownObjectHandle: TargetPointer.Null, + CurrentCustomDebuggerNotificationHandle: TargetPointer.Null, + LastThrownObjectIsUnhandled: false, + HasUnhandledException: false, + NextThread: TargetPointer.Null, + ThreadHandle: TargetPointer.Null, + IsInteropDebuggingHijacked: false, + DebuggerFilterContext: TargetPointer.Null, + GCFrame: TargetPointer.Null, + IsExceptionInProgress: true, + OSExceptionRecord: new TargetPointer(exceptionRecord.Address), + OSExceptionContextRecord: TargetPointer.Null)); + + TestPlaceholderTarget target = targetBuilder + .AddMockContract(mockThread) + .Build(); + return new ClrDataExceptionState( + target, + threadAddress, + (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + thrownObjectHandle: TargetPointer.Null, + previousExInfoAddress: TargetPointer.Null, + legacyImpl: null); + } + [Theory] [InlineData((uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, false, (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT)] [InlineData((uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, true, (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_NESTED)] @@ -293,6 +344,68 @@ public void GetTask() Assert.NotNull(task.Interface); } + [Theory] + [ClassData(typeof(MockTarget.StdArch))] + public void IsSameState_MatchingAddress(MockTarget.Architecture arch) + { + const ulong exceptionAddress = 0xAA00_0000; + IXCLRDataExceptionState exceptionState = CreateExceptionStateWithRecord(arch, exceptionAddress); + EXCEPTION_RECORD64 inputRecord = new() { ExceptionAddress = exceptionAddress }; + + int hr = exceptionState.IsSameState(&inputRecord, 0, null); + + Assert.Equal(HResults.S_OK, hr); + } + + [Theory] + [ClassData(typeof(MockTarget.StdArch))] + public void IsSameState2_DifferentAddress(MockTarget.Architecture arch) + { + const ulong exceptionAddress = 0x1234_5678; + IXCLRDataExceptionState exceptionState = CreateExceptionStateWithRecord(arch, exceptionAddress); + EXCEPTION_RECORD64 inputRecord = new() { ExceptionAddress = exceptionAddress + 1 }; + + int hr = exceptionState.IsSameState2(0, &inputRecord, 0, null); + + Assert.Equal(HResults.S_FALSE, hr); + } + + [Theory] + [InlineData(0u)] + [InlineData(1u)] + public void IsSameState2_PartialState(uint flags) + { + IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( + target: null!, + threadAddress: TargetPointer.Null, + flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_PARTIAL, + thrownObjectHandle: TargetPointer.Null, + previousExInfoAddress: TargetPointer.Null, + legacyImpl: null); + + int hr = exceptionState.IsSameState2(flags, null, 0, null); + + Assert.Equal(flags == 1 ? HResults.S_OK : HResults.S_FALSE, hr); + } + + [Theory] + [InlineData(2u)] + [InlineData(uint.MaxValue)] + public void IsSameState2_InvalidFlags(uint flags) + { + IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( + target: null!, + threadAddress: TargetPointer.Null, + flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_PARTIAL, + thrownObjectHandle: TargetPointer.Null, + previousExInfoAddress: TargetPointer.Null, + legacyImpl: null); + + int hr = exceptionState.IsSameState2(flags, null, 0, null); + + Assert.Equal(HResults.E_INVALIDARG, hr); + } + [Theory] [ClassData(typeof(MockTarget.StdArch))] public void GetCurrentExceptionState_NestedException(MockTarget.Architecture arch) From a554b966fd22349468c536c526bbe10255fd5723 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Jul 2026 05:13:01 +0000 Subject: [PATCH 2/4] Address exception state comparison feedback Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com> --- .../ClrDataExceptionState.cs | 32 +++++--- .../ClrDataTask.cs | 4 +- .../IXCLRData.cs | 7 ++ .../SOSDacImpl.IXCLRDataProcess.cs | 1 + .../UnitTests/ClrDataExceptionStateTests.cs | 78 ++++++++++++++++--- 5 files changed, 100 insertions(+), 22 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs index e6d30d718709ce..1237b70d1ce0b7 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs @@ -11,11 +11,10 @@ namespace Microsoft.Diagnostics.DataContractReader.Legacy; [GeneratedComClass] public sealed unsafe partial class ClrDataExceptionState : IXCLRDataExceptionState { - private const uint FirstChance = 0x1; - private readonly Target _target; private readonly TargetPointer _threadAddress; private readonly uint _flags; + private readonly TargetPointer _exceptionInfoAddress; private readonly TargetPointer _thrownObjectHandle; private readonly TargetPointer _previousExInfoAddress; private readonly IXCLRDataExceptionState? _legacyImpl; @@ -24,6 +23,7 @@ public ClrDataExceptionState( Target target, TargetPointer threadAddress, uint flags, + TargetPointer exceptionInfoAddress, TargetPointer thrownObjectHandle, TargetPointer previousExInfoAddress, IXCLRDataExceptionState? legacyImpl) @@ -31,6 +31,7 @@ public ClrDataExceptionState( _target = target; _threadAddress = threadAddress; _flags = flags; + _exceptionInfoAddress = exceptionInfoAddress; _thrownObjectHandle = thrownObjectHandle; _previousExInfoAddress = previousExInfoAddress; _legacyImpl = legacyImpl; @@ -93,6 +94,7 @@ int IXCLRDataExceptionState.GetPrevious(DacComNullableByRefExceptionAddress diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataTask.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataTask.cs index 08ac8cc706117e..acf00aa870c80b 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataTask.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataTask.cs @@ -114,7 +114,7 @@ int IXCLRDataTask.GetCurrentExceptionState(DacComNullableByRef(); + SetupGetNestedExceptionInfo( + mockException, + exceptionInfoAddress, + nextNestedException: TargetPointer.Null, + thrownObjectHandle: TargetPointer.Null); + targetBuilder.AddMockContract(mockException); + targetBuilder.AddTypes(new Dictionary + { + [DataType.ExceptionInfo] = new Target.TypeInfo + { + Size = (uint)helpers.PointerSize, + Fields = new Dictionary + { + ["ExceptionRecord"] = new Target.FieldInfo { Offset = 0 } + } + } + }); + } + TargetPointer threadAddress = new(0x1000); var mockThread = new Mock(); mockThread.Setup(t => t.GetThreadData(threadAddress)).Returns(new ThreadData( @@ -164,7 +193,7 @@ private static IXCLRDataExceptionState CreateExceptionStateWithRecord( DebuggerFilterContext: TargetPointer.Null, GCFrame: TargetPointer.Null, IsExceptionInProgress: true, - OSExceptionRecord: new TargetPointer(exceptionRecord.Address), + OSExceptionRecord: hasExceptionInfo ? TargetPointer.Null : new TargetPointer(exceptionRecord.Address), OSExceptionContextRecord: TargetPointer.Null)); TestPlaceholderTarget target = targetBuilder @@ -174,8 +203,9 @@ private static IXCLRDataExceptionState CreateExceptionStateWithRecord( target, threadAddress, (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + exceptionInfoAddress: TargetPointer.Null, thrownObjectHandle: TargetPointer.Null, - previousExInfoAddress: TargetPointer.Null, + previousExInfoAddress: exceptionInfoAddress, legacyImpl: null); } @@ -190,6 +220,7 @@ public void GetFlags(uint inputFlags, bool hasNestedException, uint expectedFlag target: null!, threadAddress: new TargetPointer(0x1000), flags: inputFlags, + exceptionInfoAddress: TargetPointer.Null, thrownObjectHandle: new TargetPointer(0x2000), previousExInfoAddress: previousExInfo, legacyImpl: null); @@ -206,7 +237,7 @@ public void GetString_WithMessage(MockTarget.Architecture arch) (TestPlaceholderTarget target, TargetPointer thrownObjectHandle) = CreateTargetWithException(arch, messageAddr, expectedMessage); IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( target, new TargetPointer(0x1000), (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, - thrownObjectHandle, TargetPointer.Null, null); + TargetPointer.Null, thrownObjectHandle, TargetPointer.Null, null); (int hr, uint strLen, char[] buffer) = CallGetString(exceptionState, bufLen: 256); Assert.Equal(HResults.S_OK, hr); @@ -221,7 +252,7 @@ public void GetString_NullMessage(MockTarget.Architecture arch) (TestPlaceholderTarget target, TargetPointer thrownObjectHandle) = CreateTargetWithException(arch, TargetPointer.Null, null); IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( target, new TargetPointer(0x1000), (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, - thrownObjectHandle, TargetPointer.Null, null); + TargetPointer.Null, thrownObjectHandle, TargetPointer.Null, null); (int hr, uint strLen, char[] buffer) = CallGetString(exceptionState, bufLen: 256); Assert.Equal(HResults.S_OK, hr); @@ -236,7 +267,7 @@ public void GetString_NullMessageNonEmptyBuffer(MockTarget.Architecture arch) (TestPlaceholderTarget target, TargetPointer thrownObjectHandle) = CreateTargetWithException(arch, TargetPointer.Null, null); IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( target, new TargetPointer(0x1000), (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, - thrownObjectHandle, TargetPointer.Null, null); + TargetPointer.Null, thrownObjectHandle, TargetPointer.Null, null); uint bufferSize = 256; char* str = null; @@ -255,7 +286,7 @@ public void GetString_BufferOverflow(MockTarget.Architecture arch) (TestPlaceholderTarget target, TargetPointer thrownObjectHandle) = CreateTargetWithException(arch, messageAddr, expectedMessage); IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( target, new TargetPointer(0x1000), (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, - thrownObjectHandle, TargetPointer.Null, null); + TargetPointer.Null, thrownObjectHandle, TargetPointer.Null, null); (int hr, uint strLen, _) = CallGetString(exceptionState, bufLen: 5); Assert.Equal(HResults.S_FALSE, hr); @@ -273,6 +304,7 @@ public void Request_NullInBuffer_InvalidArgs(uint reqCode, uint inBufferSize, ui target: null!, threadAddress: default, flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + exceptionInfoAddress: default, thrownObjectHandle: default, previousExInfoAddress: default, legacyImpl: null); @@ -292,6 +324,7 @@ public void Request_NonNullInBuffer_InvalidArgs() target: null!, threadAddress: default, flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + exceptionInfoAddress: default, thrownObjectHandle: default, previousExInfoAddress: default, legacyImpl: null); @@ -313,6 +346,7 @@ public void Request_Success() target: null!, threadAddress: default, flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + exceptionInfoAddress: default, thrownObjectHandle: default, previousExInfoAddress: default, legacyImpl: null); @@ -334,6 +368,7 @@ public void GetTask() target: null!, threadAddress: new TargetPointer(0x1000), flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + exceptionInfoAddress: TargetPointer.Null, thrownObjectHandle: new TargetPointer(0x2000), previousExInfoAddress: TargetPointer.Null, legacyImpl: null); @@ -365,27 +400,44 @@ public void IsSameState2_DifferentAddress(MockTarget.Architecture arch) IXCLRDataExceptionState exceptionState = CreateExceptionStateWithRecord(arch, exceptionAddress); EXCEPTION_RECORD64 inputRecord = new() { ExceptionAddress = exceptionAddress + 1 }; - int hr = exceptionState.IsSameState2(0, &inputRecord, 0, null); + int hr = exceptionState.IsSameState2((uint)CLRDataExceptionSameFlag.CLRDATA_EXSAME_SECOND_CHANCE, &inputRecord, 0, null); Assert.Equal(HResults.S_FALSE, hr); } [Theory] - [InlineData(0u)] - [InlineData(1u)] + [ClassData(typeof(MockTarget.StdArch))] + public void IsSameState2_MatchingNestedAddress(MockTarget.Architecture arch) + { + const ulong exceptionAddress = 0x1234_5678; + IXCLRDataExceptionState exceptionState = CreateExceptionStateWithRecord(arch, exceptionAddress, hasExceptionInfo: true); + DacComNullableByRef previous = new(isNullRef: false); + Assert.Equal(HResults.S_OK, exceptionState.GetPrevious(previous)); + Assert.NotNull(previous.Interface); + EXCEPTION_RECORD64 inputRecord = new() { ExceptionAddress = exceptionAddress }; + + int hr = previous.Interface.IsSameState2((uint)CLRDataExceptionSameFlag.CLRDATA_EXSAME_SECOND_CHANCE, &inputRecord, 0, null); + + Assert.Equal(HResults.S_OK, hr); + } + + [Theory] + [InlineData((uint)CLRDataExceptionSameFlag.CLRDATA_EXSAME_SECOND_CHANCE)] + [InlineData((uint)CLRDataExceptionSameFlag.CLRDATA_EXSAME_FIRST_CHANCE)] public void IsSameState2_PartialState(uint flags) { IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( target: null!, threadAddress: TargetPointer.Null, flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_PARTIAL, + exceptionInfoAddress: TargetPointer.Null, thrownObjectHandle: TargetPointer.Null, previousExInfoAddress: TargetPointer.Null, legacyImpl: null); int hr = exceptionState.IsSameState2(flags, null, 0, null); - Assert.Equal(flags == 1 ? HResults.S_OK : HResults.S_FALSE, hr); + Assert.Equal(flags == (uint)CLRDataExceptionSameFlag.CLRDATA_EXSAME_FIRST_CHANCE ? HResults.S_OK : HResults.S_FALSE, hr); } [Theory] @@ -397,6 +449,7 @@ public void IsSameState2_InvalidFlags(uint flags) target: null!, threadAddress: TargetPointer.Null, flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_PARTIAL, + exceptionInfoAddress: TargetPointer.Null, thrownObjectHandle: TargetPointer.Null, previousExInfoAddress: TargetPointer.Null, legacyImpl: null); @@ -468,6 +521,7 @@ public void GetPrevious_NoPrevious() target: null!, threadAddress: new TargetPointer(0x1000), flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + exceptionInfoAddress: TargetPointer.Null, thrownObjectHandle: new TargetPointer(0x2000), previousExInfoAddress: TargetPointer.Null, legacyImpl: null); @@ -498,6 +552,7 @@ public void GetPrevious_HasPrevious_ReturnsState(MockTarget.Architecture arch) target, threadAddress: new TargetPointer(0x1000), flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + exceptionInfoAddress: TargetPointer.Null, thrownObjectHandle: new TargetPointer(0x2000), previousExInfoAddress: previousExInfoAddr, legacyImpl: null); @@ -533,6 +588,7 @@ public void GetPrevious_NestedExceptionsChain(MockTarget.Architecture arch) target, threadAddress: new TargetPointer(0x1000), flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + exceptionInfoAddress: TargetPointer.Null, thrownObjectHandle: new TargetPointer(0x2000), previousExInfoAddress: firstNestedAddr, legacyImpl: null); From 48f1797dea53de3e083229d45dd2aeb694f842eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Jul 2026 05:15:02 +0000 Subject: [PATCH 3/4] Clarify nested exception info flow Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com> --- .../ClrDataExceptionState.cs | 14 +++++++------- .../UnitTests/ClrDataExceptionStateTests.cs | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs index 1237b70d1ce0b7..00d1416f311a84 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs @@ -91,13 +91,13 @@ int IXCLRDataExceptionState.GetPrevious(DacComNullableByRef(); SetupGetNestedExceptionInfo( mockException, - exceptionInfoAddress, + previousExInfoAddress, nextNestedException: TargetPointer.Null, thrownObjectHandle: TargetPointer.Null); targetBuilder.AddMockContract(mockException); @@ -193,7 +193,7 @@ private static IXCLRDataExceptionState CreateExceptionStateWithRecord( DebuggerFilterContext: TargetPointer.Null, GCFrame: TargetPointer.Null, IsExceptionInProgress: true, - OSExceptionRecord: hasExceptionInfo ? TargetPointer.Null : new TargetPointer(exceptionRecord.Address), + OSExceptionRecord: hasPreviousExceptionInfo ? TargetPointer.Null : new TargetPointer(exceptionRecord.Address), OSExceptionContextRecord: TargetPointer.Null)); TestPlaceholderTarget target = targetBuilder @@ -205,7 +205,7 @@ private static IXCLRDataExceptionState CreateExceptionStateWithRecord( (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, exceptionInfoAddress: TargetPointer.Null, thrownObjectHandle: TargetPointer.Null, - previousExInfoAddress: exceptionInfoAddress, + previousExInfoAddress: previousExInfoAddress, legacyImpl: null); } @@ -410,7 +410,7 @@ public void IsSameState2_DifferentAddress(MockTarget.Architecture arch) public void IsSameState2_MatchingNestedAddress(MockTarget.Architecture arch) { const ulong exceptionAddress = 0x1234_5678; - IXCLRDataExceptionState exceptionState = CreateExceptionStateWithRecord(arch, exceptionAddress, hasExceptionInfo: true); + IXCLRDataExceptionState exceptionState = CreateExceptionStateWithRecord(arch, exceptionAddress, hasPreviousExceptionInfo: true); DacComNullableByRef previous = new(isNullRef: false); Assert.Equal(HResults.S_OK, exceptionState.GetPrevious(previous)); Assert.NotNull(previous.Interface); From 999caed0da5317795648effd23c91cb03eb7f7a7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Jul 2026 05:38:58 +0000 Subject: [PATCH 4/4] Make ClrDataExceptionState constructor calls positional Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com> --- .../ClrDataExceptionState.cs | 14 +- .../UnitTests/ClrDataExceptionStateTests.cs | 144 +++++++++--------- 2 files changed, 79 insertions(+), 79 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs index 00d1416f311a84..1237b70d1ce0b7 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs @@ -91,13 +91,13 @@ int IXCLRDataExceptionState.GetPrevious(DacComNullableByRef task = new(isNullRef: false); int hr = exceptionState.GetTask(task); @@ -427,13 +427,13 @@ public void IsSameState2_MatchingNestedAddress(MockTarget.Architecture arch) public void IsSameState2_PartialState(uint flags) { IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( - target: null!, - threadAddress: TargetPointer.Null, - flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_PARTIAL, - exceptionInfoAddress: TargetPointer.Null, - thrownObjectHandle: TargetPointer.Null, - previousExInfoAddress: TargetPointer.Null, - legacyImpl: null); + null!, + TargetPointer.Null, + (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_PARTIAL, + TargetPointer.Null, + TargetPointer.Null, + TargetPointer.Null, + null); int hr = exceptionState.IsSameState2(flags, null, 0, null); @@ -446,13 +446,13 @@ public void IsSameState2_PartialState(uint flags) public void IsSameState2_InvalidFlags(uint flags) { IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( - target: null!, - threadAddress: TargetPointer.Null, - flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_PARTIAL, - exceptionInfoAddress: TargetPointer.Null, - thrownObjectHandle: TargetPointer.Null, - previousExInfoAddress: TargetPointer.Null, - legacyImpl: null); + null!, + TargetPointer.Null, + (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_PARTIAL, + TargetPointer.Null, + TargetPointer.Null, + TargetPointer.Null, + null); int hr = exceptionState.IsSameState2(flags, null, 0, null); @@ -518,13 +518,13 @@ public void GetCurrentExceptionState_NoException(MockTarget.Architecture arch) public void GetPrevious_NoPrevious() { IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( - target: null!, - threadAddress: new TargetPointer(0x1000), - flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, - exceptionInfoAddress: TargetPointer.Null, - thrownObjectHandle: new TargetPointer(0x2000), - previousExInfoAddress: TargetPointer.Null, - legacyImpl: null); + null!, + new TargetPointer(0x1000), + (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + TargetPointer.Null, + new TargetPointer(0x2000), + TargetPointer.Null, + null); DacComNullableByRef previous = new(isNullRef: false); int hr = exceptionState.GetPrevious(previous); @@ -550,12 +550,12 @@ public void GetPrevious_HasPrevious_ReturnsState(MockTarget.Architecture arch) IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( target, - threadAddress: new TargetPointer(0x1000), - flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, - exceptionInfoAddress: TargetPointer.Null, - thrownObjectHandle: new TargetPointer(0x2000), - previousExInfoAddress: previousExInfoAddr, - legacyImpl: null); + new TargetPointer(0x1000), + (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + TargetPointer.Null, + new TargetPointer(0x2000), + previousExInfoAddr, + null); DacComNullableByRef previous = new(isNullRef: false); int hr = exceptionState.GetPrevious(previous); @@ -586,12 +586,12 @@ public void GetPrevious_NestedExceptionsChain(MockTarget.Architecture arch) IXCLRDataExceptionState exceptionState = new ClrDataExceptionState( target, - threadAddress: new TargetPointer(0x1000), - flags: (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, - exceptionInfoAddress: TargetPointer.Null, - thrownObjectHandle: new TargetPointer(0x2000), - previousExInfoAddress: firstNestedAddr, - legacyImpl: null); + new TargetPointer(0x1000), + (uint)CLRDataExceptionStateFlag.CLRDATA_EXCEPTION_DEFAULT, + TargetPointer.Null, + new TargetPointer(0x2000), + firstNestedAddr, + null); DacComNullableByRef first = new(isNullRef: false); int hr1 = exceptionState.GetPrevious(first);