diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.h b/src/coreclr/debug/runtimeinfo/datadescriptor.h index b23b5ea39eb00d..d9a0556b9742b1 100644 --- a/src/coreclr/debug/runtimeinfo/datadescriptor.h +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.h @@ -764,7 +764,7 @@ CDAC_GLOBAL_POINTER(GCThread, &::g_pSuspensionThread) // Add FrameIdentifier for all defined Frame types. Used to differentiate Frame objects. #define FRAME_TYPE_NAME(frameType) \ - CDAC_GLOBAL_POINTER(frameType##Identifier, FrameIdentifier::frameType) + CDAC_GLOBAL(frameType##Identifier, nuint, (uint64_t)FrameIdentifier::frameType) #include "frames.h" #undef FRAME_TYPE_NAME diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/Target.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/Target.cs index 266e0b2b0ba7f1..a9a73560c8b9b7 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/Target.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/Target.cs @@ -69,6 +69,14 @@ public enum CorDebugPlatform : int /// The value of the global public abstract TargetPointer ReadGlobalPointer(string global); + /// + /// Reads a well-known global pointer value from the target process + /// + /// The name of the global + /// The value of the global, if found. + /// True if the global is found, false otherwise. + public abstract bool TryReadGlobalPointer(string name, [NotNullWhen(true)] out TargetPointer? value); + /// /// Read a pointer from the target in target endianness /// @@ -119,6 +127,15 @@ public enum CorDebugPlatform : int /// A numeric value public abstract T ReadGlobal(string name) where T : struct, INumber; + /// + /// Read a well known global from the target process as a number in the target endianness + /// + /// The numeric type to be read + /// The name of the global + /// The numeric value read. + /// True if a global is found, false otherwise. + public abstract bool TryReadGlobal(string name, [NotNullWhen(true)] out T? value) where T : struct, INumber; + /// /// Read a value from the target in target endianness /// diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameIterator.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameIterator.cs index 34dd04e874848d..0fd8bb8a50ba47 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameIterator.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameIterator.cs @@ -144,19 +144,13 @@ private static FrameType GetFrameType(Target target, TargetPointer frameIdentifi { foreach (FrameType frameType in Enum.GetValues()) { - TargetPointer foundFrameIdentifier; - try + if (target.TryReadGlobalPointer(frameType.ToString() + "Identifier", out TargetPointer? id)) { - // not all Frames are in all builds, so we need to catch the exception - foundFrameIdentifier = target.ReadGlobalPointer(frameType.ToString() + "Identifier"); - if (frameIdentifier == foundFrameIdentifier) + if (frameIdentifier == id) { return frameType; } } - catch (InvalidOperationException) - { - } } return FrameType.Unknown; diff --git a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs index e2885d60f74b05..018d77120ee7c1 100644 --- a/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs +++ b/src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs @@ -496,6 +496,22 @@ public bool IsAlignedToPointerSize(ulong value) public override bool IsAlignedToPointerSize(TargetPointer pointer) => IsAligned(pointer.Value, _config.PointerSize); + public override bool TryReadGlobal(string name, [NotNullWhen(true)] out T? value) + => TryReadGlobal(name, out value, out _); + + public bool TryReadGlobal(string name, [NotNullWhen(true)] out T? value, out string? type) where T : struct, INumber + { + value = null; + type = null; + if (!_globals.TryGetValue(name, out (ulong Value, string? Type) global)) + { + return false; + } + type = global.Type; + value = T.CreateChecked(global.Value); + return true; + } + public override T ReadGlobal(string name) => ReadGlobal(name, out _); @@ -508,6 +524,21 @@ public T ReadGlobal(string name, out string? type) where T : struct, INumber< return T.CreateChecked(global.Value); } + public override bool TryReadGlobalPointer(string name, [NotNullWhen(true)] out TargetPointer? value) + => TryReadGlobalPointer(name, out value, out _); + + public bool TryReadGlobalPointer(string name, [NotNullWhen(true)] out TargetPointer? value, out string? type) + { + value = null; + type = null; + if (!_globals.TryGetValue(name, out (ulong Value, string? Type) global)) + return false; + + type = global.Type; + value = new TargetPointer(global.Value); + return true; + } + public override TargetPointer ReadGlobalPointer(string name) => ReadGlobalPointer(name, out _); diff --git a/src/native/managed/cdacreader/tests/TestPlaceholderTarget.cs b/src/native/managed/cdacreader/tests/TestPlaceholderTarget.cs index 92f0a924f2e2dc..6a5ca9328f39ee 100644 --- a/src/native/managed/cdacreader/tests/TestPlaceholderTarget.cs +++ b/src/native/managed/cdacreader/tests/TestPlaceholderTarget.cs @@ -51,6 +51,20 @@ public override bool IsAlignedToPointerSize(TargetPointer pointer) return (pointer.Value & (ulong)(PointerSize - 1)) == 0; } + public override bool TryReadGlobalPointer(string name, [NotNullWhen(true)] out TargetPointer? value) + { + value = null; + foreach (var global in _globals) + { + if (global.Name == name) + { + value = new TargetPointer(global.Value); + return true; + } + } + return false; + } + public override TargetPointer ReadGlobalPointer(string name) { foreach (var global in _globals) @@ -93,6 +107,20 @@ public override string ReadUtf16String(ulong address) } public override TargetNUInt ReadNUInt(ulong address) => DefaultReadNUInt(address); + + public override bool TryReadGlobal(string name, [NotNullWhen(true)] out T? value) + { + value = default; + foreach (var global in _globals) + { + if (global.Name == name) + { + value = T.CreateChecked(global.Value); + return true; + } + } + return false; + } public override T ReadGlobal(string name) { foreach (var global in _globals)