public IEnumerable EnumerateStackTrace()

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);
        }