static void arch_sigreturn(struct tcb *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; if (umove(tcp, esp, &sc) < 0) { tprintf("{mask=%#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=", mask); tprints("}"); } }
static void decode_old_sigaction(struct tcb *tcp, long addr) { struct old_sigaction sa; #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 if (current_wordsize != sizeof(sa.__sa_handler) && current_wordsize == 4) { struct old_sigaction32 sa32; if (umove_or_printaddr(tcp, addr, &sa32)) return; memset(&sa, 0, sizeof(sa)); sa.__sa_handler = (void*)(uintptr_t)sa32.__sa_handler; sa.sa_flags = sa32.sa_flags; #if HAVE_SA_RESTORER && defined SA_RESTORER sa.sa_restorer = (void*)(uintptr_t)sa32.sa_restorer; #endif sa.sa_mask = sa32.sa_mask; } else #endif if (umove_or_printaddr(tcp, addr, &sa)) return; /* Architectures using function pointers, like * hppa, may need to manipulate the function pointer * to compute the result of a comparison. However, * the __sa_handler function pointer exists only in * the address space of the traced process, and can't * be manipulated by strace. In order to prevent the * compiler from generating code to manipulate * __sa_handler we cast the function pointers to long. */ tprints("{"); if ((long)sa.__sa_handler == (long)SIG_ERR) tprints("SIG_ERR"); else if ((long)sa.__sa_handler == (long)SIG_DFL) tprints("SIG_DFL"); else if ((long)sa.__sa_handler == (long)SIG_IGN) tprints("SIG_IGN"); else printaddr((long) sa.__sa_handler); tprints(", "); #ifdef MIPS tprintsigmask_addr("", sa.sa_mask); #else tprintsigmask_val("", sa.sa_mask); #endif tprints(", "); printflags(sigact_flags, sa.sa_flags, "SA_???"); #if HAVE_SA_RESTORER && defined SA_RESTORER if (sa.sa_flags & SA_RESTORER) tprintf(", %p", sa.sa_restorer); #endif tprints("}"); }
static void arch_sigreturn(struct tcb *tcp) { long fp = sparc_regs.u_regs[U_REG_FP] + SIZEOF_STRUCT_SPARC_STACKF + SIZEOF_STRUCT_PT_REGS; struct { unsigned int mask; char fpu_save[PERSONALITY_WORDSIZE]; char insns[PERSONALITY_WORDSIZE * 2] ATTRIBUTE_ALIGNED(8); unsigned int extramask[NSIG / 8 / sizeof(int) - 1]; } frame; if (umove(tcp, fp, &frame) < 0) { tprintf("{mask=%#lx}", fp); } else { unsigned int mask[NSIG / 8 / sizeof(int)]; mask[0] = frame.mask; memcpy(mask + 1, frame.extramask, sizeof(frame.extramask)); tprintsigmask_addr("{mask=", mask); tprints("}"); } }
int sys_sigreturn(struct tcb *tcp) { #if defined(ARM) if (entering(tcp)) { struct arm_sigcontext { unsigned long trap_no; unsigned long error_code; unsigned long oldmask; unsigned long arm_r0; unsigned long arm_r1; unsigned long arm_r2; unsigned long arm_r3; unsigned long arm_r4; unsigned long arm_r5; unsigned long arm_r6; unsigned long arm_r7; unsigned long arm_r8; unsigned long arm_r9; unsigned long arm_r10; unsigned long arm_fp; unsigned long arm_ip; unsigned long arm_sp; unsigned long arm_lr; unsigned long arm_pc; unsigned long arm_cpsr; unsigned long fault_address; }; struct arm_ucontext { unsigned long uc_flags; unsigned long uc_link; /* struct ucontext* */ /* The next three members comprise stack_t struct: */ unsigned long ss_sp; /* void* */ unsigned long ss_flags; /* int */ unsigned long ss_size; /* size_t */ struct arm_sigcontext sc; /* These two members are sigset_t: */ unsigned long uc_sigmask[2]; /* more fields follow, which we aren't interested in */ }; struct arm_ucontext uc; if (umove(tcp, arm_regs.ARM_sp, &uc) < 0) return 0; /* * Kernel fills out uc.sc.oldmask too when it sets up signal stack, * but for sigmask restore, sigreturn syscall uses uc.uc_sigmask instead. */ tprintsigmask_addr(") (mask ", uc.uc_sigmask); } #elif defined(S390) || defined(S390X) if (entering(tcp)) { long usp; struct sigcontext sc; if (upeek(tcp->pid, PT_GPR15, &usp) < 0) return 0; if (umove(tcp, usp + __SIGNAL_FRAMESIZE, &sc) < 0) return 0; tprintsigmask_addr(") (mask ", sc.oldmask); } #elif defined(I386) || defined(X86_64) # if defined(X86_64) if (current_personality == 0) /* 64-bit */ return 0; # endif if (entering(tcp)) { struct i386_sigcontext_struct { uint16_t gs, __gsh; uint16_t fs, __fsh; uint16_t es, __esh; uint16_t ds, __dsh; uint32_t edi; uint32_t esi; uint32_t ebp; uint32_t esp; uint32_t ebx; uint32_t edx; uint32_t ecx; uint32_t eax; uint32_t trapno; uint32_t err; uint32_t eip; uint16_t cs, __csh; uint32_t eflags; uint32_t esp_at_signal; uint16_t ss, __ssh; uint32_t i387; uint32_t oldmask; uint32_t cr2; }; struct i386_fpstate { uint32_t cw; uint32_t sw; uint32_t tag; uint32_t ipoff; uint32_t cssel; uint32_t dataoff; uint32_t datasel; uint8_t st[8][10]; /* 8*10 bytes: FP regs */ uint16_t status; uint16_t magic; uint32_t fxsr_env[6]; uint32_t mxcsr; uint32_t reserved; uint8_t stx[8][16]; /* 8*16 bytes: FP regs, each padded to 16 bytes */ uint8_t xmm[8][16]; /* 8 XMM regs */ uint32_t padding1[44]; uint32_t padding2[12]; /* union with struct _fpx_sw_bytes */ }; struct { struct i386_sigcontext_struct sc; struct i386_fpstate fp; uint32_t extramask[1]; } signal_stack; /* On i386, sc is followed on stack by struct fpstate * and after it an additional u32 extramask[1] which holds * upper half of the mask. */ uint32_t sigmask[2]; if (umove(tcp, *i386_esp_ptr, &signal_stack) < 0) return 0; sigmask[0] = signal_stack.sc.oldmask; sigmask[1] = signal_stack.extramask[0]; tprintsigmask_addr(") (mask ", sigmask); } #elif defined(IA64) if (entering(tcp)) { struct sigcontext sc; long sp; /* offset of sigcontext in the kernel's sigframe structure: */ # define SIGFRAME_SC_OFFSET 0x90 if (upeek(tcp->pid, PT_R12, &sp) < 0) return 0; if (umove(tcp, sp + 16 + SIGFRAME_SC_OFFSET, &sc) < 0) return 0; tprintsigmask_val(") (mask ", sc.sc_mask); } #elif defined(POWERPC) if (entering(tcp)) { long esp; struct sigcontext sc; esp = ppc_regs.gpr[1]; /* Skip dummy stack frame. */ #ifdef POWERPC64 if (current_personality == 0) esp += 128; else esp += 64; #else esp += 64; #endif if (umove(tcp, esp, &sc) < 0) return 0; tprintsigmask_val(") (mask ", sc.oldmask); } #elif defined(M68K) if (entering(tcp)) { long usp; struct sigcontext sc; if (upeek(tcp->pid, 4*PT_USP, &usp) < 0) return 0; if (umove(tcp, usp, &sc) < 0) return 0; tprintsigmask_val(") (mask ", sc.sc_mask); } #elif defined(ALPHA) if (entering(tcp)) { long fp; struct sigcontext sc; if (upeek(tcp->pid, REG_FP, &fp) < 0) return 0; if (umove(tcp, fp, &sc) < 0) return 0; tprintsigmask_val(") (mask ", sc.sc_mask); } #elif defined(SPARC) || defined(SPARC64) if (entering(tcp)) { long i1; m_siginfo_t si; i1 = sparc_regs.u_regs[U_REG_O1]; if (umove(tcp, i1, &si) < 0) { perror_msg("sigreturn: umove"); return 0; } tprintsigmask_val(") (mask ", si.si_mask); } #elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64) /* This decodes rt_sigreturn. The 64-bit ABIs do not have sigreturn. */ if (entering(tcp)) { long sp; struct ucontext uc; if (upeek(tcp->pid, REG_SP, &sp) < 0) return 0; /* There are six words followed by a 128-byte siginfo. */ sp = sp + 6 * 4 + 128; if (umove(tcp, sp, &uc) < 0) return 0; tprintsigmask_val(") (mask ", uc.uc_sigmask); } #elif defined(MIPS) if (entering(tcp)) { long sp; struct pt_regs regs; m_siginfo_t si; if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) { perror_msg("sigreturn: PTRACE_GETREGS"); return 0; } sp = regs.regs[29]; if (umove(tcp, sp, &si) < 0) return 0; tprintsigmask_val(") (mask ", si.si_mask); } #elif defined(CRISV10) || defined(CRISV32) if (entering(tcp)) { struct sigcontext sc; long regs[PT_MAX+1]; if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long)regs) < 0) { perror_msg("sigreturn: PTRACE_GETREGS"); return 0; } if (umove(tcp, regs[PT_USP], &sc) < 0) return 0; tprintsigmask_val(") (mask ", sc.oldmask); } #elif defined(TILE) if (entering(tcp)) { struct ucontext uc; /* offset of ucontext in the kernel's sigframe structure */ # define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(siginfo_t) if (umove(tcp, tile_regs.sp + SIGFRAME_UC_OFFSET, &uc) < 0) return 0; tprintsigmask_val(") (mask ", uc.uc_sigmask); } #elif defined(MICROBLAZE) /* TODO: Verify that this is correct... */ if (entering(tcp)) { struct sigcontext sc; long sp; /* Read r1, the stack pointer. */ if (upeek(tcp->pid, 1 * 4, &sp) < 0) return 0; if (umove(tcp, sp, &sc) < 0) return 0; tprintsigmask_val(") (mask ", sc.oldmask); } #elif defined(XTENSA) /* Xtensa only has rt_sys_sigreturn */ #elif defined(ARC) /* ARC syscall ABI only supports rt_sys_sigreturn */ #else # warning No sys_sigreturn() for this architecture # warning (no problem, just a reminder :-) #endif return 0; }
static void decode_old_sigaction(struct tcb *tcp, long addr) { struct old_sigaction sa; int r; if (!addr) { tprints("NULL"); return; } if (!verbose(tcp) || (exiting(tcp) && syserror(tcp))) { tprintf("%#lx", addr); return; } #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 if (current_wordsize != sizeof(sa.__sa_handler) && current_wordsize == 4) { struct old_sigaction32 sa32; r = umove(tcp, addr, &sa32); if (r >= 0) { memset(&sa, 0, sizeof(sa)); sa.__sa_handler = (void*)(uintptr_t)sa32.__sa_handler; sa.sa_flags = sa32.sa_flags; sa.sa_restorer = (void*)(uintptr_t)sa32.sa_restorer; sa.sa_mask = sa32.sa_mask; } } else #endif { r = umove(tcp, addr, &sa); } if (r < 0) { tprints("{...}"); return; } /* Architectures using function pointers, like * hppa, may need to manipulate the function pointer * to compute the result of a comparison. However, * the __sa_handler function pointer exists only in * the address space of the traced process, and can't * be manipulated by strace. In order to prevent the * compiler from generating code to manipulate * __sa_handler we cast the function pointers to long. */ if ((long)sa.__sa_handler == (long)SIG_ERR) tprints("{SIG_ERR, "); else if ((long)sa.__sa_handler == (long)SIG_DFL) tprints("{SIG_DFL, "); else if ((long)sa.__sa_handler == (long)SIG_IGN) tprints("{SIG_IGN, "); else tprintf("{%#lx, ", (long) sa.__sa_handler); #ifdef MIPS tprintsigmask_addr("", sa.sa_mask); #else tprintsigmask_val("", sa.sa_mask); #endif tprints(", "); printflags(sigact_flags, sa.sa_flags, "SA_???"); #ifdef SA_RESTORER if (sa.sa_flags & SA_RESTORER) tprintf(", %p", sa.sa_restorer); #endif tprints("}"); }