1 /*
2 * Copyright 2014, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef _SIGNAL_PORTABLE_H_
18 #define _SIGNAL_PORTABLE_H_
19
20 #if (__mips__)
21
22 #include <portability.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 struct stack_t_portable {
28 void *ss_sp;
29 int ss_flags;
30 size_t ss_size;
31 };
32
stack_t_pton(const struct stack_t_portable * ptr_p,stack_t * ptr_n)33 static inline void stack_t_pton(const struct stack_t_portable *ptr_p, stack_t *ptr_n) {
34 memset(ptr_n, '\0', sizeof(stack_t));
35 ptr_n->ss_sp = ptr_p->ss_sp;
36 ptr_n->ss_flags = ptr_p->ss_flags;
37 ptr_n->ss_size = ptr_p->ss_size;
38 }
39
stack_t_ntop(const stack_t * ptr_n,struct stack_t_portable * ptr_p)40 static inline void stack_t_ntop(const stack_t *ptr_n, struct stack_t_portable *ptr_p) {
41 memset(ptr_p, '\0', sizeof(struct stack_t_portable));
42 ptr_p->ss_sp = ptr_n->ss_sp;
43 ptr_p->ss_flags = ptr_n->ss_flags;
44 ptr_p->ss_size = ptr_n->ss_size;
45 }
46
WRAP(sigaltstack)47 int WRAP(sigaltstack)(const struct stack_t_portable *ss, struct stack_t_portable *oss) {
48 stack_t ss_n, oss_n;
49 if (ss != NULL) {
50 stack_t_pton(ss, &ss_n);
51 if (oss != NULL){
52 int ret = REAL(sigaltstack)(&ss_n, &oss_n);
53 stack_t_ntop(&oss_n, oss);
54 return ret;
55 }
56 else
57 return REAL(sigaltstack)(&ss_n, NULL);
58 }
59 else if (oss != NULL) {
60 int ret = REAL(sigaltstack)(NULL, &oss_n);
61 stack_t_ntop(&oss_n, oss);
62 return ret;
63 }
64 else
65 return REAL(sigaltstack)(NULL, NULL);
66 }
67
68 #define SIGHUP_PORTABLE 1
69 #define SIGINT_PORTABLE 2
70 #define SIGQUIT_PORTABLE 3
71 #define SIGILL_PORTABLE 4
72 #define SIGTRAP_PORTABLE 5
73 #define SIGABRT_PORTABLE 6
74 #define SIGIOT_PORTABLE 6
75 #define SIGBUS_PORTABLE 7
76 #define SIGFPE_PORTABLE 8
77 #define SIGKILL_PORTABLE 9
78 #define SIGUSR1_PORTABLE 10
79 #define SIGSEGV_PORTABLE 11
80 #define SIGUSR2_PORTABLE 12
81 #define SIGPIPE_PORTABLE 13
82 #define SIGALRM_PORTABLE 14
83 #define SIGTERM_PORTABLE 15
84 // unsupported in MIPS
85 #define SIGSTKFLT_PORTABLE 16
86 //
87 #define SIGCHLD_PORTABLE 17
88 #define SIGCONT_PORTABLE 18
89 #define SIGSTOP_PORTABLE 19
90 #define SIGTSTP_PORTABLE 20
91 #define SIGTTIN_PORTABLE 21
92 #define SIGTTOU_PORTABLE 22
93 #define SIGURG_PORTABLE 23
94 #define SIGXCPU_PORTABLE 24
95 #define SIGXFSZ_PORTABLE 25
96 #define SIGVTALRM_PORTABLE 26
97 #define SIGPROF_PORTABLE 27
98 #define SIGWINCH_PORTABLE 28
99 #define SIGIO_PORTABLE 29
100 #define SIGPOLL_PORTABLE SIGIO_PORTABLE
101 #define SIGPWR_PORTABLE 30
102 #define SIGSYS_PORTABLE 31
103 #define SIGUNUSED_PORTABLE 31
104 // unsupported in MIPS
105 #define SIGSWI_PORTABLE 32
106 //
107
signo_pton(int signum_p)108 static inline int signo_pton(int signum_p) {
109 switch(signum_p) {
110 case SIGHUP_PORTABLE: return SIGHUP;
111 case SIGINT_PORTABLE: return SIGINT;
112 case SIGQUIT_PORTABLE: return SIGQUIT;
113 case SIGILL_PORTABLE: return SIGILL;
114 case SIGTRAP_PORTABLE: return SIGTRAP;
115 case SIGABRT_PORTABLE: return SIGABRT;
116 case SIGBUS_PORTABLE: return SIGBUS;
117 case SIGFPE_PORTABLE: return SIGFPE;
118 case SIGKILL_PORTABLE: return SIGKILL;
119 case SIGUSR1_PORTABLE: return SIGUSR1;
120 case SIGSEGV_PORTABLE: return SIGSEGV;
121 case SIGUSR2_PORTABLE: return SIGUSR2;
122 case SIGPIPE_PORTABLE: return SIGPIPE;
123 case SIGALRM_PORTABLE: return SIGALRM;
124 case SIGTERM_PORTABLE: return SIGTERM;
125 case SIGCHLD_PORTABLE: return SIGCHLD;
126 case SIGCONT_PORTABLE: return SIGCONT;
127 case SIGSTOP_PORTABLE: return SIGSTOP;
128 case SIGTSTP_PORTABLE: return SIGTSTP;
129 case SIGTTIN_PORTABLE: return SIGTTIN;
130 case SIGTTOU_PORTABLE: return SIGTTOU;
131 case SIGURG_PORTABLE: return SIGURG;
132 case SIGXCPU_PORTABLE: return SIGXCPU;
133 case SIGXFSZ_PORTABLE: return SIGXFSZ;
134 case SIGVTALRM_PORTABLE: return SIGVTALRM;
135 case SIGPROF_PORTABLE: return SIGPROF;
136 case SIGWINCH_PORTABLE: return SIGWINCH;
137 case SIGIO_PORTABLE: return SIGIO;
138 case SIGPWR_PORTABLE: return SIGPWR;
139 case SIGSYS_PORTABLE: return SIGSYS;
140 default:
141 fprintf(stderr, "Unknown SIGNAL:%d\n", signum_p);
142 abort();
143 }
144 }
145
signo_ntop(int signum_n)146 static inline int signo_ntop(int signum_n) {
147 switch(signum_n) {
148 case SIGHUP: return SIGHUP_PORTABLE;
149 case SIGINT: return SIGINT_PORTABLE;
150 case SIGQUIT: return SIGQUIT_PORTABLE;
151 case SIGILL: return SIGILL_PORTABLE;
152 case SIGTRAP: return SIGTRAP_PORTABLE;
153 case SIGABRT: return SIGABRT_PORTABLE;
154 case SIGBUS: return SIGBUS_PORTABLE;
155 case SIGFPE: return SIGFPE_PORTABLE;
156 case SIGKILL: return SIGKILL_PORTABLE;
157 case SIGUSR1: return SIGUSR1_PORTABLE;
158 case SIGSEGV: return SIGSEGV_PORTABLE;
159 case SIGUSR2: return SIGUSR2_PORTABLE;
160 case SIGPIPE: return SIGPIPE_PORTABLE;
161 case SIGALRM: return SIGALRM_PORTABLE;
162 case SIGTERM: return SIGTERM_PORTABLE;
163 case SIGCHLD: return SIGCHLD_PORTABLE;
164 case SIGCONT: return SIGCONT_PORTABLE;
165 case SIGSTOP: return SIGSTOP_PORTABLE;
166 case SIGTSTP: return SIGTSTP_PORTABLE;
167 case SIGTTIN: return SIGTTIN_PORTABLE;
168 case SIGTTOU: return SIGTTOU_PORTABLE;
169 case SIGURG: return SIGURG_PORTABLE;
170 case SIGXCPU: return SIGXCPU_PORTABLE;
171 case SIGXFSZ: return SIGXFSZ_PORTABLE;
172 case SIGVTALRM: return SIGVTALRM_PORTABLE;
173 case SIGPROF: return SIGPROF_PORTABLE;
174 case SIGWINCH: return SIGWINCH_PORTABLE;
175 case SIGIO: return SIGIO_PORTABLE;
176 case SIGPWR: return SIGPWR_PORTABLE;
177 case SIGSYS: return SIGSYS_PORTABLE;
178 default:
179 fprintf(stderr, "Unknown SIGNAL:%d\n", signum_n);
180 abort();
181 }
182 }
183
184 #define SA_NOCLDSTOP_PORTABLE 0x00000001
185 #define SA_NOCLDWAIT_PORTABLE 0x00000002
186 #define SA_SIGINFO_PORTABLE 0x00000004
187 // unsupported in MIPS
188 #define SA_THIRTYTWO_PORTABLE 0x02000000
189 #define SA_RESTORER_PORTABLE 0x04000000
190 //
191 #define SA_ONSTACK_PORTABLE 0x08000000
192 #define SA_RESTART_PORTABLE 0x10000000
193 #define SA_NODEFER_PORTABLE 0x40000000
194 #define SA_RESETHAND_PORTABLE 0x80000000
195 #define SA_NOMASK_PORTABLE SA_NODEFER_PORTABLE
196 #define SA_ONESHOT_PORTABLE SA_RESETHAND_PORTABLE
197
sa_flags_pton(int sa_flags_p)198 static inline int sa_flags_pton(int sa_flags_p) {
199 int sa_flags_n = 0;
200 sa_flags_n |= (sa_flags_p & SA_NOCLDSTOP_PORTABLE) ? SA_NOCLDSTOP : 0;
201 sa_flags_n |= (sa_flags_p & SA_NOCLDWAIT_PORTABLE) ? SA_NOCLDWAIT : 0;
202 sa_flags_n |= (sa_flags_p & SA_SIGINFO_PORTABLE) ? SA_SIGINFO : 0;
203 sa_flags_n |= (sa_flags_p & SA_ONSTACK_PORTABLE) ? SA_ONSTACK : 0;
204 sa_flags_n |= (sa_flags_p & SA_RESTART_PORTABLE) ? SA_RESTART : 0;
205 sa_flags_n |= (sa_flags_p & SA_NODEFER_PORTABLE) ? SA_NODEFER : 0;
206 sa_flags_n |= (sa_flags_p & SA_RESETHAND_PORTABLE) ? SA_RESETHAND : 0;
207 return sa_flags_n;
208 }
209
sa_flags_ntop(int sa_flags_n)210 static inline int sa_flags_ntop(int sa_flags_n) {
211 int sa_flags_p = 0;
212 sa_flags_p |= (sa_flags_n & SA_NOCLDSTOP) ? SA_NOCLDSTOP_PORTABLE : 0;
213 sa_flags_p |= (sa_flags_n & SA_NOCLDWAIT) ? SA_NOCLDWAIT_PORTABLE : 0;
214 sa_flags_p |= (sa_flags_n & SA_SIGINFO) ? SA_SIGINFO_PORTABLE : 0;
215 sa_flags_p |= (sa_flags_n & SA_ONSTACK) ? SA_ONSTACK_PORTABLE : 0;
216 sa_flags_p |= (sa_flags_n & SA_RESTART) ? SA_RESTART_PORTABLE : 0;
217 sa_flags_p |= (sa_flags_n & SA_NODEFER) ? SA_NODEFER_PORTABLE : 0;
218 sa_flags_p |= (sa_flags_n & SA_RESETHAND) ? SA_RESETHAND_PORTABLE : 0;
219 return sa_flags_p;
220 }
221
222 typedef unsigned long sigset_t_portable;
223 struct sigaction_portable {
224 union {
225 __sighandler_t _sa_handler;
226 void (*_sa_sigaction)(int, struct siginfo *, void *);
227 } _u;
228 sigset_t_portable sa_mask;
229 unsigned long sa_flags;
230 void (*sa_restorer)(void); // obsolete
231 };
232
sigset_t_pton(const sigset_t_portable * ptr_p,sigset_t * ptr_n)233 static inline void sigset_t_pton(const sigset_t_portable *ptr_p, sigset_t *ptr_n) {
234 memset(ptr_n, '\0', sizeof(sigset_t));
235 ptr_n->sig[0] = *ptr_p;
236 }
237
sigset_t_ntop(const sigset_t * ptr_n,sigset_t_portable * ptr_p)238 static inline void sigset_t_ntop(const sigset_t *ptr_n, sigset_t_portable *ptr_p) {
239 memset(ptr_p, '\0', sizeof(sigset_t_portable));
240 *ptr_p = ptr_n->sig[0];
241 }
242
sigaction_pton(const struct sigaction_portable * ptr_p,struct sigaction * ptr_n)243 static inline void sigaction_pton(const struct sigaction_portable *ptr_p, struct sigaction *ptr_n) {
244 memset(ptr_n, '\0', sizeof(struct sigaction));
245 ptr_n->sa_sigaction = ptr_p->_u._sa_sigaction;
246 sigset_t_pton(&ptr_p->sa_mask, &ptr_n->sa_mask);
247 ptr_n->sa_flags = sa_flags_pton(ptr_p->sa_flags);
248 }
249
sigaction_ntop(const struct sigaction * ptr_n,struct sigaction_portable * ptr_p)250 static inline void sigaction_ntop(const struct sigaction *ptr_n, struct sigaction_portable *ptr_p) {
251 memset(ptr_p, '\0', sizeof(struct sigaction_portable));
252 ptr_p->_u._sa_sigaction = ptr_n->sa_sigaction;
253 sigset_t_ntop(&ptr_n->sa_mask, &ptr_p->sa_mask);
254 ptr_p->sa_flags = sa_flags_ntop(ptr_n->sa_flags);
255 }
256
WRAP(sigaction)257 int WRAP(sigaction)(int signum, const struct sigaction_portable *act, struct sigaction_portable *oldact) {
258 struct sigaction act_n, oldact_n;
259 int signum_n = signo_pton(signum);
260
261 if (act != NULL) {
262 sigaction_pton(act, &act_n);
263 if (oldact != NULL) {
264 int ret = REAL(sigaction)(signum_n, &act_n, &oldact_n);
265 sigaction_ntop(&oldact_n, oldact);
266 return ret;
267 }
268 else
269 return REAL(sigaction)(signum_n, &act_n, NULL);
270 }
271 else if (oldact != NULL) {
272 int ret = REAL(sigaction)(signum_n, NULL, &oldact_n);
273 sigaction_ntop(&oldact_n, oldact);
274 return ret;
275 }
276 else
277 return REAL(sigaction)(signum_n, NULL, NULL);
278 }
279
WRAP(sigaddset)280 int WRAP(sigaddset)(sigset_t_portable *set, int signum) {
281 int signum_n = signo_pton(signum);
282 sigset_t set_n;
283 sigset_t_pton(set, &set_n);
284 int ret = REAL(sigaddset)(&set_n, signum_n);
285 sigset_t_ntop(&set_n, set);
286 return ret;
287 }
288
WRAP(sigdelset)289 int WRAP(sigdelset)(sigset_t_portable *set, int signum) {
290 int signum_n = signo_pton(signum);
291 sigset_t set_n;
292 sigset_t_pton(set, &set_n);
293 int ret = REAL(sigdelset)(&set_n, signum_n);
294 sigset_t_ntop(&set_n, set);
295 return ret;
296 }
297
WRAP(sigemptyset)298 int WRAP(sigemptyset)(sigset_t_portable *set){
299 sigset_t set_n;
300 sigset_t_pton(set, &set_n);
301 int ret = REAL(sigemptyset)(&set_n);
302 sigset_t_ntop(&set_n, set);
303 return ret;
304 }
305
WRAP(sigfillset)306 int WRAP(sigfillset)(sigset_t_portable *set){
307 sigset_t set_n;
308 sigset_t_pton(set, &set_n);
309 int ret = REAL(sigfillset)(&set_n);
310 sigset_t_ntop(&set_n, set);
311 return ret;
312 }
313
WRAP(sigismember)314 int WRAP(sigismember)(const sigset_t_portable *set, int signum) {
315 int signum_n = signo_pton(signum);
316 sigset_t set_n;
317 sigset_t_pton(set, &set_n);
318 return REAL(sigismember)(&set_n, signum_n);
319 }
320
WRAP(sigpending)321 int WRAP(sigpending)(sigset_t_portable *set) {
322 sigset_t set_n;
323 sigset_t_pton(set, &set_n);
324 int ret = REAL(sigpending)(&set_n);
325 sigset_t_ntop(&set_n, set);
326 return ret;
327 }
328
329 #define SIG_BLOCK_PORTABLE 0
330 #define SIG_UNBLOCK_PORTABLE 1
331 #define SIG_SETMASK_PORTABLE 2
332
WRAP(sigprocmask)333 int WRAP(sigprocmask)(int how, const sigset_t_portable *set, sigset_t_portable *oldset) {
334 int how_n;
335 switch(how) {
336 case SIG_BLOCK_PORTABLE: how_n = SIG_BLOCK; break;
337 case SIG_UNBLOCK_PORTABLE: how_n = SIG_UNBLOCK; break;
338 case SIG_SETMASK_PORTABLE: how_n = SIG_SETMASK; break;
339 default:
340 fprintf(stderr, "Unknown sigprocmask action:%d\n", how);
341 abort();
342 }
343 sigset_t set_n, oldset_n;
344 if (set != NULL) {
345 sigset_t_pton(set, &set_n);
346 if (oldset != NULL) {
347 int ret = REAL(sigprocmask)(how_n, &set_n, &oldset_n);
348 sigset_t_ntop(&oldset_n, oldset);
349 return ret;
350 }
351 else
352 return REAL(sigprocmask)(how_n, &set_n, NULL);
353 }
354 else if (oldset != NULL) {
355 int ret = REAL(sigprocmask)(how_n, NULL, &oldset_n);
356 sigset_t_ntop(&oldset_n, oldset);
357 return ret;
358 }
359 else
360 return REAL(sigprocmask)(how_n, NULL, NULL);
361 }
362
WRAP(sigsuspend)363 int WRAP(sigsuspend)(const sigset_t_portable *mask) {
364 sigset_t mask_n;
365 sigset_t_pton(mask, &mask_n);
366 return REAL(sigsuspend)(&mask_n);
367 }
368
WRAP(sigwait)369 int WRAP(sigwait)(const sigset_t_portable *set, int *sig) {
370 sigset_t set_n;
371 sigset_t_pton(set, &set_n);
372 int ret = REAL(sigwait)(&set_n, sig);
373 *sig = signo_ntop(*sig);
374 return ret;
375 }
376
WRAP(kill)377 int WRAP(kill)(pid_t pid, int sig) {
378 int sig_n = signo_pton(sig);
379 return REAL(kill)(pid, sig_n);
380 }
381
382 // sigset_t related function
383 #include <sys/select.h>
WRAP(pselect)384 int WRAP(pselect)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t_portable *sigmask) {
385 sigset_t sigmask_n;
386 sigset_t_pton(sigmask, &sigmask_n);
387 return REAL(pselect)(nfds, readfds, writefds, exceptfds, timeout, sigmask_n);
388 }
389
390 #include <sys/signalfd.h>
WRAP(signalfd)391 int WRAP(signalfd)(int fd, const sigset_t_portable* mask, int flags) {
392 sigset_t mask_n;
393 sigset_t_pton(mask, &mask_n);
394 return REAL(signalfd)(fd, mask_n, flags);
395 }
396
397 #include <poll.h>
WRAP(ppoll)398 int WRAP(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts, const sigset_t_portable *sigmask) {
399 sigset_t sigmask_n;
400 sigset_t_pton(sigmask, &sigmask_n);
401 return REAL(ppoll)(fds, nfds, timeout_ts, sigmask_n);
402 }
403
404 #include <pthread.h>
WRAP(pthread_sigmask)405 int WRAP(pthread_sigmask)(int how, const sigset_t_portable *set, sigset_t_portable *oldset) {
406 int how_n;
407 switch(how) {
408 case SIG_BLOCK_PORTABLE: how_n = SIG_BLOCK; break;
409 case SIG_UNBLOCK_PORTABLE: how_n = SIG_UNBLOCK; break;
410 case SIG_SETMASK_PORTABLE: how_n = SIG_SETMASK; break;
411 default:
412 fprintf(stderr, "Unknown pthread_sigmask action:%d\n", how);
413 abort();
414 }
415 sigset_t set_n, oldset_n;
416 if (set != NULL) {
417 sigset_t_pton(set, &set_n);
418 if (oldset != NULL) {
419 int ret = REAL(pthread_sigmask)(how_n, &set_n, &oldset_n);
420 sigset_t_ntop(&oldset_n, oldset);
421 return ret;
422 }
423 else
424 return REAL(pthread_sigmask)(how_n, &set_n, NULL);
425 }
426 else if (oldset != NULL) {
427 int ret = REAL(pthread_sigmask)(how_n, NULL, &oldset_n);
428 sigset_t_ntop(&oldset_n, oldset);
429 return ret;
430 }
431 else
432 return REAL(pthread_sigmask)(how_n, NULL, NULL);
433 }
434
435 #include <sys/epoll.h>
WRAP(epoll_pwait)436 int WRAP(epoll_pwait)(int fd, struct epoll_event* events, int max_events, int timeout, const sigset_t_portable* ss) {
437 sigset_t ss_n;
438 sigset_t_pton(ss, &ss_n);
439 return REAL(epoll_pwait)(fd, events, max_events, timeout, ss_n);
440 }
441 #endif /* __mips__ */
442 #endif /* _SIGNAL_PORTABLE_H */
443