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