#include "defs.h" #include "regs.h" #include "ptrace.h" #if defined HAVE_ASM_SIGCONTEXT_H && !defined HAVE_STRUCT_SIGCONTEXT # include #endif #ifndef NSIG # warning NSIG is not defined, using 32 # define NSIG 32 #elif NSIG < 32 # error NSIG < 32 #endif int sys_sigreturn(struct tcb *tcp) { #if defined AARCH64 || defined ARM if (entering(tcp)) { # define SIZEOF_STRUCT_SIGINFO 128 # define SIZEOF_STRUCT_SIGCONTEXT (21 * 4) # define OFFSETOF_STRUCT_UCONTEXT_UC_SIGMASK (5 * 4 + SIZEOF_STRUCT_SIGCONTEXT) const long addr = # ifdef AARCH64 current_personality == 1 ? (*aarch64_sp_ptr + SIZEOF_STRUCT_SIGINFO + offsetof(struct ucontext, uc_sigmask)) : # endif (*arm_sp_ptr + OFFSETOF_STRUCT_UCONTEXT_UC_SIGMASK); tprints("{mask="); print_sigset_addr_len(tcp, addr, NSIG / 8); tprints("}"); } #elif defined(S390) || defined(S390X) if (entering(tcp)) { long mask[NSIG / 8 / sizeof(long)]; tprints("{mask="); const long addr = *s390_frame_ptr + __SIGNAL_FRAMESIZE; if (umove(tcp, addr, &mask) < 0) { tprintf("%#lx", addr); } else { # ifdef S390 long v = mask[0]; mask[0] = mask[1]; mask[1] = v; # endif tprintsigmask_addr("", mask); } tprints("}"); } #elif defined I386 || defined X86_64 || defined X32 if (entering(tcp)) { # ifndef I386 if (current_personality != 1) { const unsigned long addr = (unsigned long) *x86_64_rsp_ptr + offsetof(struct ucontext, uc_sigmask); tprints("{mask="); print_sigset_addr_len(tcp, addr, NSIG / 8); tprints("}"); return 0; } # endif /* * On i386, sigcontext is followed on stack by struct fpstate * and after it an additional u32 extramask which holds * upper half of the mask. */ struct { uint32_t struct_sigcontext_padding1[20]; uint32_t oldmask; uint32_t struct_sigcontext_padding2; uint32_t struct_fpstate_padding[156]; uint32_t extramask; } frame; tprints("{mask="); if (umove(tcp, *i386_esp_ptr, &frame) < 0) { tprintf("%#lx", (unsigned long) *i386_esp_ptr); } else { uint32_t mask[2] = { frame.oldmask, frame.extramask }; tprintsigmask_addr("", mask); } tprints("}"); } #elif defined(IA64) if (entering(tcp)) { /* offsetof(struct sigframe, sc) */ # define OFFSETOF_STRUCT_SIGFRAME_SC 0xA0 const long addr = *ia64_frame_ptr + 16 + OFFSETOF_STRUCT_SIGFRAME_SC + offsetof(struct sigcontext, sc_mask); tprints("{mask="); print_sigset_addr_len(tcp, addr, NSIG / 8); tprints("}"); } #elif defined(POWERPC) if (entering(tcp)) { long esp = ppc_regs.gpr[1]; struct sigcontext sc; /* Skip dummy stack frame. */ #ifdef POWERPC64 if (current_personality == 0) esp += 128; else #endif esp += 64; tprints("{mask="); if (umove(tcp, esp, &sc) < 0) { tprintf("%#lx", esp); } else { unsigned long mask[NSIG / 8 / sizeof(long)]; #ifdef POWERPC64 mask[0] = sc.oldmask | (sc._unused[3] << 32); #else mask[0] = sc.oldmask; mask[1] = sc._unused[3]; #endif tprintsigmask_addr("", mask); } tprints("}"); } #elif defined(M68K) if (entering(tcp)) { long addr; if (upeek(tcp->pid, 4*PT_USP, &addr) < 0) return 0; /* Fetch pointer to struct sigcontext. */ if (umove(tcp, addr + 2 * sizeof(int), &addr) < 0) return 0; unsigned long mask[NSIG / 8 / sizeof(long)]; /* Fetch first word of signal mask. */ if (umove(tcp, addr, &mask[0]) < 0) return 0; /* Fetch remaining words of signal mask, located immediately before. */ addr -= sizeof(mask) - sizeof(long); if (umoven(tcp, addr, sizeof(mask) - sizeof(long), (char *) &mask[1]) < 0) return 0; tprints("{mask="); tprintsigmask_addr("", mask); tprints("}"); } #elif defined(ALPHA) if (entering(tcp)) { long addr; if (upeek(tcp->pid, REG_FP, &addr) < 0) return 0; addr += offsetof(struct sigcontext, sc_mask); tprints("{mask="); print_sigset_addr_len(tcp, addr, NSIG / 8); tprints("}"); } #elif defined(SPARC) || defined(SPARC64) if (entering(tcp)) { long fp = sparc_regs.u_regs[U_REG_FP] + sizeof(struct sparc_stackf); struct { struct pt_regs si_regs; int si_mask; void *fpu_save; long insns[2] __attribute__ ((aligned (8))); unsigned int extramask[NSIG / 8 / sizeof(int) - 1]; } frame; tprints("{mask="); if (umove(tcp, fp, &frame) < 0) { tprintf("%#lx", fp); } else { unsigned int mask[NSIG / 8 / sizeof(int)]; mask[0] = frame.si_mask; memcpy(mask + 1, frame.extramask, sizeof(frame.extramask)); tprintsigmask_addr("", mask); } tprints("}"); } #elif defined MIPS if (entering(tcp)) { # if defined LINUX_MIPSO32 /* * offsetof(struct sigframe, sf_mask) == * sizeof(sf_ass) + sizeof(sf_pad) + sizeof(struct sigcontext) */ const long addr = mips_REG_SP + 6 * 4 + sizeof(struct sigcontext); # else /* * This decodes rt_sigreturn. * The 64-bit ABIs do not have sigreturn. * * offsetof(struct rt_sigframe, rs_uc) == * sizeof(sf_ass) + sizeof(sf_pad) + sizeof(struct siginfo) */ const long addr = mips_REG_SP + 6 * 4 + 128 + offsetof(struct ucontext, uc_sigmask); # endif tprints("{mask="); print_sigset_addr_len(tcp, addr, NSIG / 8); tprints("}"); } #elif defined(CRISV10) || defined(CRISV32) if (entering(tcp)) { long regs[PT_MAX+1]; if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long)regs) < 0) { perror_msg("sigreturn: PTRACE_GETREGS"); return 0; } const long addr = regs[PT_USP] + offsetof(struct sigcontext, oldmask); tprints("{mask="); print_sigset_addr_len(tcp, addr, NSIG / 8); tprints("}"); } #elif defined(TILE) if (entering(tcp)) { /* offset of ucontext in the kernel's sigframe structure */ # define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(siginfo_t) const long addr = tile_regs.sp + SIGFRAME_UC_OFFSET + offsetof(struct ucontext, uc_sigmask); tprints("{mask="); print_sigset_addr_len(tcp, addr, NSIG / 8); tprints("}"); } #elif defined(MICROBLAZE) /* TODO: Verify that this is correct... */ if (entering(tcp)) { long addr; /* Read r1, the stack pointer. */ if (upeek(tcp->pid, 1 * 4, &addr) < 0) return 0; addr += offsetof(struct sigcontext, oldmask); tprints("{mask="); print_sigset_addr_len(tcp, addr, NSIG / 8); tprints("}"); } #else # warning sigreturn/rt_sigreturn signal mask decoding is not implemented for this architecture #endif return 0; }