From: Dmitry V. Levin Date: Fri, 6 Mar 2015 01:47:18 +0000 (+0000) Subject: Move sigreturn/rt_sigreturn parser to a separate file X-Git-Tag: v4.10~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=74219ea36f86d934abfb962964047f05e611baba;p=strace Move sigreturn/rt_sigreturn parser to a separate file * sigreturn.c: New file. * Makefile.am (strace_SOURCES): Add it. * defs.h (sprintsigmask_n): New prototype. (tprintsigmask_addr): New macro. * signal.c (sprintsigmask_n): Make global. (tprintsigmask_addr): Remove. (sys_sigreturn): Move to sigreturn.c. --- diff --git a/Makefile.am b/Makefile.am index 589e61b4..2030f9b4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -93,6 +93,7 @@ strace_SOURCES = \ scsi.c \ seccomp.c \ signal.c \ + sigreturn.c \ sock.c \ socketutils.c \ sram_alloc.c \ diff --git a/defs.h b/defs.h index adbc0062..dad4fe8b 100644 --- a/defs.h +++ b/defs.h @@ -501,6 +501,9 @@ extern void printrusage32(struct tcb *, long); #endif extern void printuid(const char *, const unsigned int); extern void print_sigset_addr_len(struct tcb *, long, long); +extern const char *sprintsigmask_n(const char *, const void *, unsigned int); +#define tprintsigmask_addr(prefix, mask) \ + tprints(sprintsigmask_n((prefix), (mask), sizeof(mask))) extern void printsignal(int); extern void tprint_iov(struct tcb *, unsigned long, unsigned long, int decode_iov); extern void tprint_iov_upto(struct tcb *, unsigned long, unsigned long, int decode_iov, unsigned long); diff --git a/signal.c b/signal.c index 7a915dad..710fb19b 100644 --- a/signal.c +++ b/signal.c @@ -32,41 +32,12 @@ */ #include "defs.h" -#include - -#include "regs.h" -#include "ptrace.h" - -#if defined(SPARC) || defined(SPARC64) || defined(MIPS) -typedef struct { - struct pt_regs si_regs; - int si_mask; -} m_siginfo_t; -#elif defined HAVE_ASM_SIGCONTEXT_H -# if !defined(IA64) && !defined(X86_64) && !defined(X32) -# include -# endif -#else /* !HAVE_ASM_SIGCONTEXT_H */ -# if defined M68K && !defined HAVE_STRUCT_SIGCONTEXT -struct sigcontext { - unsigned long sc_mask; - unsigned long sc_usp; - unsigned long sc_d0; - unsigned long sc_d1; - unsigned long sc_a0; - unsigned long sc_a1; - unsigned short sc_sr; - unsigned long sc_pc; - unsigned short sc_formatvec; -}; -# endif /* M68K */ -#endif /* !HAVE_ASM_SIGCONTEXT_H */ #ifndef NSIG -# warning: NSIG is not defined, using 32 +# warning NSIG is not defined, using 32 # define NSIG 32 #elif NSIG < 32 -# error: NSIG < 32 +# error NSIG < 32 #endif /* The libc headers do not define this constant since it should only be @@ -181,7 +152,7 @@ popcount32(const uint32_t *a, unsigned int size) return count; } -static const char * +const char * sprintsigmask_n(const char *prefix, const void *sig_mask, unsigned int bytes) { /* @@ -239,9 +210,6 @@ sprintsigmask_n(const char *prefix, const void *sig_mask, unsigned int bytes) return outstr; } -#define tprintsigmask_addr(prefix, mask) \ - tprints(sprintsigmask_n((prefix), (mask), sizeof(mask))) - #define sprintsigmask_val(prefix, mask) \ sprintsigmask_n((prefix), &(mask), sizeof(mask)) @@ -695,223 +663,6 @@ sys_signal(struct tcb *tcp) #endif /* HAVE_SIGACTION */ -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 == 0 ? - (*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_val("", mask); - } - tprints("}"); - } -#elif defined(M68K) - if (entering(tcp)) { - long addr; - if (upeek(tcp->pid, 4*PT_USP, &addr) < 0) - return 0; - addr += offsetof(struct sigcontext, sc_mask); - tprints("{mask="); - print_sigset_addr_len(tcp, addr, NSIG / 8); - 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 { - m_siginfo_t si; - 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.si_mask; - memcpy(mask + 1, frame.extramask, sizeof(frame.extramask)); - tprintsigmask_val("", 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; -} - int sys_siggetmask(struct tcb *tcp) { diff --git a/sigreturn.c b/sigreturn.c new file mode 100644 index 00000000..648bd0a4 --- /dev/null +++ b/sigreturn.c @@ -0,0 +1,231 @@ +#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 == 0 ? + (*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; + tprints("{mask="); + print_sigset_addr_len(tcp, addr, NSIG / 8); + 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; +}