summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Breakpad/src/client/minidump_file_writer.cc')
-rw-r--r--3rdParty/Breakpad/src/client/minidump_file_writer.cc98
1 files changed, 82 insertions, 16 deletions
diff --git a/3rdParty/Breakpad/src/client/minidump_file_writer.cc b/3rdParty/Breakpad/src/client/minidump_file_writer.cc
index c267410..a1957f3 100644
--- a/3rdParty/Breakpad/src/client/minidump_file_writer.cc
+++ b/3rdParty/Breakpad/src/client/minidump_file_writer.cc
@@ -42,3 +42,3 @@
#include "common/string_conversion.h"
-#if __linux__
+#if defined(__linux__) && __linux__
#include "third_party/lss/linux_syscall_support.h"
@@ -46,2 +46,43 @@
+#if defined(__ANDROID__)
+#include <errno.h>
+
+namespace {
+
+bool g_need_ftruncate_workaround = false;
+bool g_checked_need_ftruncate_workaround = false;
+
+void CheckNeedsFTruncateWorkAround(int file) {
+ if (g_checked_need_ftruncate_workaround) {
+ return;
+ }
+ g_checked_need_ftruncate_workaround = true;
+
+ // Attempt an idempotent truncate that chops off nothing and see if we
+ // run into any sort of errors.
+ off_t offset = sys_lseek(file, 0, SEEK_END);
+ if (offset == -1) {
+ // lseek failed. Don't apply work around. It's unlikely that we can write
+ // to a minidump with either method.
+ return;
+ }
+
+ int result = ftruncate(file, offset);
+ if (result == -1 && errno == EACCES) {
+ // It very likely that we are running into the kernel bug in M devices.
+ // We are going to deploy the workaround for writing minidump files
+ // without uses of ftruncate(). This workaround should be fine even
+ // for kernels without the bug.
+ // See http://crbug.com/542840 for more details.
+ g_need_ftruncate_workaround = true;
+ }
+}
+
+bool NeedsFTruncateWorkAround() {
+ return g_need_ftruncate_workaround;
+}
+
+} // namespace
+#endif // defined(__ANDROID__)
+
namespace google_breakpad {
@@ -64,3 +105,3 @@ bool MinidumpFileWriter::Open(const char *path) {
assert(file_ == -1);
-#if __linux__
+#if defined(__linux__) && __linux__
file_ = sys_open(path, O_WRONLY | O_CREAT | O_EXCL, 0600);
@@ -77,2 +118,5 @@ void MinidumpFileWriter::SetFile(const int file) {
close_file_when_destroyed_ = false;
+#if defined(__ANDROID__)
+ CheckNeedsFTruncateWorkAround(file);
+#endif
}
@@ -83,6 +127,12 @@ bool MinidumpFileWriter::Close() {
if (file_ != -1) {
- if (-1 == ftruncate(file_, position_)) {
+#if defined(__ANDROID__)
+ if (!NeedsFTruncateWorkAround() && ftruncate(file_, position_)) {
return false;
}
-#if __linux__
+#else
+ if (ftruncate(file_, position_)) {
+ return false;
+ }
+#endif
+#if defined(__linux__) && __linux__
result = (sys_close(file_) == 0);
@@ -101,3 +151,3 @@ bool MinidumpFileWriter::CopyStringToMDString(const wchar_t *str,
bool result = true;
- if (sizeof(wchar_t) == sizeof(u_int16_t)) {
+ if (sizeof(wchar_t) == sizeof(uint16_t)) {
// Shortcut if wchar_t is the same size as MDString's buffer
@@ -105,3 +155,3 @@ bool MinidumpFileWriter::CopyStringToMDString(const wchar_t *str,
} else {
- u_int16_t out[2];
+ uint16_t out[2];
int out_idx = 0;
@@ -122,3 +172,3 @@ bool MinidumpFileWriter::CopyStringToMDString(const wchar_t *str,
int out_count = out[1] ? 2 : 1;
- size_t out_size = sizeof(u_int16_t) * out_count;
+ size_t out_size = sizeof(uint16_t) * out_count;
result = mdstring->CopyIndexAfterObject(out_idx, out, out_size);
@@ -134,3 +184,3 @@ bool MinidumpFileWriter::CopyStringToMDString(const char *str,
bool result = true;
- u_int16_t out[2];
+ uint16_t out[2];
int out_idx = 0;
@@ -149,3 +199,3 @@ bool MinidumpFileWriter::CopyStringToMDString(const char *str,
int out_count = out[1] ? 2 : 1;
- size_t out_size = sizeof(u_int16_t) * out_count;
+ size_t out_size = sizeof(uint16_t) * out_count;
result = mdstring->CopyIndexAfterObject(out_idx, out, out_size);
@@ -172,3 +222,3 @@ bool MinidumpFileWriter::WriteStringCore(const CharType *str,
TypedMDRVA<MDString> mdstring(this);
- if (!mdstring.AllocateObjectAndArray(mdstring_length + 1, sizeof(u_int16_t)))
+ if (!mdstring.AllocateObjectAndArray(mdstring_length + 1, sizeof(uint16_t)))
return false;
@@ -177,3 +227,3 @@ bool MinidumpFileWriter::WriteStringCore(const CharType *str,
mdstring.get()->length =
- static_cast<u_int32_t>(mdstring_length * sizeof(u_int16_t));
+ static_cast<uint32_t>(mdstring_length * sizeof(uint16_t));
bool result = CopyStringToMDString(str, mdstring_length, &mdstring);
@@ -182,3 +232,3 @@ bool MinidumpFileWriter::WriteStringCore(const CharType *str,
if (result) {
- u_int16_t ch = 0;
+ uint16_t ch = 0;
result = mdstring.CopyIndexAfterObject(mdstring_length, &ch, sizeof(ch));
@@ -213,3 +263,3 @@ bool MinidumpFileWriter::WriteMemory(const void *src, size_t size,
- output->start_of_memory_range = reinterpret_cast<u_int64_t>(src);
+ output->start_of_memory_range = reinterpret_cast<uint64_t>(src);
output->memory = mem.location();
@@ -222,2 +272,16 @@ MDRVA MinidumpFileWriter::Allocate(size_t size) {
assert(file_ != -1);
+#if defined(__ANDROID__)
+ if (NeedsFTruncateWorkAround()) {
+ // If ftruncate() is not available. We simply increase the size beyond the
+ // current file size. sys_write() will expand the file when data is written
+ // to it. Because we did not over allocate to fit memory pages, we also
+ // do not need to ftruncate() the file once we are done.
+ size_ += size;
+
+ // We don't need to seek since the file is unchanged.
+ MDRVA current_position = position_;
+ position_ += static_cast<MDRVA>(size);
+ return current_position;
+ }
+#endif
size_t aligned_size = (size + 7) & ~7; // 64-bit alignment
@@ -255,5 +319,8 @@ bool MinidumpFileWriter::Copy(MDRVA position, const void *src, ssize_t size) {
// Seek and write the data
-#if __linux__
+#if defined(__linux__) && __linux__
if (sys_lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) {
if (sys_write(file_, src, size) == size) {
+ return true;
+ }
+ }
#else
@@ -261,3 +328,2 @@ bool MinidumpFileWriter::Copy(MDRVA position, const void *src, ssize_t size) {
if (write(file_, src, size) == size) {
-#endif
return true;
@@ -265,3 +331,3 @@ bool MinidumpFileWriter::Copy(MDRVA position, const void *src, ssize_t size) {
}
-
+#endif
return false;