StackFrame try_unwind_sigreturn(StackFrame frame, TargetMemoryAccess memory)
{
byte[] data = memory.ReadMemory (frame.TargetAddress, 9).Contents;
/*
* Check for signal return trampolines:
*
* mov __NR_rt_sigreturn, %eax
* syscall
*/
if ((data [0] != 0x48) || (data [1] != 0xc7) ||
(data [2] != 0xc0) || (data [3] != 0x0f) ||
(data [4] != 0x00) || (data [5] != 0x00) ||
(data [6] != 0x00) || (data [7] != 0x0f) ||
(data [8] != 0x05))
return null;
TargetAddress stack = frame.StackPointer;
/* See `struct sigcontext' in <asm/sigcontext.h> */
int[] regoffsets = {
(int) X86_Register.R8, (int) X86_Register.R9,
(int) X86_Register.R10, (int) X86_Register.R11,
(int) X86_Register.R12, (int) X86_Register.R13,
(int) X86_Register.R14, (int) X86_Register.R15,
(int) X86_Register.RDI, (int) X86_Register.RSI,
(int) X86_Register.RBP, (int) X86_Register.RBX,
(int) X86_Register.RDX, (int) X86_Register.RAX,
(int) X86_Register.RCX, (int) X86_Register.RSP,
(int) X86_Register.RIP, (int) X86_Register.EFLAGS
};
Registers regs = CopyRegisters (frame.Registers);
int offset = 0x28;
/* The stack contains the `struct ucontext' from <asm/ucontext.h>; the
* `struct sigcontext' starts at offset 0x28 in it. */
foreach (int regoffset in regoffsets) {
TargetAddress new_value = memory.ReadAddress (stack + offset);
regs [regoffset].SetValue (new_value);
offset += 8;
}
TargetAddress rip = new TargetAddress (
memory.AddressDomain, regs [(int) X86_Register.RIP].GetValue ());
TargetAddress rsp = new TargetAddress (
memory.AddressDomain, regs [(int) X86_Register.RSP].GetValue ());
TargetAddress rbp = new TargetAddress (
memory.AddressDomain, regs [(int) X86_Register.RBP].GetValue ());
Symbol name = new Symbol ("<signal handler>", rip, 0);
return new StackFrame (
frame.Thread, FrameType.Signal, rip, rsp, rbp, regs, frame.Thread.NativeLanguage, name);
}