| 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 |