LCOV - code coverage report
Current view: top level - xpcom/build - NSPRInterposer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 48 67 71.6 %
Date: 2017-07-14 16:53:18 Functions: 9 11 81.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "IOInterposer.h"
       8             : #include "NSPRInterposer.h"
       9             : 
      10             : #include "prio.h"
      11             : #include "private/pprio.h"
      12             : #include "nsDebug.h"
      13             : #include "nscore.h"
      14             : 
      15             : namespace {
      16             : 
      17             : using namespace mozilla;
      18             : 
      19             : /* Original IO methods */
      20             : PRCloseFN sCloseFn = nullptr;
      21             : PRReadFN  sReadFn  = nullptr;
      22             : PRWriteFN sWriteFn = nullptr;
      23             : PRFsyncFN sFSyncFn = nullptr;
      24             : PRFileInfoFN sFileInfoFn = nullptr;
      25             : PRFileInfo64FN sFileInfo64Fn = nullptr;
      26             : 
      27             : /**
      28             :  * RAII class for timing the duration of an NSPR I/O call and reporting the
      29             :  * result to the IOInterposeObserver API.
      30             :  */
      31             : class NSPRIOAutoObservation : public IOInterposeObserver::Observation
      32             : {
      33             : public:
      34        1695 :   explicit NSPRIOAutoObservation(IOInterposeObserver::Operation aOp)
      35        1695 :     : IOInterposeObserver::Observation(aOp, "NSPRIOInterposer")
      36             :   {
      37        1695 :   }
      38             : 
      39        1695 :   ~NSPRIOAutoObservation() override
      40        3390 :   {
      41        1695 :     Report();
      42        1695 :   }
      43             : };
      44             : 
      45             : PRStatus PR_CALLBACK
      46         599 : interposedClose(PRFileDesc* aFd)
      47             : {
      48             :   // If we don't have a valid original function pointer something is very wrong.
      49         599 :   NS_ASSERTION(sCloseFn, "NSPR IO Interposing: sCloseFn is NULL");
      50             : 
      51        1198 :   NSPRIOAutoObservation timer(IOInterposeObserver::OpClose);
      52        1198 :   return sCloseFn(aFd);
      53             : }
      54             : 
      55             : int32_t PR_CALLBACK
      56         628 : interposedRead(PRFileDesc* aFd, void* aBuf, int32_t aAmt)
      57             : {
      58             :   // If we don't have a valid original function pointer something is very wrong.
      59         628 :   NS_ASSERTION(sReadFn, "NSPR IO Interposing: sReadFn is NULL");
      60             : 
      61        1256 :   NSPRIOAutoObservation timer(IOInterposeObserver::OpRead);
      62        1256 :   return sReadFn(aFd, aBuf, aAmt);
      63             : }
      64             : 
      65             : int32_t PR_CALLBACK
      66         116 : interposedWrite(PRFileDesc* aFd, const void* aBuf, int32_t aAmt)
      67             : {
      68             :   // If we don't have a valid original function pointer something is very wrong.
      69         116 :   NS_ASSERTION(sWriteFn, "NSPR IO Interposing: sWriteFn is NULL");
      70             : 
      71         232 :   NSPRIOAutoObservation timer(IOInterposeObserver::OpWrite);
      72         232 :   return sWriteFn(aFd, aBuf, aAmt);
      73             : }
      74             : 
      75             : PRStatus PR_CALLBACK
      76           6 : interposedFSync(PRFileDesc* aFd)
      77             : {
      78             :   // If we don't have a valid original function pointer something is very wrong.
      79           6 :   NS_ASSERTION(sFSyncFn, "NSPR IO Interposing: sFSyncFn is NULL");
      80             : 
      81          12 :   NSPRIOAutoObservation timer(IOInterposeObserver::OpFSync);
      82          12 :   return sFSyncFn(aFd);
      83             : }
      84             : 
      85             : PRStatus PR_CALLBACK
      86           1 : interposedFileInfo(PRFileDesc* aFd, PRFileInfo* aInfo)
      87             : {
      88             :   // If we don't have a valid original function pointer something is very wrong.
      89           1 :   NS_ASSERTION(sFileInfoFn, "NSPR IO Interposing: sFileInfoFn is NULL");
      90             : 
      91           2 :   NSPRIOAutoObservation timer(IOInterposeObserver::OpStat);
      92           2 :   return sFileInfoFn(aFd, aInfo);
      93             : }
      94             : 
      95             : PRStatus PR_CALLBACK
      96         345 : interposedFileInfo64(PRFileDesc* aFd, PRFileInfo64* aInfo)
      97             : {
      98             :   // If we don't have a valid original function pointer something is very wrong.
      99         345 :   NS_ASSERTION(sFileInfo64Fn, "NSPR IO Interposing: sFileInfo64Fn is NULL");
     100             : 
     101         690 :   NSPRIOAutoObservation timer(IOInterposeObserver::OpStat);
     102         690 :   return sFileInfo64Fn(aFd, aInfo);
     103             : }
     104             : 
     105             : } // namespace
     106             : 
     107             : namespace mozilla {
     108             : 
     109             : void
     110           1 : InitNSPRIOInterposing()
     111             : {
     112             :   // Check that we have not interposed any of the IO methods before
     113           1 :   MOZ_ASSERT(!sCloseFn && !sReadFn && !sWriteFn && !sFSyncFn && !sFileInfoFn &&
     114             :              !sFileInfo64Fn);
     115             : 
     116             :   // We can't actually use this assertion because we initialize this code
     117             :   // before XPCOM is initialized, so NS_IsMainThread() always returns false.
     118             :   // MOZ_ASSERT(NS_IsMainThread());
     119             : 
     120             :   // Get IO methods from NSPR and const cast the structure so we can modify it.
     121           1 :   PRIOMethods* methods = const_cast<PRIOMethods*>(PR_GetFileMethods());
     122             : 
     123             :   // Something is badly wrong if we don't get IO methods... However, we don't
     124             :   // want to crash over that in non-debug builds. This is unlikely to happen
     125             :   // so an assert is enough, no need to report it to the caller.
     126           1 :   MOZ_ASSERT(methods);
     127           1 :   if (!methods) {
     128           0 :     return;
     129             :   }
     130             : 
     131             :   // Store original functions
     132           1 :   sCloseFn      = methods->close;
     133           1 :   sReadFn       = methods->read;
     134           1 :   sWriteFn      = methods->write;
     135           1 :   sFSyncFn      = methods->fsync;
     136           1 :   sFileInfoFn   = methods->fileInfo;
     137           1 :   sFileInfo64Fn = methods->fileInfo64;
     138             : 
     139             :   // Overwrite with our interposed functions
     140           1 :   methods->close      = &interposedClose;
     141           1 :   methods->read       = &interposedRead;
     142           1 :   methods->write      = &interposedWrite;
     143           1 :   methods->fsync      = &interposedFSync;
     144           1 :   methods->fileInfo   = &interposedFileInfo;
     145           1 :   methods->fileInfo64 = &interposedFileInfo64;
     146             : }
     147             : 
     148             : void
     149           0 : ClearNSPRIOInterposing()
     150             : {
     151             :   // If we have already cleared IO interposing, or not initialized it this is
     152             :   // actually bad.
     153           0 :   MOZ_ASSERT(sCloseFn && sReadFn && sWriteFn && sFSyncFn && sFileInfoFn &&
     154             :              sFileInfo64Fn);
     155             : 
     156             :   // Get IO methods from NSPR and const cast the structure so we can modify it.
     157           0 :   PRIOMethods* methods = const_cast<PRIOMethods*>(PR_GetFileMethods());
     158             : 
     159             :   // Something is badly wrong if we don't get IO methods... However, we don't
     160             :   // want to crash over that in non-debug builds. This is unlikely to happen
     161             :   // so an assert is enough, no need to report it to the caller.
     162           0 :   MOZ_ASSERT(methods);
     163           0 :   if (!methods) {
     164           0 :     return;
     165             :   }
     166             : 
     167             :   // Restore original functions
     168           0 :   methods->close      = sCloseFn;
     169           0 :   methods->read       = sReadFn;
     170           0 :   methods->write      = sWriteFn;
     171           0 :   methods->fsync      = sFSyncFn;
     172           0 :   methods->fileInfo   = sFileInfoFn;
     173           0 :   methods->fileInfo64 = sFileInfo64Fn;
     174             : 
     175             :   // Forget about original functions
     176           0 :   sCloseFn      = nullptr;
     177           0 :   sReadFn       = nullptr;
     178           0 :   sWriteFn      = nullptr;
     179           0 :   sFSyncFn      = nullptr;
     180           0 :   sFileInfoFn   = nullptr;
     181           0 :   sFileInfo64Fn = nullptr;
     182             : }
     183             : 
     184             : } // namespace mozilla
     185             : 

Generated by: LCOV version 1.13