LCOV - code coverage report
Current view: directory - src/trusted/gio - gio_shm_test.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 207 139 67.1 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright 2010 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can
       4                 :  * be 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/sys/errno.h"
      19                 : #include "native_client/src/trusted/service_runtime/include/sys/mman.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                 :   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                 :   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                 : size_t MemWalk(size_t (*visitor)(uint32_t *, uintptr_t),
      63                 :                uint32_t *buf,
      64               4 :                size_t nwords) {
      65               4 :   size_t  ix = 0;
      66               4 :   size_t  err_count = 0;
      67                 : 
      68          196612 :   for (ix = 0; ix < nwords; ++ix) {
      69          196608 :     err_count += (*visitor)(&buf[ix], ix);
      70                 :   }
      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          393218 :   if (self->cur_ix == self->nbytes) return -1;
      88          393216 :   *checkbytes = 1;
      89          393216 :   return self->cur_ix++;
      90                 : }
      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                 :   int r;
     125                 :   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            4096 :   CHECK(r >= 0);
     133            4096 :   remain = self->nbytes - r;
     134            4096 :   if (remain > MAX_CHECK) {
     135            3999 :     remain = MAX_CHECK;
     136                 :   }
     137            4096 :   *checkbytes = rand() % remain;
     138            4096 :   CHECK(*checkbytes <= remain);
     139            4096 :   return r;
     140                 : }
     141                 : 
     142                 : void RandomProberCtor(struct RandomProber *self,
     143                 :                       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                 : size_t CheckGioOpWithProber(struct Prober *pp,
     157                 :                             struct Gio    *gp,
     158                 :                             uint8_t       *addr,
     159                 :                             size_t        nbytes,
     160               6 :                             ssize_t       (*Op)(struct Gio *, void *, size_t)) {
     161               6 :   size_t    errs = 0;
     162                 :   ssize_t   ix;
     163                 :   size_t    checkbytes;
     164                 :   uint8_t   val[MAX_CHECK];
     165                 :   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                 :     }
     174          790528 :     if (checkbytes > sizeof val) {
     175               0 :       checkbytes = sizeof val;
     176                 :     }
     177                 : 
     178                 :     /* fill with something we don't expect to be in real data */
     179         9897614 :     for (valix = 0; valix < checkbytes; ++valix) {
     180         9107086 :       val[valix] = (uint8_t) (~valix);
     181                 :     }
     182                 : 
     183          790528 :     if (gVerbose > 2) {
     184               0 :       printf("Seeking to 0x%"NACL_PRIxS"\n", ix);
     185                 :     }
     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                 :       }
     191               0 :       ++errs;
     192               0 :       continue;
     193                 :     }
     194          790528 :     if (gVerbose > 2) {
     195               0 :       printf("Operating on 0x%"NACL_PRIxS" bytes\n", checkbytes);
     196                 :     }
     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                 :       }
     202               0 :       ++errs;
     203               0 :       continue;
     204                 :     }
     205                 : 
     206          790528 :     if (gVerbose > 2) {
     207               0 :       printf("Comparing against plain mmap view\n");
     208                 :     }
     209         9897614 :     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                 :       }
     216         9107086 :       if (val[valix] != addr[ix + valix]) {
     217               0 :         ++errs;
     218                 :       }
     219                 :     }
     220                 :   }
     221               6 :   return errs;
     222                 : }
     223                 : 
     224                 : size_t CheckGioReadWithProber(struct Prober *pp,
     225                 :                               struct Gio    *gp,
     226                 :                               uint8_t       *addr,
     227               3 :                               size_t        nbytes) {
     228               3 :   return CheckGioOpWithProber(pp, gp, addr, nbytes, gp->vtbl->Read);
     229                 : }
     230                 : 
     231                 : size_t CheckGioWriteWithProber(struct Prober *pp,
     232                 :                                struct Gio    *gp,
     233                 :                                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                 : size_t CheckGioOp(struct Gio  *gp,
     242                 :                   uint8_t     *addr,
     243                 :                   size_t      nbytes,
     244                 :                   size_t      (*Op)(struct Prober *,
     245                 :                                     struct Gio    *,
     246                 :                                     uint8_t       *,
     247               2 :                                     size_t)) {
     248                 :   struct LinearProber lp;
     249                 :   struct ReverseProber rp;
     250                 :   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                 : size_t CheckGioRead(struct Gio  *gp,
     269                 :                     uint8_t     *addr,
     270               1 :                     size_t      nbytes) {
     271               1 :   return CheckGioOp(gp, addr, nbytes, CheckGioReadWithProber);
     272                 : }
     273                 : 
     274                 : size_t CheckGioWrite(struct Gio  *gp,
     275                 :                      uint8_t     *addr,
     276               1 :                      size_t      nbytes) {
     277               1 :   return CheckGioOp(gp, addr, nbytes, CheckGioWriteWithProber);
     278                 : }
     279                 : 
     280                 : size_t CheckGioZeros(struct Gio *gp,
     281               1 :                      size_t     nbytes) {
     282                 :   unsigned char byte;
     283                 :   ssize_t       rv;
     284               1 :   size_t        nerrors = 0;
     285                 :   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          196609 :   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                 :     }
     308                 :   }
     309               1 :   return nerrors;
     310                 : }
     311                 : 
     312                 : 
     313                 : int main(int ac,
     314               1 :          char **av) {
     315                 :   int                   opt;
     316                 : 
     317                 :   struct NaClDescImcShm *shmp;
     318                 :   struct NaClDescEffectorTrustedMem eff;
     319                 :   struct NaClDesc *dp;
     320                 :   struct NaClDescEffector *effp;
     321                 :   uintptr_t addr;
     322                 :   uintptr_t addr2;
     323                 :   size_t nbytes;
     324                 :   size_t errs;
     325                 :   int rv;
     326                 :   struct NaClGioShm gio_shm;
     327               1 :   size_t map_chunks = NCHUNKS;
     328                 : 
     329               2 :   while (EOF != (opt = getopt(ac, av, "m:n:s:v"))) {
     330               0 :     switch (opt) {
     331                 :       case 'm':
     332               0 :         map_chunks = strtoul(optarg, (char **) NULL, 0);
     333               0 :         break;
     334                 :       case 'n':
     335               0 :         gNumSamples = strtoul(optarg, (char **) NULL, 0);
     336               0 :         break;
     337                 :       case 's':
     338               0 :         gRandomSeed = strtoul(optarg, (char **) NULL, 0);
     339               0 :         break;
     340                 :       case 'v':
     341               0 :         ++gVerbose;
     342               0 :         break;
     343                 :       default:
     344               0 :         fprintf(stderr,
     345                 :                 ("Usage: gio_shm_test [-v] [-m map_chunks]"
     346                 :                  " [-n num_samples] [-s seed]\n"));
     347               0 :         return EXIT_FAILURE;
     348                 :     }
     349                 :   }
     350                 : 
     351               1 :   printf("Using seed %d (0x%x)\n", gRandomSeed, gRandomSeed);
     352               1 :   srand(gRandomSeed);
     353                 : 
     354               1 :   NaClNrdAllModulesInit();
     355                 : 
     356               1 :   shmp = malloc(sizeof *shmp);
     357               1 :   if (NULL == shmp) {
     358               0 :     printf("No memory\n");
     359               0 :     printf("FAILED\n");
     360               0 :     return EXIT_FAILURE;
     361                 :   }
     362                 : 
     363               1 :   nbytes = map_chunks * NACL_MAP_PAGESIZE;
     364               1 :   if (!NaClDescImcShmAllocCtor(shmp, nbytes, /* executable= */ 0)) {
     365               0 :     printf("NaClDescImcShmAllocCtor failed\n");
     366               0 :     printf("FAILED\n");
     367               0 :     return EXIT_FAILURE;
     368                 :   }
     369               1 :   if (!NaClDescEffectorTrustedMemCtor(&eff)) {
     370               0 :     printf("NaClDescEffectorTrustedMemCtor failed\n");
     371               0 :     printf("FAILED\n");
     372               0 :     return EXIT_FAILURE;
     373                 :   }
     374               1 :   dp = &shmp->base;
     375               1 :   effp = &eff.base;
     376                 : 
     377               1 :   addr = (*((struct NaClDescVtbl const *) dp->base.vtbl)->
     378                 :           Map)(dp,
     379                 :                effp,
     380                 :                NULL,
     381                 :                nbytes,
     382                 :                NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE,
     383                 :                NACL_ABI_MAP_SHARED,
     384                 :                0);
     385               1 :   if (NaClPtrIsNegErrno(&addr)) {
     386               0 :     printf("Map failed\n");
     387               0 :     return EXIT_FAILURE;
     388                 :   }
     389                 : 
     390               1 :   MemWalk(MemFiller, (uint32_t *) addr, nbytes / sizeof(uint32_t));
     391               1 :   printf("Checking basic consistency\n");
     392               1 :   if (0 != MemWalk(MemChecker, (uint32_t *) addr, nbytes / sizeof(uint32_t))) {
     393               0 :     printf("Initial consistency check failed\n");
     394               0 :     printf("FAILED\n");
     395               0 :     return EXIT_FAILURE;
     396                 :   }
     397                 : 
     398               1 :   addr2 = (*((struct NaClDescVtbl const *) dp->base.vtbl)->
     399                 :            Map)(dp,
     400                 :                 effp,
     401                 :                 NULL,
     402                 :                 nbytes,
     403                 :                 NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE,
     404                 :                 NACL_ABI_MAP_SHARED,
     405                 :                 0);
     406               1 :   if (NaClPtrIsNegErrno(&addr2)) {
     407               0 :     printf("Second Map failed\n");
     408               0 :     return EXIT_FAILURE;
     409                 :   }
     410               1 :   printf("Checking second view consistency\n");
     411               1 :   if (0 != MemWalk(MemChecker, (uint32_t *) addr2, nbytes / sizeof(uint32_t))) {
     412               0 :     printf("Second view consistency check failed\n");
     413               0 :     printf("FAILED\n");
     414               0 :     return EXIT_FAILURE;
     415                 :   }
     416               1 :   if (0 != (rv = (*((struct NaClDescVtbl const *) dp->base.vtbl)->
     417                 :                   UnmapUnsafe)(dp, effp, (void *) addr2, nbytes))) {
     418               0 :     printf("UnmapUnsafe failed, returned %d\n", rv);
     419               0 :     printf("FAILED\n");
     420               0 :     return EXIT_FAILURE;
     421                 :   }
     422                 : 
     423               1 :   if (!NaClGioShmCtor(&gio_shm, dp, nbytes)) {
     424               0 :     printf("NaClGioShmCtor failed\n");
     425               0 :     printf("FAILED\n");
     426               0 :     return EXIT_FAILURE;
     427                 :   }
     428                 : 
     429               1 :   printf("Checking Gio vs direct shm consistency, read\n");
     430               1 :   if (0 != (errs = CheckGioRead((struct Gio *) &gio_shm,
     431                 :                                 (uint8_t *) addr,
     432                 :                                 nbytes))) {
     433               0 :     printf("ERROR: CheckGioRead failed, found %"NACL_PRIdS" errors\n", errs);
     434                 :   }
     435                 : 
     436               1 :   printf("Zeroing shared memory\n");
     437               1 :   MemWalk(ZeroFiller, (uint32_t *) addr, nbytes / sizeof(uint32_t));
     438               1 :   printf("Reading for zeros\n");
     439               1 :   if (0 != (errs = CheckGioZeros((struct Gio *) &gio_shm,
     440                 :                                  nbytes))) {
     441               0 :     printf("ERROR: Gio found non-zero bytes!\n");
     442                 :   }
     443                 : 
     444               1 :   printf("Checking Gio vs direct shm consistency, write\n");
     445               1 :   if (0 != (errs = CheckGioWrite((struct Gio *) &gio_shm,
     446                 :                                  (uint8_t *) addr,
     447                 :                                  nbytes))) {
     448               0 :     printf("ERROR: CheckGioWrite failed, found %"NACL_PRIdS" errors\n", errs);
     449                 :   }
     450                 : 
     451               1 :   (*gio_shm.base.vtbl->Dtor)((struct Gio *) &gio_shm);
     452                 : 
     453               1 :   NaClDescUnref(dp);
     454               1 :   (*effp->vtbl->Dtor)(effp);
     455                 : 
     456               1 :   NaClNrdAllModulesFini();
     457               1 :   if (0 != errs) {
     458               0 :     printf("FAILED\n");
     459               0 :     return EXIT_FAILURE;
     460                 :   } else {
     461               1 :     printf("PASSED\n");
     462               1 :     return EXIT_SUCCESS;
     463                 :   }
     464                 : }

Generated by: LCOV version 1.7