]>
Commit | Line | Data |
---|---|---|
e9ce8d39 | 1 | /* |
224c7076 | 2 | * Copyright (c) 1999, 2007 Apple Inc. All rights reserved. |
e9ce8d39 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
734aad71 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
e9ce8d39 A |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
734aad71 A |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
e9ce8d39 A |
20 | * |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | /* | |
24 | * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved | |
25 | */ | |
26 | #import "sigcatch.h" | |
59e0d9fe | 27 | #import <sys/types.h> |
e9ce8d39 | 28 | #import <signal.h> |
224c7076 A |
29 | #import <strings.h> |
30 | #import <unistd.h> | |
5b2abdfb | 31 | #import <ucontext.h> |
3d9156a7 | 32 | #import <mach/thread_status.h> |
e9ce8d39 | 33 | |
224c7076 A |
34 | extern int __sigreturn(ucontext_t *, int); |
35 | ||
e9ce8d39 A |
36 | /* |
37 | * sigvec registers _sigtramp as the handler for any signal requiring | |
38 | * user-mode intervention. All _sigtramp does is find the real handler, | |
39 | * calls it, then sigreturn's. | |
40 | * | |
41 | * Note that the kernel saves/restores all of our register state. | |
42 | */ | |
224c7076 A |
43 | |
44 | /* On i386, i386/sys/_sigtramp.s defines this. */ | |
45 | #if defined(__DYNAMIC__) && ! defined(__i386__) | |
e9ce8d39 A |
46 | int __in_sigtramp = 0; |
47 | #endif | |
48 | ||
9385eb3d A |
49 | /* These defn should match the kernel one */ |
50 | #define UC_TRAD 1 | |
eb1cde05 | 51 | #define UC_FLAVOR 30 |
59e0d9fe | 52 | #if defined(__ppc__) || defined(__ppc64__) |
9385eb3d A |
53 | #define UC_TRAD64 20 |
54 | #define UC_TRAD64_VEC 25 | |
9385eb3d A |
55 | #define UC_FLAVOR_VEC 35 |
56 | #define UC_FLAVOR64 40 | |
57 | #define UC_FLAVOR64_VEC 45 | |
58 | #define UC_DUAL 50 | |
59 | #define UC_DUAL_VEC 55 | |
60 | ||
61 | /* The following are valid mcontext sizes */ | |
62 | #define UC_FLAVOR_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int)) | |
63 | ||
64 | #define UC_FLAVOR_VEC_SIZE ((PPC_THREAD_STATE_COUNT + PPC_EXCEPTION_STATE_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int)) | |
65 | ||
66 | #define UC_FLAVOR64_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT) * sizeof(int)) | |
67 | ||
68 | #define UC_FLAVOR64_VEC_SIZE ((PPC_THREAD_STATE64_COUNT + PPC_EXCEPTION_STATE64_COUNT + PPC_FLOAT_STATE_COUNT + PPC_VECTOR_STATE_COUNT) * sizeof(int)) | |
69 | #endif | |
70 | ||
224c7076 A |
71 | #define UC_SET_ALT_STACK 0x40000000 |
72 | #define UC_RESET_ALT_STACK 0x80000000 | |
73 | ||
74 | #if defined(__ppc__) | |
9385eb3d A |
75 | /* This routine will be replaced by an assembly soon */ |
76 | static int | |
3d9156a7 | 77 | restore64_state(mcontext_t mctx, mcontext64_t mctx64, int sigstyle) |
9385eb3d A |
78 | { |
79 | if (mctx->ss.srr0 != (unsigned int)mctx64->ss.srr0) | |
80 | return(0); | |
81 | if (mctx->ss.srr1 != (unsigned int)mctx64->ss.srr1) | |
82 | return(0); | |
83 | if (mctx->ss.r0 != (unsigned int)mctx64->ss.r0) | |
84 | return(0); | |
224c7076 | 85 | if (mctx->ss.r1 != (unsigned int)mctx64->ss.r1) |
9385eb3d | 86 | return(0); |
224c7076 | 87 | if (mctx->ss.r2 != (unsigned int)mctx64->ss.r2) |
9385eb3d | 88 | return(0); |
224c7076 | 89 | if (mctx->ss.r3 != (unsigned int)mctx64->ss.r3) |
9385eb3d | 90 | return(0); |
224c7076 | 91 | if (mctx->ss.r4 != (unsigned int)mctx64->ss.r4) |
9385eb3d | 92 | return(0); |
224c7076 | 93 | if (mctx->ss.r5 != (unsigned int)mctx64->ss.r5) |
9385eb3d | 94 | return(0); |
224c7076 | 95 | if (mctx->ss.r6 != (unsigned int)mctx64->ss.r6) |
9385eb3d | 96 | return(0); |
224c7076 | 97 | if (mctx->ss.r7 != (unsigned int)mctx64->ss.r7) |
9385eb3d | 98 | return(0); |
224c7076 | 99 | if (mctx->ss.r8 != (unsigned int)mctx64->ss.r8) |
9385eb3d | 100 | return(0); |
224c7076 | 101 | if (mctx->ss.r9 != (unsigned int)mctx64->ss.r9) |
9385eb3d | 102 | return(0); |
224c7076 | 103 | if (mctx->ss.r10 != (unsigned int)mctx64->ss.r10) |
9385eb3d | 104 | return(0); |
224c7076 | 105 | if (mctx->ss.r11 != (unsigned int)mctx64->ss.r11) |
9385eb3d | 106 | return(0); |
224c7076 | 107 | if (mctx->ss.r12 != (unsigned int)mctx64->ss.r12) |
9385eb3d | 108 | return(0); |
224c7076 | 109 | if (mctx->ss.r13 != (unsigned int)mctx64->ss.r13) |
9385eb3d | 110 | return(0); |
224c7076 | 111 | if (mctx->ss.r14 != (unsigned int)mctx64->ss.r14) |
9385eb3d | 112 | return(0); |
224c7076 | 113 | if (mctx->ss.r15 != (unsigned int)mctx64->ss.r15) |
9385eb3d | 114 | return(0); |
224c7076 | 115 | if (mctx->ss.r16 != (unsigned int)mctx64->ss.r16) |
9385eb3d | 116 | return(0); |
224c7076 | 117 | if (mctx->ss.r17 != (unsigned int)mctx64->ss.r17) |
9385eb3d | 118 | return(0); |
224c7076 | 119 | if (mctx->ss.r18 != (unsigned int)mctx64->ss.r18) |
9385eb3d | 120 | return(0); |
224c7076 | 121 | if (mctx->ss.r19 != (unsigned int)mctx64->ss.r19) |
9385eb3d | 122 | return(0); |
224c7076 | 123 | if (mctx->ss.r20 != (unsigned int)mctx64->ss.r20) |
9385eb3d | 124 | return(0); |
224c7076 | 125 | if (mctx->ss.r21 != (unsigned int)mctx64->ss.r21) |
9385eb3d A |
126 | return(0); |
127 | if (mctx->ss.r22 != (unsigned int)mctx64->ss.r22) | |
128 | return(0); | |
129 | if (mctx->ss.r23 != (unsigned int)mctx64->ss.r23) | |
130 | return(0); | |
131 | if (mctx->ss.r24 != (unsigned int)mctx64->ss.r24) | |
132 | return(0); | |
133 | if (mctx->ss.r25 != (unsigned int)mctx64->ss.r25) | |
134 | return(0); | |
135 | if (mctx->ss.r26 != (unsigned int)mctx64->ss.r26) | |
136 | return(0); | |
137 | if (mctx->ss.r27 != (unsigned int)mctx64->ss.r27) | |
138 | return(0); | |
139 | if (mctx->ss.r28 != (unsigned int)mctx64->ss.r28) | |
140 | return(0); | |
141 | if (mctx->ss.r29 != (unsigned int)mctx64->ss.r29) | |
142 | return(0); | |
143 | if (mctx->ss.r30 != (unsigned int)mctx64->ss.r30) | |
144 | return(0); | |
145 | if (mctx->ss.r31 != (unsigned int)mctx64->ss.r31) | |
146 | return(0); | |
147 | ||
148 | if (mctx->ss.cr != mctx64->ss.cr) | |
149 | return(0); | |
150 | if (mctx->ss.xer != (unsigned int)mctx64->ss.xer) | |
151 | return(0); | |
152 | if (mctx->ss.lr != (unsigned int)mctx64->ss.lr) | |
153 | return(0); | |
154 | if (mctx->ss.ctr != (unsigned int)mctx64->ss.ctr) | |
155 | return(0); | |
156 | ||
224c7076 | 157 | if (bcmp(&mctx->fs, &mctx64->fs, (PPC_FLOAT_STATE_COUNT * sizeof(int)))) |
3d9156a7 A |
158 | return(0); |
159 | if ((sigstyle == UC_DUAL_VEC) && bcmp(&mctx->vs, &mctx64->vs, (PPC_VECTOR_STATE_COUNT * sizeof(int)))) | |
160 | return(0); | |
161 | ||
9385eb3d A |
162 | return(1); |
163 | ||
164 | } | |
165 | ||
224c7076 A |
166 | /* This routine is called from ppc/sys/_sigtramp.s on return from |
167 | sa_handler. */ | |
9385eb3d | 168 | |
e9ce8d39 | 169 | void |
224c7076 A |
170 | __finish_sigtramp( |
171 | ucontext_t *uctx, | |
172 | int sigstyle | |
e9ce8d39 | 173 | ) { |
f74c7596 | 174 | int ctxstyle = UC_FLAVOR; |
9385eb3d A |
175 | mcontext_t mctx; |
176 | mcontext64_t mctx64; | |
9385eb3d | 177 | |
9385eb3d A |
178 | if ((sigstyle == UC_DUAL) || (sigstyle == UC_DUAL_VEC)) { |
179 | mctx = uctx->uc_mcontext; | |
180 | mctx64 = (mcontext64_t)((char *)(uctx->uc_mcontext) + sizeof(struct mcontext)); | |
181 | /* restore 64bit state ? */ | |
3d9156a7 | 182 | if (restore64_state(mctx, mctx64, sigstyle)) { |
9385eb3d A |
183 | uctx->uc_mcontext = (void *)mctx64; |
184 | if (sigstyle == UC_DUAL) { | |
185 | uctx->uc_mcsize = UC_FLAVOR64_SIZE; | |
186 | ctxstyle = UC_FLAVOR64; | |
187 | } else { | |
188 | uctx->uc_mcsize = UC_FLAVOR64_VEC_SIZE; | |
189 | ctxstyle = UC_FLAVOR64_VEC; | |
190 | } | |
191 | } else { | |
192 | if (sigstyle == UC_DUAL) | |
193 | ctxstyle = UC_FLAVOR; | |
194 | else | |
195 | ctxstyle = UC_FLAVOR_VEC; | |
196 | } | |
197 | } else | |
198 | ctxstyle = sigstyle; | |
224c7076 A |
199 | |
200 | #if defined(__DYNAMIC__) | |
201 | __in_sigtramp--; | |
202 | #endif | |
203 | ||
204 | __sigreturn (uctx, ctxstyle); | |
205 | } | |
206 | ||
207 | #endif /* ppc */ | |
208 | ||
209 | /* | |
210 | * Reset the kernel's idea of the use of an alternate stack; this is used by | |
211 | * both longjmp() and siglongjmp(). Nothing other than this reset is needed, | |
212 | * since restoring the registers and other operations that would normally be | |
213 | * done by sigreturn() are handled in user space, so we do not pass a user | |
214 | * context (in PPC, a user context is not the same as a jmpbuf mcontext, due | |
215 | * to having more than one set of registers, etc., for the various 32/64 etc. | |
216 | * contexts).. | |
217 | */ | |
218 | void | |
219 | _sigunaltstack(int set) | |
220 | { | |
221 | /* sigreturn(uctx, ctxstyle); */ | |
222 | /* syscall (SYS_SIGRETURN, uctx, ctxstyle); */ | |
223 | __sigreturn (NULL, (set == SS_ONSTACK) ? UC_SET_ALT_STACK : UC_RESET_ALT_STACK); | |
224 | } | |
225 | ||
226 | /* On these architectures, _sigtramp is implemented in assembly to | |
227 | ensure it matches its DWARF unwind information. */ | |
228 | #if ! defined (__ppc__) && ! defined (__ppc64__) && ! defined (__i386__) \ | |
229 | && ! defined (__x86_64__) | |
230 | ||
231 | void | |
232 | _sigtramp( | |
233 | union __sigaction_u __sigaction_u, | |
234 | int sigstyle, | |
235 | int sig, | |
236 | siginfo_t *sinfo, | |
237 | ucontext_t *uctx | |
238 | ) { | |
239 | int ctxstyle = UC_FLAVOR; | |
240 | ||
241 | #if defined(__DYNAMIC__) | |
242 | __in_sigtramp++; | |
243 | #endif | |
244 | ||
245 | if (sigstyle == UC_TRAD) | |
246 | sa_handler(sig); | |
247 | else { | |
248 | sa_sigaction(sig, sinfo, uctx); | |
249 | } | |
9385eb3d | 250 | |
e9ce8d39 A |
251 | #if defined(__DYNAMIC__) |
252 | __in_sigtramp--; | |
253 | #endif | |
9385eb3d A |
254 | /* sigreturn(uctx, ctxstyle); */ |
255 | /* syscall (SYS_SIGRETURN, uctx, ctxstyle); */ | |
224c7076 | 256 | __sigreturn (uctx, ctxstyle); |
e9ce8d39 | 257 | } |
9385eb3d | 258 | |
224c7076 | 259 | #endif /* not ppc nor ppc64 nor i386 nor x86_64 */ |