LCOV - code coverage report
Current view: directory - src/shared/imc - nacl_imc_unistd.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 49 27 55.1 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : 
       8                 : // NaCl inter-module communication primitives.
       9                 : //
      10                 : // This file implements common parts of IMC for "unix like systems" (i.e. not
      11                 : // used on Windows).
      12                 : 
      13                 : // TODO(shiki): Perhaps this file should go into a platform-specific directory
      14                 : // (posix? unixlike?)  We have a little convention going where mac/linux stuff
      15                 : // goes in the linux directory and is referenced by the mac build but that's a
      16                 : // little sloppy.
      17                 : 
      18                 : #include <assert.h>
      19                 : #include <ctype.h>
      20                 : #include <errno.h>
      21                 : #include <fcntl.h>
      22                 : #include <limits.h>
      23                 : #include <stdio.h>
      24                 : #include <string.h>
      25                 : #include <unistd.h>
      26                 : #include <sys/mman.h>
      27                 : #include <sys/types.h>
      28                 : 
      29                 : #include <algorithm>
      30                 : 
      31                 : #include "native_client/src/include/atomic_ops.h"
      32                 : 
      33                 : #include "native_client/src/shared/imc/nacl_imc.h"
      34                 : #include "native_client/src/shared/platform/nacl_check.h"
      35                 : 
      36                 : namespace nacl {
      37                 : 
      38                 : namespace {
      39                 : 
      40                 : const char kNaClTempPrefixVar[] = "NACL_TMPFS_PREFIX";
      41                 : 
      42                 : // The pathname or SHM-namespace prefixes for memory objects created
      43                 : // by CreateMemoryObject().
      44                 : const char kShmTempPrefix[] = "/tmp/google-nacl-shm-";
      45                 : const char kShmOpenPrefix[] = "/google-nacl-shm-";
      46                 : 
      47                 : }  // namespace
      48                 : 
      49               0 : bool WouldBlock() {
      50               0 :   return (errno == EAGAIN) ? true : false;
      51                 : }
      52                 : 
      53               0 : int GetLastErrorString(char* buffer, size_t length) {
      54                 : #if NACL_LINUX
      55                 :   // Note some Linux distributions provide only GNU version of strerror_r().
      56                 :   if (buffer == NULL || length == 0) {
      57                 :     errno = ERANGE;
      58                 :     return -1;
      59                 :   }
      60                 :   char* message = strerror_r(errno, buffer, length);
      61                 :   if (message != buffer) {
      62                 :     size_t message_bytes = strlen(message) + 1;
      63                 :     length = std::min(message_bytes, length);
      64                 :     memmove(buffer, message, length);
      65                 :     buffer[length - 1] = '\0';
      66                 :   }
      67                 :   return 0;
      68                 : #else
      69               0 :   return strerror_r(errno, buffer, length);
      70                 : #endif
      71                 : }
      72                 : 
      73                 : static Atomic32 memory_object_count = 0;
      74                 : 
      75              11 : static int TryShmOrTempOpen(size_t length, const char* prefix, bool use_temp) {
      76              11 :   if (0 == length) {
      77               0 :     return -1;
      78                 :   }
      79                 : 
      80                 :   char name[PATH_MAX];
      81               0 :   for (;;) {
      82                 :     snprintf(name, sizeof name, "%s-%u.%u", prefix,
      83                 :              getpid(),
      84              11 :              static_cast<uint32_t>(AtomicIncrement(&memory_object_count, 1)));
      85                 :     int m;
      86              11 :     if (use_temp) {
      87              11 :       m = open(name, O_RDWR | O_CREAT | O_EXCL, 0);
      88                 :     } else {
      89               0 :       m = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0);
      90                 :     }
      91              11 :     if (0 <= m) {
      92              11 :       if (use_temp) {
      93              11 :         int rc = unlink(name);
      94              11 :         DCHECK(rc == 0);
      95                 :       } else {
      96               0 :         int rc = shm_unlink(name);
      97               0 :         DCHECK(rc == 0);
      98                 :       }
      99              11 :       if (ftruncate(m, length) == -1) {
     100               0 :         close(m);
     101               0 :         m = -1;
     102                 :       }
     103              11 :       return m;
     104                 :     }
     105               0 :     if (errno != EEXIST) {
     106               0 :       return -1;
     107                 :     }
     108                 :     // Retry only if we got EEXIST.
     109                 :   }
     110                 : }
     111                 : 
     112                 : static CreateMemoryObjectFunc g_create_memory_object_func = NULL;
     113                 : 
     114               0 : void SetCreateMemoryObjectFunc(CreateMemoryObjectFunc func) {
     115               0 :   g_create_memory_object_func = func;
     116               0 : }
     117                 : 
     118              11 : Handle CreateMemoryObject(size_t length, bool executable) {
     119              11 :   if (0 == length) {
     120               0 :     return -1;
     121                 :   }
     122                 :   int fd;
     123                 : 
     124              11 :   if (g_create_memory_object_func != NULL) {
     125               0 :     fd = g_create_memory_object_func(length, executable);
     126               0 :     if (fd >= 0)
     127               0 :       return fd;
     128                 :   }
     129                 : 
     130                 :   // /dev/shm is not always available on Linux.
     131                 :   // Sometimes it's mounted as noexec.
     132                 :   // To handle this case, sel_ldr can take a path
     133                 :   // to tmpfs from the environment.
     134                 : 
     135                 : #if NACL_LINUX && defined(NACL_ENABLE_TMPFS_REDIRECT_VAR)
     136                 :   if (NACL_ENABLE_TMPFS_REDIRECT_VAR) {
     137                 :     const char* prefix = getenv(kNaClTempPrefixVar);
     138                 :     if (prefix != NULL) {
     139                 :       fd = TryShmOrTempOpen(length, prefix, true);
     140                 :       if (fd >= 0) {
     141                 :         return fd;
     142                 :       }
     143                 :     }
     144                 :   }
     145                 : #endif
     146                 : 
     147                 :   // On Mac OS X, shm_open() gives us file descriptors that the OS
     148                 :   // won't mmap() with PROT_EXEC, which is no good for the dynamic
     149                 :   // code region.  Try open()ing a file in /tmp first, but fall back
     150                 :   // to using shm_open() if /tmp is not available, which will be the
     151                 :   // case inside the Chromium sandbox.  This means that dynamic
     152                 :   // loading will only work with --no-sandbox.
     153                 :   //
     154                 :   // TODO(mseaborn): We will probably need to do IPC to acquire SHM FDs
     155                 :   // inside the Chromium Mac sandbox, as on Linux.
     156                 : 
     157                 : #if NACL_OSX
     158                 :   // Try /tmp first.  It would be OK to enable this for Linux, but
     159                 :   // there's no need because shm_open() (which uses /dev/shm rather
     160                 :   // than /tmp) is fine on Linux.
     161              11 :   fd = TryShmOrTempOpen(length, kShmTempPrefix, true);
     162              11 :   if (fd >= 0)
     163              11 :     return fd;
     164                 : #endif
     165                 : 
     166                 :   // Try shm_open().
     167               0 :   return TryShmOrTempOpen(length, kShmOpenPrefix, false);
     168                 : }
     169                 : 
     170                 : void* Map(void* start, size_t length, int prot, int flags,
     171           12318 :           Handle memory, off_t offset) {
     172                 :   static const int kPosixProt[] = {
     173                 :     PROT_NONE,
     174                 :     PROT_READ,
     175                 :     PROT_WRITE,
     176                 :     PROT_READ | PROT_WRITE,
     177                 :     PROT_EXEC,
     178                 :     PROT_READ | PROT_EXEC,
     179                 :     PROT_WRITE | PROT_EXEC,
     180                 :     PROT_READ | PROT_WRITE | PROT_EXEC
     181                 :   };
     182                 : 
     183           12318 :   int adjusted = 0;
     184           12318 :   if (flags & kMapShared) {
     185           12318 :     adjusted |= MAP_SHARED;
     186                 :   }
     187           12318 :   if (flags & kMapPrivate) {
     188               0 :     adjusted |= MAP_PRIVATE;
     189                 :   }
     190           12318 :   if (flags & kMapFixed) {
     191           12318 :     adjusted |= MAP_FIXED;
     192                 :   }
     193           12318 :   return mmap(start, length, kPosixProt[prot & 7], adjusted, memory, offset);
     194                 : }
     195                 : 
     196               8 : int Unmap(void* start, size_t length) {
     197               8 :   return munmap(start, length);
     198                 : }
     199                 : 
     200                 : }  // namespace nacl

Generated by: LCOV version 1.7