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