]> granicus.if.org Git - strace/blob - sigreturn.c
m68k: fix sigreturn decoding
[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                 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                 /* Fetch pointer to struct sigcontext.  */
132                 if (umove(tcp, addr + 2 * sizeof(int), &addr) < 0)
133                         return 0;
134                 unsigned long mask[NSIG / 8 / sizeof(long)];
135                 /* Fetch first word of signal mask.  */
136                 if (umove(tcp, addr, &mask[0]) < 0)
137                         return 0;
138                 /* Fetch remaining words of signal mask, located
139                    immediately before.  */
140                 addr -= sizeof(mask) - sizeof(long);
141                 if (umoven(tcp, addr, sizeof(mask) - sizeof(long), (char *) &mask[1]) < 0)
142                         return 0;
143                 tprints("{mask=");
144                 tprintsigmask_addr("", mask);
145                 tprints("}");
146         }
147 #elif defined(ALPHA)
148         if (entering(tcp)) {
149                 long addr;
150                 if (upeek(tcp->pid, REG_FP, &addr) < 0)
151                         return 0;
152                 addr += offsetof(struct sigcontext, sc_mask);
153                 tprints("{mask=");
154                 print_sigset_addr_len(tcp, addr, NSIG / 8);
155                 tprints("}");
156         }
157 #elif defined(SPARC) || defined(SPARC64)
158         if (entering(tcp)) {
159                 long fp = sparc_regs.u_regs[U_REG_FP] + sizeof(struct sparc_stackf);
160                 struct {
161                         struct pt_regs si_regs;
162                         int si_mask;
163                         void *fpu_save;
164                         long insns[2] __attribute__ ((aligned (8)));
165                         unsigned int extramask[NSIG / 8 / sizeof(int) - 1];
166                 } frame;
167
168                 tprints("{mask=");
169                 if (umove(tcp, fp, &frame) < 0) {
170                         tprintf("%#lx", fp);
171                 } else {
172                         unsigned int mask[NSIG / 8 / sizeof(int)];
173
174                         mask[0] = frame.si_mask;
175                         memcpy(mask + 1, frame.extramask, sizeof(frame.extramask));
176                         tprintsigmask_addr("", mask);
177                 }
178                 tprints("}");
179         }
180 #elif defined MIPS
181         if (entering(tcp)) {
182 # if defined LINUX_MIPSO32
183                 /*
184                  * offsetof(struct sigframe, sf_mask) ==
185                  * sizeof(sf_ass) + sizeof(sf_pad) + sizeof(struct sigcontext)
186                  */
187                 const long addr = mips_REG_SP + 6 * 4 +
188                                   sizeof(struct sigcontext);
189 # else
190                 /*
191                  * This decodes rt_sigreturn.
192                  * The 64-bit ABIs do not have sigreturn.
193                  *
194                  * offsetof(struct rt_sigframe, rs_uc) ==
195                  * sizeof(sf_ass) + sizeof(sf_pad) + sizeof(struct siginfo)
196                  */
197                 const long addr = mips_REG_SP + 6 * 4 + 128 +
198                                   offsetof(struct ucontext, uc_sigmask);
199 # endif
200                 tprints("{mask=");
201                 print_sigset_addr_len(tcp, addr, NSIG / 8);
202                 tprints("}");
203         }
204 #elif defined(CRISV10) || defined(CRISV32)
205         if (entering(tcp)) {
206                 long regs[PT_MAX+1];
207                 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long)regs) < 0) {
208                         perror_msg("sigreturn: PTRACE_GETREGS");
209                         return 0;
210                 }
211                 const long addr = regs[PT_USP] +
212                         offsetof(struct sigcontext, oldmask);
213                 tprints("{mask=");
214                 print_sigset_addr_len(tcp, addr, NSIG / 8);
215                 tprints("}");
216         }
217 #elif defined(TILE)
218         if (entering(tcp)) {
219                 /* offset of ucontext in the kernel's sigframe structure */
220 # define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(siginfo_t)
221                 const long addr = tile_regs.sp + SIGFRAME_UC_OFFSET +
222                                   offsetof(struct ucontext, uc_sigmask);
223                 tprints("{mask=");
224                 print_sigset_addr_len(tcp, addr, NSIG / 8);
225                 tprints("}");
226         }
227 #elif defined(MICROBLAZE)
228         /* TODO: Verify that this is correct...  */
229         if (entering(tcp)) {
230                 long addr;
231                 /* Read r1, the stack pointer.  */
232                 if (upeek(tcp->pid, 1 * 4, &addr) < 0)
233                         return 0;
234                 addr += offsetof(struct sigcontext, oldmask);
235                 tprints("{mask=");
236                 print_sigset_addr_len(tcp, addr, NSIG / 8);
237                 tprints("}");
238         }
239 #else
240 # warning sigreturn/rt_sigreturn signal mask decoding is not implemented for this architecture
241 #endif
242         return 0;
243 }