LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - nacl_error_gio.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 69 57 82.6 %
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 <string.h>
       8                 : 
       9                 : #include "native_client/src/include/nacl_macros.h"
      10                 : #include "native_client/src/shared/gio/gio.h"
      11                 : #include "native_client/src/trusted/service_runtime/nacl_error_gio.h"
      12                 : 
      13                 : /*
      14                 :  * This is a service-runtime provided subclass of Gio that is used for
      15                 :  * NaClLog's output Gio stream.  In addition to the normal logging and
      16                 :  * error reporting function, it retains a copy of the last (N>=2) line
      17                 :  * of logging output for use with fatal error reporting -- the abort
      18                 :  * behavior in NaClLog is modified to use a functor that takes the
      19                 :  * retained last output lines and sends them to the plugin prior to
      20                 :  * copying it to an on-stack buffer and crashing.  The latter is for
      21                 :  * inclusion in breakpad's minidump, which should capture the thread
      22                 :  * stack.  The former is to allow the plugin to forward the log
      23                 :  * message to the JavaScript console, so developers can get a better
      24                 :  * idea of what happened -- they won't have direct access to the
      25                 :  * minidumps (potential user privacy issue), so without this they'd
      26                 :  * have to ask Google, which isn't exactly scalable.
      27                 :  *
      28                 :  * Since trying to use the reverse channel or SRPC when there's a
      29                 :  * fatal error might not be kosher, we shouldn't rely on too much
      30                 :  * infrastructure to be operational.  The system may be so messed up
      31                 :  * that doing so will just lead to another LOG_FATAL error.  We could
      32                 :  * prevent infinite regress by setting a global variable to prevent
      33                 :  * recursive plugin logging, but rather than hacks like that, we
      34                 :  * commandeer the bootstrap channel -- which is currently only used to
      35                 :  * pass the socket address used to connect to the secure command
      36                 :  * channel to the service runtime and then to connect to the PPAPI
      37                 :  * proxy.  We use low-level, platform-specific I/O routines to send
      38                 :  * the logging string via this channel.
      39                 :  *
      40                 :  * (The reason N>=2 above is because the log module will, after
      41                 :  * printing the LOG_FATAL message, always append a LOG_ERROR message
      42                 :  * "LOG_FATAL abort exit\n" as an easy-to-recognize output for drivers
      43                 :  * of the software, and that will be the last entry in the output
      44                 :  * stream.  So if N==1, that's all that we'd see.)
      45                 :  */
      46                 : 
      47                 : struct GioVtbl const kNaClErrorGioVtbl;  /* fwd */
      48                 : 
      49            1268 : int NaClErrorGioCtor(struct NaClErrorGio *self,
      50            1268 :                      struct Gio *pass_through) {
      51            3804 :   memset(self->circular_buffer, 0, NACL_ARRAY_SIZE(self->circular_buffer));
      52            1268 :   self->insert_ix = 0;
      53            1268 :   self->num_bytes = 0;
      54            1268 :   self->pass_through = pass_through;
      55            1268 :   self->vtbl = &kNaClErrorGioVtbl;
      56            1268 :   return 1;
      57                 : }
      58                 : 
      59            1002 : void NaClErrorGioDtor(struct Gio *vself) {
      60            1002 :   struct NaClErrorGio *self = (struct NaClErrorGio *) vself;
      61                 : 
      62                 :   /* excessive paranoia? */
      63            3006 :   memset(self->circular_buffer, 0, NACL_ARRAY_SIZE(self->circular_buffer));
      64            1002 :   self->insert_ix = 0;
      65            1002 :   self->num_bytes = 0;
      66            1002 :   self->pass_through = NULL;
      67            1002 :   self->vtbl = NULL;
      68            1002 : }
      69                 : 
      70               0 : ssize_t NaClErrorGioRead(struct Gio *vself,
      71               0 :                          void *buf,
      72               0 :                          size_t count) {
      73               0 :   struct NaClErrorGio *self = (struct NaClErrorGio *) vself;
      74               0 :   return (*self->pass_through->vtbl->Read)(self->pass_through, buf, count);
      75                 : }
      76                 : 
      77           73974 : ssize_t NaClErrorGioWrite(struct Gio *vself,
      78           73974 :                           void const *buf,
      79           73974 :                           size_t count) {
      80           73974 :   struct NaClErrorGio *self = (struct NaClErrorGio *) vself;
      81           73974 :   uint8_t *byte_buf = (uint8_t *) buf;
      82           73974 :   ssize_t actual;
      83           73974 :   size_t ix;
      84                 : 
      85           73974 :   actual = (*self->pass_through->vtbl->Write)(self->pass_through, buf, count);
      86           73974 :   if (actual > 0) {
      87         2716128 :     for (ix = 0; ix < (size_t) actual; ++ix) {
      88         1286185 :       self->circular_buffer[self->insert_ix] = byte_buf[ix];
      89         1286185 :       self->insert_ix = (self->insert_ix + 1) %
      90                 :           NACL_ARRAY_SIZE(self->circular_buffer);
      91         1286185 :     }
      92           71879 :     if ((size_t) actual >
      93                 :         NACL_ARRAY_SIZE(self->circular_buffer) - self->num_bytes) {
      94           41719 :       self->num_bytes = NACL_ARRAY_SIZE(self->circular_buffer);
      95           41719 :     } else {
      96           30160 :       self->num_bytes += actual;
      97                 :     }
      98           71879 :   }
      99           73974 :   return actual;
     100                 : }
     101                 : 
     102               0 : off_t NaClErrorGioSeek(struct Gio *vself,
     103               0 :                        off_t offset,
     104               0 :                        int whence) {
     105               0 :   struct NaClErrorGio *self = (struct NaClErrorGio *) vself;
     106               0 :   return (*self->pass_through->vtbl->Seek)(self->pass_through, offset, whence);
     107                 : }
     108                 : 
     109            3629 : int NaClErrorGioFlush(struct Gio *vself) {
     110            3629 :   struct NaClErrorGio *self = (struct NaClErrorGio *) vself;
     111            3629 :   return (*self->pass_through->vtbl->Flush)(self->pass_through);
     112                 : }
     113                 : 
     114               0 : int NaClErrorGioClose(struct Gio *vself) {
     115               0 :   return (*vself->vtbl->Flush)(vself);
     116                 : }
     117                 : 
     118                 : struct GioVtbl const kNaClErrorGioVtbl = {
     119                 :   NaClErrorGioDtor,
     120                 :   NaClErrorGioRead,
     121                 :   NaClErrorGioWrite,
     122                 :   NaClErrorGioSeek,
     123                 :   NaClErrorGioFlush,
     124                 :   NaClErrorGioClose,
     125                 : };
     126                 : 
     127            1009 : size_t NaClErrorGioGetOutput(struct NaClErrorGio *self,
     128            1009 :                              char *buffer,
     129            1009 :                              size_t buffer_size) {
     130            1009 :   size_t num_copy;
     131            1009 :   size_t ix;
     132            1009 :   size_t count;
     133                 : 
     134            1009 :   num_copy = self->num_bytes;
     135                 :   /* 0 <= num_copy <= NACL_ARRAY_SIZE(self->circular_buffer) */
     136            1009 :   if (0 == buffer_size) {
     137               1 :     return self->num_bytes;
     138                 :   }
     139                 :   /* buffer_size > 0 */
     140            1008 :   if (num_copy > buffer_size) {
     141               1 :     num_copy = buffer_size;
     142               1 :   }
     143                 :   /*
     144                 :    * 0 <= num_copy <= min(NACL_ARRAY_SIZE(self->circular_buffer),
     145                 :    *                                      buffer_size)
     146                 :    */
     147            1008 :   ix = (self->insert_ix +
     148                 :         NACL_ARRAY_SIZE(self->circular_buffer) - self->num_bytes) %
     149                 :       NACL_ARRAY_SIZE(self->circular_buffer);
     150          910624 :   for (count = 0; count < num_copy; ++count) {
     151          454304 :     buffer[count] = self->circular_buffer[ix];
     152          454304 :     ix = (ix + 1) % NACL_ARRAY_SIZE(self->circular_buffer);
     153          454304 :   }
     154                 :   /*
     155                 :    * count = num_copy
     156                 :    *       <= min(NACL_ARRAY_SIZE(self->circular_buffer), buffer_size)
     157                 :    */
     158            1008 :   return self->num_bytes;
     159            1009 : }
     160                 : 

Generated by: LCOV version 1.7