Dmitry V. Levin | 74219ea | 2015-03-06 01:47:18 +0000 | [diff] [blame] | 1 | #include "defs.h" |
| 2 | #include "regs.h" |
| 3 | #include "ptrace.h" |
| 4 | |
| 5 | #if defined HAVE_ASM_SIGCONTEXT_H && !defined HAVE_STRUCT_SIGCONTEXT |
| 6 | # include <asm/sigcontext.h> |
| 7 | #endif |
| 8 | |
| 9 | #ifndef NSIG |
| 10 | # warning NSIG is not defined, using 32 |
| 11 | # define NSIG 32 |
| 12 | #elif NSIG < 32 |
| 13 | # error NSIG < 32 |
| 14 | #endif |
| 15 | |
| 16 | int |
| 17 | sys_sigreturn(struct tcb *tcp) |
| 18 | { |
| 19 | #if defined AARCH64 || defined ARM |
| 20 | if (entering(tcp)) { |
| 21 | # define SIZEOF_STRUCT_SIGINFO 128 |
| 22 | # define SIZEOF_STRUCT_SIGCONTEXT (21 * 4) |
| 23 | # define OFFSETOF_STRUCT_UCONTEXT_UC_SIGMASK (5 * 4 + SIZEOF_STRUCT_SIGCONTEXT) |
| 24 | const long addr = |
| 25 | # ifdef AARCH64 |
Dmitry V. Levin | d76d306 | 2015-03-11 14:32:25 +0000 | [diff] [blame] | 26 | current_personality == 1 ? |
Dmitry V. Levin | 74219ea | 2015-03-06 01:47:18 +0000 | [diff] [blame] | 27 | (*aarch64_sp_ptr + SIZEOF_STRUCT_SIGINFO + |
| 28 | offsetof(struct ucontext, uc_sigmask)) : |
| 29 | # endif |
| 30 | (*arm_sp_ptr + |
| 31 | OFFSETOF_STRUCT_UCONTEXT_UC_SIGMASK); |
| 32 | tprints("{mask="); |
| 33 | print_sigset_addr_len(tcp, addr, NSIG / 8); |
| 34 | tprints("}"); |
| 35 | } |
| 36 | #elif defined(S390) || defined(S390X) |
| 37 | if (entering(tcp)) { |
| 38 | long mask[NSIG / 8 / sizeof(long)]; |
| 39 | tprints("{mask="); |
| 40 | const long addr = *s390_frame_ptr + __SIGNAL_FRAMESIZE; |
| 41 | if (umove(tcp, addr, &mask) < 0) { |
| 42 | tprintf("%#lx", addr); |
| 43 | } else { |
| 44 | # ifdef S390 |
| 45 | long v = mask[0]; |
| 46 | mask[0] = mask[1]; |
| 47 | mask[1] = v; |
| 48 | # endif |
| 49 | tprintsigmask_addr("", mask); |
| 50 | } |
| 51 | tprints("}"); |
| 52 | } |
| 53 | #elif defined I386 || defined X86_64 || defined X32 |
| 54 | if (entering(tcp)) { |
| 55 | # ifndef I386 |
| 56 | if (current_personality != 1) { |
| 57 | const unsigned long addr = |
| 58 | (unsigned long) *x86_64_rsp_ptr + |
| 59 | offsetof(struct ucontext, uc_sigmask); |
| 60 | tprints("{mask="); |
| 61 | print_sigset_addr_len(tcp, addr, NSIG / 8); |
| 62 | tprints("}"); |
| 63 | return 0; |
| 64 | } |
| 65 | # endif |
| 66 | /* |
| 67 | * On i386, sigcontext is followed on stack by struct fpstate |
| 68 | * and after it an additional u32 extramask which holds |
| 69 | * upper half of the mask. |
| 70 | */ |
| 71 | struct { |
| 72 | uint32_t struct_sigcontext_padding1[20]; |
| 73 | uint32_t oldmask; |
| 74 | uint32_t struct_sigcontext_padding2; |
| 75 | uint32_t struct_fpstate_padding[156]; |
| 76 | uint32_t extramask; |
| 77 | } frame; |
| 78 | tprints("{mask="); |
| 79 | if (umove(tcp, *i386_esp_ptr, &frame) < 0) { |
| 80 | tprintf("%#lx", (unsigned long) *i386_esp_ptr); |
| 81 | } else { |
| 82 | uint32_t mask[2] = { frame.oldmask, frame.extramask }; |
| 83 | tprintsigmask_addr("", mask); |
| 84 | } |
| 85 | tprints("}"); |
| 86 | } |
| 87 | #elif defined(IA64) |
| 88 | if (entering(tcp)) { |
| 89 | /* offsetof(struct sigframe, sc) */ |
| 90 | # define OFFSETOF_STRUCT_SIGFRAME_SC 0xA0 |
| 91 | const long addr = *ia64_frame_ptr + 16 + |
| 92 | OFFSETOF_STRUCT_SIGFRAME_SC + |
| 93 | offsetof(struct sigcontext, sc_mask); |
| 94 | tprints("{mask="); |
| 95 | print_sigset_addr_len(tcp, addr, NSIG / 8); |
| 96 | tprints("}"); |
| 97 | } |
| 98 | #elif defined(POWERPC) |
| 99 | if (entering(tcp)) { |
| 100 | long esp = ppc_regs.gpr[1]; |
| 101 | struct sigcontext sc; |
| 102 | |
| 103 | /* Skip dummy stack frame. */ |
| 104 | #ifdef POWERPC64 |
| 105 | if (current_personality == 0) |
| 106 | esp += 128; |
| 107 | else |
| 108 | #endif |
| 109 | esp += 64; |
| 110 | |
| 111 | tprints("{mask="); |
| 112 | if (umove(tcp, esp, &sc) < 0) { |
| 113 | tprintf("%#lx", esp); |
| 114 | } else { |
| 115 | unsigned long mask[NSIG / 8 / sizeof(long)]; |
| 116 | #ifdef POWERPC64 |
| 117 | mask[0] = sc.oldmask | (sc._unused[3] << 32); |
| 118 | #else |
| 119 | mask[0] = sc.oldmask; |
| 120 | mask[1] = sc._unused[3]; |
| 121 | #endif |
| 122 | tprintsigmask_addr("", mask); |
| 123 | } |
| 124 | tprints("}"); |
| 125 | } |
| 126 | #elif defined(M68K) |
| 127 | if (entering(tcp)) { |
| 128 | long addr; |
| 129 | if (upeek(tcp->pid, 4*PT_USP, &addr) < 0) |
| 130 | return 0; |
| 131 | tprints("{mask="); |
| 132 | print_sigset_addr_len(tcp, addr, NSIG / 8); |
| 133 | tprints("}"); |
| 134 | } |
| 135 | #elif defined(ALPHA) |
| 136 | if (entering(tcp)) { |
| 137 | long addr; |
| 138 | if (upeek(tcp->pid, REG_FP, &addr) < 0) |
| 139 | return 0; |
| 140 | addr += offsetof(struct sigcontext, sc_mask); |
| 141 | tprints("{mask="); |
| 142 | print_sigset_addr_len(tcp, addr, NSIG / 8); |
| 143 | tprints("}"); |
| 144 | } |
| 145 | #elif defined(SPARC) || defined(SPARC64) |
| 146 | if (entering(tcp)) { |
| 147 | long fp = sparc_regs.u_regs[U_REG_FP] + sizeof(struct sparc_stackf); |
| 148 | struct { |
| 149 | struct pt_regs si_regs; |
| 150 | int si_mask; |
| 151 | void *fpu_save; |
| 152 | long insns[2] __attribute__ ((aligned (8))); |
| 153 | unsigned int extramask[NSIG / 8 / sizeof(int) - 1]; |
| 154 | } frame; |
| 155 | |
| 156 | tprints("{mask="); |
| 157 | if (umove(tcp, fp, &frame) < 0) { |
| 158 | tprintf("%#lx", fp); |
| 159 | } else { |
| 160 | unsigned int mask[NSIG / 8 / sizeof(int)]; |
| 161 | |
| 162 | mask[0] = frame.si_mask; |
| 163 | memcpy(mask + 1, frame.extramask, sizeof(frame.extramask)); |
| 164 | tprintsigmask_addr("", mask); |
| 165 | } |
| 166 | tprints("}"); |
| 167 | } |
| 168 | #elif defined MIPS |
| 169 | if (entering(tcp)) { |
| 170 | # if defined LINUX_MIPSO32 |
| 171 | /* |
| 172 | * offsetof(struct sigframe, sf_mask) == |
| 173 | * sizeof(sf_ass) + sizeof(sf_pad) + sizeof(struct sigcontext) |
| 174 | */ |
| 175 | const long addr = mips_REG_SP + 6 * 4 + |
| 176 | sizeof(struct sigcontext); |
| 177 | # else |
| 178 | /* |
| 179 | * This decodes rt_sigreturn. |
| 180 | * The 64-bit ABIs do not have sigreturn. |
| 181 | * |
| 182 | * offsetof(struct rt_sigframe, rs_uc) == |
| 183 | * sizeof(sf_ass) + sizeof(sf_pad) + sizeof(struct siginfo) |
| 184 | */ |
| 185 | const long addr = mips_REG_SP + 6 * 4 + 128 + |
| 186 | offsetof(struct ucontext, uc_sigmask); |
| 187 | # endif |
| 188 | tprints("{mask="); |
| 189 | print_sigset_addr_len(tcp, addr, NSIG / 8); |
| 190 | tprints("}"); |
| 191 | } |
| 192 | #elif defined(CRISV10) || defined(CRISV32) |
| 193 | if (entering(tcp)) { |
| 194 | long regs[PT_MAX+1]; |
| 195 | if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long)regs) < 0) { |
| 196 | perror_msg("sigreturn: PTRACE_GETREGS"); |
| 197 | return 0; |
| 198 | } |
| 199 | const long addr = regs[PT_USP] + |
| 200 | offsetof(struct sigcontext, oldmask); |
| 201 | tprints("{mask="); |
| 202 | print_sigset_addr_len(tcp, addr, NSIG / 8); |
| 203 | tprints("}"); |
| 204 | } |
| 205 | #elif defined(TILE) |
| 206 | if (entering(tcp)) { |
| 207 | /* offset of ucontext in the kernel's sigframe structure */ |
| 208 | # define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(siginfo_t) |
| 209 | const long addr = tile_regs.sp + SIGFRAME_UC_OFFSET + |
| 210 | offsetof(struct ucontext, uc_sigmask); |
| 211 | tprints("{mask="); |
| 212 | print_sigset_addr_len(tcp, addr, NSIG / 8); |
| 213 | tprints("}"); |
| 214 | } |
| 215 | #elif defined(MICROBLAZE) |
| 216 | /* TODO: Verify that this is correct... */ |
| 217 | if (entering(tcp)) { |
| 218 | long addr; |
| 219 | /* Read r1, the stack pointer. */ |
| 220 | if (upeek(tcp->pid, 1 * 4, &addr) < 0) |
| 221 | return 0; |
| 222 | addr += offsetof(struct sigcontext, oldmask); |
| 223 | tprints("{mask="); |
| 224 | print_sigset_addr_len(tcp, addr, NSIG / 8); |
| 225 | tprints("}"); |
| 226 | } |
| 227 | #else |
| 228 | # warning sigreturn/rt_sigreturn signal mask decoding is not implemented for this architecture |
| 229 | #endif |
| 230 | return 0; |
| 231 | } |