LCOV - code coverage report
Current view: directory - src/trusted/gio - gio_shm_test.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 269 192 71.4 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 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                 : #include <stdio.h>
       8                 : #include <stdlib.h>
       9                 : 
      10                 : #include "native_client/src/include/portability.h"
      11                 : 
      12                 : #include "native_client/src/shared/platform/nacl_check.h"
      13                 : 
      14                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      15                 : #include "native_client/src/trusted/desc/nacl_desc_imc_shm.h"
      16                 : #include "native_client/src/trusted/desc/nacl_desc_effector_trusted_mem.h"
      17                 : 
      18                 : #include "native_client/src/trusted/service_runtime/include/bits/mman.h"
      19                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      20                 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
      21                 : #include "native_client/src/trusted/gio/gio_shm.h"
      22                 : #include "native_client/src/trusted/desc/nrd_all_modules.h"
      23                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      24                 : 
      25                 : #define NCHUNKS   3
      26                 : 
      27                 : #define MAX_CHECK (4096)
      28                 : 
      29                 : int           gVerbose = 0;
      30                 : unsigned int  gRandomSeed = 0x31415926;
      31                 : size_t        gNumSamples = 2048;
      32                 : 
      33          147456 : uint32_t patgen(uint32_t offset) {
      34          147456 :   return (((offset + 3) << (3 * 8)) ^
      35                 :           ((offset + 2) << (2 * 8)) ^
      36                 :           ((offset + 1) << (1 * 8)) ^
      37                 :           ((offset + 0) << (0 * 8)));
      38                 : }
      39                 : 
      40                 : 
      41           49152 : size_t ZeroFiller(uint32_t *mem, size_t offset) {
      42           98304 :   UNREFERENCED_PARAMETER(offset);
      43           49152 :   *mem = 0;
      44           49152 :   return 0;
      45                 : }
      46                 : 
      47               0 : size_t ZeroChecker(uint32_t *mem, size_t offset) {
      48               0 :   UNREFERENCED_PARAMETER(offset);
      49               0 :   return *mem != 0;
      50                 : }
      51                 : 
      52           49152 : size_t MemFiller(uint32_t *mem, size_t offset) {
      53           49152 :   *mem = patgen((uint32_t) offset);
      54           49152 :   return 0;
      55                 : }
      56                 : 
      57           98304 : size_t MemChecker(uint32_t *mem, size_t offset) {
      58           98304 :   uint32_t pat = patgen((uint32_t) offset);
      59           98304 :   return *mem != pat;
      60                 : }
      61                 : 
      62               4 : size_t MemWalk(size_t (*visitor)(uint32_t *, uintptr_t),
      63               4 :                uint32_t *buf,
      64               4 :                size_t nwords) {
      65               4 :   size_t  ix = 0;
      66               4 :   size_t  err_count = 0;
      67                 : 
      68          393224 :   for (ix = 0; ix < nwords; ++ix) {
      69          196608 :     err_count += (*visitor)(&buf[ix], ix);
      70          196608 :   }
      71               4 :   return err_count;
      72                 : }
      73                 : 
      74                 : struct Prober {
      75                 :   /* inline vtbl */
      76                 :   ssize_t  (*NextIx)(struct Prober  *self, size_t *nbytes);
      77                 : };
      78                 : 
      79                 : struct LinearProber {
      80                 :   struct Prober base;
      81                 :   size_t        cur_ix;
      82                 :   size_t        nbytes;
      83                 : };
      84                 : 
      85          393218 : ssize_t LinearProberIndex(struct Prober *vself, size_t *checkbytes) {
      86          393218 :   struct LinearProber *self = (struct LinearProber *) vself;
      87          393220 :   if (self->cur_ix == self->nbytes) return -1;
      88          393216 :   *checkbytes = 1;
      89          393216 :   return self->cur_ix++;
      90          393218 : }
      91                 : 
      92               2 : void LinearProberCtor(struct LinearProber *self, size_t nbytes) {
      93               2 :   self->base.NextIx = LinearProberIndex;
      94               2 :   self->cur_ix = 0;
      95               2 :   self->nbytes = nbytes;
      96               2 : }
      97                 : 
      98                 : struct ReverseProber {
      99                 :   struct Prober base;
     100                 :   size_t        nbytes;
     101                 : };
     102                 : 
     103          393218 : ssize_t ReverseProberIndex(struct Prober *vself, size_t *checkbytes) {
     104          393218 :   struct ReverseProber *self = (struct ReverseProber *) vself;
     105                 : 
     106          393218 :   *checkbytes = 1;
     107          393218 :   return --self->nbytes;
     108                 : }
     109                 : 
     110               2 : void ReverseProberCtor(struct ReverseProber *self, size_t nbytes) {
     111               2 :   self->base.NextIx = ReverseProberIndex;
     112               2 :   self->nbytes = nbytes;
     113               2 : }
     114                 : 
     115                 : struct RandomProber {
     116                 :   struct Prober base;
     117                 :   size_t        nbytes;
     118                 :   /* windows does not have rand_r, so this test must be single threaded */
     119                 :   size_t        count;
     120                 : };
     121                 : 
     122            4098 : ssize_t RandomProberIndex(struct Prober *vself, size_t *checkbytes) {
     123            4098 :   struct RandomProber *self = (struct RandomProber *) vself;
     124            4098 :   int r;
     125            4098 :   size_t remain;
     126                 : 
     127            4098 :   if (0 == self->count) {
     128               2 :     return -1;
     129                 :   }
     130            4096 :   --self->count;
     131            4096 :   r = (int) ((size_t) rand() % self->nbytes);
     132           12288 :   CHECK(r >= 0);
     133            4096 :   remain = self->nbytes - r;
     134            4096 :   if (remain > MAX_CHECK) {
     135            3999 :     remain = MAX_CHECK;
     136            3999 :   }
     137            4096 :   *checkbytes = rand() % remain;
     138           12288 :   CHECK(*checkbytes <= remain);
     139            4096 :   return r;
     140            4098 : }
     141                 : 
     142               2 : void RandomProberCtor(struct RandomProber *self,
     143               2 :                       size_t nbytes,
     144               2 :                       size_t nsamples) {
     145               2 :   self->base.NextIx = RandomProberIndex;
     146               2 :   self->nbytes = nbytes;
     147               2 :   self->count = nsamples;
     148               2 : }
     149                 : 
     150                 : /*
     151                 :  * Op is sort of a funny virtual function pointer -- it's not an
     152                 :  * offset in the vtbl, so changing the object is bad (esp w/
     153                 :  * subclasses that might have overridden the virtual function), but
     154                 :  * the extracted function pointer.
     155                 :  */
     156               6 : size_t CheckGioOpWithProber(struct Prober *pp,
     157               6 :                             struct Gio    *gp,
     158               6 :                             uint8_t       *addr,
     159               6 :                             size_t        nbytes,
     160               6 :                             ssize_t       (*Op)(struct Gio *, void *, size_t)) {
     161               6 :   size_t    errs = 0;
     162               6 :   ssize_t   ix;
     163               6 :   size_t    checkbytes;
     164               6 :   uint8_t   val[MAX_CHECK];
     165               6 :   size_t    valix;
     166                 : 
     167          790540 :   while (-1 != (ix = (*pp->NextIx)(pp, &checkbytes))) {
     168          790528 :     if (nbytes <= (size_t) ix) {
     169               0 :       break;
     170                 :     }
     171          790528 :     if (gVerbose > 1) {
     172               0 :       printf("0x%"NACL_PRIxS", 0x%"NACL_PRIxS"\n", ix, checkbytes);
     173               0 :     }
     174          790528 :     if (checkbytes > sizeof val) {
     175               0 :       checkbytes = sizeof val;
     176               0 :     }
     177                 : 
     178                 :     /* fill with something we don't expect to be in real data */
     179        19795228 :     for (valix = 0; valix < checkbytes; ++valix) {
     180         9107086 :       val[valix] = (uint8_t) (~valix);
     181         9107086 :     }
     182                 : 
     183          790528 :     if (gVerbose > 2) {
     184               0 :       printf("Seeking to 0x%"NACL_PRIxS"\n", ix);
     185               0 :     }
     186                 : 
     187          790528 :     if (-1 == (*gp->vtbl->Seek)(gp, (off_t) ix, SEEK_SET)) {
     188               0 :       if (gVerbose) {
     189               0 :         printf("Seek to %"NACL_PRIdS" failed\n", ix);
     190               0 :       }
     191               0 :       ++errs;
     192               0 :       continue;
     193                 :     }
     194          790528 :     if (gVerbose > 2) {
     195               0 :       printf("Operating on 0x%"NACL_PRIxS" bytes\n", checkbytes);
     196               0 :     }
     197                 : 
     198          790528 :     if (-1 == (*Op)(gp, val, checkbytes)) {
     199               0 :       if (gVerbose) {
     200               0 :         printf("Apply Op at %"NACL_PRIdS" failed\n", ix);
     201               0 :       }
     202               0 :       ++errs;
     203               0 :       continue;
     204                 :     }
     205                 : 
     206          790528 :     if (gVerbose > 2) {
     207               0 :       printf("Comparing against plain mmap view\n");
     208               0 :     }
     209        19795228 :     for (valix = 0; valix < checkbytes; ++valix) {
     210         9107086 :       if (1 < gVerbose) {
     211               0 :         printf(("Value from gio is 0x%08"NACL_PRIx8","
     212                 :                 " from memory is 0x%08"NACL_PRIx8"\n"),
     213                 :                val[valix],
     214                 :                addr[ix + valix]);
     215               0 :       }
     216         9107086 :       if (val[valix] != addr[ix + valix]) {
     217               0 :         ++errs;
     218               0 :       }
     219         9107086 :     }
     220          790528 :   }
     221               6 :   return errs;
     222                 : }
     223                 : 
     224               3 : size_t CheckGioReadWithProber(struct Prober *pp,
     225               3 :                               struct Gio    *gp,
     226               3 :                               uint8_t       *addr,
     227               3 :                               size_t        nbytes) {
     228               3 :   return CheckGioOpWithProber(pp, gp, addr, nbytes, gp->vtbl->Read);
     229                 : }
     230                 : 
     231               3 : size_t CheckGioWriteWithProber(struct Prober *pp,
     232               3 :                                struct Gio    *gp,
     233               3 :                                uint8_t       *addr,
     234               3 :                                size_t        nbytes) {
     235               3 :   return CheckGioOpWithProber(pp, gp, addr, nbytes,
     236                 :                               (ssize_t (*)(struct Gio *, void *, size_t))
     237                 :                               gp->vtbl->Write);
     238                 : }
     239                 : 
     240                 : 
     241               2 : size_t CheckGioOp(struct Gio  *gp,
     242               2 :                   uint8_t     *addr,
     243               2 :                   size_t      nbytes,
     244               2 :                   size_t      (*Op)(struct Prober *,
     245                 :                                     struct Gio    *,
     246                 :                                     uint8_t       *,
     247                 :                                     size_t)) {
     248               2 :   struct LinearProber lp;
     249               2 :   struct ReverseProber rp;
     250               2 :   struct RandomProber rand_probe;
     251               2 :   ssize_t num_err = 0;
     252                 : 
     253               2 :   LinearProberCtor(&lp, nbytes);
     254               2 :   printf("Testing w/ LinearProber\n");
     255               2 :   num_err += (*Op)((struct Prober *) &lp, gp, addr, nbytes);
     256                 : 
     257               2 :   ReverseProberCtor(&rp, nbytes);
     258               2 :   printf("Testing w/ ReverseProber\n");
     259               2 :   num_err += (*Op)((struct Prober *) &rp, gp, addr, nbytes);
     260                 : 
     261               2 :   RandomProberCtor(&rand_probe, nbytes, gNumSamples);
     262               2 :   printf("Testing w/ RandomProber\n");
     263               2 :   num_err += (*Op)((struct Prober *) &rand_probe, gp, addr, nbytes);
     264                 : 
     265               2 :   return num_err;
     266                 : }
     267                 : 
     268               1 : size_t CheckGioRead(struct Gio  *gp,
     269               1 :                     uint8_t     *addr,
     270               1 :                     size_t      nbytes) {
     271               1 :   return CheckGioOp(gp, addr, nbytes, CheckGioReadWithProber);
     272                 : }
     273                 : 
     274               1 : size_t CheckGioWrite(struct Gio  *gp,
     275               1 :                      uint8_t     *addr,
     276               1 :                      size_t      nbytes) {
     277               1 :   return CheckGioOp(gp, addr, nbytes, CheckGioWriteWithProber);
     278                 : }
     279                 : 
     280               1 : size_t CheckGioZeros(struct Gio *gp,
     281               1 :                      size_t     nbytes) {
     282               1 :   unsigned char byte;
     283               1 :   ssize_t       rv;
     284               1 :   size_t        nerrors = 0;
     285               1 :   size_t        ix;
     286               1 :   uint64_t      temp_nbytes = nbytes;
     287                 : 
     288               1 :   if (temp_nbytes > OFF_T_MAX) {
     289               0 :     return 1;
     290                 :   }
     291                 : 
     292          393218 :   for (ix = 0; ix < nbytes; ++ix) {
     293          196608 :     byte = 0xff;
     294          196608 :     if (-1 == (*gp->vtbl->Seek)(gp, (off_t) ix, SEEK_SET)) {
     295               0 :       printf("Seek to byt %"NACL_PRIuS" failed\n", ix);
     296               0 :       ++nerrors;
     297               0 :       continue;
     298                 :     }
     299          196608 :     if (1 != (rv = (*gp->vtbl->Read)(gp, &byte, 1))) {
     300               0 :       printf("Read of byte %"NACL_PRIuS" failed\n", ix);
     301               0 :       ++nerrors;
     302               0 :       continue;
     303                 :     }
     304          196608 :     if (0 != byte) {
     305               0 :       printf("Byte %"NACL_PRIuS" not zero: 0x%02x\n", ix, 0xff & byte);
     306               0 :       ++nerrors;
     307               0 :     }
     308          196608 :   }
     309               1 :   return nerrors;
     310               1 : }
     311                 : 
     312                 : 
     313               1 : int main(int ac,
     314               1 :          char **av) {
     315               1 :   int                   opt;
     316                 : 
     317               1 :   struct NaClDescImcShm *shmp;
     318               1 :   struct NaClDesc *dp;
     319               1 :   uintptr_t addr;
     320               1 :   uintptr_t addr2;
     321               1 :   size_t nbytes;
     322               1 :   size_t errs;
     323               1 :   struct NaClGioShm gio_shm;
     324               1 :   size_t map_chunks = NCHUNKS;
     325                 : 
     326               2 :   while (EOF != (opt = getopt(ac, av, "m:n:s:v"))) {
     327               0 :     switch (opt) {
     328                 :       case 'm':
     329               0 :         map_chunks = strtoul(optarg, (char **) NULL, 0);
     330               0 :         break;
     331                 :       case 'n':
     332               0 :         gNumSamples = strtoul(optarg, (char **) NULL, 0);
     333               0 :         break;
     334                 :       case 's':
     335               0 :         gRandomSeed = strtoul(optarg, (char **) NULL, 0);
     336               0 :         break;
     337                 :       case 'v':
     338               0 :         ++gVerbose;
     339               0 :         break;
     340                 :       default:
     341               0 :         fprintf(stderr,
     342                 :                 ("Usage: gio_shm_test [-v] [-m map_chunks]"
     343                 :                  " [-n num_samples] [-s seed]\n"));
     344               0 :         return EXIT_FAILURE;
     345                 :     }
     346               0 :   }
     347                 : 
     348               1 :   printf("Using seed %d (0x%x)\n", gRandomSeed, gRandomSeed);
     349               1 :   srand(gRandomSeed);
     350                 : 
     351               1 :   NaClNrdAllModulesInit();
     352                 : 
     353               1 :   shmp = malloc(sizeof *shmp);
     354               1 :   if (NULL == shmp) {
     355               0 :     printf("No memory\n");
     356               0 :     printf("FAILED\n");
     357               0 :     return EXIT_FAILURE;
     358                 :   }
     359                 : 
     360               1 :   nbytes = map_chunks * NACL_MAP_PAGESIZE;
     361               1 :   if (!NaClDescImcShmAllocCtor(shmp, nbytes, /* executable= */ 0)) {
     362               0 :     printf("NaClDescImcShmAllocCtor failed\n");
     363               0 :     printf("FAILED\n");
     364               0 :     return EXIT_FAILURE;
     365                 :   }
     366               1 :   dp = &shmp->base;
     367                 : 
     368               2 :   addr = (*((struct NaClDescVtbl const *) dp->base.vtbl)->
     369                 :           Map)(dp,
     370               1 :                NaClDescEffectorTrustedMem(),
     371                 :                NULL,
     372                 :                nbytes,
     373                 :                NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE,
     374                 :                NACL_ABI_MAP_SHARED,
     375                 :                0);
     376               1 :   if (NaClPtrIsNegErrno(&addr)) {
     377               0 :     printf("Map failed\n");
     378               0 :     return EXIT_FAILURE;
     379                 :   }
     380                 : 
     381               1 :   MemWalk(MemFiller, (uint32_t *) addr, nbytes / sizeof(uint32_t));
     382               1 :   printf("Checking basic consistency\n");
     383               1 :   if (0 != MemWalk(MemChecker, (uint32_t *) addr, nbytes / sizeof(uint32_t))) {
     384               0 :     printf("Initial consistency check failed\n");
     385               0 :     printf("FAILED\n");
     386               0 :     return EXIT_FAILURE;
     387                 :   }
     388                 : 
     389               2 :   addr2 = (*((struct NaClDescVtbl const *) dp->base.vtbl)->
     390                 :            Map)(dp,
     391               1 :                 NaClDescEffectorTrustedMem(),
     392                 :                 NULL,
     393                 :                 nbytes,
     394                 :                 NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE,
     395                 :                 NACL_ABI_MAP_SHARED,
     396                 :                 0);
     397               1 :   if (NaClPtrIsNegErrno(&addr2)) {
     398               0 :     printf("Second Map failed\n");
     399               0 :     return EXIT_FAILURE;
     400                 :   }
     401               1 :   printf("Checking second view consistency\n");
     402               1 :   if (0 != MemWalk(MemChecker, (uint32_t *) addr2, nbytes / sizeof(uint32_t))) {
     403               0 :     printf("Second view consistency check failed\n");
     404               0 :     printf("FAILED\n");
     405               0 :     return EXIT_FAILURE;
     406                 :   }
     407               1 :   NaClDescUnmapUnsafe(dp, (void *) addr2, nbytes);
     408                 : 
     409               1 :   if (!NaClGioShmCtor(&gio_shm, dp, nbytes)) {
     410               0 :     printf("NaClGioShmCtor failed\n");
     411               0 :     printf("FAILED\n");
     412               0 :     return EXIT_FAILURE;
     413                 :   }
     414                 : 
     415               1 :   printf("Checking Gio vs direct shm consistency, read\n");
     416               1 :   if (0 != (errs = CheckGioRead((struct Gio *) &gio_shm,
     417                 :                                 (uint8_t *) addr,
     418                 :                                 nbytes))) {
     419               0 :     printf("ERROR: CheckGioRead failed, found %"NACL_PRIdS" errors\n", errs);
     420               0 :   }
     421                 : 
     422               1 :   printf("Zeroing shared memory\n");
     423               1 :   MemWalk(ZeroFiller, (uint32_t *) addr, nbytes / sizeof(uint32_t));
     424               1 :   printf("Reading for zeros\n");
     425               1 :   if (0 != (errs = CheckGioZeros((struct Gio *) &gio_shm,
     426                 :                                  nbytes))) {
     427               0 :     printf("ERROR: Gio found non-zero bytes!\n");
     428               0 :   }
     429                 : 
     430               1 :   printf("Checking Gio vs direct shm consistency, write\n");
     431               1 :   if (0 != (errs = CheckGioWrite((struct Gio *) &gio_shm,
     432                 :                                  (uint8_t *) addr,
     433                 :                                  nbytes))) {
     434               0 :     printf("ERROR: CheckGioWrite failed, found %"NACL_PRIdS" errors\n", errs);
     435               0 :   }
     436                 : 
     437               1 :   (*gio_shm.base.vtbl->Dtor)((struct Gio *) &gio_shm);
     438                 : 
     439               1 :   NaClDescUnref(dp);
     440                 : 
     441               1 :   NaClNrdAllModulesFini();
     442               1 :   if (0 != errs) {
     443               0 :     printf("FAILED\n");
     444               0 :     return EXIT_FAILURE;
     445                 :   } else {
     446               1 :     printf("PASSED\n");
     447               1 :     return EXIT_SUCCESS;
     448                 :   }
     449               1 : }

Generated by: LCOV version 1.7