Chromium Code Reviews| Index: chrome/app/breakpad_linux.cc |
| =================================================================== |
| --- chrome/app/breakpad_linux.cc (revision 152529) |
| +++ chrome/app/breakpad_linux.cc (working copy) |
| @@ -54,6 +54,10 @@ |
| #include "sandbox/linux/seccomp-legacy/linux_syscall_support.h" |
| #endif |
| +#if defined(ADDRESS_SANITIZER) |
| +#include <ucontext.h> // for getcontext(). |
| +#endif |
| + |
| #if defined(OS_ANDROID) |
| #define STAT_STRUCT struct stat |
| #define FSTAT_FUNC fstat |
| @@ -73,12 +77,21 @@ |
| namespace { |
| +#if !defined(ADDRESS_SANITIZER) |
| const char kUploadURL[] = "https://clients2.google.com/cr/report"; |
| +#else |
| +// AddressSanitizer should currently upload the crash reports to the staging |
| +// crash server. |
| +const char kUploadURL[] = "https://clients2.google.com/cr/staging_report"; |
| +#endif |
| bool g_is_crash_reporter_enabled = false; |
| uint64_t g_process_start_time = 0; |
| char* g_crash_log_path = NULL; |
| ExceptionHandler* g_breakpad = NULL; |
| +#if defined(ADDRESS_SANITIZER) |
| +char* g_asan_report_str = NULL; |
| +#endif |
| // Writes the value |v| as 16 hex characters to the memory pointed at by |
| // |output|. |
| @@ -171,6 +184,9 @@ |
| const char g_quote_msg[] = "\""; |
| const char g_dashdash_msg[] = "--"; |
| const char g_dump_msg[] = "upload_file_minidump\"; filename=\"dump\""; |
| +#if defined(ADDRESS_SANITIZER) |
| +const char g_log_msg[] = "upload_file_log\"; filename=\"log\""; |
| +#endif |
| const char g_content_type_msg[] = "Content-Type: application/octet-stream"; |
| // MimeWriter manages an iovec for writing MIMEs to a file. |
| @@ -210,10 +226,10 @@ |
| size_t chunk_size, |
| bool strip_trailing_spaces); |
| - // Add binary file dump. Currently this is only done once, so the name is |
| - // fixed. |
| - void AddFileDump(uint8_t* file_data, |
| - size_t file_size); |
| + // Add binary file contents to be uploaded with the specified filename. |
| + void AddFileContents(const char* filename_msg, |
| + uint8_t* file_data, |
| + size_t file_size); |
| // Flush any pending iovecs to the output file. |
| void Flush() { |
| @@ -312,10 +328,10 @@ |
| } |
| } |
| -void MimeWriter::AddFileDump(uint8_t* file_data, |
| - size_t file_size) { |
| +void MimeWriter::AddFileContents(const char* filename_msg, uint8_t* file_data, |
| + size_t file_size) { |
| AddString(g_form_data_msg); |
| - AddString(g_dump_msg); |
| + AddString(filename_msg); |
| AddString(g_rn); |
| AddString(g_content_type_msg); |
| AddString(g_rn); |
| @@ -372,6 +388,15 @@ |
| BreakpadInfo info; |
| info.filename = minidump.path(); |
| +#if defined(ADDRESS_SANITIZER) |
| + google_breakpad::PageAllocator allocator; |
| + const size_t log_path_len = my_strlen(minidump.path()); |
| + char* log_path = reinterpret_cast<char*>(allocator.Alloc(log_path_len + 1)); |
| + my_memcpy(log_path, minidump.path(), log_path_len); |
| + my_memcpy(log_path + log_path_len - 4, ".log", 4); |
| + log_path[log_path_len] = '\0'; |
| + info.log_filename = log_path; |
| +#endif |
| info.process_type = "browser"; |
| info.process_type_length = 7; |
| info.crash_url = NULL; |
| @@ -404,6 +429,18 @@ |
| } |
| #endif |
| +#if defined(ADDRESS_SANITIZER) |
| +extern "C" |
| +void __asan_set_error_report_callback(void (*cb)(const char*)); |
| + |
| +extern "C" |
| +void AsanLinuxBreakpadCallback(const char* report) { |
| + g_asan_report_str = const_cast<char*>(report); |
|
Lei Zhang
2012/08/21 18:35:17
nit: Can we make |g_asan_report_str| const char an
Alexander Potapenko
2012/08/22 12:15:08
Ok. This however has introduced a const_cast below
Lei Zhang
2012/08/22 18:41:55
Blah.
|
| + // Send minidump here. |
| + g_breakpad->SimulateSignalDelivery(9); |
|
Lei Zhang
2012/08/21 18:35:17
nit: Can we use a SIGKILL constant from signal.h h
Alexander Potapenko
2012/08/22 12:15:08
Done.
|
| +} |
| +#endif |
| + |
| void EnableCrashDumping(bool unattended) { |
| g_is_crash_reporter_enabled = true; |
| @@ -483,7 +520,12 @@ |
| static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize); |
| static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize); |
| +#if !defined(ADDRESS_SANITIZER) |
| const size_t kIovSize = 8; |
| +#else |
| + // Additional field to pass the AddressSanitizer log to the crash handler. |
| + const size_t kIovSize = 9; |
| +#endif |
| struct kernel_msghdr msg; |
| my_memset(&msg, 0, sizeof(struct kernel_msghdr)); |
| struct kernel_iovec iov[kIovSize]; |
| @@ -503,6 +545,10 @@ |
| iov[6].iov_len = sizeof(g_process_start_time); |
| iov[7].iov_base = &base::g_oom_size; |
| iov[7].iov_len = sizeof(base::g_oom_size); |
| +#if defined(ADDRESS_SANITIZER) |
| + iov[8].iov_base = g_asan_report_str; |
| + iov[8].iov_len = kMaxAsanReportSize + 1; |
| +#endif |
| msg.msg_iov = iov; |
| msg.msg_iovlen = kIovSize; |
| @@ -551,40 +597,60 @@ |
| } // namespace |
| -void HandleCrashDump(const BreakpadInfo& info) { |
| +void LoadDataFromFile(google_breakpad::PageAllocator& allocator, |
| + const BreakpadInfo& info, int* fd, |
| + uint8_t** file_data, size_t* size, |
| + const char* filename) { |
|
Lei Zhang
2012/08/21 18:35:17
nit: Can we move |filename| in front of the out pa
Alexander Potapenko
2012/08/22 12:15:08
Done.
|
| // WARNING: this code runs in a compromised context. It may not call into |
| // libc nor allocate memory normally. |
| + *fd = sys_open(filename, O_RDONLY, 0); |
| + *size = 0; |
| - const int dumpfd = sys_open(info.filename, O_RDONLY, 0); |
| - if (dumpfd < 0) { |
| + if (*fd < 0) { |
| static const char msg[] = "Cannot upload crash dump: failed to open\n"; |
| WriteLog(msg, sizeof(msg)); |
| return; |
| } |
| STAT_STRUCT st; |
| - if (FSTAT_FUNC(dumpfd, &st) != 0) { |
| + if (FSTAT_FUNC(*fd, &st) != 0) { |
| static const char msg[] = "Cannot upload crash dump: stat failed\n"; |
| WriteLog(msg, sizeof(msg)); |
| - IGNORE_RET(sys_close(dumpfd)); |
| + IGNORE_RET(sys_close(*fd)); |
| return; |
| } |
| - google_breakpad::PageAllocator allocator; |
| - |
| - uint8_t* dump_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size)); |
| - if (!dump_data) { |
| + *file_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size)); |
| + if (!(*file_data)) { |
| static const char msg[] = "Cannot upload crash dump: cannot alloc\n"; |
| WriteLog(msg, sizeof(msg)); |
| - IGNORE_RET(sys_close(dumpfd)); |
| + IGNORE_RET(sys_close(*fd)); |
| return; |
| } |
| + my_memset(*file_data, 0xf, st.st_size); |
| - sys_read(dumpfd, dump_data, st.st_size); |
| - IGNORE_RET(sys_close(dumpfd)); |
| + *size = st.st_size; |
| + sys_read(*fd, *file_data, *size); |
| + IGNORE_RET(sys_close(*fd)); |
| +} |
| +void HandleCrashDump(const BreakpadInfo& info) { |
| + int dumpfd; |
| + size_t dump_size; |
| + uint8_t *dump_data; |
| + google_breakpad::PageAllocator allocator; |
| + LoadDataFromFile(allocator, info, &dumpfd, &dump_data, &dump_size, |
| + info.filename); |
| +#if defined(ADDRESS_SANITIZER) |
| + int logfd; |
| + size_t log_size; |
| + uint8_t *log_data; |
| + // Load the AddressSanitizer log into log_data. |
| + LoadDataFromFile(allocator, info, &logfd, &log_data, &log_size, |
| + info.log_filename); |
| +#endif |
| + |
| // We need to build a MIME block for uploading to the server. Since we are |
| // going to fork and run wget, it needs to be written to a temp file. |
| - |
| const int ufd = sys_open("/dev/urandom", O_RDONLY, 0); |
| if (ufd < 0) { |
| static const char msg[] = "Cannot upload crash dump because /dev/urandom" |
| @@ -916,7 +982,12 @@ |
| writer.Flush(); |
| } |
| - writer.AddFileDump(dump_data, st.st_size); |
| + writer.AddFileContents(g_dump_msg, dump_data, dump_size); |
| +#if defined(ADDRESS_SANITIZER) |
| + // Append a multipart boundary and the contents of the AddressSanitizer log. |
| + writer.AddBoundary(); |
| + writer.AddFileContents(g_log_msg, log_data, log_size); |
| +#endif |
| writer.AddEnd(); |
| writer.Flush(); |
| @@ -1097,6 +1168,9 @@ |
| // Helper process. |
| IGNORE_RET(sys_unlink(info.filename)); |
| +#if defined(ADDRESS_SANITIZER) |
| + IGNORE_RET(sys_unlink(info.log_filename)); |
| +#endif |
| IGNORE_RET(sys_unlink(temp_file)); |
| sys__exit(0); |
| } |
| @@ -1158,6 +1232,10 @@ |
| g_process_start_time = 0; |
| logging::SetDumpWithoutCrashingFunction(&DumpProcess); |
| +#if defined(ADDRESS_SANITIZER) |
| + // Register the callback for AddressSanitizer error reporting. |
| + __asan_set_error_report_callback(AsanLinuxBreakpadCallback); |
| +#endif |
| } |
| bool IsCrashReporterEnabled() { |