LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - nacl_error_gio.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 59 44 74.6 %
Date: 2014-09-25 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                 : int NaClErrorGioCtor(struct NaClErrorGio *self,
      50               1 :                      struct Gio *pass_through) {
      51               1 :   memset(self->circular_buffer, 0, NACL_ARRAY_SIZE(self->circular_buffer));
      52               1 :   self->insert_ix = 0;
      53               1 :   self->num_bytes = 0;
      54               1 :   self->pass_through = pass_through;
      55               1 :   self->vtbl = &kNaClErrorGioVtbl;
      56               1 :   return 1;
      57               1 : }
      58                 : 
      59               1 : void NaClErrorGioDtor(struct Gio *vself) {
      60               1 :   struct NaClErrorGio *self = (struct NaClErrorGio *) vself;
      61                 : 
      62                 :   /* excessive paranoia? */
      63               1 :   memset(self->circular_buffer, 0, NACL_ARRAY_SIZE(self->circular_buffer));
      64               1 :   self->insert_ix = 0;
      65               1 :   self->num_bytes = 0;
      66               1 :   self->pass_through = NULL;
      67               1 :   self->vtbl = NULL;
      68               1 : }
      69                 : 
      70                 : ssize_t NaClErrorGioRead(struct Gio *vself,
      71                 :                          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               0 : }
      76                 : 
      77                 : ssize_t NaClErrorGioWrite(struct Gio *vself,
      78                 :                           void const *buf,
      79               1 :                           size_t count) {
      80               1 :   struct NaClErrorGio *self = (struct NaClErrorGio *) vself;
      81               1 :   uint8_t *byte_buf = (uint8_t *) buf;
      82                 :   ssize_t actual;
      83                 :   size_t ix;
      84                 : 
      85               1 :   actual = (*self->pass_through->vtbl->Write)(self->pass_through, buf, count);
      86               1 :   if (actual > 0) {
      87               1 :     for (ix = 0; ix < (size_t) actual; ++ix) {
      88               1 :       self->circular_buffer[self->insert_ix] = byte_buf[ix];
      89                 :       self->insert_ix = (self->insert_ix + 1) %
      90               1 :           NACL_ARRAY_SIZE(self->circular_buffer);
      91               1 :     }
      92                 :     if ((size_t) actual >
      93               1 :         NACL_ARRAY_SIZE(self->circular_buffer) - self->num_bytes) {
      94               1 :       self->num_bytes = NACL_ARRAY_SIZE(self->circular_buffer);
      95               1 :     } else {
      96               1 :       self->num_bytes += actual;
      97                 :     }
      98                 :   }
      99               1 :   return actual;
     100               1 : }
     101                 : 
     102                 : off_t NaClErrorGioSeek(struct Gio *vself,
     103                 :                        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               0 : }
     108                 : 
     109               0 : int NaClErrorGioFlush(struct Gio *vself) {
     110               0 :   struct NaClErrorGio *self = (struct NaClErrorGio *) vself;
     111               0 :   return (*self->pass_through->vtbl->Flush)(self->pass_through);
     112               0 : }
     113                 : 
     114               0 : int NaClErrorGioClose(struct Gio *vself) {
     115               0 :   return (*vself->vtbl->Flush)(vself);
     116               0 : }
     117                 : 
     118                 : struct GioVtbl const kNaClErrorGioVtbl = {
     119                 :   NaClErrorGioDtor,
     120                 :   NaClErrorGioRead,
     121                 :   NaClErrorGioWrite,
     122                 :   NaClErrorGioSeek,
     123                 :   NaClErrorGioFlush,
     124                 :   NaClErrorGioClose,
     125                 : };
     126                 : 
     127                 : size_t NaClErrorGioGetOutput(struct NaClErrorGio *self,
     128                 :                              char *buffer,
     129               1 :                              size_t buffer_size) {
     130                 :   size_t num_copy;
     131                 :   size_t ix;
     132                 :   size_t count;
     133                 : 
     134               1 :   num_copy = self->num_bytes;
     135                 :   /* 0 <= num_copy <= NACL_ARRAY_SIZE(self->circular_buffer) */
     136               1 :   if (0 == buffer_size) {
     137               1 :     return self->num_bytes;
     138                 :   }
     139                 :   /* buffer_size > 0 */
     140               1 :   if (num_copy > buffer_size) {
     141               1 :     num_copy = buffer_size;
     142                 :   }
     143                 :   /*
     144                 :    * 0 <= num_copy <= min(NACL_ARRAY_SIZE(self->circular_buffer),
     145                 :    *                                      buffer_size)
     146                 :    */
     147                 :   ix = (self->insert_ix +
     148                 :         NACL_ARRAY_SIZE(self->circular_buffer) - self->num_bytes) %
     149               1 :       NACL_ARRAY_SIZE(self->circular_buffer);
     150               1 :   for (count = 0; count < num_copy; ++count) {
     151               1 :     buffer[count] = self->circular_buffer[ix];
     152               1 :     ix = (ix + 1) % NACL_ARRAY_SIZE(self->circular_buffer);
     153               1 :   }
     154                 :   /*
     155                 :    * count = num_copy
     156                 :    *       <= min(NACL_ARRAY_SIZE(self->circular_buffer), buffer_size)
     157                 :    */
     158               1 :   return self->num_bytes;
     159               1 : }
     160                 : 

Generated by: LCOV version 1.7