blob: c253a0c5fecb727f69faf18f12b164c21bb1dfef [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)];
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}