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