Home | History | Annotate | Download | only in nacl_io
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <sys/types.h>  // Include something that will define __GLIBC__.
      6 
      7 // The entire file is wrapped in this #if. We do this so this .cc file can be
      8 // compiled, even on a non-newlib build.
      9 #if defined(__native_client__) && !defined(__GLIBC__)
     10 
     11 #include "nacl_io/kernel_wrap.h"
     12 #include <assert.h>
     13 #include <dirent.h>
     14 #include <errno.h>
     15 #include <irt.h>
     16 #include <sys/mman.h>
     17 #include <sys/stat.h>
     18 #include <sys/time.h>
     19 #include "nacl_io/kernel_intercept.h"
     20 
     21 EXTERN_C_BEGIN
     22 
     23 // Macro to get the REAL function pointer
     24 #define REAL(name) __nacl_irt_##name##_real
     25 
     26 // Macro to get the WRAP function
     27 #define WRAP(name) __nacl_irt_##name##_wrap
     28 
     29 // Declare REAL function pointer.
     30 #define DECLARE_REAL_PTR(group, name) \
     31   typeof(__libnacl_irt_##group.name) REAL(name);
     32 
     33 // Assign the REAL function pointer.
     34 #define ASSIGN_REAL_PTR(group, name) \
     35   assert(__libnacl_irt_##group.name != NULL); \
     36   REAL(name) = __libnacl_irt_##group.name;
     37 
     38 // Switch IRT's pointer to the REAL pointer
     39 #define USE_REAL(group, name) \
     40   __libnacl_irt_##group.name = (typeof(REAL(name))) REAL(name); \
     41 
     42 // Switch the IRT's pointer to the WRAP function
     43 #define USE_WRAP(group, name) \
     44   __libnacl_irt_##group.name = (typeof(REAL(name))) WRAP(name); \
     45 
     46 extern void __libnacl_irt_filename_init(void);
     47 
     48 extern struct nacl_irt_fdio __libnacl_irt_fdio;
     49 extern struct nacl_irt_dev_filename __libnacl_irt_dev_filename;
     50 extern struct nacl_irt_memory __libnacl_irt_memory;
     51 
     52 // Create function pointers to the REAL implementation
     53 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \
     54   OP(fdio, close); \
     55   OP(fdio, dup); \
     56   OP(fdio, dup2); \
     57   OP(fdio, fstat); \
     58   OP(fdio, getdents); \
     59   OP(fdio, read); \
     60   OP(fdio, seek); \
     61   OP(fdio, write); \
     62   OP(dev_filename, open); \
     63   OP(dev_filename, stat); \
     64   OP(memory, mmap); \
     65   OP(memory, munmap);
     66 
     67 
     68 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR);
     69 
     70 int WRAP(close)(int fd) {
     71   return (ki_close(fd) < 0) ? errno : 0;
     72 }
     73 
     74 int WRAP(dup)(int fd, int* newfd) {
     75   *newfd = ki_dup(fd);
     76   return (*newfd < 0) ? errno : 0;
     77 }
     78 
     79 int WRAP(dup2)(int fd, int newfd) {
     80   newfd = ki_dup2(fd, newfd);
     81   return (newfd < 0) ? errno : 0;
     82 }
     83 
     84 int WRAP(fstat)(int fd, struct stat* buf) {
     85   return (ki_fstat(fd, buf) < 0) ? errno : 0;
     86 }
     87 
     88 int WRAP(getdents)(int fd, dirent* buf, size_t count, size_t* nread) {
     89   return (ki_getdents(fd, buf, count) < 0) ? errno : 0;
     90 }
     91 
     92 int WRAP(mmap)(void** addr, size_t length, int prot, int flags, int fd,
     93                off_t offset) {
     94   if (flags & MAP_ANONYMOUS)
     95     return REAL(mmap)(addr, length, prot, flags, fd, offset);
     96 
     97   *addr = ki_mmap(*addr, length, prot, flags, fd, offset);
     98   return *addr == (void*)-1 ? errno : 0;
     99 }
    100 
    101 int WRAP(munmap)(void* addr, size_t length) {
    102   // Always let the real munmap run on the address range. It is not an error if
    103   // there are no mapped pages in that range.
    104   ki_munmap(addr, length);
    105   return REAL(munmap)(addr, length);
    106 }
    107 
    108 int WRAP(open)(const char* pathname, int oflag, mode_t cmode, int* newfd) {
    109   *newfd = ki_open(pathname, oflag);
    110   return (*newfd < 0) ? errno : 0;
    111 }
    112 
    113 int WRAP(read)(int fd, void* buf, size_t count, size_t* nread) {
    114   if (!ki_is_initialized())
    115     return REAL(read)(fd, buf, count, nread);
    116 
    117   ssize_t signed_nread = ki_read(fd, buf, count);
    118   *nread = static_cast<size_t>(signed_nread);
    119   return (signed_nread < 0) ? errno : 0;
    120 }
    121 
    122 int WRAP(seek)(int fd, off_t offset, int whence, off_t* new_offset) {
    123   *new_offset = ki_lseek(fd, offset, whence);
    124   return (*new_offset < 0) ? errno : 0;
    125 }
    126 
    127 int WRAP(stat)(const char* pathname, struct stat* buf) {
    128   return (ki_stat(pathname, buf) < 0) ? errno : 0;
    129 }
    130 
    131 int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) {
    132   if (!ki_is_initialized())
    133     return REAL(write)(fd, buf, count, nwrote);
    134 
    135   ssize_t signed_nwrote = ki_write(fd, buf, count);
    136   *nwrote = static_cast<size_t>(signed_nwrote);
    137   return (signed_nwrote < 0) ? errno : 0;
    138 }
    139 
    140 // "real" functions, i.e. the unwrapped original functions.
    141 
    142 int _real_close(int fd) {
    143   return REAL(close)(fd);
    144 }
    145 
    146 int _real_fstat(int fd, struct stat* buf) {
    147   return REAL(fstat)(fd, buf);
    148 }
    149 
    150 int _real_getdents(int fd, dirent* nacl_buf, size_t nacl_count, size_t* nread) {
    151   return REAL(getdents)(fd, nacl_buf, nacl_count, nread);
    152 }
    153 
    154 int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset) {
    155   return REAL(seek)(fd, offset, whence, new_offset);
    156 }
    157 
    158 int _real_mkdir(const char* pathname, mode_t mode) {
    159   return ENOSYS;
    160 }
    161 
    162 int _real_mmap(void** addr, size_t length, int prot, int flags, int fd,
    163                off_t offset) {
    164   return REAL(mmap)(addr, length, prot, flags, fd, offset);
    165 }
    166 
    167 int _real_munmap(void* addr, size_t length) {
    168   return REAL(munmap)(addr, length);
    169 }
    170 
    171 int _real_open(const char* pathname, int oflag, mode_t cmode, int* newfd) {
    172   return REAL(open)(pathname, oflag, cmode, newfd);
    173 }
    174 
    175 int _real_open_resource(const char* file, int* fd) {
    176   return ENOSYS;
    177 }
    178 
    179 int _real_read(int fd, void* buf, size_t count, size_t* nread) {
    180   return REAL(read)(fd, buf, count, nread);
    181 }
    182 
    183 int _real_rmdir(const char* pathname) {
    184   return ENOSYS;
    185 }
    186 
    187 int _real_write(int fd, const void* buf, size_t count, size_t* nwrote) {
    188   return REAL(write)(fd, buf, count, nwrote);
    189 }
    190 
    191 uint64_t usec_since_epoch() {
    192   struct timeval tv;
    193   gettimeofday(&tv, NULL);
    194   return tv.tv_usec + (tv.tv_sec * 1000000);
    195 }
    196 
    197 static bool s_wrapped = false;
    198 static bool s_assigned = false;
    199 void kernel_wrap_init() {
    200   if (!s_wrapped) {
    201     if (!s_assigned) {
    202       __libnacl_irt_filename_init();
    203       EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
    204       s_assigned = true;
    205     }
    206     EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
    207     s_wrapped = true;
    208   }
    209 }
    210 
    211 void kernel_wrap_uninit() {
    212   if (s_wrapped) {
    213     EXPAND_SYMBOL_LIST_OPERATION(USE_REAL)
    214     s_wrapped = false;
    215   }
    216 }
    217 
    218 EXTERN_C_END
    219 
    220 
    221 #endif  // defined(__native_client__) && !defined(__GLIBC__)
    222 
    223