in src/Microsoft.Diagnostics.Runtime/DacImplementation/DacThreadHelpers.cs [30:83]
public IEnumerable<StackRootInfo> EnumerateStackRoots(uint osThreadId, bool traceErrors)
{
using SOSStackRefEnum? stackRefEnum = _sos.EnumerateStackRefs(osThreadId);
if (stackRefEnum is null)
yield break;
const int GCInteriorFlag = 1;
const int GCPinnedFlag = 2;
const int SOS_StackSourceIP = 0;
const int SOS_StackSourceFrame = 1;
foreach (StackRefData stackRef in stackRefEnum.ReadStackRefs())
{
if (stackRef.Object == 0)
{
if (traceErrors)
Trace.TraceWarning($"EnumerateStackRoots found an unexpected entry with Object == 0, addr:{(ulong)stackRef.Address:x} srcType:{stackRef.SourceType:x}");
continue;
}
bool interior = (stackRef.Flags & GCInteriorFlag) == GCInteriorFlag;
bool isPinned = (stackRef.Flags & GCPinnedFlag) == GCPinnedFlag;
int regOffset = 0;
string? regName = null;
if (stackRef.HasRegisterInformation != 0)
{
regOffset = stackRef.Offset;
regName = _sos.GetRegisterName(stackRef.Register);
}
ulong ip = 0;
ulong frame = 0;
if (stackRef.SourceType == SOS_StackSourceIP)
ip = stackRef.Source;
else if (stackRef.SourceType == SOS_StackSourceFrame)
frame = stackRef.Source;
yield return new StackRootInfo()
{
InstructionPointer = ip,
StackPointer = stackRef.StackPointer,
InternalFrame = frame,
IsInterior = interior,
IsPinned = isPinned,
Address = stackRef.Address,
Object = stackRef.Object,
IsEnregistered = stackRef.HasRegisterInformation != 0,
RegisterName = regName,
RegisterOffset = regOffset,
};
}
}