AutoMemMap.cpp (2861B)
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 "AutoMemMap.h" 8 #include "ScriptPreloader-inl.h" 9 10 #include "mozilla/Try.h" 11 #include "mozilla/ipc/FileDescriptor.h" 12 #include "nsIFile.h" 13 14 #include <private/pprio.h> 15 16 namespace mozilla { 17 namespace loader { 18 19 using namespace mozilla::ipc; 20 21 AutoMemMap::~AutoMemMap() { reset(); } 22 23 FileDescriptor AutoMemMap::cloneFileDescriptor() const { 24 if (fd.get()) { 25 auto handle = 26 FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(fd.get())); 27 return FileDescriptor(handle); 28 } 29 return FileDescriptor(); 30 } 31 32 Result<Ok, nsresult> AutoMemMap::init(nsIFile* file, int flags, int mode, 33 PRFileMapProtect prot) { 34 MOZ_ASSERT(!fd); 35 36 MOZ_TRY(file->OpenNSPRFileDesc(flags, mode, getter_Transfers(fd))); 37 38 return initInternal(prot); 39 } 40 41 Result<Ok, nsresult> AutoMemMap::init(const FileDescriptor& file, 42 PRFileMapProtect prot, size_t maybeSize) { 43 MOZ_ASSERT(!fd); 44 if (!file.IsValid()) { 45 return Err(NS_ERROR_INVALID_ARG); 46 } 47 48 auto handle = file.ClonePlatformHandle(); 49 50 fd.reset(PR_ImportFile(PROsfd(handle.get()))); 51 if (!fd) { 52 return Err(NS_ERROR_FAILURE); 53 } 54 (void)handle.release(); 55 56 return initInternal(prot, maybeSize); 57 } 58 59 Result<Ok, nsresult> AutoMemMap::initInternal(PRFileMapProtect prot, 60 size_t maybeSize) { 61 MOZ_ASSERT(!fileMap); 62 MOZ_ASSERT(!addr); 63 64 if (maybeSize > 0) { 65 // Some OSes' shared memory objects can't be stat()ed, either at 66 // all (Android) or without loosening the sandbox (Mac) so just 67 // use the size. 68 size_ = maybeSize; 69 } else { 70 // But if we don't have the size, assume it's a regular file and 71 // ask for it. 72 PRFileInfo64 fileInfo; 73 MOZ_TRY(PR_GetOpenFileInfo64(fd.get(), &fileInfo)); 74 75 if (fileInfo.size > UINT32_MAX) { 76 return Err(NS_ERROR_INVALID_ARG); 77 } 78 size_ = fileInfo.size; 79 } 80 81 fileMap = PR_CreateFileMap(fd.get(), 0, prot); 82 if (!fileMap) { 83 return Err(NS_ERROR_FAILURE); 84 } 85 86 addr = PR_MemMap(fileMap, 0, size_); 87 if (!addr) { 88 return Err(NS_ERROR_FAILURE); 89 } 90 91 return Ok(); 92 } 93 94 FileDescriptor AutoMemMap::cloneHandle() const { return cloneFileDescriptor(); } 95 96 void AutoMemMap::reset() { 97 if (addr && !persistent_) { 98 (void)NS_WARN_IF(PR_MemUnmap(addr, size()) != PR_SUCCESS); 99 addr = nullptr; 100 } 101 if (fileMap) { 102 (void)NS_WARN_IF(PR_CloseFileMap(fileMap) != PR_SUCCESS); 103 fileMap = nullptr; 104 } 105 fd = nullptr; 106 } 107 108 } // namespace loader 109 } // namespace mozilla