OLD | NEW |
1 // Copyright (c) 2011, Google Inc. | 1 // Copyright (c) 2011, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 28 matching lines...) Expand all Loading... |
39 #endif | 39 #endif |
40 #include <unistd.h> | 40 #include <unistd.h> |
41 | 41 |
42 #include "common/memory_range.h" | 42 #include "common/memory_range.h" |
43 #include "third_party/lss/linux_syscall_support.h" | 43 #include "third_party/lss/linux_syscall_support.h" |
44 | 44 |
45 namespace google_breakpad { | 45 namespace google_breakpad { |
46 | 46 |
47 MemoryMappedFile::MemoryMappedFile() {} | 47 MemoryMappedFile::MemoryMappedFile() {} |
48 | 48 |
49 MemoryMappedFile::MemoryMappedFile(const char* path) { | 49 MemoryMappedFile::MemoryMappedFile(const char* path, size_t offset) { |
50 Map(path); | 50 Map(path, offset); |
51 } | 51 } |
52 | 52 |
53 MemoryMappedFile::~MemoryMappedFile() { | 53 MemoryMappedFile::~MemoryMappedFile() { |
54 Unmap(); | 54 Unmap(); |
55 } | 55 } |
56 | 56 |
57 bool MemoryMappedFile::Map(const char* path) { | 57 bool MemoryMappedFile::Map(const char* path, size_t offset) { |
58 Unmap(); | 58 Unmap(); |
59 | 59 |
60 int fd = sys_open(path, O_RDONLY, 0); | 60 int fd = sys_open(path, O_RDONLY, 0); |
61 if (fd == -1) { | 61 if (fd == -1) { |
62 return false; | 62 return false; |
63 } | 63 } |
64 | 64 |
65 #if defined(__x86_64__) || defined(__aarch64__) | 65 #if defined(__x86_64__) || defined(__aarch64__) |
66 struct kernel_stat st; | 66 struct kernel_stat st; |
67 if (sys_fstat(fd, &st) == -1 || st.st_size < 0) { | 67 if (sys_fstat(fd, &st) == -1 || st.st_size < 0) { |
68 #else | 68 #else |
69 struct kernel_stat64 st; | 69 struct kernel_stat64 st; |
70 if (sys_fstat64(fd, &st) == -1 || st.st_size < 0) { | 70 if (sys_fstat64(fd, &st) == -1 || st.st_size < 0) { |
71 #endif | 71 #endif |
72 sys_close(fd); | 72 sys_close(fd); |
73 return false; | 73 return false; |
74 } | 74 } |
75 | 75 |
76 // If the file size is zero, simply use an empty MemoryRange and return | 76 // Strangely file size can be negative, but we check above that it is not. |
77 // true. Don't bother to call mmap() even though mmap() can handle an | 77 size_t file_len = static_cast<size_t>(st.st_size); |
78 // empty file on some platforms. | 78 // If the file does not extend beyond the offset, simply use an empty |
79 if (st.st_size == 0) { | 79 // MemoryRange and return true. Don't bother to call mmap() |
| 80 // even though mmap() can handle an empty file on some platforms. |
| 81 if (offset >= file_len) { |
80 sys_close(fd); | 82 sys_close(fd); |
81 return true; | 83 return true; |
82 } | 84 } |
83 | 85 |
84 #if defined(__x86_64__) || defined(__aarch64__) | 86 #if defined(__x86_64__) || defined(__aarch64__) |
85 void* data = sys_mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); | 87 void* data = sys_mmap(NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset); |
86 #else | 88 #else |
87 void* data = sys_mmap2(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); | 89 if ((offset & 4095) != 0) { |
| 90 // Not page aligned. |
| 91 sys_close(fd); |
| 92 return false; |
| 93 } |
| 94 void* data = sys_mmap2( |
| 95 NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset >> 12); |
88 #endif | 96 #endif |
89 sys_close(fd); | 97 sys_close(fd); |
90 if (data == MAP_FAILED) { | 98 if (data == MAP_FAILED) { |
91 return false; | 99 return false; |
92 } | 100 } |
93 | 101 |
94 content_.Set(data, st.st_size); | 102 content_.Set(data, file_len - offset); |
95 return true; | 103 return true; |
96 } | 104 } |
97 | 105 |
98 void MemoryMappedFile::Unmap() { | 106 void MemoryMappedFile::Unmap() { |
99 if (content_.data()) { | 107 if (content_.data()) { |
100 sys_munmap(const_cast<uint8_t*>(content_.data()), content_.length()); | 108 sys_munmap(const_cast<uint8_t*>(content_.data()), content_.length()); |
101 content_.Set(NULL, 0); | 109 content_.Set(NULL, 0); |
102 } | 110 } |
103 } | 111 } |
104 | 112 |
105 } // namespace google_breakpad | 113 } // namespace google_breakpad |
OLD | NEW |