summaryrefslogtreecommitdiffstats
path: root/xpcom/build/NSPRInterposer.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /xpcom/build/NSPRInterposer.cpp
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'xpcom/build/NSPRInterposer.cpp')
-rw-r--r--xpcom/build/NSPRInterposer.cpp185
1 files changed, 185 insertions, 0 deletions
diff --git a/xpcom/build/NSPRInterposer.cpp b/xpcom/build/NSPRInterposer.cpp
new file mode 100644
index 000000000..a7c53a97a
--- /dev/null
+++ b/xpcom/build/NSPRInterposer.cpp
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "IOInterposer.h"
+#include "NSPRInterposer.h"
+
+#include "prio.h"
+#include "private/pprio.h"
+#include "nsDebug.h"
+#include "nscore.h"
+
+namespace {
+
+using namespace mozilla;
+
+/* Original IO methods */
+PRCloseFN sCloseFn = nullptr;
+PRReadFN sReadFn = nullptr;
+PRWriteFN sWriteFn = nullptr;
+PRFsyncFN sFSyncFn = nullptr;
+PRFileInfoFN sFileInfoFn = nullptr;
+PRFileInfo64FN sFileInfo64Fn = nullptr;
+
+/**
+ * RAII class for timing the duration of an NSPR I/O call and reporting the
+ * result to the IOInterposeObserver API.
+ */
+class NSPRIOAutoObservation : public IOInterposeObserver::Observation
+{
+public:
+ explicit NSPRIOAutoObservation(IOInterposeObserver::Operation aOp)
+ : IOInterposeObserver::Observation(aOp, "NSPRIOInterposer")
+ {
+ }
+
+ ~NSPRIOAutoObservation()
+ {
+ Report();
+ }
+};
+
+PRStatus PR_CALLBACK
+interposedClose(PRFileDesc* aFd)
+{
+ // If we don't have a valid original function pointer something is very wrong.
+ NS_ASSERTION(sCloseFn, "NSPR IO Interposing: sCloseFn is NULL");
+
+ NSPRIOAutoObservation timer(IOInterposeObserver::OpClose);
+ return sCloseFn(aFd);
+}
+
+int32_t PR_CALLBACK
+interposedRead(PRFileDesc* aFd, void* aBuf, int32_t aAmt)
+{
+ // If we don't have a valid original function pointer something is very wrong.
+ NS_ASSERTION(sReadFn, "NSPR IO Interposing: sReadFn is NULL");
+
+ NSPRIOAutoObservation timer(IOInterposeObserver::OpRead);
+ return sReadFn(aFd, aBuf, aAmt);
+}
+
+int32_t PR_CALLBACK
+interposedWrite(PRFileDesc* aFd, const void* aBuf, int32_t aAmt)
+{
+ // If we don't have a valid original function pointer something is very wrong.
+ NS_ASSERTION(sWriteFn, "NSPR IO Interposing: sWriteFn is NULL");
+
+ NSPRIOAutoObservation timer(IOInterposeObserver::OpWrite);
+ return sWriteFn(aFd, aBuf, aAmt);
+}
+
+PRStatus PR_CALLBACK
+interposedFSync(PRFileDesc* aFd)
+{
+ // If we don't have a valid original function pointer something is very wrong.
+ NS_ASSERTION(sFSyncFn, "NSPR IO Interposing: sFSyncFn is NULL");
+
+ NSPRIOAutoObservation timer(IOInterposeObserver::OpFSync);
+ return sFSyncFn(aFd);
+}
+
+PRStatus PR_CALLBACK
+interposedFileInfo(PRFileDesc* aFd, PRFileInfo* aInfo)
+{
+ // If we don't have a valid original function pointer something is very wrong.
+ NS_ASSERTION(sFileInfoFn, "NSPR IO Interposing: sFileInfoFn is NULL");
+
+ NSPRIOAutoObservation timer(IOInterposeObserver::OpStat);
+ return sFileInfoFn(aFd, aInfo);
+}
+
+PRStatus PR_CALLBACK
+interposedFileInfo64(PRFileDesc* aFd, PRFileInfo64* aInfo)
+{
+ // If we don't have a valid original function pointer something is very wrong.
+ NS_ASSERTION(sFileInfo64Fn, "NSPR IO Interposing: sFileInfo64Fn is NULL");
+
+ NSPRIOAutoObservation timer(IOInterposeObserver::OpStat);
+ return sFileInfo64Fn(aFd, aInfo);
+}
+
+} // namespace
+
+namespace mozilla {
+
+void
+InitNSPRIOInterposing()
+{
+ // Check that we have not interposed any of the IO methods before
+ MOZ_ASSERT(!sCloseFn && !sReadFn && !sWriteFn && !sFSyncFn && !sFileInfoFn &&
+ !sFileInfo64Fn);
+
+ // We can't actually use this assertion because we initialize this code
+ // before XPCOM is initialized, so NS_IsMainThread() always returns false.
+ // MOZ_ASSERT(NS_IsMainThread());
+
+ // Get IO methods from NSPR and const cast the structure so we can modify it.
+ PRIOMethods* methods = const_cast<PRIOMethods*>(PR_GetFileMethods());
+
+ // Something is badly wrong if we don't get IO methods... However, we don't
+ // want to crash over that in non-debug builds. This is unlikely to happen
+ // so an assert is enough, no need to report it to the caller.
+ MOZ_ASSERT(methods);
+ if (!methods) {
+ return;
+ }
+
+ // Store original functions
+ sCloseFn = methods->close;
+ sReadFn = methods->read;
+ sWriteFn = methods->write;
+ sFSyncFn = methods->fsync;
+ sFileInfoFn = methods->fileInfo;
+ sFileInfo64Fn = methods->fileInfo64;
+
+ // Overwrite with our interposed functions
+ methods->close = &interposedClose;
+ methods->read = &interposedRead;
+ methods->write = &interposedWrite;
+ methods->fsync = &interposedFSync;
+ methods->fileInfo = &interposedFileInfo;
+ methods->fileInfo64 = &interposedFileInfo64;
+}
+
+void
+ClearNSPRIOInterposing()
+{
+ // If we have already cleared IO interposing, or not initialized it this is
+ // actually bad.
+ MOZ_ASSERT(sCloseFn && sReadFn && sWriteFn && sFSyncFn && sFileInfoFn &&
+ sFileInfo64Fn);
+
+ // Get IO methods from NSPR and const cast the structure so we can modify it.
+ PRIOMethods* methods = const_cast<PRIOMethods*>(PR_GetFileMethods());
+
+ // Something is badly wrong if we don't get IO methods... However, we don't
+ // want to crash over that in non-debug builds. This is unlikely to happen
+ // so an assert is enough, no need to report it to the caller.
+ MOZ_ASSERT(methods);
+ if (!methods) {
+ return;
+ }
+
+ // Restore original functions
+ methods->close = sCloseFn;
+ methods->read = sReadFn;
+ methods->write = sWriteFn;
+ methods->fsync = sFSyncFn;
+ methods->fileInfo = sFileInfoFn;
+ methods->fileInfo64 = sFileInfo64Fn;
+
+ // Forget about original functions
+ sCloseFn = nullptr;
+ sReadFn = nullptr;
+ sWriteFn = nullptr;
+ sFSyncFn = nullptr;
+ sFileInfoFn = nullptr;
+ sFileInfo64Fn = nullptr;
+}
+
+} // namespace mozilla
+