diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.h b/src/coreclr/debug/runtimeinfo/datadescriptor.h index 60193392bd9732..67203e2864daca 100644 --- a/src/coreclr/debug/runtimeinfo/datadescriptor.h +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.h @@ -862,11 +862,6 @@ CDAC_GLOBAL_POINTER(GCThread, &::g_pSuspensionThread) #undef FRAME_TYPE_NAME CDAC_GLOBAL(MethodDescTokenRemainderBitCount, uint8, METHOD_TOKEN_REMAINDER_BIT_COUNT) -#if FEATURE_EH_FUNCLETS -CDAC_GLOBAL(FeatureEHFunclets, uint8, 1) -#else -CDAC_GLOBAL(FeatureEHFunclets, uint8, 0) -#endif #if FEATURE_COMINTEROP CDAC_GLOBAL(FeatureCOMInterop, uint8, 1) #else diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.cs index ea0381d93a1097..ab45f4a9bbe290 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.cs @@ -15,7 +15,6 @@ public static class Globals public const string GCThread = nameof(GCThread); public const string FeatureCOMInterop = nameof(FeatureCOMInterop); - public const string FeatureEHFunclets = nameof(FeatureEHFunclets); public const string ObjectToMethodTableUnmask = nameof(ObjectToMethodTableUnmask); public const string SOSBreakingChangeVersion = nameof(SOSBreakingChangeVersion); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.EEJitManager.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.EEJitManager.cs index 128394b97d2234..6a23be3be862d4 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.EEJitManager.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.EEJitManager.cs @@ -46,7 +46,6 @@ public override bool GetMethodInfo(RangeSection rangeSection, TargetCodePointer public override TargetPointer GetUnwindInfo(RangeSection rangeSection, TargetCodePointer jittedCodeAddress) { - // TODO: This only works with funclets enabled. See runtime definition of RealCodeHeader for more info. if (rangeSection.IsRangeList) return TargetPointer.Null; if (rangeSection.Data == null) @@ -60,16 +59,7 @@ public override TargetPointer GetUnwindInfo(RangeSection rangeSection, TargetCod if (!GetRealCodeHeader(rangeSection, codeStart, out Data.RealCodeHeader? realCodeHeader)) return TargetPointer.Null; - if (realCodeHeader.NumUnwindInfos is not uint numUnwindInfos) - { - throw new InvalidOperationException("Unable to get NumUnwindInfos"); - } - if (realCodeHeader.UnwindInfos is not TargetPointer unwindInfos) - { - throw new InvalidOperationException("Unable to get NumUnwindInfos"); - } - - if (numUnwindInfos == 0) + if (realCodeHeader.NumUnwindInfos == 0) { return TargetPointer.Null; } @@ -79,10 +69,10 @@ public override TargetPointer GetUnwindInfo(RangeSection rangeSection, TargetCod TargetPointer imageBase = rangeSection.Data.RangeBegin; TargetPointer relativeAddr = addr - imageBase; - if (!_runtimeFunctions.TryGetRuntimeFunctionIndexForAddress(unwindInfos, numUnwindInfos, relativeAddr, out uint index)) + if (!_runtimeFunctions.TryGetRuntimeFunctionIndexForAddress(realCodeHeader.UnwindInfos, realCodeHeader.NumUnwindInfos, relativeAddr, out uint index)) return TargetPointer.Null; - return _runtimeFunctions.GetRuntimeFunctionAddress(unwindInfos, index); + return _runtimeFunctions.GetRuntimeFunctionAddress(realCodeHeader.UnwindInfos, index); } public override void GetGCInfo(RangeSection rangeSection, TargetCodePointer jittedCodeAddress, out TargetPointer gcInfo, out uint gcVersion) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/AMD64FrameHandler.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/AMD64FrameHandler.cs index d5649e2a861994..b3950dd1205086 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/AMD64FrameHandler.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/AMD64FrameHandler.cs @@ -13,11 +13,7 @@ internal class AMD64FrameHandler(Target target, ContextHolder cont void IPlatformFrameHandler.HandleFaultingExceptionFrame(FaultingExceptionFrame frame) { - if (frame.TargetContext is not TargetPointer targetContext) - { - throw new InvalidOperationException("Unexpected null context pointer on FaultingExceptionFrame"); - } - _holder.ReadFromAddress(_target, targetContext); + _holder.ReadFromAddress(_target, frame.TargetContext); // Clear the CONTEXT_XSTATE, since the AMD64Context contains just plain CONTEXT structure // that does not support holding any extended state. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/ARM64FrameHandler.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/ARM64FrameHandler.cs index 59d8b055ba5078..756d20c8e5e27c 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/ARM64FrameHandler.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/ARM64FrameHandler.cs @@ -15,11 +15,7 @@ internal class ARM64FrameHandler(Target target, ContextHolder cont void IPlatformFrameHandler.HandleFaultingExceptionFrame(FaultingExceptionFrame frame) { - if (frame.TargetContext is not TargetPointer targetContext) - { - throw new InvalidOperationException("Unexpected null context pointer on FaultingExceptionFrame"); - } - _holder.ReadFromAddress(_target, targetContext); + _holder.ReadFromAddress(_target, frame.TargetContext); // Clear the CONTEXT_XSTATE, since the ARM64Context contains just plain CONTEXT structure // that does not support holding any extended state. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/X86FrameHandler.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/X86FrameHandler.cs index b179c923e5ba1b..e1044b6ccfcafa 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/X86FrameHandler.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/X86FrameHandler.cs @@ -14,11 +14,7 @@ internal class X86FrameHandler(Target target, ContextHolder contextH public void HandleFaultingExceptionFrame(FaultingExceptionFrame frame) { - if (frame.TargetContext is not TargetPointer targetContext) - { - throw new InvalidOperationException("Unexpected null context pointer on FaultingExceptionFrame"); - } - _context.ReadFromAddress(_target, targetContext); + _context.ReadFromAddress(_target, frame.TargetContext); // Clear the CONTEXT_XSTATE, since the X86Context contains just plain CONTEXT structure // that does not support holding any extended state. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Thread_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Thread_1.cs index 796eb89dffce71..f0587a674c3058 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Thread_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Thread_1.cs @@ -46,10 +46,7 @@ ThreadData IThread.GetThreadData(TargetPointer threadPointer) { Data.Thread thread = _target.ProcessedData.GetOrAdd(threadPointer); - // Exception tracker is a pointer when EH funclets are enabled - TargetPointer address = _target.ReadGlobal(Constants.Globals.FeatureEHFunclets) != 0 - ? _target.ReadPointer(thread.ExceptionTracker) - : thread.ExceptionTracker; + TargetPointer address = _target.ReadPointer(thread.ExceptionTracker); TargetPointer firstNestedException = TargetPointer.Null; if (address != TargetPointer.Null) { diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FaultingExceptionFrame.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FaultingExceptionFrame.cs index a205b59f78bb41..0560cba528d18c 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FaultingExceptionFrame.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/FaultingExceptionFrame.cs @@ -11,15 +11,10 @@ static FaultingExceptionFrame IData.Create(Target target public FaultingExceptionFrame(Target target, TargetPointer address) { Target.TypeInfo type = target.GetTypeInfo(DataType.FaultingExceptionFrame); - - // TargetContextPtr only exists when FEATURE_EH_FUNCLETS is defined - if (type.Fields.ContainsKey(nameof(TargetContext))) - { - TargetContext = address + (ulong)type.Fields[nameof(TargetContext)].Offset; - } + TargetContext = address + (ulong)type.Fields[nameof(TargetContext)].Offset; Address = address; } public TargetPointer Address { get; } - public TargetPointer? TargetContext { get; } + public TargetPointer TargetContext { get; } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/SoftwareExceptionFrame.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/SoftwareExceptionFrame.cs index e318aa2638f58f..0cec284982faea 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/SoftwareExceptionFrame.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/SoftwareExceptionFrame.cs @@ -10,8 +10,6 @@ static SoftwareExceptionFrame IData.Create(Target target public SoftwareExceptionFrame(Target target, TargetPointer address) { - // TypeInfo will only exist if FEATURE_EH_FUNCLETS is enabled. - // If it doesn't exist, then this type of frame is not present in target. Target.TypeInfo type = target.GetTypeInfo(DataType.SoftwareExceptionFrame); Address = address; TargetContext = address + (ulong)type.Fields[nameof(TargetContext)].Offset; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RealCodeHeader.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RealCodeHeader.cs index 35a90171ee6ba2..f40998be18b114 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RealCodeHeader.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RealCodeHeader.cs @@ -13,18 +13,12 @@ public RealCodeHeader(Target target, TargetPointer address) Target.TypeInfo type = target.GetTypeInfo(DataType.RealCodeHeader); MethodDesc = target.ReadPointer(address + (ulong)type.Fields[nameof(MethodDesc)].Offset); GCInfo = target.ReadPointer(address + (ulong)type.Fields[nameof(GCInfo)].Offset); - - // Only available if FEATURE_EH_FUNCLETS is enabled. - if (type.Fields.ContainsKey(nameof(NumUnwindInfos))) - NumUnwindInfos = target.Read(address + (ulong)type.Fields[nameof(NumUnwindInfos)].Offset); - - // Only available if FEATURE_EH_FUNCLETS is enabled. - if (type.Fields.ContainsKey(nameof(UnwindInfos))) - UnwindInfos = address + (ulong)type.Fields[nameof(UnwindInfos)].Offset; + NumUnwindInfos = target.Read(address + (ulong)type.Fields[nameof(NumUnwindInfos)].Offset); + UnwindInfos = address + (ulong)type.Fields[nameof(UnwindInfos)].Offset; } public TargetPointer MethodDesc { get; init; } public TargetPointer GCInfo { get; init; } - public uint? NumUnwindInfos { get; init; } - public TargetPointer? UnwindInfos { get; init; } + public uint NumUnwindInfos { get; init; } + public TargetPointer UnwindInfos { get; init; } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Thread.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Thread.cs index c98753d6385d96..1d6c484b7b8f37 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Thread.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Thread.cs @@ -31,7 +31,7 @@ public Thread(Target target, TargetPointer address) target.ReadPointer(address + (ulong)type.Fields[nameof(LastThrownObject)].Offset)); LinkNext = target.ReadPointer(address + (ulong)type.Fields[nameof(LinkNext)].Offset); - // Address of the exception tracker - how it should be read depends on EH funclets feature global value + // Address of the exception tracker ExceptionTracker = address + (ulong)type.Fields[nameof(ExceptionTracker)].Offset; } diff --git a/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs b/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs index d7017cfceab2d9..35b99995868a71 100644 --- a/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs +++ b/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs @@ -17,7 +17,7 @@ internal class ExecutionManager { public const ulong ExecutionManagerCodeRangeMapAddress = 0x000a_fff0; - const int RealCodeHeaderSize = 0x10; // must be big enough for the offsets of RealCodeHeader size in ExecutionManagerTestTarget, below + const int RealCodeHeaderSize = 0x20; // must be big enough for the offsets of RealCodeHeader size in ExecutionManagerTestTarget, below public struct AllocationRange { @@ -233,6 +233,8 @@ public static RangeSectionMapTestBuilder CreateRangeSection(MockTarget.Architect [ new(nameof(Data.RealCodeHeader.MethodDesc), DataType.pointer), new(nameof(Data.RealCodeHeader.GCInfo), DataType.pointer), + new(nameof(Data.RealCodeHeader.NumUnwindInfos), DataType.uint32), + new(nameof(Data.RealCodeHeader.UnwindInfos), DataType.pointer), ] }; @@ -292,13 +294,10 @@ internal ExecutionManager(int version, MockMemorySpace.Builder builder, Allocati .Concat(_rfBuilder.Types) .ToDictionary(); - // Tests are currently always set to use funclets - bool useFunclets = true; Globals = [ (nameof(Constants.Globals.ExecutionManagerCodeRangeMapAddress), ExecutionManagerCodeRangeMapAddress), (nameof(Constants.Globals.StubCodeBlockLast), 0x0Fu), - (nameof(Constants.Globals.FeatureEHFunclets), useFunclets ? 1u : 0u), ]; Globals = Globals .Concat(MockDescriptors.HashMap.GetGlobals(Builder.TargetTestHelpers)) @@ -430,6 +429,11 @@ public TargetCodePointer AddJittedMethod(JittedCodeRange jittedCodeRange, uint c var tyInfo = Types[DataType.RealCodeHeader]; Builder.TargetTestHelpers.WritePointer(chf.Slice(tyInfo.Fields[nameof(Data.RealCodeHeader.MethodDesc)].Offset, Builder.TargetTestHelpers.PointerSize), methodDescAddress); + // fields are not used in the test, but we still need to write them + Builder.TargetTestHelpers.WritePointer(chf.Slice(tyInfo.Fields[nameof(Data.RealCodeHeader.GCInfo)].Offset, Builder.TargetTestHelpers.PointerSize), TargetPointer.Null); + Builder.TargetTestHelpers.Write(chf.Slice(tyInfo.Fields[nameof(Data.RealCodeHeader.NumUnwindInfos)].Offset, sizeof(uint)), 0u); + Builder.TargetTestHelpers.WritePointer(chf.Slice(tyInfo.Fields[nameof(Data.RealCodeHeader.UnwindInfos)].Offset, Builder.TargetTestHelpers.PointerSize), TargetPointer.Null); + return codeStart; } diff --git a/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.Thread.cs b/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.Thread.cs index 8b47fa9cb894a1..12dc6299503998 100644 --- a/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.Thread.cs +++ b/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.Thread.cs @@ -10,7 +10,6 @@ internal partial class MockDescriptors { public class Thread { - const bool UseFunclets = false; private const ulong DefaultAllocationRangeStart = 0x0003_0000; private const ulong DefaultAllocationRangeEnd = 0x0004_0000; @@ -68,7 +67,6 @@ public Thread(MockMemorySpace.Builder builder, (ulong Start, ulong End) allocati (nameof(Constants.Globals.ThreadStore), threadStoreGlobal.Address), (nameof(Constants.Globals.FinalizerThread), finalizerThreadGlobal.Address), (nameof(Constants.Globals.GCThread), gcThreadGlobal.Address), - (nameof(Constants.Globals.FeatureEHFunclets), UseFunclets ? 1 : 0), ]; } @@ -108,28 +106,24 @@ internal void SetThreadCounts(int threadCount, int unstartedCount, int backgroun internal TargetPointer AddThread(uint id, TargetNUInt osId) { TargetTestHelpers helpers = Builder.TargetTestHelpers; - Target.TypeInfo typeInfo = Types[DataType.Thread]; - if (UseFunclets) - throw new NotImplementedException("todo for funclets: allocate the ExceptionInfo separately"); - ulong allocSize = typeInfo.Size.Value + (UseFunclets ? 0 : Types[DataType.ExceptionInfo].Size.Value); - MockMemorySpace.HeapFragment thread = _allocator.Allocate(allocSize, UseFunclets ? "Thread" : "Thread and ExceptionInfo"); + Target.TypeInfo threadType = Types[DataType.Thread]; + Target.TypeInfo exceptionInfoType = Types[DataType.ExceptionInfo]; + MockMemorySpace.HeapFragment exceptionInfo = _allocator.Allocate(exceptionInfoType.Size.Value, "ExceptionInfo"); + MockMemorySpace.HeapFragment thread = _allocator.Allocate(threadType.Size.Value, "Thread"); Span data = thread.Data.AsSpan(); helpers.Write( - data.Slice(typeInfo.Fields[nameof(Data.Thread.Id)].Offset), + data.Slice(threadType.Fields[nameof(Data.Thread.Id)].Offset), id); helpers.WriteNUInt( - data.Slice(typeInfo.Fields[nameof(Data.Thread.OSId)].Offset), + data.Slice(threadType.Fields[nameof(Data.Thread.OSId)].Offset), osId); - Builder.AddHeapFragment(thread); - - // Add exception info for the thread - // TODO: [cdac] Handle when UseFunclets is true - see NotImplementedException thrown above - TargetPointer exceptionInfoAddress = thread.Address + Types[DataType.ExceptionInfo].Size.Value; helpers.WritePointer( - data.Slice(typeInfo.Fields[nameof(Data.Thread.ExceptionTracker)].Offset), - exceptionInfoAddress); + data.Slice(threadType.Fields[nameof(Data.Thread.ExceptionTracker)].Offset), + exceptionInfo.Address); + Builder.AddHeapFragment(thread); + Builder.AddHeapFragment(exceptionInfo); - ulong threadLinkOffset = (ulong)typeInfo.Fields[nameof(Data.Thread.LinkNext)].Offset; + ulong threadLinkOffset = (ulong)threadType.Fields[nameof(Data.Thread.LinkNext)].Offset; if (_previousThread != TargetPointer.Null) { // Set the next link for the previously added thread to the newly added one