]> granicus.if.org Git - strace/blob - sigreturn.c
Move get_regs error check from trace_syscall_entering to get_scno
[strace] / sigreturn.c
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
26                         current_personality == 1 ?
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                 const long addr = *s390_frame_ptr + __SIGNAL_FRAMESIZE;
40                 if (umove(tcp, addr, &mask) < 0) {
41                         tprintf("{mask=%#lx}", addr);
42                 } else {
43 # ifdef S390
44                         long v = mask[0];
45                         mask[0] = mask[1];
46                         mask[1] = v;
47 # endif
48                         tprintsigmask_addr("{mask=", mask);
49                         tprints("}");
50                 }
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;
77                 if (umove(tcp, *i386_esp_ptr, &frame) < 0) {
78                         tprintf("{mask=%#lx}", (unsigned long) *i386_esp_ptr);
79                 } else {
80                         uint32_t mask[2] = { frame.oldmask, frame.extramask };
81                         tprintsigmask_addr("{mask=", mask);
82                         tprints("}");
83                 }
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
109                 if (umove(tcp, esp, &sc) < 0) {
110                         tprintf("{mask=%#lx}", esp);
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
119                         tprintsigmask_addr("{mask=", mask);
120                         tprints("}");
121                 }
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;
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);
138                 if (umoven(tcp, addr, sizeof(mask) - sizeof(long), &mask[1]) < 0)
139                         return 0;
140                 tprintsigmask_addr("{mask=", mask);
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
164                 if (umove(tcp, fp, &frame) < 0) {
165                         tprintf("{mask=%#lx}", fp);
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));
171                         tprintsigmask_addr("{mask=", mask);
172                         tprints("}");
173                 }
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 }