1f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// Copyright (c) 2011, Google Inc. 2f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// All rights reserved. 3f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// 4f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// Redistribution and use in source and binary forms, with or without 5f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// modification, are permitted provided that the following conditions are 6f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// met: 7f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// 8f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// * Redistributions of source code must retain the above copyright 9f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// notice, this list of conditions and the following disclaimer. 10f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// * Redistributions in binary form must reproduce the above 11f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// copyright notice, this list of conditions and the following disclaimer 12f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// in the documentation and/or other materials provided with the 13f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// distribution. 14f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// * Neither the name of Google Inc. nor the names of its 15f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// contributors may be used to endorse or promote products derived from 16f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// this software without specific prior written permission. 17f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// 18f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 30f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// memory_mapped_file.cc: Implement google_breakpad::MemoryMappedFile. 31f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org// See memory_mapped_file.h for details. 32f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 33f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org#include "common/linux/memory_mapped_file.h" 34f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 35f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org#include <fcntl.h> 36f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org#include <sys/mman.h> 37aa52a01f8a977bdb8a1f79ccabab963131574301mark@chromium.org#if defined(__ANDROID__) 38aa52a01f8a977bdb8a1f79ccabab963131574301mark@chromium.org#include <sys/stat.h> 39aa52a01f8a977bdb8a1f79ccabab963131574301mark@chromium.org#endif 40f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org#include <unistd.h> 41f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 42f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org#include "common/memory_range.h" 43f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org#include "third_party/lss/linux_syscall_support.h" 44f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 45f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.orgnamespace google_breakpad { 46f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 47f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.orgMemoryMappedFile::MemoryMappedFile() {} 48f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 49dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.orgMemoryMappedFile::MemoryMappedFile(const char* path, size_t offset) { 50dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org Map(path, offset); 51f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org} 52f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 53f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.orgMemoryMappedFile::~MemoryMappedFile() { 54f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org Unmap(); 55f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org} 56f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 57dbb392886ffce4fd927b826080b4faff49965f10Gordana Cmiljanovic#include <unistd.h> 58dbb392886ffce4fd927b826080b4faff49965f10Gordana Cmiljanovic 59dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.orgbool MemoryMappedFile::Map(const char* path, size_t offset) { 60f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org Unmap(); 61f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 62f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org int fd = sys_open(path, O_RDONLY, 0); 63f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org if (fd == -1) { 64f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org return false; 65f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org } 66f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 67dbb392886ffce4fd927b826080b4faff49965f10Gordana Cmiljanovic#if defined(__x86_64__) || defined(__aarch64__) || \ 68dbb392886ffce4fd927b826080b4faff49965f10Gordana Cmiljanovic (defined(__mips__) && _MIPS_SIM == _ABI64) 69dbb392886ffce4fd927b826080b4faff49965f10Gordana Cmiljanovic 70f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org struct kernel_stat st; 71f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org if (sys_fstat(fd, &st) == -1 || st.st_size < 0) { 72f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org#else 73f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org struct kernel_stat64 st; 74f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org if (sys_fstat64(fd, &st) == -1 || st.st_size < 0) { 75f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org#endif 76f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org sys_close(fd); 77f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org return false; 78f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org } 79f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 80dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org // Strangely file size can be negative, but we check above that it is not. 81dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org size_t file_len = static_cast<size_t>(st.st_size); 82dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org // If the file does not extend beyond the offset, simply use an empty 83dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org // MemoryRange and return true. Don't bother to call mmap() 84dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org // even though mmap() can handle an empty file on some platforms. 85dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org if (offset >= file_len) { 86f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org sys_close(fd); 87f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org return true; 88f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org } 89f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 90dbb392886ffce4fd927b826080b4faff49965f10Gordana Cmiljanovic#if defined(__x86_64__) || defined(__aarch64__) || \ 91dbb392886ffce4fd927b826080b4faff49965f10Gordana Cmiljanovic (defined(__mips__) && _MIPS_SIM == _ABI64) 92dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org void* data = sys_mmap(NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset); 93f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org#else 94dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org if ((offset & 4095) != 0) { 95dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org // Not page aligned. 96dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org sys_close(fd); 97dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org return false; 98dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org } 99dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org void* data = sys_mmap2( 100dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset >> 12); 101f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org#endif 102f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org sys_close(fd); 103f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org if (data == MAP_FAILED) { 104f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org return false; 105f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org } 106f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 107dd5dd85f3795609723082a2b34f81e19b4f1679frmcilroy@chromium.org content_.Set(data, file_len - offset); 108f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org return true; 109f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org} 110f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 111f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.orgvoid MemoryMappedFile::Unmap() { 112f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org if (content_.data()) { 1136162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com sys_munmap(const_cast<uint8_t*>(content_.data()), content_.length()); 114f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org content_.Set(NULL, 0); 115f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org } 116f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org} 117f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org 118f058b4faa7e16838d2120564fdb627076c3137f9benchan@chromium.org} // namespace google_breakpad 119