in src/Microsoft.Diagnostics.Runtime/Linux/LinuxLiveDataReader.cs [208:260]
public unsafe bool GetThreadContext(uint threadID, uint contextFlags, Span<byte> context)
{
LoadThreads();
if (!_threadIDs.Contains(threadID) || Architecture == Architecture.X86)
return false;
int regSize = Architecture switch
{
Architecture.Arm => sizeof(RegSetArm),
Architecture.Arm64 => sizeof(RegSetArm64),
(Architecture)9 /* Architecture.RiscV64 */ => sizeof(RegSetRiscV64),
(Architecture)6 /* Architecture.LoongArch64 */ => sizeof(RegSetLoongArch64),
Architecture.X64 => sizeof(RegSetX64),
_ => sizeof(RegSetX86),
};
byte[] buffer = ArrayPool<byte>.Shared.Rent(regSize);
try
{
fixed (byte* data = buffer)
{
ptrace(PTRACE_GETREGS, (int)threadID, IntPtr.Zero, new IntPtr(data));
}
switch (Architecture)
{
case Architecture.Arm:
Unsafe.As<byte, RegSetArm>(ref MemoryMarshal.GetReference(buffer.AsSpan())).CopyContext(context);
break;
case Architecture.Arm64:
Unsafe.As<byte, RegSetArm64>(ref MemoryMarshal.GetReference(buffer.AsSpan())).CopyContext(context);
break;
case (Architecture)9 /* Architecture.RiscV64 */:
Unsafe.As<byte, RegSetRiscV64>(ref MemoryMarshal.GetReference(buffer.AsSpan())).CopyContext(context);
break;
case (Architecture)6 /* Architecture.LoongArch64 */:
Unsafe.As<byte, RegSetLoongArch64>(ref MemoryMarshal.GetReference(buffer.AsSpan())).CopyContext(context);
break;
case Architecture.X64:
Unsafe.As<byte, RegSetX64>(ref MemoryMarshal.GetReference(buffer.AsSpan())).CopyContext(context);
break;
default:
Unsafe.As<byte, RegSetX86>(ref MemoryMarshal.GetReference(buffer.AsSpan())).CopyContext(context);
break;
}
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
return true;
}