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)