1 /*
2 * Copyright 2012, 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 #include <portability.h>
18 #include <unistd.h>
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <signal.h>
22 #include <signal_portable.h>
23 #include <portability.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <errno_portable.h>
27 #include <asm/unistd-portable.h>
28 #include <asm/unistd.h>
29 #include <signalfd_portable.h>
30 #include <filefd_portable.h>
31
32 #define PORTABLE_TAG "signal_portable"
33 #include <log_portable.h>
34
35 /* for build against old platforms when SIGRT* defined instead of __SIGRT* */
36 #ifndef __SIGRTMIN
37 #define __SIGRTMIN SIGRTMIN
38 #endif
39 #ifndef __SIGRTMAX
40 #define __SIGRTMAX SIGRTMAX
41 #endif
42
43 #if SIGBUS_PORTABLE == SIGBUS
44 #error Bad build environment
45 #endif
46
47 typedef void (*sig3handler_t)(int, siginfo_t *, void *);
48
49 static volatile int signal_handler_mapping_enabled = 1;
50
51 extern int syscall(int, ...);
52
53
signal_disable_mapping()54 __hidden void signal_disable_mapping()
55 {
56 ALOGV("%s(): signal_handler_mapping_enabled:%d = 0;", __func__,
57 signal_handler_mapping_enabled);
58
59 signal_handler_mapping_enabled = 0;
60 }
61
62
63 /*
64 * The next five hidden functions are not exposed in the
65 * libportable shared object. They are used here and other
66 * functions, like waitpid(), which need to map signal numbers.
67 */
map_portable_signum_to_name(int portable_signum)68 __hidden char *map_portable_signum_to_name(int portable_signum)
69 {
70 char *name;
71
72 switch(portable_signum) {
73 case 0: name = "SIG_0_PORTABLE:0"; break;
74 case SIGHUP_PORTABLE: name = "SIGHUP_PORTABLE:1"; break;
75 case SIGINT_PORTABLE: name = "SIGINT_PORTABLE:2"; break;
76 case SIGQUIT_PORTABLE: name = "SIGQUIT_PORTABLE:3"; break;
77 case SIGILL_PORTABLE: name = "SIGILL_PORTABLE:4"; break;
78 case SIGTRAP_PORTABLE: name = "SIGTRAP_PORTABLE:5"; break;
79 case SIGABRT_PORTABLE: name = "SIGABRT_PORTABLE:6"; break;
80 case SIGBUS_PORTABLE: name = "SIGBUS_PORTABLE:7"; break;
81 case SIGFPE_PORTABLE: name = "SIGFPE_PORTABLE:8"; break;
82 case SIGKILL_PORTABLE: name = "SIGKILL_PORTABLE:9"; break;
83 case SIGUSR1_PORTABLE: name = "SIGUSR1_PORTABLE:10"; break;
84 case SIGSEGV_PORTABLE: name = "SIGSEGV_PORTABLE:11"; break;
85 case SIGUSR2_PORTABLE: name = "SIGUSR2_PORTABLE:12"; break;
86 case SIGPIPE_PORTABLE: name = "SIGPIPE_PORTABLE:13"; break;
87 case SIGALRM_PORTABLE: name = "SIGALRM_PORTABLE:14"; break;
88 case SIGTERM_PORTABLE: name = "SIGTERM_PORTABLE:15"; break;
89 case SIGSTKFLT_PORTABLE: name = "SIGSTKFLT_PORTABLE:16"; break;
90 case SIGCHLD_PORTABLE: name = "SIGCHLD_PORTABLE:17"; break;
91 case SIGCONT_PORTABLE: name = "SIGCONT_PORTABLE:18"; break;
92 case SIGSTOP_PORTABLE: name = "SIGSTOP_PORTABLE:19"; break;
93 case SIGTSTP_PORTABLE: name = "SIGTSTP_PORTABLE:20"; break;
94 case SIGTTIN_PORTABLE: name = "SIGTTIN_PORTABLE:21"; break;
95 case SIGTTOU_PORTABLE: name = "SIGTTOU_PORTABLE:22"; break;
96 case SIGURG_PORTABLE: name = "SIGURG_PORTABLE:23"; break;
97 case SIGXCPU_PORTABLE: name = "SIGXCPU_PORTABLE:24"; break;
98 case SIGXFSZ_PORTABLE: name = "SIGXFSZ_PORTABLE:25"; break;
99 case SIGVTALRM_PORTABLE: name = "SIGVTALRM_PORTABLE:26"; break;
100 case SIGPROF_PORTABLE: name = "SIGPROF_PORTABLE:27"; break;
101 case SIGWINCH_PORTABLE: name = "SIGWINCH_PORTABLE:28"; break;
102 case SIGIO_PORTABLE: name = "SIGIO_PORTABLE:29"; break;
103 case SIGPWR_PORTABLE: name = "SIGPWR_PORTABLE:30"; break;
104 case SIGSYS_PORTABLE: name = "SIGSYS_PORTABLE:31"; break;
105 case SIGRTMIN_PORTABLE: name = "SIGRTMIN_PORTABLE:32"; break;
106
107 case SIGRT_1_PORTABLE: name = "SIGRT_1_PORTABLE:33"; break;
108 case SIGRT_2_PORTABLE: name = "SIGRT_2_PORTABLE:34"; break;
109 case SIGRT_3_PORTABLE: name = "SIGRT_3_PORTABLE:35"; break;
110 case SIGRT_4_PORTABLE: name = "SIGRT_4_PORTABLE:36"; break;
111 case SIGRT_5_PORTABLE: name = "SIGRT_5_PORTABLE:37"; break;
112 case SIGRT_6_PORTABLE: name = "SIGRT_6_PORTABLE:38"; break;
113 case SIGRT_7_PORTABLE: name = "SIGRT_7_PORTABLE:39"; break;
114 case SIGRT_8_PORTABLE: name = "SIGRT_8_PORTABLE:40"; break;
115 case SIGRT_9_PORTABLE: name = "SIGRT_9_PORTABLE:41"; break;
116 case SIGRT_10_PORTABLE: name = "SIGRT_10_PORTABLE:42"; break;
117 case SIGRT_11_PORTABLE: name = "SIGRT_11_PORTABLE:43"; break;
118 case SIGRT_12_PORTABLE: name = "SIGRT_12_PORTABLE:44"; break;
119 case SIGRT_13_PORTABLE: name = "SIGRT_13_PORTABLE:45"; break;
120 case SIGRT_14_PORTABLE: name = "SIGRT_14_PORTABLE:46"; break;
121 case SIGRT_15_PORTABLE: name = "SIGRT_15_PORTABLE:47"; break;
122 case SIGRT_16_PORTABLE: name = "SIGRT_16_PORTABLE:48"; break;
123 case SIGRT_17_PORTABLE: name = "SIGRT_17_PORTABLE:49"; break;
124 case SIGRT_18_PORTABLE: name = "SIGRT_18_PORTABLE:50"; break;
125 case SIGRT_19_PORTABLE: name = "SIGRT_19_PORTABLE:51"; break;
126 case SIGRT_20_PORTABLE: name = "SIGRT_20_PORTABLE:52"; break;
127 case SIGRT_21_PORTABLE: name = "SIGRT_21_PORTABLE:53"; break;
128 case SIGRT_22_PORTABLE: name = "SIGRT_22_PORTABLE:54"; break;
129 case SIGRT_23_PORTABLE: name = "SIGRT_23_PORTABLE:55"; break;
130 case SIGRT_24_PORTABLE: name = "SIGRT_24_PORTABLE:56"; break;
131 case SIGRT_25_PORTABLE: name = "SIGRT_25_PORTABLE:57"; break;
132 case SIGRT_26_PORTABLE: name = "SIGRT_26_PORTABLE:58"; break;
133 case SIGRT_27_PORTABLE: name = "SIGRT_27_PORTABLE:59"; break;
134 case SIGRT_28_PORTABLE: name = "SIGRT_28_PORTABLE:60"; break;
135 case SIGRT_29_PORTABLE: name = "SIGRT_29_PORTABLE:61"; break;
136 case SIGRT_30_PORTABLE: name = "SIGRT_30_PORTABLE:62"; break;
137 case SIGRT_31_PORTABLE: name = "SIGRT_31_PORTABLE:63"; break;
138 case SIGRTMAX_PORTABLE: name = "SIGRTMAX_PORTABLE:64"; break;
139
140 default: name = "<<UNKNOWN>>"; break;
141 }
142 return name;
143 }
144
145
map_mips_signum_to_name(int mips_signum)146 __hidden char *map_mips_signum_to_name(int mips_signum)
147 {
148 char *name;
149
150 switch(mips_signum) {
151 case 0: name = "SIG_0:0"; break;
152 case SIGHUP: name = "SIGHUP:1"; break;
153 case SIGINT: name = "SIGINT:2"; break;
154 case SIGQUIT: name = "SIGQUIT:3"; break;
155 case SIGILL: name = "SIGILL:4"; break;
156 case SIGTRAP: name = "SIGTRAP:5"; break;
157 case SIGIOT: name = "SIGIOT:6"; break;
158 case SIGEMT: name = "SIGEMT:7"; break;
159 case SIGFPE: name = "SIGFPE:8"; break;
160 case SIGKILL: name = "SIGKILL:9"; break;
161 case SIGBUS: name = "SIGBUS:10"; break;
162 case SIGSEGV: name = "SIGSEGV:11"; break;
163 case SIGSYS: name = "SIGSYS:12"; break;
164 case SIGPIPE: name = "SIGPIPE:13"; break;
165 case SIGALRM: name = "SIGALRM:14"; break;
166 case SIGTERM: name = "SIGTERM:15"; break;
167 case SIGUSR1: name = "SIGUSR1:16"; break;
168 case SIGUSR2: name = "SIGUSR2:17"; break;
169 case SIGCHLD: name = "SIGCHLD:18"; break;
170 case SIGPWR: name = "SIGPWR:19"; break;
171 case SIGWINCH: name = "SIGWINCH:20"; break;
172 case SIGURG: name = "SIGURG:21"; break;
173 case SIGIO: name = "SIGIO:22"; break;
174 case SIGSTOP: name = "SIGSTOP:23"; break;
175 case SIGTSTP: name = "SIGTSTP:24"; break;
176 case SIGCONT: name = "SIGCONT:25"; break;
177 case SIGTTIN: name = "SIGTTIN:26"; break;
178 case SIGTTOU: name = "SIGTTOU:27"; break;
179 case SIGVTALRM: name = "SIGVTALRM:28"; break;
180 case SIGPROF: name = "SIGPROF:29"; break;
181 case SIGXCPU: name = "SIGXCPU:30"; break;
182 case SIGXFSZ: name = "SIGXFSZ:31"; break;
183
184 case __SIGRTMIN: name = "SIGRTMIN:32"; break;
185 case SIGRT_1: name = "SIGRT_1:33"; break;
186 case SIGRT_2: name = "SIGRT_2:34"; break;
187 case SIGRT_3: name = "SIGRT_3:35"; break;
188 case SIGRT_4: name = "SIGRT_4:36"; break;
189 case SIGRT_5: name = "SIGRT_5:37"; break;
190 case SIGRT_6: name = "SIGRT_6:38"; break;
191 case SIGRT_7: name = "SIGRT_7:39"; break;
192 case SIGRT_8: name = "SIGRT_8:40"; break;
193 case SIGRT_9: name = "SIGRT_9:41"; break;
194 case SIGRT_10: name = "SIGRT_10:42"; break;
195 case SIGRT_11: name = "SIGRT_11:43"; break;
196 case SIGRT_12: name = "SIGRT_12:44"; break;
197 case SIGRT_13: name = "SIGRT_13:45"; break;
198 case SIGRT_14: name = "SIGRT_14:46"; break;
199 case SIGRT_15: name = "SIGRT_15:47"; break;
200 case SIGRT_16: name = "SIGRT_16:48"; break;
201 case SIGRT_17: name = "SIGRT_17:49"; break;
202 case SIGRT_18: name = "SIGRT_18:50"; break;
203 case SIGRT_19: name = "SIGRT_19:51"; break;
204 case SIGRT_20: name = "SIGRT_20:52"; break;
205 case SIGRT_21: name = "SIGRT_21:53"; break;
206 case SIGRT_22: name = "SIGRT_22:54"; break;
207 case SIGRT_23: name = "SIGRT_23:55"; break;
208 case SIGRT_24: name = "SIGRT_24:56"; break;
209 case SIGRT_25: name = "SIGRT_25:57"; break;
210 case SIGRT_26: name = "SIGRT_26:58"; break;
211 case SIGRT_27: name = "SIGRT_27:59"; break;
212 case SIGRT_28: name = "SIGRT_28:60"; break;
213 case SIGRT_29: name = "SIGRT_29:61"; break;
214 case SIGRT_30: name = "SIGRT_30:62"; break;
215 case SIGRT_31: name = "SIGRT_31:63"; break;
216 case SIGRT_32: name = "SIGRT_32:64"; break;
217
218 /* NOTE: SIGRT_33...SIGRTMAX-1 Not printed */
219
220 case __SIGRTMAX: name = "SIGRTMAX:128"; break;
221 default: name = "<<UNKNOWN>>"; break;
222 }
223 return name;
224 }
225
226
227 /*
228 * Maps a signal number from portable to native.
229 */
signum_pton(int portable_signum)230 __hidden int signum_pton(int portable_signum)
231 {
232 int mips_signum = -1;
233
234 switch(portable_signum) {
235
236 case 0: /* 0 */
237 return 0;
238
239 case SIGHUP_PORTABLE: /* 1 */
240 return SIGHUP;
241
242 case SIGINT_PORTABLE: /* 2 */
243 return SIGINT;
244
245 case SIGQUIT_PORTABLE: /* 3 */
246 return SIGQUIT;
247
248 case SIGILL_PORTABLE: /* 4 */
249 return SIGILL;
250
251 case SIGTRAP_PORTABLE: /* 5 */
252 return SIGTRAP;
253
254 case SIGABRT_PORTABLE: /* 6 */
255 return SIGABRT;
256
257 case SIGBUS_PORTABLE: /* 7 --> 10 */
258 return SIGBUS;
259
260 case SIGFPE_PORTABLE: /* 8 */
261 return SIGFPE;
262
263 case SIGKILL_PORTABLE: /* 9 */
264 return SIGKILL;
265
266 case SIGUSR1_PORTABLE: /* 10 --> 16 */
267 return SIGUSR1;
268
269 case SIGSEGV_PORTABLE: /* 11 */
270 return SIGSEGV;
271
272 case SIGUSR2_PORTABLE: /* 12 --> 17 */
273 return SIGUSR2;
274
275 case SIGPIPE_PORTABLE: /* 13 */
276 return SIGPIPE;
277
278 case SIGALRM_PORTABLE: /* 14 */
279 return SIGALRM;
280
281 case SIGTERM_PORTABLE: /* 15 */
282 return SIGTERM;
283
284 case SIGSTKFLT_PORTABLE: /* 16 --> 7 */
285 return SIGEMT; /* No native SIGSTKFLT exist ...
286 ... mapping it to SIGEMT. */
287
288 case SIGCHLD_PORTABLE: /* 17 --> 18 */
289 return SIGCHLD;
290
291 case SIGCONT_PORTABLE: /* 18 --> 25 */
292 return SIGCONT;
293
294 case SIGSTOP_PORTABLE: /* 19 --> 23 */
295 return SIGSTOP;
296
297 case SIGTSTP_PORTABLE: /* 20 --> 24 */
298 return SIGTSTP;
299
300 case SIGTTIN_PORTABLE: /* 21 --> 26 */
301 return SIGTTIN;
302
303 case SIGTTOU_PORTABLE: /* 22 --> 27 */
304 return SIGTTOU;
305
306 case SIGURG_PORTABLE: /* 23 --> 21 */
307 return SIGURG;
308
309 case SIGXCPU_PORTABLE: /* 24 --> 30 */
310 return SIGXCPU;
311
312 case SIGXFSZ_PORTABLE: /* 25 --> 31 */
313 return SIGXFSZ;
314
315 case SIGVTALRM_PORTABLE: /* 26 --> 28 */
316 return SIGVTALRM;
317
318 case SIGPROF_PORTABLE: /* 27 --> 29 */
319 return SIGPROF;
320
321 case SIGWINCH_PORTABLE: /* 28 --> 20 */
322 return SIGWINCH;
323
324 case SIGIO_PORTABLE: /* 29 --> 22 */
325 return SIGIO;
326
327 case SIGPWR_PORTABLE: /* 30 --> 19 */
328 return SIGPWR;
329
330 case SIGSYS_PORTABLE: /* 31 --> 12 */
331 return SIGSYS;
332 /*
333 * Mapping lower 32 Real Time signals to identical Native signal numbers.
334 * NOTE: SIGRTMAX_PORTABLE == 64 but SIGRTMAX == 128.
335 */
336 case SIGRTMIN_PORTABLE...SIGRTMAX_PORTABLE: /* 32 ... 64 */
337 ASSERT(SIGRTMIN_PORTABLE == __SIGRTMIN);
338 ASSERT(SIGRTMAX_PORTABLE <= __SIGRTMAX);
339 return portable_signum;
340
341 default:
342 ALOGE("%s: switch default: NOTE portable_signum:%d Not supported. Just a Test?",
343 __func__, portable_signum);
344 /*
345 * User could be LTP testing with bogus signal numbers,
346 * if so we mimic the test.
347 *
348 * If the signal is just outside the PORTABLE range
349 * we use a signal just outside the Native/MIPS range.
350 */
351 if (portable_signum < 0) {
352 mips_signum = portable_signum;
353 } else if (portable_signum > NSIG_PORTABLE) {
354 mips_signum = (portable_signum - NSIG_PORTABLE) + NSIG;
355 } else {
356 ALOGE("%s: 0 < portable_signum:%d <= NSIG_PORTABLE:%d; Not supported, return(0);",
357 __func__, portable_signum, NSIG_PORTABLE);
358
359 mips_signum = 0;
360 }
361 break;
362 }
363 ALOGV("%s(portable_signum:%d): return(mips_signum:%d);", __func__,
364 portable_signum, mips_signum);
365
366 return mips_signum;
367 }
368
369
370 /*
371 * Maps a signal number from native to portable.
372 */
signum_ntop(int mips_signum)373 __hidden int signum_ntop(int mips_signum)
374 {
375 int portable_ssignum = -1;
376
377 switch(mips_signum) {
378 case 0: /* 0 */
379 return 0;
380
381 case SIGHUP: /* 1 */
382 return SIGHUP_PORTABLE;
383
384 case SIGINT: /* 2 */
385 return SIGINT_PORTABLE;
386
387 case SIGQUIT: /* 3 */
388 return SIGQUIT_PORTABLE;
389
390 case SIGILL: /* 4 */
391 return SIGILL_PORTABLE;
392
393 case SIGTRAP: /* 5 */
394 return SIGTRAP_PORTABLE;
395
396 case SIGABRT: /* 6 */
397 return SIGABRT_PORTABLE;
398
399 case SIGBUS: /* 7 <-- 10 */
400 return SIGBUS_PORTABLE;
401
402 case SIGFPE: /* 8 */
403 return SIGFPE_PORTABLE;
404
405 case SIGKILL: /* 9 */
406 return SIGKILL_PORTABLE;
407
408 case SIGUSR1: /* 10 <-- 16 */
409 return SIGUSR1_PORTABLE;
410
411 case SIGSEGV: /* 11 */
412 return SIGSEGV_PORTABLE;
413
414 case SIGUSR2: /* 12 <-- 17 */
415 return SIGUSR2_PORTABLE;
416
417 case SIGPIPE: /* 13 */
418 return SIGPIPE_PORTABLE;
419
420 case SIGALRM: /* 14 */
421 return SIGALRM_PORTABLE;
422
423 case SIGTERM: /* 15 */
424 return SIGTERM_PORTABLE;
425
426 case SIGEMT: /* 16 <--- 7 */
427 return SIGSTKFLT_PORTABLE; /* No native SIGSTKFLT exist ...
428 ... reverse mapping SIGEMT ...
429 ... back to SIGSTKFLT. */
430
431 case SIGCHLD: /* 17 <-- 18 */
432 return SIGCHLD_PORTABLE;
433
434 case SIGCONT: /* 18 <-- 15 */
435 return SIGCONT_PORTABLE;
436
437 case SIGSTOP: /* 19 <-- 23 */
438 return SIGSTOP_PORTABLE;
439
440 case SIGTSTP: /* 20 <-- 24 */
441 return SIGTSTP_PORTABLE;
442
443 case SIGTTIN: /* 21 <-- 26 */
444 return SIGTTIN_PORTABLE;
445
446 case SIGTTOU: /* 22 <-- 27 */
447 return SIGTTOU_PORTABLE;
448
449 case SIGURG: /* 23 <-- 21 */
450 return SIGURG_PORTABLE;
451
452 case SIGXCPU: /* 24 <-- 30 */
453 return SIGXCPU_PORTABLE;
454
455 case SIGXFSZ: /* 25 <-- 31 */
456 return SIGXFSZ_PORTABLE;
457
458 case SIGVTALRM: /* 26 <-- 28 */
459 return SIGVTALRM_PORTABLE;
460
461 case SIGPROF: /* 27 <-- 29 */
462 return SIGPROF_PORTABLE;
463
464 case SIGWINCH: /* 28 <-- 20 */
465 return SIGWINCH_PORTABLE;
466
467 case SIGIO: /* 29 <-- 22 */
468 return SIGIO_PORTABLE;
469
470 case SIGPWR: /* 30 <-- 19 */
471 return SIGPWR_PORTABLE;
472
473 case SIGSYS: /* 31 <-- 12 */
474 return SIGSYS_PORTABLE;
475
476 /*
477 * Mapping lower 32 Real Time signals to identical Portable signal numbers.
478 * NOTE: SIGRTMAX_PORTABLE == 64 but SIGRTMAX == 128.
479 */
480 case __SIGRTMIN...SIGRTMAX_PORTABLE: /* 32 ... 64 */
481 ASSERT(__SIGRTMIN == SIGRTMIN_PORTABLE);
482 ASSERT(__SIGRTMAX >= SIGRTMAX_PORTABLE);
483 return mips_signum;
484
485 /*
486 * Mapping upper 63 Native Real Time signals to the last Portable signal number.
487 * Shouldn't even be possible to be using these signals.
488 */
489 case (SIGRTMAX_PORTABLE+1)...__SIGRTMAX: /* 65 ... 128 */
490 ASSERT(__SIGRTMIN == SIGRTMIN_PORTABLE);
491 ASSERT(__SIGRTMAX >= SIGRTMAX_PORTABLE);
492
493 ALOGE("%s: mips_signum:%d Can't be mapped to a unique portable signal;", __func__,
494 mips_signum);
495
496 ALOGE("%s: Mapping highest 63 Real Time Signals to the largest RT Portable SigNo.",
497 __func__);
498
499 return SIGRTMAX_PORTABLE;
500
501
502 default:
503 ALOGE("%s: switch default: mips_signum:%d Not supported! return(0);", __func__,
504 mips_signum);
505 #if 0
506 LOG_FATAL("%s: mips_signum:%d is not portable;", __func__, mips_signum);
507 #endif
508 return 0;
509 }
510 return portable_ssignum;
511 }
512
513
514 /*
515 * Deal with siginfo structure being a bit different.
516 * Need to swap errno and code fields.
517 */
siginfo_pton(siginfo_portable_t * portable_sip,siginfo_t * native_sip)518 static void siginfo_pton(siginfo_portable_t *portable_sip, siginfo_t *native_sip)
519 {
520
521 ALOGV("%s(portable_sip:%p, native_sip:%p) {", __func__,
522 portable_sip, native_sip);
523
524 ASSERT(sizeof(siginfo_portable_t) == sizeof(siginfo_t));
525
526 /*
527 * Default to the same structure members,
528 * code and errno are swapped between ARM and MIPS,
529 * and errno needs to be translated.
530 *
531 * The signal number isn't translated, as the kernel
532 * will fill it it when it delivers the signal.
533 */
534
535 *native_sip = *((siginfo_t *)portable_sip);
536 native_sip->si_signo = 0;
537 native_sip->si_code = portable_sip->si_code;
538 native_sip->si_errno = errno_pton(portable_sip->si_errno);
539
540 ALOGV("%s: return; }", __func__);
541 }
542
543
siginfo_ntop(siginfo_t * native_sip,siginfo_portable_t * portable_sip)544 static void siginfo_ntop(siginfo_t *native_sip, siginfo_portable_t *portable_sip)
545 {
546
547 ALOGV("%s(native_sip,:%p, portable_sip:%p) {", __func__,
548 native_sip, portable_sip);
549
550 ASSERT(sizeof(siginfo_portable_t) == sizeof(siginfo_t));
551
552 /*
553 * Structure assignment to default to the same structure members,
554 * as only the code and errno are swapped in position between
555 * ARM and MIPS; errno and signal number also need to be translated.
556 */
557 *portable_sip = *((siginfo_portable_t *)native_sip);
558
559 portable_sip->si_signo = signum_ntop(native_sip->si_signo);
560 portable_sip->si_code = native_sip->si_code;
561 portable_sip->si_errno = errno_ntop(native_sip->si_errno);
562
563 ALOGV("%s: return; }", __func__);
564 }
565
566
567 /*
568 * Array of signal handlers as the portable users expects they
569 * they have been registered in the kernel. Problem is we need
570 * to have our own handler to map the MIPS signal number to a
571 * portable signal number.
572 */
573 static sig3handler_portable_t mips_portable_sighandler[NSIG_PORTABLE + 1] = { NULL };
574
mips_sigaction_handler(int mips_signum,siginfo_t * sip,void * ucp)575 static void mips_sigaction_handler(int mips_signum, siginfo_t *sip, void *ucp)
576 {
577 int portable_signum;
578 char *portable_signame;
579 char *mips_signame = map_mips_signum_to_name(mips_signum);
580 sig3handler_portable_t portable_sighandler;
581 siginfo_portable_t portable_si;
582 siginfo_portable_t *portable_sip;
583
584 ALOGV(" ");
585 ALOGV("%s(mips_signum:%d:'%s', sip:%p, ucp:%p) {", __func__,
586 mips_signum,
587 mips_signame, sip, ucp);
588
589 portable_signum = signum_ntop(mips_signum);
590 portable_signame = map_portable_signum_to_name(portable_signum);
591 portable_sighandler = mips_portable_sighandler[portable_signum];
592
593 if (invalid_pointer(portable_sighandler)) {
594 /*
595 * If a portable/ARM application tries to set signals in the signal mask > 32
596 * it results in a signal_handler being set to -1:SIG_ERR. Calling a function
597 * at location -1 doesn't produce very informative Android backtraces on MIPS.
598 */
599 ALOGE("%s: invalid_pointer(portable_sighandler:%p); Likely about to Trap or Bus Error!",
600 __func__, portable_sighandler);
601
602 ALOGE("%s: HINT: Likely best to use gdbserver and look at sigaction arguments.", __func__);
603 }
604 ASSERT(portable_sighandler != NULL);
605 ASSERT(portable_sighandler != (sig3handler_portable_t) SIG_DFL);
606 ASSERT(portable_sighandler != (sig3handler_portable_t) SIG_IGN);
607
608 if (sip == NULL) {
609 portable_sip = NULL;
610 } else {
611 /* Map signinfo from native to portable format */
612 portable_sip = &portable_si;
613 siginfo_ntop(sip, portable_sip);
614 }
615
616
617 ALOGV("%s: Calling portable_sighandler:%p(portable_signum:%d, portable_sip:%p, ucp:%p);",
618 __func__, portable_sighandler, portable_signum, portable_sip, ucp);
619
620 portable_sighandler(portable_signum, portable_sip, ucp);
621
622 ALOGV("%s: return; }", __func__);
623 }
624
625
mips_sighandler(int mips_signum)626 static void mips_sighandler(int mips_signum)
627 {
628 int portable_signum;
629 char *portable_signame;
630 char *mips_signame = map_mips_signum_to_name(mips_signum);
631 sig3handler_portable_t portable_sighandler;
632
633 ALOGV(" ");
634 ALOGV("%s(mips_signum:%d:'%s') {", __func__, mips_signum, mips_signame);
635
636 mips_sigaction_handler(mips_signum, NULL, NULL);
637
638 ALOGV("%s: return; }", __func__);
639 }
640
641
sighandler_pton(sighandler_portable_t portable_handler,int sigaction)642 static sighandler_t sighandler_pton(sighandler_portable_t portable_handler, int sigaction)
643 {
644 sighandler_t mips_handler;
645
646 ALOGV("%s(portable_handler:%p, sigaction:%d) {", __func__,
647 portable_handler, sigaction);
648
649 switch((int) portable_handler) {
650 case (int) SIG_DFL:
651 case (int) SIG_IGN:
652 mips_handler = portable_handler;
653 break;
654
655 default: /* NOTE: Includes SIG_ERR:-1 */
656 if (invalid_pointer(portable_handler)) {
657 /*
658 * Calling sigaction() with a bogus signal handler doesn't fail,
659 * so we let the portable cases fail later as the native case would.
660 */
661 ALOGE("%s: invalid_pointer(portable_handler:%p)!", __func__, portable_handler);
662 ALOGE("%s: HINT: Likely to cause a BUS Error ....", __func__);
663 ALOGE("%s: HINT: ... when the signal handler is called!", __func__);
664 }
665
666 /*
667 * Signal Mapping can be disabled in the rare case of the clone
668 * flags not being compatble for VM and file descriptors.
669 */
670 if (signal_handler_mapping_enabled) {
671 if (sigaction)
672 mips_handler = (sighandler_t) mips_sigaction_handler;
673 else
674 mips_handler = (sighandler_t) mips_sighandler;
675 } else {
676 mips_handler = portable_handler; /* Don't MAP */
677 }
678 break;
679 }
680
681 ALOGV("%s: return(mips_handler:%p); }", __func__, mips_handler);
682 return mips_handler;
683 }
684
685
686 /*
687 * This function maps the signal number and calls one of the low level mips signal()
688 * functions implemented in libc/unistd/signal.c:
689 * sysv_signal()
690 * bsd_signal()
691 *
692 * The last 2 parameters to this static function, mips_signal_fn*, specify which of
693 * these functions to call. We intercept the above to functions, as well as signal(),
694 * and call the associated *_portable() functions below.
695 *
696 * In addition, we intercept the signal_handler with our own handlers that map the
697 * signal number from the MIPS convention to the PORTABLE/ARM convention.
698 */
699 static sighandler_portable_t
do_signal_portable(int portable_signum,sighandler_portable_t portable_handler,__sighandler_t (mips_signal_fn)(int,__sighandler_t))700 do_signal_portable(int portable_signum, sighandler_portable_t portable_handler,
701 __sighandler_t (mips_signal_fn)(int, __sighandler_t))
702 {
703 char *portable_signame = map_portable_signum_to_name(portable_signum);
704 int mips_signum;
705 sighandler_t mips_handler;
706 sighandler_portable_t rv;
707 sighandler_portable_t prev_portable_handler;
708
709 ALOGV("%s(portable_signum:%d:%s, portable_handler:%p, mips_signal_fn:%p) {", __func__,
710 portable_signum,
711 portable_signame, portable_handler, mips_signal_fn);
712
713 mips_signum = signum_pton(portable_signum);
714
715 if ((mips_signum <= 0) || (mips_signum > NSIG)) {
716 /*
717 * Invalid signal number, perhaps zero. Let the kernel generate the
718 * proper return value and set errno.
719 */
720 mips_handler = sighandler_pton(portable_handler, 0);
721 rv = mips_signal_fn(mips_signum, mips_handler);
722 } else {
723 /*
724 * We have a usable signal number, redirect it to our signal handler
725 * if a portable handler was provided so we can convert the signal number.
726 * Save our current mapped signal handler for likely return.
727 */
728 prev_portable_handler = (sighandler_portable_t) mips_portable_sighandler[portable_signum];
729
730 mips_handler = sighandler_pton(portable_handler, 0);
731 if (mips_handler != portable_handler) {
732 mips_portable_sighandler[portable_signum] = (sig3handler_portable_t) portable_handler;
733 }
734 rv = mips_signal_fn(mips_signum, mips_handler);
735
736 if ((rv == (sighandler_portable_t) mips_sighandler) ||
737 (rv == (sighandler_portable_t) mips_sigaction_handler)) {
738
739 rv = (sighandler_t) prev_portable_handler;
740 }
741 }
742
743 ALOGV("%s: return(rv:%p); }", __func__, rv);
744 return rv;
745 }
746
747
748 /*
749 * signal() can't be called directly, due to an in-line function in signal.h which
750 * redirects the call to bsd_signal(). _signal() is a static function; not to be called
751 * directly. This function isn't actually needed.
752 */
WRAP(signal)753 sighandler_portable_t WRAP(signal)(int portable_signum, sighandler_portable_t handler)
754 {
755 extern __sighandler_t REAL(bsd_signal)(int, __sighandler_t);
756 sighandler_portable_t rv;
757
758 ALOGV(" ");
759 ALOGV("%s(portable_signum:%d, handler:%p) {", __func__,
760 portable_signum, handler);
761
762 /* bsd does a SA_RESTART */
763 rv = do_signal_portable(portable_signum, handler, REAL(bsd_signal));
764
765 ALOGV("%s: return(ret:%p); }", __func__, rv);
766 return rv;
767 }
768
769
WRAP(sysv_signal)770 sighandler_portable_t WRAP(sysv_signal)(int portable_signum, sighandler_portable_t handler)
771 {
772 extern __sighandler_t REAL(sysv_signal)(int, __sighandler_t);
773 sighandler_portable_t rv;
774
775 ALOGV(" ");
776 ALOGV("%s(portable_signum:%d, handler:%p) {", __func__,
777 portable_signum, handler);
778
779 /* sysv does a SA_RESETHAND */
780 rv = do_signal_portable(portable_signum, handler, REAL(sysv_signal));
781
782 ALOGV("%s: return(ret:%p); }", __func__, rv);
783 return rv;
784 }
785
786
787 /*
788 * NOTE:
789 * handler is either the Bionic
790 * bsd_signal() signal handler
791 * or
792 * the sysv_signal() signal handler.
793 */
794
WRAP(bsd_signal)795 sighandler_portable_t WRAP(bsd_signal)(int portable_signum, sighandler_portable_t handler)
796 {
797 extern __sighandler_t REAL(bsd_signal)(int, __sighandler_t);
798 sighandler_portable_t rv;
799
800 ALOGV(" ");
801 ALOGV("%s(portable_signum:%d, handler:%p) {", __func__,
802 portable_signum, handler);
803
804 /* bsd does a SA_RESTART */
805 rv = do_signal_portable(portable_signum, handler, REAL(bsd_signal));
806
807 ALOGV("%s: return(ret:%p); }", __func__, rv);
808 return rv;
809 }
810
811
do_kill(int id,int portable_signum,int (* fn)(int,int))812 static int do_kill(int id, int portable_signum, int (*fn)(int, int))
813 {
814 char *portable_signame = map_portable_signum_to_name(portable_signum);
815 int mips_signum;
816 int rv;
817
818 ALOGV("%s(id:%d, portable_signum:%d:'%s', fn:%p) {", __func__,
819 id, portable_signum,
820 portable_signame, fn);
821
822 mips_signum = signum_pton(portable_signum);
823
824 /*
825 * SIG_0 gets passed down to the kernel to test for the existence of a process.
826 * If a non-zero portable_signum has been mapped to 0,
827 * it's unsupported and will be ignored.
828 */
829 if ((portable_signum != 0) && (mips_signum == 0)) {
830 rv = 0;
831 } else {
832 ALOGV("%s: Calling fn:%p(id:%d, mips_signum:%d);", __func__,
833 fn, id, mips_signum);
834
835 rv = fn(id, mips_signum);
836 }
837 ALOGV("%s: return(rv:%d); }", __func__, rv);
838 return rv;
839 }
840
841
WRAP(killpg)842 int WRAP(killpg)(int pgrp, int portable_signum)
843 {
844 extern int REAL(killpg)(int pgrp, int sig);
845 int rv;
846
847 ALOGV(" ");
848 ALOGV("%s(pgrp:%d, portable_signum:%d) {", __func__,
849 pgrp, portable_signum);
850
851 rv = do_kill(pgrp, portable_signum, REAL(killpg));
852
853 ALOGV("%s: return(rv:%d); }", __func__, rv);
854 return rv;
855 }
856
857
WRAP(kill)858 int WRAP(kill)(pid_t pid, int portable_signum)
859 {
860 extern int REAL(kill)(pid_t, int);
861 int rv;
862
863 ALOGV(" ");
864 ALOGV("%s(pid:%d, portable_signum:%d) {", __func__,
865 pid, portable_signum);
866
867 rv = do_kill(pid, portable_signum, REAL(kill));
868
869 ALOGV("%s: return(rv:%d); }", __func__, rv);
870 return rv;
871 }
872
873
874 /* tgkill is not exported from android-14 libc.so */
875 #if 0
876 int WRAP(tgkill)(int tgid, int tid, int portable_signum)
877 {
878 extern int tgkill(int, int, int);
879 char *portable_signame = map_portable_signum_to_name(portable_signum);
880 int mips_signum;
881 int rv;
882
883 ALOGV("%s(tgid:%d, tid:%d, portable_signum:%d:'%s') {", __func__,
884 tgid, tid, portable_signum, portable_signame);
885
886 mips_signum = signum_pton(portable_signum);
887
888 /*
889 * If a non-zero portable_signum has been mapped to 0,
890 * it is unsupported and will be ignored.
891 */
892 if ((portable_signum != 0) && (mips_signum == 0))
893 rv = 0;
894 else
895 rv = REAL(tgkill)(tgid, tid, mips_signum);
896
897 ALOGV("%s: return rv:%d; }", __func__, rv);
898 return rv;
899 }
900 #endif
901
902
WRAP(raise)903 int WRAP(raise)(int portable_signum)
904 {
905 char *portable_signame = map_portable_signum_to_name(portable_signum);
906 int mips_signum = signum_pton(portable_signum);
907 int rv;
908
909 ALOGV("%s(portable_signum:%d:'%s') {", __func__, portable_signum, portable_signame);
910
911 /*
912 * SIG_0 gets passed down to the kernel to test for the existence of a process.
913 * If a non-zero portable_signum has been mapped to 0,
914 * it's unsupported and will be ignored.
915 */
916 if ((portable_signum != 0) && (mips_signum == 0))
917 rv = 0;
918 else
919 rv = REAL(raise)(mips_signum);
920
921 ALOGV("%s: return(rv:%d); }", __func__, rv);
922 return rv;
923 }
924
925
sigset_pton(sigset_portable_t * portable_sigset,sigset_t * mips_sigset)926 void sigset_pton(sigset_portable_t *portable_sigset, sigset_t *mips_sigset)
927 {
928 int portable_signum;
929
930 ASSERT(mips_sigset != NULL);
931
932 ALOGV("%s(portable_sigset:%p, mips_sigset:%p) {", __func__,
933 portable_sigset, mips_sigset);
934
935 sigemptyset(mips_sigset);
936 if (invalid_pointer((void *)portable_sigset)) {
937 ALOGE("%s: portable_sigset:%p is not valid; returning empty set.", __func__,
938 portable_sigset);
939 goto done;
940 }
941
942 for(portable_signum = 1; portable_signum <= NSIG_PORTABLE; portable_signum++) {
943
944 if (WRAP(sigismember)(portable_sigset, portable_signum)) {
945 char *portable_signame = map_portable_signum_to_name(portable_signum);
946 int mips_signum = signum_pton(portable_signum);
947 char *mips_signame;
948
949 if (mips_signum != 0) {
950 int err;
951
952 mips_signame = map_mips_signum_to_name(mips_signum);
953 ALOGV("%s: sigaddset(mips_sigset:%p, mips_signum:%d:'%s');", __func__,
954 mips_sigset, mips_signum,
955 mips_signame);
956
957 err = sigaddset(mips_sigset, mips_signum);
958 if (err == -1) {
959 PERROR("sigaddset");
960 }
961 }
962 }
963 }
964
965 done:
966 ALOGV("%s: return; }", __func__);
967 return;
968 }
969
970
971 void
sigset_ntop(const sigset_t * const_mips_sigset,sigset_portable_t * portable_sigset)972 sigset_ntop(const sigset_t *const_mips_sigset, sigset_portable_t *portable_sigset)
973 {
974 int mips_signum;
975 sigset_t *mips_sigset = (sigset_t *) const_mips_sigset;
976
977 ALOGV("%s(const_mips_sigset:%p, portable_sigset:%p) {", __func__,
978 const_mips_sigset, portable_sigset);
979
980 ASSERT(mips_sigset != NULL);
981
982 if (invalid_pointer((void *)portable_sigset)) {
983 ALOGE("%s: portable_sigset:%p is not Valid; can't return sigset", __func__,
984 portable_sigset);
985 goto done;
986 }
987 WRAP(sigemptyset)(portable_sigset);
988
989 for(mips_signum = 1; mips_signum <= NSIG; mips_signum++) {
990 if (sigismember(mips_sigset, mips_signum)) {
991 int portable_signum = signum_ntop(mips_signum);
992
993 if (portable_signum != 0)
994 WRAP(sigaddset)(portable_sigset, portable_signum);
995 }
996 }
997
998 done:
999 ALOGV("%s: return; }", __func__);
1000 return;
1001 }
1002
1003
sigaction_flags_pton(int portable_flags)1004 static int sigaction_flags_pton(int portable_flags)
1005 {
1006 int mips_flags = 0;
1007
1008 if (portable_flags & SA_NOCLDSTOP_PORTABLE) {
1009 mips_flags |= SA_NOCLDSTOP;
1010 }
1011 if (portable_flags & SA_NOCLDWAIT_PORTABLE) {
1012 mips_flags |= SA_NOCLDWAIT;
1013 }
1014 if (portable_flags & SA_SIGINFO_PORTABLE) {
1015 mips_flags |= SA_SIGINFO;
1016 }
1017 if (portable_flags & SA_THIRTYTWO_PORTABLE) {
1018 ALOGV("%s: SA_THIRTYTWO_PORTABLE isn't SUPPORTED.", __func__);
1019 }
1020 if (portable_flags & SA_RESTORER_PORTABLE) {
1021 ALOGV("%s: SA_RESTORER isn't SUPPORTED.", __func__);
1022 }
1023 if (portable_flags & SA_ONSTACK_PORTABLE) {
1024 mips_flags |= SA_ONSTACK;
1025 }
1026 if (portable_flags & SA_RESTART_PORTABLE) {
1027 mips_flags |= SA_RESTART;
1028 }
1029 if (portable_flags & SA_NODEFER_PORTABLE) {
1030 mips_flags |= SA_NODEFER;
1031 }
1032 if (portable_flags & SA_RESETHAND_PORTABLE) {
1033 mips_flags |= SA_RESETHAND;
1034 }
1035
1036 ALOGV("%s(portable_flags:0x%x) return(mips_flags:0x%x);", __func__,
1037 portable_flags, mips_flags);
1038
1039 return mips_flags;
1040 }
1041
1042
sigaction_flags_ntop(int mips_flags)1043 int sigaction_flags_ntop(int mips_flags)
1044 {
1045 int portable_flags = 0;
1046
1047 if (mips_flags & SA_NOCLDSTOP) portable_flags |= SA_NOCLDSTOP_PORTABLE;
1048 if (mips_flags & SA_NOCLDWAIT) portable_flags |= SA_NOCLDWAIT_PORTABLE;
1049 if (mips_flags & SA_SIGINFO) portable_flags |= SA_SIGINFO_PORTABLE;
1050 #ifdef SA_THIRTYTWO
1051 if (mips_flags & SA_THIRTYTWO) portable_flags |= SA_THIRTYTWO_PORTABLE;
1052 #endif
1053 if (mips_flags & SA_ONSTACK) portable_flags |= SA_ONSTACK_PORTABLE;
1054 if (mips_flags & SA_RESTART) portable_flags |= SA_RESTART_PORTABLE;
1055 if (mips_flags & SA_NODEFER) portable_flags |= SA_NODEFER_PORTABLE;
1056 if (mips_flags & SA_RESETHAND) portable_flags |= SA_RESETHAND_PORTABLE;
1057
1058 ALOGV("%s(mips_flags:0x%x) return(portable_flags:0x%x);", __func__,
1059 mips_flags, portable_flags);
1060
1061 return portable_flags;
1062 }
1063
1064
1065 /*
1066 * Called by portable/ARM code, which we map and do MIPS system calls.
1067 *
1068 * The incoming system call used a Portable/ARM sigaction structure:
1069 * ------------------------------------------------------------------
1070 * struct sigaction_portable {
1071 * union {
1072 * __sighandler_portable_t _sa_handler;
1073 * __sigaction_handler_portable_t _sa_sigaction;
1074 * } _u;
1075 * sigset_portable_t sa_mask;
1076 * unsigned long sa_flags;
1077 * void (*sa_restorer)(void);
1078 * };
1079 *
1080 * A similar, but different, structure is used in the MIPS/Native system call:
1081 * ---------------------------------------------------------------------------
1082 * struct sigaction {
1083 * unsigned int sa_flags;
1084 * union {
1085 * __sighandler_t sa_handler;
1086 * __sigaction_handler_portable_t _sa_sigaction;
1087 * } __u;
1088 * sigset_t sa_mask;
1089 * };
1090 *
1091 * This sigaction structure needs to be mapped before the MIPS systems call as well as after for
1092 * returning the old/previous sigaction. Also, like signal_portable() above, we need to maintain
1093 * a table of signal handlers that our intercepting handler can call after it converts the signal
1094 * numbers.
1095 */
do_sigaction_portable(int portable_signum,const struct sigaction_portable * act,struct sigaction_portable * oldact,sigaction_fn fn,rt_sigaction_fn rt_fn)1096 static int do_sigaction_portable(int portable_signum, const struct sigaction_portable *act,
1097 struct sigaction_portable *oldact, sigaction_fn fn,
1098 rt_sigaction_fn rt_fn)
1099 {
1100 int mips_signum;
1101 char *mips_signame;
1102 struct sigaction mips_act;
1103 struct sigaction *mips_act_ptr;
1104 struct sigaction mips_oldact;
1105 sighandler_t mips_handler;
1106 sighandler_portable_t portable_handler;
1107 sig3handler_portable_t prev_portable_handler;
1108 char *portable_signame = map_portable_signum_to_name(portable_signum);
1109 int rv;
1110
1111 ALOGV("%s(portable_signum:%d:'%s', act:%p, oldact:%p, fn:%p, rt_fn:%p) {", __func__,
1112 portable_signum,
1113 portable_signame, act, oldact, fn, rt_fn);
1114
1115 mips_signum = signum_pton(portable_signum);
1116 mips_signame = map_mips_signum_to_name(mips_signum);
1117
1118 /*
1119 * If a non-zero portable_signum has been mapped to 0,
1120 * it's unsupported and will be ignored.
1121 */
1122 if ((portable_signum != 0) && (mips_signum == 0)) {
1123 rv = 0;
1124 goto done;
1125 }
1126 if (portable_signum > 0 && portable_signum <= NSIG_PORTABLE)
1127 prev_portable_handler = mips_portable_sighandler[portable_signum];
1128 else
1129 prev_portable_handler = NULL;
1130
1131 memset(&mips_act, 0, sizeof(mips_act));
1132
1133 if (invalid_pointer((void *)act)) {
1134 mips_act_ptr = (struct sigaction *)act;
1135 } else {
1136 /*
1137 * Make the MIPS version of sigaction, which has no sa_restorer function pointer.
1138 * Also the handler will be called with a pointer to a to a sigcontext structure
1139 * which is totally non-portable.
1140 */
1141 sigset_pton(((sigset_portable_t *)&act->sa_mask),
1142 ((sigset_t *) &mips_act.sa_mask));
1143
1144 mips_act.sa_flags = sigaction_flags_pton(act->sa_flags);
1145
1146 if (mips_act.sa_flags & SA_SIGINFO) {
1147 /*
1148 * Providing the three argument version of a signal handler.
1149 */
1150 portable_handler = (sighandler_portable_t) act->sa_sigaction_portable;
1151 if ((portable_signum <= 0) || (portable_signum > NSIG_PORTABLE)) {
1152 /*
1153 * Let the kernel generate the proper return value and set errno.
1154 */
1155 mips_act.sa_sigaction = (sig3handler_t) portable_handler;
1156 } else {
1157 mips_handler = sighandler_pton(portable_handler, 1);
1158 if (mips_handler != portable_handler) {
1159 mips_portable_sighandler[portable_signum] =
1160 (sig3handler_portable_t) portable_handler;
1161 }
1162 mips_act.sa_sigaction = (sig3handler_t) mips_handler;
1163 }
1164 } else {
1165 /*
1166 * Providing the classic single argument version of a signal handler.
1167 */
1168 portable_handler = act->sa_handler_portable;
1169 if ((portable_signum <= 0) || (portable_signum > NSIG_PORTABLE)) {
1170 /*
1171 * Let the kernel generate the proper return value and set errno.
1172 */
1173 mips_act.sa_handler = (sighandler_t) portable_handler;
1174 } else {
1175 mips_handler = sighandler_pton(portable_handler, 1);
1176 if (mips_handler != portable_handler) {
1177 mips_portable_sighandler[portable_signum] =
1178 (sig3handler_portable_t) portable_handler;
1179 }
1180 mips_act.sa_handler = mips_handler;
1181 }
1182 }
1183 mips_act_ptr = &mips_act;
1184 }
1185
1186 if (fn != NULL) {
1187 ASSERT(rt_fn == NULL);
1188 rv = fn(mips_signum, mips_act_ptr, &mips_oldact);
1189 } else {
1190 ASSERT(rt_fn != NULL);
1191 rv = rt_fn(mips_signum, mips_act_ptr, &mips_oldact, sizeof(sigset_t));
1192 }
1193
1194 if (rv == 0 && oldact) {
1195 if (mips_oldact.sa_sigaction == (__sigaction_handler_portable_t) mips_sigaction_handler ||
1196 mips_oldact.sa_sigaction == (__sigaction_handler_portable_t) mips_sighandler) {
1197
1198 oldact->sa_sigaction_portable =
1199 (__sigaction_handler_portable_t) prev_portable_handler;
1200 } else {
1201 oldact->sa_sigaction_portable =
1202 (__sigaction_handler_portable_t) mips_oldact.sa_sigaction;
1203 }
1204 sigset_ntop((sigset_t *) &(mips_oldact.sa_mask),
1205 (sigset_portable_t *) &(oldact->sa_mask));
1206
1207 oldact->sa_flags = sigaction_flags_ntop(mips_oldact.sa_flags);
1208 oldact->sa_restorer = NULL;
1209 }
1210
1211 done:
1212 ALOGV("%s: return(rv:%d); }", __func__, rv);
1213 return rv;
1214 }
1215
1216
WRAP(sigaction)1217 int WRAP(sigaction)(int portable_signum, const struct sigaction_portable *act,
1218 struct sigaction_portable *oldact)
1219 {
1220 extern int REAL(sigaction)(int, const struct sigaction *, struct sigaction *);
1221 int rv;
1222
1223 ALOGV(" ");
1224 ALOGV("%s(portable_signum:%d, act:%p, oldact:%p) {", __func__,
1225 portable_signum, act, oldact);
1226
1227 rv = do_sigaction_portable(portable_signum, act, oldact, REAL(sigaction), NULL);
1228
1229 ALOGV("%s: return(rv:%d); }", __func__, rv);
1230 return rv;
1231 }
1232
1233
1234 /*
1235 * Currently signalfd() isn't supported by bionic with
1236 * only the portable syscall.c code using this code by
1237 * intercepting the syscall(__NR_signalfd4, ...) in bionic.
1238 */
do_signalfd4_portable(int fd,const sigset_portable_t * portable_sigmask,int portable_sigsetsize,int portable_flags)1239 __hidden int do_signalfd4_portable(int fd, const sigset_portable_t *portable_sigmask,
1240 int portable_sigsetsize, int portable_flags)
1241 {
1242 sigset_t native_sigmask;
1243 int native_sigsetsize = sizeof(native_sigmask);
1244 int native_flags = 0;
1245 int rv;
1246
1247 ALOGV("%s(fd:%d, portable_sigmask:%p, portable_sigsetsize:%d, portable_flags:0x%x) {",
1248 __func__, fd, portable_sigmask, portable_sigsetsize, portable_flags);
1249
1250 sigset_pton((sigset_portable_t *)portable_sigmask, &native_sigmask);
1251
1252 if (portable_flags & SFD_NONBLOCK_PORTABLE) {
1253 native_flags |= SFD_NONBLOCK;
1254 }
1255 if (portable_flags & SFD_CLOEXEC_PORTABLE) {
1256 native_flags |= SFD_CLOEXEC;
1257 }
1258 rv = syscall(__NR_signalfd4, fd, &native_sigmask, native_sigsetsize, native_flags);
1259
1260 if (rv >= 0) {
1261 if (native_flags & SFD_CLOEXEC) {
1262 filefd_CLOEXEC_enabled(rv);
1263 }
1264
1265 /*
1266 * Reads on this file descriptor must be mapped to be portable.
1267 * The mapping should survive a fork and most clones naturally.
1268 * For the system call to be completely portable it has to propagate
1269 * these mapped files after an execve(). Environment variables have
1270 * been added to do that. See filefd.c for details.
1271 */
1272 filefd_opened(rv, SIGNAL_FD_TYPE);
1273 }
1274
1275 ALOGV("%s: return(rv:%d); }", __func__, rv);
1276 return rv;
1277 }
1278
1279
1280 #if 0
1281 /*
1282 * signalfd() isn't available in Bionic yet. When it is, it will be implemented like
1283 * the glibc version where the sigsetsize is computed in the bionic code and passed
1284 * down to the kernel with __NR_signalfd4.
1285 *
1286 * This function can't be called from bionic, so there isn't an entry in the experimental
1287 * linker.cpp table for testing and this function.
1288 */
1289 int WRAP(signalfd)(int fd, const sigset_portable_t *portable_sigmask, int portable_flags)
1290 {
1291 int portable_sigsetsize = sizeof(sigset_portable_t);
1292 int rv;
1293
1294 ALOGV("%s(fd:%d, portable_sigmask:%p, portable_flags:0x%x) {", __func__,
1295 fd, portable_sigmask, portable_flags);
1296
1297 rv = do_signalfd4_portable(fd, portable_sigsetsize, portable_sigmask, portable_flags);
1298
1299 ALOGV("%s: return(rv:%d); }", __func__, rv);
1300 return rv;
1301 }
1302 #endif
1303
1304
1305 /*
1306 * Called by read_portable() to do signalfd read() mapping.
1307 */
read_signalfd_mapper(int fd,void * buf,size_t count)1308 __hidden int read_signalfd_mapper(int fd, void *buf, size_t count)
1309 {
1310 int rv;
1311
1312 ALOGV("%s(fd:%d, buf:0x%p, count:%d) {", __func__,
1313 fd, buf, count);
1314
1315 rv = read(fd, buf, count);
1316 if (rv > 0) {
1317 int siginfos = rv/sizeof(struct signalfd_siginfo);
1318 struct signalfd_siginfo *si = (struct signalfd_siginfo *) buf;
1319 int i;
1320
1321 /* Read signalfd_siginfo structure(s) if read is large enough */
1322 for (i = 0; i < siginfos; i++, si++) {
1323 int ssi_signo;
1324
1325 ssi_signo = si->ssi_signo;
1326 si->ssi_signo = signum_ntop(si->ssi_signo);
1327 ALOGV("%s: si->ssi_signo:%d = signum_ntop(si->ssi_signo:%d); i:%d", __func__,
1328 si->ssi_signo, ssi_signo, i);
1329
1330 si->ssi_errno = errno_ntop(si->ssi_errno);
1331
1332 /*
1333 * The ssi_codes appear to be generic; defined in
1334 * the kernel in include/asm-generic/siginfo.h
1335 */
1336 if (si->ssi_status > 0 && si->ssi_status <= NSIG) {
1337 si->ssi_status = signum_ntop(si->ssi_status);
1338 }
1339
1340 /*
1341 * The rest of the struct members, like
1342 * ssi_trapno, ssi_int, ssi_ptr
1343 * are not likely worth dealing with.
1344 */
1345 }
1346 }
1347
1348 ALOGV("%s: return(rv:%d); }", __func__, rv);
1349 return rv;
1350 }
1351
WRAP(sigsuspend)1352 int WRAP(sigsuspend)(const sigset_portable_t *portable_sigmask)
1353 {
1354 int rv;
1355 sigset_t mips_sigmask;
1356
1357 ALOGV("%s(portable_sigmask:%p) {", __func__, portable_sigmask);
1358
1359 if (invalid_pointer((void *)portable_sigmask)) {
1360 *REAL(__errno)() = EFAULT;
1361 rv = -1;
1362 } else {
1363 sigset_pton((sigset_portable_t *)portable_sigmask, &mips_sigmask);
1364 rv = REAL(sigsuspend)(&mips_sigmask);
1365 }
1366
1367 ALOGV("%s: return(rv:%d); }", __func__, rv);
1368 return rv;
1369 }
1370
1371
WRAP(sigpending)1372 int WRAP(sigpending)(sigset_portable_t *portable_sigset)
1373 {
1374 int rv;
1375 sigset_t mips_sigset;
1376
1377 ALOGV("%s(portable_sigset:%p) {", __func__,
1378 portable_sigset);
1379
1380 if (invalid_pointer((void *)portable_sigset)) {
1381 *REAL(__errno)() = EFAULT;
1382 rv = -1;
1383 } else {
1384 rv = REAL(sigpending)(&mips_sigset);
1385 sigset_ntop(&mips_sigset, portable_sigset);
1386 }
1387
1388 ALOGV("%s: return(rv:%d); }", __func__, rv);
1389 return rv;
1390 }
1391
1392
WRAP(sigwait)1393 int WRAP(sigwait)(const sigset_portable_t *portable_sigset, int *ptr_to_portable_sig)
1394 {
1395 int rv;
1396 sigset_t mips_sigset;
1397 int mips_sig;
1398 int portable_sig;
1399
1400 ALOGV("%s(portable_sigset:%p, ptr_to_portable_sig:%p) {", __func__,
1401 portable_sigset, ptr_to_portable_sig);
1402
1403 if (invalid_pointer((void *)portable_sigset)) {
1404 *REAL(__errno)() = EFAULT;
1405 rv = -1;
1406 } else {
1407 sigset_pton((sigset_portable_t *)portable_sigset, &mips_sigset);
1408
1409 rv = REAL(sigwait)(&mips_sigset, &mips_sig);
1410
1411 portable_sig = signum_ntop(mips_sig);
1412 *ptr_to_portable_sig = portable_sig;
1413 }
1414 ALOGV("%s: return(rv:%d); }", __func__, rv);
1415 return rv;
1416 }
1417
1418
WRAP(siginterrupt)1419 int WRAP(siginterrupt)(int portable_signum, int flag)
1420
1421 {
1422 int rv;
1423 int mips_signum;
1424
1425 ALOGV("%s(portable_signum:%d, flag:0x%x) {", __func__,
1426 portable_signum, flag);
1427
1428 mips_signum = signum_pton(portable_signum);
1429
1430 /*
1431 * If a non-zero portable_signum has been mapped to 0,
1432 * it's unsupported and will be ignored.
1433 */
1434 if ((portable_signum != 0) && (mips_signum == 0)) {
1435 rv = 0;
1436 } else {
1437 rv = REAL(siginterrupt)(mips_signum, flag);
1438 }
1439 ALOGV("%s: return(rv:%d); }", __func__, rv);
1440 return rv;
1441 }
1442
1443
do_sigmask(int portable_how,const sigset_portable_t * portable_sigset,sigset_portable_t * portable_oldset,sigmask_fn fn,rt_sigmask_fn rt_fn)1444 __hidden int do_sigmask(int portable_how, const sigset_portable_t *portable_sigset,
1445 sigset_portable_t *portable_oldset, sigmask_fn fn,
1446 rt_sigmask_fn rt_fn)
1447 {
1448 int rv;
1449 int how;
1450 char *how_name;
1451 sigset_t mips_sigset, *mips_sigset_p;
1452 sigset_t mips_oldset, *mips_oldset_p;
1453
1454 ALOGV("%s(portable_how:%d, portable_sigset:%p, portable_oldset:%p, fn:%p, rt_fn:%p) {",
1455 __func__, portable_how, portable_sigset, portable_oldset, fn, rt_fn);
1456
1457 switch(portable_how) {
1458 case SIG_BLOCK_PORTABLE: how = SIG_BLOCK; how_name = "SIG_BLOCK"; break;
1459 case SIG_UNBLOCK_PORTABLE: how = SIG_UNBLOCK; how_name = "SIG_UNBLOCK"; break;
1460 case SIG_SETMASK_PORTABLE: how = SIG_SETMASK; how_name = "SIG_SETMASK"; break;
1461
1462 default:
1463 ALOGE("%s: portable_how:%d NOT SUPPORTED!", __func__, portable_how);
1464 how = -1;
1465 break;
1466 }
1467
1468 if (invalid_pointer((void *)portable_sigset)) {
1469 mips_sigset_p = (sigset_t *) portable_sigset;
1470 } else {
1471 mips_sigset_p = &mips_sigset;
1472 memset(mips_sigset_p, 0, sizeof(mips_sigset));
1473 sigemptyset(mips_sigset_p);
1474 sigset_pton((sigset_portable_t *)portable_sigset, &mips_sigset);
1475 }
1476
1477 if (invalid_pointer((void *)portable_oldset)) {
1478 mips_oldset_p = (sigset_t *) portable_oldset;
1479 } else {
1480 mips_oldset_p = &mips_oldset;
1481 memset(mips_oldset_p, 0, sizeof(mips_oldset));
1482 sigemptyset(mips_oldset_p);
1483 }
1484
1485 if (fn != NULL) {
1486 ASSERT(rt_fn == NULL);
1487 rv = fn(how, mips_sigset_p, mips_oldset_p);
1488 } else {
1489 ASSERT(rt_fn != NULL);
1490 rv = rt_fn(how, mips_sigset_p, mips_oldset_p, sizeof(sigset_t));
1491 }
1492
1493 if (rv == 0 && !invalid_pointer(portable_oldset)) {
1494 /* Map returned mips_oldset to portable_oldset for return to caller */
1495 sigset_ntop(mips_oldset_p, portable_oldset);
1496 }
1497
1498 ALOGV("%s: return(rv:%d); }", __func__, rv);
1499 return rv;
1500 }
1501
1502
WRAP(sigprocmask)1503 int WRAP(sigprocmask)(int portable_how, const sigset_portable_t *portable_sigset,
1504 sigset_portable_t *portable_oldset)
1505 {
1506 extern int REAL(sigprocmask)(int, const sigset_t *, sigset_t *);
1507 int rv;
1508
1509 ALOGV(" ");
1510 ALOGV("%s(portable_how:%d, portable_sigset:%p, portable_oldset:%p) {", __func__,
1511 portable_how, portable_sigset, portable_oldset);
1512
1513 rv = do_sigmask(portable_how, portable_sigset, portable_oldset, REAL(sigprocmask), NULL);
1514
1515 ALOGV("%s: return(rv:%d); }", __func__, rv);
1516 return rv;
1517 }
1518
1519
WRAP(__rt_sigaction)1520 int WRAP(__rt_sigaction)(int portable_signum, const struct sigaction_portable *act,
1521 struct sigaction_portable *oldact, size_t sigsetsize)
1522 {
1523 extern int REAL(__rt_sigaction)(int , const struct sigaction *, struct sigaction *, size_t);
1524 int rv;
1525
1526 ALOGV(" ");
1527 ALOGV("%s(portable_signum:%d, act:%p, oldset:%p, sigsetsize:%d) {", __func__,
1528 portable_signum, act, oldact, sigsetsize);
1529
1530 /* NOTE: ARM kernel is expecting sizeof(sigset_t) to be 8 bytes */
1531 if (sigsetsize != (2* sizeof(long))) {
1532 *REAL(__errno)() = EINVAL;
1533 rv = -1;
1534 goto done;
1535 }
1536 rv = do_sigaction_portable(portable_signum, act, oldact, NULL, REAL(__rt_sigaction));
1537
1538 done:
1539 ALOGV("%s: return(rv:%d); }", __func__, rv);
1540 return rv;
1541 }
1542
WRAP(__rt_sigprocmask)1543 int WRAP(__rt_sigprocmask)(int portable_how,
1544 const sigset_portable_t *portable_sigset,
1545 sigset_portable_t *portable_oldset,
1546 size_t sigsetsize)
1547 {
1548 extern int REAL(__rt_sigprocmask)(int, const sigset_t *, sigset_t *, size_t);
1549 int rv;
1550
1551 ALOGV(" ");
1552 ALOGV("%s(portable_how:%d, portable_sigset:%p, portable_oldset:%p, sigsetsize:%d) {",
1553 __func__, portable_how, portable_sigset, portable_oldset, sigsetsize);
1554
1555 /* NOTE: ARM kernel is expecting sizeof(sigset_t) to be 8 bytes */
1556 if (sigsetsize != (2* sizeof(long))) {
1557 *REAL(__errno)() = EINVAL;
1558 rv = -1;
1559 goto done;
1560 }
1561 rv = do_sigmask(portable_how, portable_sigset, portable_oldset, NULL, REAL(__rt_sigprocmask));
1562
1563 done:
1564 ALOGV("%s: return(rv:%d); }", __func__, rv);
1565
1566 return rv;
1567 }
1568
1569
WRAP(__rt_sigtimedwait)1570 int WRAP(__rt_sigtimedwait)(const sigset_portable_t *portable_sigset,
1571 siginfo_portable_t *portable_siginfo,
1572 const struct timespec *timeout,
1573 size_t portable_sigsetsize)
1574 {
1575 extern int REAL(__rt_sigtimedwait)(const sigset_t *, siginfo_t *, const struct timespec *, size_t);
1576
1577 sigset_t native_sigset_struct;
1578 sigset_t *native_sigset = &native_sigset_struct;
1579 siginfo_t native_siginfo_struct;
1580 siginfo_t *native_siginfo;
1581 int rv;
1582
1583 ALOGV(" ");
1584 ALOGV("%s(portable_sigset:%p, portable_siginfo:%p, timeout:%p, portable_sigsetsize:%d) {",
1585 __func__, portable_sigset, portable_siginfo, timeout, portable_sigsetsize);
1586
1587 /* NOTE: ARM kernel is expecting sizeof(sigset_t) to be 8 bytes */
1588 if (portable_sigsetsize != (2* sizeof(long))) {
1589 *REAL(__errno)() = EINVAL;
1590 rv = -1;
1591 goto done;
1592 }
1593 if (portable_sigset == NULL) {
1594 native_sigset = NULL;
1595 } else {
1596 sigset_pton((sigset_portable_t *)portable_sigset, native_sigset);
1597 }
1598 if (portable_siginfo == NULL) {
1599 native_siginfo = NULL;
1600 } else {
1601 native_siginfo = &native_siginfo_struct;
1602 }
1603 rv = REAL(__rt_sigtimedwait)(native_sigset, native_siginfo, timeout, sizeof(sigset_t));
1604 if (rv == 0 && native_siginfo != NULL) {
1605 /* Map siginfo struct from native to portable format. */
1606 siginfo_ntop(native_siginfo, portable_siginfo);
1607 }
1608
1609 done:
1610 ALOGV("%s: return(rv:%d); }", __func__, rv);
1611 return rv;
1612 }
1613
1614
1615 #ifdef __NR_rt_sigqueueinfo
1616
1617 #if 0
1618 /*
1619 * sigqueue():
1620 * This function became available in UNIX GLIBC after 1993.
1621 * It's not available in any versions of Android yet, and
1622 * it can't be called via syscall(). It's been useful for
1623 * testing with the LTP by the posix testsuite, and tests
1624 * show that it works fine.
1625 *
1626 * NOTE:
1627 * Android has in incorrect limit on the number of queueable signals
1628 * defined in libc/unistd/sysconf.c:
1629 *
1630 * #define SYSTEM_SIGQUEUE_MAX 32
1631 *
1632 * sigqueue() must return EAGAIN if exceeded and we don't on Android.
1633 */
1634 int WRAP(sigqueue)(pid_t pid, int portable_sig, const union sigval value)
1635 {
1636 siginfo_t native_siginfo;
1637 siginfo_t *native_sip;
1638 siginfo_portable_t portable_siginfo;
1639 siginfo_portable_t *portable_sip;
1640 int native_sig;
1641 int rv;
1642
1643 ALOGV(" ");
1644 ALOGV("%s(pid:%d, portable_sig:%d, value:%p) {", __func__,
1645 pid, portable_sig, value.sival_ptr);
1646
1647 native_sig = signum_pton(portable_sig);
1648 native_sip = &native_siginfo;
1649
1650 portable_sip = &portable_siginfo;
1651 portable_sip->si_signo = 0; /* Filled in by the kernel */
1652 portable_sip->si_code = SI_QUEUE;
1653 portable_sip->si_pid = getpid(); /* Process ID of sender */
1654 portable_sip->si_uid = getuid(); /* Real UID of sender */
1655 portable_sip->si_value = value; /* Last arg supplied */
1656
1657 siginfo_pton(portable_sip, native_sip);
1658
1659 /*
1660 * man page says sigqueue() is implemented via rt_sigqueueinfo().
1661 */
1662 ALOGV("%s: calling syscall(__NR_rt_sigqueueinfo:%d, pid:%d, native_sig:%d, native_sip:%p);",
1663 __func__, __NR_rt_sigqueueinfo, pid, native_sig, native_sip);
1664
1665 rv = syscall(__NR_rt_sigqueueinfo, pid, native_sig, native_sip);
1666
1667 ALOGV("%s: return(rv:%d); }", __func__, rv);
1668 return rv;
1669 }
1670 #endif
1671
1672
1673 /*
1674 * Real Time version of sigqueueinfo().
1675 */
WRAP(rt_sigqueueinfo)1676 int WRAP(rt_sigqueueinfo)(pid_t pid, int portable_sig, siginfo_portable_t *portable_sip)
1677 {
1678 int native_sig;
1679 siginfo_t native_siginfo, *native_sip;
1680 int rv;
1681
1682 ALOGV(" ");
1683 ALOGV("%s(pid:%d, portable_sig:%d, portable_sip:%p) {", __func__,
1684 pid, portable_sig, portable_sip);
1685
1686 native_sig = signum_pton(portable_sig);
1687
1688 /*
1689 * If a non-zero portable_signum has been mapped to 0,
1690 * it's unsupported and will be ignored.
1691 */
1692 if ((portable_sig != 0) && (native_sig == 0)) {
1693 rv = 0;
1694 goto done;
1695 }
1696
1697 if (portable_sip != NULL) {
1698 native_sip = &native_siginfo;
1699 siginfo_pton(portable_sip, native_sip);
1700 } else {
1701 native_sip = NULL;
1702 }
1703 rv = syscall(__NR_rt_sigqueueinfo, pid, native_sig, native_sip);
1704
1705 done:
1706 ALOGV("%s: return(rv:%d); }", __func__, rv);
1707 return rv;
1708 }
1709 #endif /* __NR_rt_sigqueueinfo */
1710
1711
1712 #ifdef __NR_rt_tgsigqueueinfo
1713 /*
1714 * Thread Group flavor of the real time version of sigqueueinfo().
1715 */
WRAP(rt_tgsigqueueinfo)1716 int WRAP(rt_tgsigqueueinfo)(pid_t tgid, pid_t pid, int portable_sig,
1717 siginfo_portable_t *portable_sip)
1718 {
1719 siginfo_t native_siginfo, *native_sip;
1720 int native_sig;
1721 int rv;
1722
1723 ALOGV(" ");
1724 ALOGV("%s(tgid:%d, pid:%d, portable_sig:%d, portable_sip:%p) {", __func__,
1725 tgid, pid, portable_sig, portable_sip);
1726
1727 native_sig = signum_pton(portable_sig);
1728
1729 /*
1730 * If a non-zero portable_signum has been mapped to 0,
1731 * it's unsupported and will be ignored.
1732 */
1733 if ((portable_sig != 0) && (native_sig == 0)) {
1734 rv = 0;
1735 goto done;
1736 }
1737 if (portable_sip != NULL) {
1738 native_sip = &native_siginfo;
1739 siginfo_pton(portable_sip, native_sip);
1740 } else {
1741 native_sip = NULL;
1742 }
1743 rv = syscall(__NR_rt_tgsigqueueinfo, pid, native_sig, native_sip);
1744
1745 done:
1746 ALOGV("%s: return(rv:%d); }", __func__, rv);
1747 return rv;
1748 }
1749 #endif /* __NR_rt_tgsigqueueinfo */
1750
1751
1752 /*
1753 * ss_flags and ss_size are located in different locations in stack_t structure:
1754 *
1755 * Incomming ARM/Portable stack_t: Outgoing MIPS stack_t:
1756 * ------------------------------- ----------------------------
1757 * typedef struct sigaltstack { typedef struct sigaltstack {
1758 * void __user *ss_sp; void *ss_sp;
1759 * int ss_flags; size_t ss_size;
1760 * size_t ss_size; int ss_flags;
1761 * } stack_t;
1762 *
1763 */
WRAP(sigaltstack)1764 int WRAP(sigaltstack)(const portable_stack_t *ss, portable_stack_t *oss)
1765 {
1766 int rv;
1767 stack_t new_stack, *mips_ss;
1768 stack_t old_stack, *mips_oss;
1769
1770 ALOGV(" ");
1771 ALOGV("%s(ss:%p, oss:%p) {", __func__, ss, oss);
1772
1773 if (ss == NULL) {
1774 mips_ss = NULL;
1775 } else {
1776 if (invalid_pointer((void *)ss)) {
1777 ALOGE("%s: invalid_pointer(ss:%p): Let kernel set proper errno and set return value.",
1778 __func__, ss);
1779
1780 mips_ss = (stack_t *) ss;
1781 } else {
1782 memset(&new_stack, 0, sizeof(stack_t));
1783 new_stack.ss_sp = ss->ss_sp;
1784 new_stack.ss_flags = ss->ss_flags;
1785 new_stack.ss_size = ss->ss_size;
1786 mips_ss = &new_stack;
1787 }
1788 }
1789 if (oss == NULL) {
1790 mips_oss = NULL;
1791 } else {
1792 if (invalid_pointer((void *)oss)) {
1793 ALOGE("%s: invalid_pointer(oss:%p): Let kernel set proper errno and return value.",
1794 __func__, oss);
1795
1796 mips_oss = (stack_t *)oss;
1797 } else {
1798 memset(&old_stack, 0, sizeof(stack_t));
1799 mips_oss = &old_stack;
1800 }
1801 }
1802
1803 rv = REAL(sigaltstack)(mips_ss, mips_oss);
1804
1805 if (!invalid_pointer(oss)) {
1806 oss->ss_sp = old_stack.ss_sp;
1807 oss->ss_flags = old_stack.ss_flags;
1808 oss->ss_size = old_stack.ss_size;
1809 }
1810 ALOGV("%s: return(rv:%d); }", __func__, rv);
1811
1812 return rv;
1813 }
1814