MmapFaultHandler.h (4274B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef MmapFaultHandler_h_ 7 #define MmapFaultHandler_h_ 8 9 #if defined(XP_WIN) 10 // Windows 11 12 # ifdef HAVE_SEH_EXCEPTIONS 13 # define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) __try { 14 # define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) __try { 15 # define MMAP_FAULT_HANDLER_CATCH(retval) \ 16 } \ 17 __except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR \ 18 ? EXCEPTION_EXECUTE_HANDLER \ 19 : EXCEPTION_CONTINUE_SEARCH) { \ 20 NS_WARNING("unexpected EXCEPTION_IN_PAGE_ERROR"); \ 21 return retval; \ 22 } 23 # else 24 # define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) { 25 # define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) { 26 # define MMAP_FAULT_HANDLER_CATCH(retval) } 27 # endif 28 29 #elif defined(XP_DARWIN) 30 // MacOS 31 32 # define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) { 33 # define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) { 34 # define MMAP_FAULT_HANDLER_CATCH(retval) } 35 36 #elif defined(__wasi__) 37 38 # define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) { 39 # define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) { 40 # define MMAP_FAULT_HANDLER_CATCH(retval) } 41 42 #else 43 // Linux 44 45 # include "mozilla/Attributes.h" 46 # include "mozilla/Types.h" 47 # include <stdint.h> 48 # include <setjmp.h> 49 50 class MOZ_RAII MmapAccessScope { 51 public: 52 MFBT_API MmapAccessScope(void* aBuf, uint32_t aBufLen, 53 const char* aFilename = nullptr); 54 MFBT_API ~MmapAccessScope(); 55 56 MmapAccessScope(const MmapAccessScope&) = delete; 57 MmapAccessScope& operator=(const MmapAccessScope&) = delete; 58 59 void SetThreadLocalScope(); 60 bool IsInsideBuffer(void* aPtr); 61 void CrashWithInfo(void* aPtr); 62 63 // sigsetjmp cannot be called from a method that returns before calling 64 // siglongjmp, so the macro must call sigsetjmp directly and mJmpBuf must be 65 // public. 66 sigjmp_buf mJmpBuf; 67 68 private: 69 void* mBuf; 70 const char* mFilename; 71 uint32_t mBufLen; 72 MmapAccessScope* mPreviousScope; 73 }; 74 75 // Gets around warnings for null-checking in a macro. 76 template <typename T> 77 inline bool ValidFD(T fd) { 78 return !!fd; 79 } 80 81 # define MMAP_FAULT_HANDLER_BEGIN_HANDLE(fd) \ 82 { \ 83 void* mmapScopeBuf = nullptr; \ 84 nsCString mmapScopeFilename; \ 85 uint32_t mmapScopeBufLen = 0; \ 86 if (ValidFD(fd) && fd->mMap) { \ 87 mmapScopeBuf = (void*)fd->mFileStart; \ 88 mmapScopeBufLen = fd->mTotalLen; \ 89 } \ 90 if (ValidFD(fd) && fd->mFile) { \ 91 nsCOMPtr<nsIFile> file = fd->mFile.GetBaseFile(); \ 92 if (file) { \ 93 file->GetNativeLeafName(mmapScopeFilename); \ 94 } \ 95 } \ 96 MmapAccessScope mmapScope(mmapScopeBuf, mmapScopeBufLen, \ 97 mmapScopeFilename.get()); \ 98 if (sigsetjmp(mmapScope.mJmpBuf, 0) == 0) { 99 # define MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, bufLen) \ 100 { \ 101 MmapAccessScope mmapScope((void*)(buf), (bufLen)); \ 102 if (sigsetjmp(mmapScope.mJmpBuf, 0) == 0) { 103 # define MMAP_FAULT_HANDLER_CATCH(retval) \ 104 } \ 105 else { \ 106 NS_WARNING("SIGBUS received when accessing mmapped file"); \ 107 return retval; \ 108 } \ 109 } 110 111 #endif 112 113 #endif