blob: f32c206498ccfd72fd013e4b3d81e5c5a86079d5 [file] [log] [blame]
Dmitry V. Levin74219ea2015-03-06 01:47:18 +00001#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
16int
17sys_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. Levind76d3062015-03-11 14:32:25 +000026 current_personality == 1 ?
Dmitry V. Levin74219ea2015-03-06 01:47:18 +000027 (*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. Levin74219ea2015-03-06 01:47:18 +000039 const long addr = *s390_frame_ptr + __SIGNAL_FRAMESIZE;
40 if (umove(tcp, addr, &mask) < 0) {
Denys Vlasenko7d27c632015-03-21 20:11:53 +010041 tprintf("{mask=%#lx}", addr);
Dmitry V. Levin74219ea2015-03-06 01:47:18 +000042 } else {
43# ifdef S390
44 long v = mask[0];
45 mask[0] = mask[1];
46 mask[1] = v;
47# endif
Denys Vlasenko7d27c632015-03-21 20:11:53 +010048 tprintsigmask_addr("{mask=", mask);
49 tprints("}");
Dmitry V. Levin74219ea2015-03-06 01:47:18 +000050 }
Dmitry V. Levin74219ea2015-03-06 01:47:18 +000051 }
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. Levin74219ea2015-03-06 01:47:18 +000077 if (umove(tcp, *i386_esp_ptr, &frame) < 0) {
Denys Vlasenko7d27c632015-03-21 20:11:53 +010078 tprintf("{mask=%#lx}", (unsigned long) *i386_esp_ptr);
Dmitry V. Levin74219ea2015-03-06 01:47:18 +000079 } else {
80 uint32_t mask[2] = { frame.oldmask, frame.extramask };
Denys Vlasenko7d27c632015-03-21 20:11:53 +010081 tprintsigmask_addr("{mask=", mask);
82 tprints("}");
Dmitry V. Levin74219ea2015-03-06 01:47:18 +000083 }
Dmitry V. Levin74219ea2015-03-06 01:47:18 +000084 }
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. Levin74219ea2015-03-06 01:47:18 +0000109 if (umove(tcp, esp, &sc) < 0) {
Denys Vlasenko7d27c632015-03-21 20:11:53 +0100110 tprintf("{mask=%#lx}", esp);
Dmitry V. Levin74219ea2015-03-06 01:47:18 +0000111 } 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 Vlasenko7d27c632015-03-21 20:11:53 +0100119 tprintsigmask_addr("{mask=", mask);
120 tprints("}");
Dmitry V. Levin74219ea2015-03-06 01:47:18 +0000121 }
Dmitry V. Levin74219ea2015-03-06 01:47:18 +0000122 }
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 Schwab712f0e12015-03-11 15:08:42 +0100128 /* 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 Vlasenko7e69ed92015-03-21 19:50:53 +0100138 if (umoven(tcp, addr, sizeof(mask) - sizeof(long), &mask[1]) < 0)
Andreas Schwab712f0e12015-03-11 15:08:42 +0100139 return 0;
Denys Vlasenko7d27c632015-03-21 20:11:53 +0100140 tprintsigmask_addr("{mask=", mask);
Dmitry V. Levin74219ea2015-03-06 01:47:18 +0000141 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. Levin74219ea2015-03-06 01:47:18 +0000164 if (umove(tcp, fp, &frame) < 0) {
Denys Vlasenko7d27c632015-03-21 20:11:53 +0100165 tprintf("{mask=%#lx}", fp);
Dmitry V. Levin74219ea2015-03-06 01:47:18 +0000166 } 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 Vlasenko7d27c632015-03-21 20:11:53 +0100171 tprintsigmask_addr("{mask=", mask);
172 tprints("}");
Dmitry V. Levin74219ea2015-03-06 01:47:18 +0000173 }
Dmitry V. Levin74219ea2015-03-06 01:47:18 +0000174 }
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}