OLD | NEW |
1 // Copyright (c) 2006, Google Inc. | 1 // Copyright (c) 2006, 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 26 matching lines...) Expand all Loading... |
37 #include <string.h> | 37 #include <string.h> |
38 #include <unistd.h> | 38 #include <unistd.h> |
39 | 39 |
40 #include "client/minidump_file_writer-inl.h" | 40 #include "client/minidump_file_writer-inl.h" |
41 #include "common/linux/linux_libc_support.h" | 41 #include "common/linux/linux_libc_support.h" |
42 #include "common/string_conversion.h" | 42 #include "common/string_conversion.h" |
43 #if defined(__linux__) && __linux__ | 43 #if defined(__linux__) && __linux__ |
44 #include "third_party/lss/linux_syscall_support.h" | 44 #include "third_party/lss/linux_syscall_support.h" |
45 #endif | 45 #endif |
46 | 46 |
| 47 #if defined(__ANDROID__) |
| 48 #include <errno.h> |
| 49 |
| 50 namespace { |
| 51 |
| 52 bool g_need_ftruncate_workaround = false; |
| 53 bool g_checked_need_ftruncate_workaround = false; |
| 54 |
| 55 void CheckNeedsFTruncateWorkAround(int file) { |
| 56 if (g_checked_need_ftruncate_workaround) { |
| 57 return; |
| 58 } |
| 59 g_checked_need_ftruncate_workaround = true; |
| 60 |
| 61 // Attempt an idempotent truncate that chops off nothing and see if we |
| 62 // run into any sort of errors. |
| 63 off_t offset = sys_lseek(file, 0, SEEK_END); |
| 64 if (offset == -1) { |
| 65 // lseek failed. Don't apply work around. It's unlikely that we can write |
| 66 // to a minidump with either method. |
| 67 return; |
| 68 } |
| 69 |
| 70 int result = ftruncate(file, offset); |
| 71 if (result == -1 && errno == EACCES) { |
| 72 // It very likely that we are running into the kernel bug in M devices. |
| 73 // We are going to deploy the workaround for writing minidump files |
| 74 // without uses of ftruncate(). This workaround should be fine even |
| 75 // for kernels without the bug. |
| 76 // See http://crbug.com/542840 for more details. |
| 77 g_need_ftruncate_workaround = true; |
| 78 } |
| 79 } |
| 80 |
| 81 bool NeedsFTruncateWorkAround() { |
| 82 return g_need_ftruncate_workaround; |
| 83 } |
| 84 |
| 85 } // namespace |
| 86 #endif // defined(__ANDROID__) |
| 87 |
47 namespace google_breakpad { | 88 namespace google_breakpad { |
48 | 89 |
49 const MDRVA MinidumpFileWriter::kInvalidMDRVA = static_cast<MDRVA>(-1); | 90 const MDRVA MinidumpFileWriter::kInvalidMDRVA = static_cast<MDRVA>(-1); |
50 | 91 |
51 MinidumpFileWriter::MinidumpFileWriter() | 92 MinidumpFileWriter::MinidumpFileWriter() |
52 : file_(-1), | 93 : file_(-1), |
53 close_file_when_destroyed_(true), | 94 close_file_when_destroyed_(true), |
54 position_(0), | 95 position_(0), |
55 size_(0) { | 96 size_(0) { |
56 } | 97 } |
(...skipping 11 matching lines...) Expand all Loading... |
68 file_ = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600); | 109 file_ = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600); |
69 #endif | 110 #endif |
70 | 111 |
71 return file_ != -1; | 112 return file_ != -1; |
72 } | 113 } |
73 | 114 |
74 void MinidumpFileWriter::SetFile(const int file) { | 115 void MinidumpFileWriter::SetFile(const int file) { |
75 assert(file_ == -1); | 116 assert(file_ == -1); |
76 file_ = file; | 117 file_ = file; |
77 close_file_when_destroyed_ = false; | 118 close_file_when_destroyed_ = false; |
| 119 #if defined(__ANDROID__) |
| 120 CheckNeedsFTruncateWorkAround(file); |
| 121 #endif |
78 } | 122 } |
79 | 123 |
80 bool MinidumpFileWriter::Close() { | 124 bool MinidumpFileWriter::Close() { |
81 bool result = true; | 125 bool result = true; |
82 | 126 |
83 if (file_ != -1) { | 127 if (file_ != -1) { |
84 if (-1 == ftruncate(file_, position_)) { | 128 #if defined(__ANDROID__) |
| 129 if (!NeedsFTruncateWorkAround() && ftruncate(file_, position_)) { |
85 return false; | 130 return false; |
86 } | 131 } |
| 132 #else |
| 133 if (ftruncate(file_, position_)) { |
| 134 return false; |
| 135 } |
| 136 #endif |
87 #if defined(__linux__) && __linux__ | 137 #if defined(__linux__) && __linux__ |
88 result = (sys_close(file_) == 0); | 138 result = (sys_close(file_) == 0); |
89 #else | 139 #else |
90 result = (close(file_) == 0); | 140 result = (close(file_) == 0); |
91 #endif | 141 #endif |
92 file_ = -1; | 142 file_ = -1; |
93 } | 143 } |
94 | 144 |
95 return result; | 145 return result; |
96 } | 146 } |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 | 263 |
214 output->start_of_memory_range = reinterpret_cast<uint64_t>(src); | 264 output->start_of_memory_range = reinterpret_cast<uint64_t>(src); |
215 output->memory = mem.location(); | 265 output->memory = mem.location(); |
216 | 266 |
217 return true; | 267 return true; |
218 } | 268 } |
219 | 269 |
220 MDRVA MinidumpFileWriter::Allocate(size_t size) { | 270 MDRVA MinidumpFileWriter::Allocate(size_t size) { |
221 assert(size); | 271 assert(size); |
222 assert(file_ != -1); | 272 assert(file_ != -1); |
| 273 #if defined(__ANDROID__) |
| 274 if (NeedsFTruncateWorkAround()) { |
| 275 // If ftruncate() is not available. We simply increase the size beyond the |
| 276 // current file size. sys_write() will expand the file when data is written |
| 277 // to it. Because we did not over allocate to fit memory pages, we also |
| 278 // do not need to ftruncate() the file once we are done. |
| 279 size_ += size; |
| 280 |
| 281 // We don't need to seek since the file is unchanged. |
| 282 MDRVA current_position = position_; |
| 283 position_ += static_cast<MDRVA>(size); |
| 284 return current_position; |
| 285 } |
| 286 #endif |
223 size_t aligned_size = (size + 7) & ~7; // 64-bit alignment | 287 size_t aligned_size = (size + 7) & ~7; // 64-bit alignment |
224 | 288 |
225 if (position_ + aligned_size > size_) { | 289 if (position_ + aligned_size > size_) { |
226 size_t growth = aligned_size; | 290 size_t growth = aligned_size; |
227 size_t minimal_growth = getpagesize(); | 291 size_t minimal_growth = getpagesize(); |
228 | 292 |
229 // Ensure that the file grows by at least the size of a memory page | 293 // Ensure that the file grows by at least the size of a memory page |
230 if (growth < minimal_growth) | 294 if (growth < minimal_growth) |
231 growth = minimal_growth; | 295 growth = minimal_growth; |
232 | 296 |
(...skipping 16 matching lines...) Expand all Loading... |
249 assert(file_ != -1); | 313 assert(file_ != -1); |
250 | 314 |
251 // Ensure that the data will fit in the allocated space | 315 // Ensure that the data will fit in the allocated space |
252 if (static_cast<size_t>(size + position) > size_) | 316 if (static_cast<size_t>(size + position) > size_) |
253 return false; | 317 return false; |
254 | 318 |
255 // Seek and write the data | 319 // Seek and write the data |
256 #if defined(__linux__) && __linux__ | 320 #if defined(__linux__) && __linux__ |
257 if (sys_lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) { | 321 if (sys_lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) { |
258 if (sys_write(file_, src, size) == size) { | 322 if (sys_write(file_, src, size) == size) { |
| 323 return true; |
| 324 } |
| 325 } |
259 #else | 326 #else |
260 if (lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) { | 327 if (lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) { |
261 if (write(file_, src, size) == size) { | 328 if (write(file_, src, size) == size) { |
262 #endif | |
263 return true; | 329 return true; |
264 } | 330 } |
265 } | 331 } |
266 | 332 #endif |
267 return false; | 333 return false; |
268 } | 334 } |
269 | 335 |
270 bool UntypedMDRVA::Allocate(size_t size) { | 336 bool UntypedMDRVA::Allocate(size_t size) { |
271 assert(size_ == 0); | 337 assert(size_ == 0); |
272 size_ = size; | 338 size_ = size; |
273 position_ = writer_->Allocate(size_); | 339 position_ = writer_->Allocate(size_); |
274 return position_ != MinidumpFileWriter::kInvalidMDRVA; | 340 return position_ != MinidumpFileWriter::kInvalidMDRVA; |
275 } | 341 } |
276 | 342 |
277 bool UntypedMDRVA::Copy(MDRVA pos, const void *src, size_t size) { | 343 bool UntypedMDRVA::Copy(MDRVA pos, const void *src, size_t size) { |
278 assert(src); | 344 assert(src); |
279 assert(size); | 345 assert(size); |
280 assert(pos + size <= position_ + size_); | 346 assert(pos + size <= position_ + size_); |
281 return writer_->Copy(pos, src, size); | 347 return writer_->Copy(pos, src, size); |
282 } | 348 } |
283 | 349 |
284 } // namespace google_breakpad | 350 } // namespace google_breakpad |
OLD | NEW |