in src/Microsoft.Diagnostics.Runtime/DacImplementation/DacThreadHelpers.cs [85:184]
public IEnumerable<StackFrameInfo> EnumerateStackTrace(uint osThreadId, bool includeContext, bool traceErrors)
{
using ClrStackWalk? stackwalk = _dac.CreateStackWalk(osThreadId, 0xf);
if (stackwalk is null)
yield break;
int ipOffset;
int spOffset;
int contextSize;
uint contextFlags = 0;
if (_dataReader.Architecture == Architecture.Arm)
{
ipOffset = 64;
spOffset = 56;
contextSize = 416;
}
else if (_dataReader.Architecture == Architecture.Arm64)
{
ipOffset = 264;
spOffset = 256;
contextSize = 912;
}
else if (_dataReader.Architecture == (Architecture)9 /* Architecture.RiscV64 */)
{
ipOffset = 264;
spOffset = 24;
contextSize = 544;
}
else if (_dataReader.Architecture == (Architecture)6 /* Architecture.LoongArch64 */)
{
ipOffset = 264;
spOffset = 32;
contextSize = 1312;
}
else if (_dataReader.Architecture == Architecture.X86)
{
ipOffset = 184;
spOffset = 196;
contextSize = 716;
contextFlags = 0x1003f;
}
else // Architecture.X64
{
ipOffset = 248;
spOffset = 152;
contextSize = 1232;
contextFlags = 0x10003f;
}
HResult hr = HResult.S_OK;
byte[] context = ArrayPool<byte>.Shared.Rent(contextSize);
while (hr.IsOK)
{
hr = stackwalk.GetContext(contextFlags, contextSize, out _, context);
if (!hr)
{
if (traceErrors)
Trace.TraceError($"GetContext failed, flags:{contextFlags:x} size: {contextSize:x} hr={hr}");
break;
}
ulong ip = context.AsSpan().AsPointer(ipOffset);
ulong sp = context.AsSpan().AsPointer(spOffset);
ulong frameVtbl = stackwalk.GetFrameVtable();
string? frameName = null;
ulong frameMethod = 0;
if (frameVtbl != 0)
{
sp = frameVtbl;
frameVtbl = _dataReader.ReadPointer(sp);
frameName = _sos.GetFrameName(frameVtbl);
frameMethod = _sos.GetMethodDescPtrFromFrame(sp);
}
byte[]? contextCopy = null;
if (includeContext)
{
contextCopy = new byte[contextSize];
context.AsSpan(0, contextSize).CopyTo(contextCopy);
}
yield return new StackFrameInfo()
{
InstructionPointer = ip,
StackPointer = sp,
Context = contextCopy,
InternalFrameVTable = frameVtbl,
InternalFrameName = frameName,
InnerMethodMethodHandle = frameMethod,
};
hr = stackwalk.Next();
if (traceErrors && !hr)
Trace.TraceInformation($"STACKWALK FAILED - hr:{hr}");
}
ArrayPool<byte>.Shared.Return(context);
}