15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/files/memory_mapped_file.h" 603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/files/file_path.h" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string16.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/threading/thread_restrictions.h" 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace base { 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)MemoryMappedFile::MemoryMappedFile() : data_(NULL), length_(0), image_(false) { 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool MemoryMappedFile::InitializeAsImageSection(const FilePath& file_name) { 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) image_ = true; 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Initialize(file_name); 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool MemoryMappedFile::MapFileRegionToMemory( 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const MemoryMappedFile::Region& region) { 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ThreadRestrictions::AssertIOAllowed(); 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!file_.IsValid()) 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int flags = image_ ? SEC_IMAGE | PAGE_READONLY : PAGE_READONLY; 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) file_mapping_.Set(::CreateFileMapping(file_.GetPlatformFile(), NULL, 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) flags, 0, 0, NULL)); 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!file_mapping_.IsValid()) 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LARGE_INTEGER map_start = {0}; 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SIZE_T map_size = 0; 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int32 data_offset = 0; 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (region == MemoryMappedFile::Region::kWholeFile) { 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int64 file_len = file_.GetLength(); 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (file_len <= 0 || file_len > kint32max) 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) length_ = static_cast<size_t>(file_len); 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The region can be arbitrarily aligned. MapViewOfFile, instead, requires 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // that the start address is aligned to the VM granularity (which is 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // typically larger than a page size, for instance 32k). 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Also, conversely to POSIX's mmap, the |map_size| doesn't have to be 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // aligned and must be less than or equal the mapped file size. 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We map here the outer region [|aligned_start|, |aligned_start+size|] 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // which contains |region| and then add up the |data_offset| displacement. 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int64 aligned_start = 0; 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int64 ignored = 0; 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CalculateVMAlignedBoundaries( 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci region.offset, region.size, &aligned_start, &ignored, &data_offset); 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int64 size = region.size + data_offset; 5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Ensure that the casts below in the MapViewOfFile call are sane. 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (aligned_start < 0 || size < 0 || 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static_cast<uint64>(size) > std::numeric_limits<SIZE_T>::max()) { 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DLOG(ERROR) << "Region bounds are not valid for MapViewOfFile"; 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) map_start.QuadPart = aligned_start; 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) map_size = static_cast<SIZE_T>(size); 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) length_ = static_cast<size_t>(region.size); 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) data_ = static_cast<uint8*>(::MapViewOfFile(file_mapping_.Get(), 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FILE_MAP_READ, 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) map_start.HighPart, 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) map_start.LowPart, 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) map_size)); 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (data_ == NULL) 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) data_ += data_offset; 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 79 80void MemoryMappedFile::CloseHandles() { 81 if (data_) 82 ::UnmapViewOfFile(data_); 83 if (file_mapping_.IsValid()) 84 file_mapping_.Close(); 85 if (file_.IsValid()) 86 file_.Close(); 87 88 data_ = NULL; 89 length_ = 0; 90} 91 92} // namespace base 93