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