Home | History | Annotate | Download | only in arch-mips
      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 <signal.h>
     21 #include <signal_portable.h>
     22 #include <time.h>
     23 #include <errno.h>
     24 #include <errno_portable.h>
     25 #include <eventfd_portable.h>
     26 #include <filefd_portable.h>
     27 #include <inotify_portable.h>
     28 #include <timerfd_portable.h>
     29 #include <asm/unistd-portable.h>
     30 #include <asm/unistd.h>
     31 
     32 #define PORTABLE_TAG "syscall_portable"
     33 #include <log_portable.h>
     34 
     35 #if __NR_gettimeofday_portable == __NR_gettimeofday
     36 #error "Bad build environment"
     37 #endif
     38 
     39 /*
     40  * Minimal syscall support for LTP testing.
     41  * These are the system calls that LTP references explicitly.
     42  * Not all of them are exported via bionic header so use #ifdef.
     43  *
     44  * TODO:
     45  *    Add existing portable system calls currently redirected from
     46  *    experimental Bionic linker code so that calls to them via
     47  *    syscall() are also processed. For example, LTP only calls open()
     48  *    directly and never does a syscall(__NR_open, ...).
     49  */
     50 
     51 
     52 extern int REAL(syscall)(int, ...);
     53 
     54 #define MAXARGS 8
     55 
     56 int WRAP(syscall)(int portable_number, ...)
     57 {
     58     va_list ap;
     59     int native_number, ret;
     60     int i, nargs, args[MAXARGS];
     61 
     62     ALOGV(" ");
     63     ALOGV("%s(portable_number:%d, ...) {", __func__, portable_number);
     64 
     65     switch (portable_number) {
     66 #ifdef __NR_add_key_portable
     67     case __NR_add_key_portable: native_number = __NR_add_key; break;
     68 #endif
     69 
     70 #ifdef __NR_cacheflush_portable
     71     case __NR_cacheflush_portable: {
     72         long start, end, flags;
     73 
     74         va_start(ap, portable_number);
     75         start = va_arg(ap, long);
     76         end = va_arg(ap, long);
     77         flags = va_arg(ap, long);
     78         va_end(ap);
     79 
     80         ret = cacheflush(start, end, flags);
     81         goto done;
     82     }
     83 #endif
     84 
     85 #ifdef __NR_capget_portable
     86     case __NR_capget_portable: native_number = __NR_capget; break;
     87 #endif
     88 
     89 #ifdef __NR_capset_portable
     90     case __NR_capset_portable: native_number = __NR_capset; break;
     91 #endif
     92 
     93 #ifdef __NR_clock_getres_portable
     94     case __NR_clock_getres_portable: native_number = __NR_clock_getres; break;
     95 #endif
     96 
     97 #ifdef __NR_clock_nanosleep
     98     case __NR_clock_nanosleep_portable: native_number = __NR_clock_nanosleep; break;
     99 #endif
    100 
    101 #ifdef __NR_dup3_portable
    102     case __NR_dup3_portable: native_number = __NR_dup3; break;
    103 #endif
    104 
    105 #ifdef __NR_epoll_create_portable
    106     case __NR_epoll_create_portable: native_number = __NR_epoll_create; break;
    107 #endif
    108 
    109 #ifdef __NR_epoll_create1_portable
    110     case __NR_epoll_create1_portable: native_number = __NR_epoll_create1; break;
    111 #endif
    112 
    113 #ifdef __NR_eventfd_portable
    114     /*
    115      * Prior to 2.6.27 we only had this system call,
    116      * which didn't have a flags argument. The kernel
    117      * just provides a zero for flags when this system
    118      * call number is used.
    119      */
    120     case __NR_eventfd_portable: {
    121         unsigned int initval;                        /* 64-bit counter initial value */
    122         int flags = 0;
    123 
    124         va_start(ap, portable_number);
    125 
    126         initval  = va_arg(ap, int);
    127 
    128         va_end(ap);
    129 
    130         ret = WRAP(eventfd)(initval, flags);      /* Android uses __NR_eventfd2 in eventfd() */
    131         goto done;
    132     }
    133 #endif
    134 
    135 #ifdef __NR_eventfd2_portable
    136     /*
    137      * Starting with Linux 2.6.27 a flags argument was added.
    138      * Both Bionic and glibc implement the eventfd() now with
    139      * the additional flags argument.
    140      */
    141     case __NR_eventfd2_portable: {
    142         unsigned int initval;                        /* 64-bit counter initial value */
    143         int flags;
    144 
    145         va_start(ap, portable_number);
    146 
    147         initval  = va_arg(ap, int);
    148         flags = va_arg(ap, int);
    149 
    150         va_end(ap);
    151 
    152         ret = WRAP(eventfd)(initval, flags);      /* Android uses __NR_eventfd2 in eventfd() */
    153         goto done;
    154     }
    155 #endif
    156 
    157 #ifdef __NR_exit_group_portable
    158     case __NR_exit_group_portable: native_number = __NR_exit_group; break;
    159 #endif
    160 
    161 #ifdef __NR_faccessat_portable
    162     case __NR_faccessat_portable: native_number = __NR_faccessat; break;
    163 #endif
    164 
    165 #ifdef __NR_fallocate_portable
    166     case __NR_fallocate_portable: native_number = __NR_fallocate; break;
    167 #endif
    168 
    169 #ifdef __NR_fchmodat_portable
    170     case __NR_fchmodat_portable: native_number = __NR_fchmodat; break;
    171 #endif
    172 
    173 #ifdef __NR_fchownat_portable
    174     case __NR_fchownat_portable: native_number = __NR_fchownat; break;
    175 #endif
    176 
    177 #ifdef __NR_fstatat64_portable
    178     case __NR_fstatat64_portable: native_number = __NR_fstatat64; break;
    179 #endif
    180 
    181 #ifdef __NR_futimesat_portable
    182     case __NR_futimesat_portable: native_number = __NR_futimesat; break;
    183 #endif
    184 
    185 #ifdef __NR_getegid_portable
    186     case __NR_getegid_portable: native_number = __NR_getegid; break;
    187 #endif
    188 
    189 #ifdef __NR_geteuid_portable
    190     case __NR_geteuid_portable: native_number = __NR_geteuid; break;
    191 #endif
    192 
    193 #ifdef __NR_getgid_portable
    194     case __NR_getgid_portable: native_number = __NR_getgid; break;
    195 #endif
    196 
    197 #ifdef __NR_get_mempolicy_portable
    198     case __NR_get_mempolicy_portable: native_number = __NR_get_mempolicy; break;
    199 #endif
    200 
    201 #ifdef __NR_get_robust_list_portable
    202     case __NR_get_robust_list_portable: native_number = __NR_get_robust_list; break;
    203 #endif
    204 
    205 #ifdef __NR_gettid_portable
    206     case __NR_gettid_portable: native_number = __NR_gettid; break;
    207 #endif
    208 
    209 #ifdef __NR_gettimeofday_portable
    210     case __NR_gettimeofday_portable: native_number = __NR_gettimeofday; break;
    211 #endif
    212 
    213 #ifdef __NR_getuid_portable
    214     case __NR_getuid_portable: native_number = __NR_getuid; break;
    215 #endif
    216 
    217 #ifdef __NR_inotify_init_portable
    218     case __NR_inotify_init_portable: native_number = __NR_inotify_init; break;
    219 #endif
    220 
    221 #ifdef __NR_inotify_add_watch_portable
    222     case __NR_inotify_add_watch_portable: native_number = __NR_inotify_add_watch; break;
    223 #endif
    224 
    225 #ifdef __NR_inotify_init1_portable
    226     case __NR_inotify_init1_portable: {
    227         int portable_flags;
    228 
    229         va_start(ap, portable_number);
    230         portable_flags = va_arg(ap, int);
    231         va_end(ap);
    232 
    233         ret = WRAP(inotify_init1)(portable_flags);
    234         goto done;
    235     }
    236 #endif
    237 
    238 #ifdef __NR_keyctl_portable
    239     case __NR_keyctl_portable: native_number = __NR_keyctl; break;
    240 #endif
    241 
    242 #ifdef __NR_linkat
    243     case __NR_linkat_portable: native_number = __NR_linkat; break;
    244 #endif
    245 
    246 #ifdef __NR_mbind_portable
    247     case __NR_mbind_portable: native_number = __NR_mbind; break;
    248 #endif
    249 
    250 #ifdef __NR_mkdirat_portable
    251     case __NR_mkdirat_portable: native_number = __NR_mkdirat; break;
    252 #endif
    253 
    254 #ifdef __NR_mknodat_portable
    255     case __NR_mknodat_portable: native_number = __NR_mknodat; break;
    256 #endif
    257 
    258 #ifdef __NR_openat_portable
    259     case __NR_openat_portable: native_number = __NR_openat; break;
    260 #endif
    261 
    262 #ifdef __NR_pipe2_portable
    263     case __NR_pipe2_portable: {
    264         int *pipefd_ptr;
    265         int portable_flags;
    266 
    267         va_start(ap, portable_number);
    268         pipefd_ptr = va_arg(ap, int *);
    269         portable_flags = va_arg(ap, int);
    270         va_end(ap);
    271 
    272         ret = WRAP(pipe2)(pipefd_ptr, portable_flags);
    273         goto done;
    274     }
    275 #endif
    276 
    277 #ifdef __NR_readahead_portable
    278     case __NR_readahead_portable: native_number = __NR_readahead; break;
    279 #endif
    280 
    281 #ifdef __NR_readlinkat_portable
    282     case __NR_readlinkat_portable: native_number = __NR_readlinkat; break;
    283 #endif
    284 
    285 #ifdef __NR_renameat_portable
    286     case __NR_renameat_portable: native_number = __NR_renameat; break;
    287 #endif
    288 
    289 #ifdef __NR_rt_sigaction_portable
    290     case __NR_rt_sigaction_portable: {
    291         int sig;
    292         struct sigaction_portable *act;
    293         struct sigaction_portable *oact;
    294         size_t sigsetsize;
    295 
    296         va_start(ap, portable_number);
    297         sig = va_arg(ap, int);
    298         act = va_arg(ap, struct sigaction_portable *);
    299         oact = va_arg(ap, struct sigaction_portable *);
    300         sigsetsize = va_arg(ap, size_t);
    301         va_end(ap);
    302         return WRAP(__rt_sigaction)(sig, act, oact, sigsetsize);
    303     }
    304 #endif
    305 
    306 #ifdef __NR_rt_sigprocmask_portable
    307     case __NR_rt_sigprocmask_portable: {
    308         int how;
    309         const sigset_portable_t *set;
    310         sigset_portable_t *oset;
    311         size_t sigsetsize;
    312 
    313         va_start(ap, portable_number);
    314         how = va_arg(ap, int);
    315         set = va_arg(ap, sigset_portable_t *);
    316         oset = va_arg(ap, sigset_portable_t *);
    317         sigsetsize = va_arg(ap, size_t);
    318         va_end(ap);
    319 
    320         ret = WRAP(__rt_sigprocmask)(how, set, oset, sigsetsize);
    321         goto done;
    322     }
    323 #endif
    324 
    325 #ifdef __NR_rt_sigtimedwait_portable
    326     case __NR_rt_sigtimedwait_portable: {
    327         const sigset_portable_t *set;
    328         siginfo_portable_t *info;
    329         const struct timespec *timeout;
    330         size_t sigsetsize;
    331 
    332         va_start(ap, portable_number);
    333         set = va_arg(ap, sigset_portable_t *);
    334         info = va_arg(ap, siginfo_portable_t *);
    335         timeout = va_arg(ap, struct timespec *);
    336         sigsetsize = va_arg(ap, size_t);
    337         va_end(ap);
    338 
    339         ret = WRAP(__rt_sigtimedwait)(set, info, timeout, sigsetsize);
    340         goto done;
    341     }
    342 #endif
    343 
    344 #ifdef __NR_rt_sigqueueinfo_portable
    345     case __NR_rt_sigqueueinfo_portable: {
    346         pid_t pid;
    347         int sig;
    348         siginfo_portable_t *uinfo;
    349 
    350         va_start(ap, portable_number);
    351         pid = va_arg(ap, pid_t);
    352         sig = va_arg(ap, int);
    353         uinfo = va_arg(ap, siginfo_portable_t *);
    354         va_end(ap);
    355 
    356         ret = WRAP(rt_sigqueueinfo)(pid, sig, uinfo);
    357         goto done;
    358     }
    359 #endif
    360 
    361 #ifdef __NR_setgid_portable
    362     case __NR_setgid_portable: native_number = __NR_setgid; break;
    363 #endif
    364 
    365 #ifdef __NR_set_mempolicy_portable
    366     case __NR_set_mempolicy_portable: native_number = __NR_set_mempolicy; break;
    367 #endif
    368 
    369 #ifdef __NR_set_robust_list_portable
    370     case __NR_set_robust_list_portable: native_number = __NR_set_robust_list; break;
    371 #endif
    372 
    373 #ifdef __NR_set_tid_address_portable
    374     case __NR_set_tid_address_portable: native_number = __NR_set_tid_address; break;
    375 #endif
    376 
    377 #ifdef __NR_sgetmask_portable
    378     case __NR_sgetmask_portable: native_number = __NR_sgetmask; break;
    379 #endif
    380 
    381 #ifdef __NR_signalfd4_portable
    382     case __NR_signalfd4_portable: {
    383         int fd;
    384         sigset_portable_t *portable_sigmask;
    385         int sigsetsize;
    386         int flags;
    387 
    388         va_start(ap, portable_number);
    389 
    390         fd = va_arg(ap, int);
    391         portable_sigmask = va_arg(ap, sigset_portable_t *);
    392         sigsetsize = va_arg(ap, int);
    393         flags = va_arg(ap, int);
    394 
    395         va_end(ap);
    396 
    397         ret = do_signalfd4_portable(fd, (const sigset_portable_t *) portable_sigmask, sigsetsize,
    398                                     flags);
    399         goto done;
    400     }
    401 #endif
    402 
    403 #ifdef __NR_socketcall_portable
    404     case __NR_socketcall_portable: native_number = __NR_socketcall; break;
    405 #endif
    406 
    407 #ifdef __NR_splice_portable
    408     case __NR_splice_portable: native_number = __NR_splice; break;
    409 #endif
    410 
    411 /* REMIND - DOUBLE CHECK THIS ONE */
    412 #ifdef __NR_ssetmask_portable
    413     case __NR_ssetmask_portable: native_number = __NR_ssetmask; break;
    414 #endif
    415 
    416 #ifdef __NR_swapoff_portable
    417     case __NR_swapoff_portable: native_number = __NR_swapoff; break;
    418 #endif
    419 
    420 #ifdef __NR_swapon_portable
    421     case __NR_swapon_portable: native_number = __NR_swapon; break;
    422 #endif
    423 
    424 #ifdef __NR_symlinkat_portable
    425     case __NR_symlinkat_portable: native_number = __NR_symlinkat; break;
    426 #endif
    427 
    428 /*
    429  * ARM uses the new, version 2, form of sync_file_range() which
    430  * doesn't waste 32 bits between the 32 bit arg and the 64 bit arg.
    431  * It does this by moving the last 32 bit arg and placing it with
    432  * the 1st 32 bit arg.
    433  *
    434  * Here's the trivial mapping function in the kernel ARM code:
    435  *
    436  *   sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes) {
    437  *       return sys_sync_file_range(fd, offset, nbytes, flags);
    438  *   }
    439  *
    440  * For portability we have to do a similar mapping for the native/MIPS system
    441  * call but have to provide the alignment padding expected by the sync_file_range()
    442  * system call. We avoid alignment issues while using varargs by avoiding the use
    443  * of 64 bit args.
    444  */
    445 #if defined( __NR_arm_sync_file_range_portable)
    446     case __NR_arm_sync_file_range_portable: native_number = __NR_sync_file_range; {
    447         int fd;
    448         int flags;
    449         int offset_low, offset_high;
    450         int nbytes_low, nbytes_high;
    451         int align_fill = 0;
    452 
    453 
    454         va_start(ap, portable_number);
    455         fd = va_arg(ap, int);
    456         flags = va_arg(ap, int);
    457         offset_low = va_arg(ap, int);
    458         offset_high = va_arg(ap, int);
    459         nbytes_low = va_arg(ap, int);
    460         nbytes_high = va_arg(ap, int);
    461         va_end(ap);
    462 
    463         ALOGV("%s: Calling syscall(native_number:%d:'sync_file_range', fd:%d, "
    464               "align_fill:0x%x, offset_low:0x%x, offset_high:0x%x, "
    465               "nbytes_low:0x%x, nbytes_high:0x%x, flags:0x%x);", __func__,
    466               native_number, fd, align_fill, offset_low, offset_high,
    467               nbytes_low, nbytes_high, flags);
    468 
    469         ret = REAL(syscall)(native_number, fd, align_fill, offset_low, offset_high,
    470                       nbytes_low, nbytes_high, flags);
    471 
    472         goto done;
    473     }
    474 #endif
    475 
    476 
    477 #ifdef __NR__sysctl_portable
    478     case __NR__sysctl_portable: native_number = __NR__sysctl; break;
    479 #endif
    480 
    481 #ifdef __NR_sysfs_portable
    482     case __NR_sysfs_portable: native_number = __NR_sysfs; break;
    483 #endif
    484 
    485 #ifdef __NR_syslog_portable
    486     case __NR_syslog_portable: native_number = __NR_syslog; break;
    487 #endif
    488 
    489 #ifdef __NR_tee_portable
    490     case __NR_tee_portable: native_number = __NR_tee; break;
    491 #endif
    492 
    493 #ifdef __NR_timer_create_portable
    494     case __NR_timer_create_portable: {
    495         clockid_t clockid;
    496         struct sigevent *evp;
    497         timer_t *timerid;
    498 
    499         va_start(ap, portable_number);
    500         clockid = va_arg(ap, clockid_t);
    501         evp = va_arg(ap, struct sigevent *);
    502         timerid = va_arg(ap, timer_t *);
    503         va_end(ap);
    504 
    505         ret = WRAP(timer_create)(clockid, evp, timerid);
    506         goto done;
    507     }
    508 #endif
    509 
    510 #ifdef __NR_timerfd_create_portable
    511     case __NR_timerfd_create_portable: {
    512         int clockid;
    513         int flags;
    514 
    515         va_start(ap, portable_number);
    516         clockid = va_arg(ap, int);              /* clockid is portable */
    517         flags = va_arg(ap, int);                /* flags need to be mapped */
    518         va_end(ap);
    519 
    520         ret = WRAP(timerfd_create)(clockid, flags);
    521         goto done;
    522     }
    523 #endif
    524 
    525 #ifdef __NR_timerfd_gettime_portable
    526     case __NR_timerfd_gettime_portable: native_number = __NR_timerfd_gettime; break;
    527 #endif
    528 
    529 #ifdef __NR_timerfd_settime_portable
    530     case __NR_timerfd_settime_portable: native_number = __NR_timerfd_settime; break;
    531 #endif
    532 
    533 #ifdef __NR_timer_getoverrun_portable
    534     case __NR_timer_getoverrun_portable: native_number = __NR_timer_getoverrun; break;
    535 #endif
    536 
    537 #ifdef __NR_timer_gettime_portable
    538     case __NR_timer_gettime_portable: native_number = __NR_timer_gettime; break;
    539 #endif
    540 
    541 #ifdef __NR_timer_settime_portable
    542     case __NR_timer_settime_portable: native_number = __NR_timer_settime; break;
    543 #endif
    544 
    545 #ifdef __NR_rt_tgsigqueueinfo_portable
    546     case __NR_rt_tgsigqueueinfo_portable: {
    547         pid_t tgid;
    548         pid_t pid;
    549         int sig;
    550         siginfo_portable_t *uinfo;
    551 
    552         va_start(ap, portable_number);
    553         tgid = va_arg(ap, pid_t);
    554         pid = va_arg(ap, pid_t);
    555         sig = va_arg(ap, int);
    556         uinfo = va_arg(ap, siginfo_portable_t *);
    557         va_end(ap);
    558 
    559         ret = WRAP(rt_tgsigqueueinfo)(tgid, pid, sig, uinfo);
    560         goto done;
    561     }
    562 #endif
    563 
    564 #ifdef __NR_uname_portable
    565     case __NR_uname_portable: native_number = __NR_uname; break;
    566 #endif
    567 
    568 #ifdef __NR_vmsplice_portable
    569     case __NR_vmsplice_portable: native_number = __NR_vmsplice; break;
    570 #endif
    571 
    572     default:
    573         ALOGV("%s(portable_number:%d,  ...): case default; native_number = -1; "
    574               "[ERROR: ADD MISSING SYSTEM CALL]", __func__, portable_number);
    575 
    576         native_number = -1;
    577         break;
    578     }
    579 
    580     ALOGV("%s: native_number = %d", __func__, native_number);
    581 
    582     if (native_number <= 0) {
    583         ALOGV("%s: native_number:%d <= 0; ret = -1; [ERROR: FIX SYSTEM CALL]", __func__,
    584                    native_number);
    585 
    586         *REAL(__errno)() = ENOSYS;
    587         ret = -1;
    588         goto done;
    589     }
    590 
    591     /*
    592      * Get the argument list
    593      * This is pretty crappy:
    594      *   It assumes that the portable and native arguments are compatible
    595      *   It assumes that no more than MAXARGS arguments are passed
    596      *
    597      * Possible changes:
    598      *  o include the argument count for each mapped system call
    599      *  o map the syscall into the equivalent library call:
    600      *    eg syscall(__NR_gettimeofday_portable, struct timeval *tv, struct timezone *tz) =>
    601      *       gettimeofday(struct timeval *tv, struct timezone *tz)
    602      *
    603      * second option is probably best as it allows argument remapping to take place if needed
    604      *
    605      */
    606     va_start(ap, portable_number);
    607     /* For now assume all syscalls take MAXARGS arguments. */
    608     nargs = MAXARGS;
    609     for (i = 0; i < nargs; i++)
    610         args[i] = va_arg(ap, int);
    611     va_end(ap);
    612 
    613     ALOGV("%s: Calling syscall(%d, %d, %d, %d, %d, %d, %d, %d, %d);", __func__,
    614           native_number, args[0], args[1], args[2], args[3], args[4],
    615           args[5], args[6], args[7]);
    616 
    617     ret = REAL(syscall)(native_number, args[0], args[1], args[2], args[3],
    618                   args[4], args[5], args[6], args[7]);
    619 
    620 done:
    621     if (ret == -1) {
    622         ALOGV("%s: ret == -1; errno:%d;", __func__, *REAL(__errno)());
    623     }
    624     ALOGV("%s: return(ret:%d); }", __func__, ret);
    625     return ret;
    626 }
    627