summaryrefslogtreecommitdiffstats
path: root/mozglue/misc/MmapFaultHandler.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--mozglue/misc/MmapFaultHandler.h105
1 files changed, 105 insertions, 0 deletions
diff --git a/mozglue/misc/MmapFaultHandler.h b/mozglue/misc/MmapFaultHandler.h
new file mode 100644
index 0000000000..5fb6cdb142
--- /dev/null
+++ b/mozglue/misc/MmapFaultHandler.h
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef MmapFaultHandler_h_
+#define MmapFaultHandler_h_
+
+#if defined(XP_WIN)
+// Windows
+
+# ifdef HAVE_SEH_EXCEPTIONS
+# define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) __try {
+# define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) __try {
+# define MMAP_FAULT_HANDLER_CATCH(retval) \
+ } \
+ __except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR \
+ ? EXCEPTION_EXECUTE_HANDLER \
+ : EXCEPTION_CONTINUE_SEARCH) { \
+ NS_WARNING("unexpected EXCEPTION_IN_PAGE_ERROR"); \
+ return retval; \
+ }
+# else
+# define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) {
+# define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) {
+# define MMAP_FAULT_HANDLER_CATCH(retval) }
+# endif
+
+#elif defined(XP_DARWIN)
+// MacOS
+
+# define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) {
+# define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) {
+# define MMAP_FAULT_HANDLER_CATCH(retval) }
+
+#else
+// Linux
+
+# include "mozilla/Attributes.h"
+# include "mozilla/Types.h"
+# include <stdint.h>
+# include <setjmp.h>
+
+class MOZ_RAII MmapAccessScope {
+ public:
+ MFBT_API MmapAccessScope(void* aBuf, uint32_t aBufLen,
+ const char* aFilename = nullptr);
+ MFBT_API ~MmapAccessScope();
+
+ MmapAccessScope(const MmapAccessScope&) = delete;
+ MmapAccessScope& operator=(const MmapAccessScope&) = delete;
+
+ void SetThreadLocalScope();
+ bool IsInsideBuffer(void* aPtr);
+ void CrashWithInfo(void* aPtr);
+
+ // sigsetjmp cannot be called from a method that returns before calling
+ // siglongjmp, so the macro must call sigsetjmp directly and mJmpBuf must be
+ // public.
+ sigjmp_buf mJmpBuf;
+
+ private:
+ void* mBuf;
+ const char* mFilename;
+ uint32_t mBufLen;
+ MmapAccessScope* mPreviousScope;
+};
+
+// Gets around warnings for null-checking in a macro.
+template <typename T>
+inline bool ValidFD(T fd) {
+ return !!fd;
+}
+
+# define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) \
+ { \
+ void* mmapScopeBuf = nullptr; \
+ nsCString mmapScopeFilename; \
+ uint32_t mmapScopeBufLen = 0; \
+ if (ValidFD(fd) && fd->mMap) { \
+ mmapScopeBuf = (void*)fd->mFileStart; \
+ mmapScopeBufLen = fd->mTotalLen; \
+ } \
+ if (ValidFD(fd) && fd->mFile) { \
+ nsCOMPtr<nsIFile> file = fd->mFile.GetBaseFile(); \
+ file->GetNativeLeafName(mmapScopeFilename); \
+ } \
+ MmapAccessScope mmapScope(mmapScopeBuf, mmapScopeBufLen, \
+ mmapScopeFilename.get()); \
+ if (sigsetjmp(mmapScope.mJmpBuf, 0) == 0) {
+# define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) \
+ { \
+ MmapAccessScope mmapScope((void*)(buf), (bufLen)); \
+ if (sigsetjmp(mmapScope.mJmpBuf, 0) == 0) {
+# define MMAP_FAULT_HANDLER_CATCH(retval) \
+ } \
+ else { \
+ NS_WARNING("SIGBUS received when accessing mmapped file"); \
+ return retval; \
+ } \
+ }
+
+#endif
+
+#endif