Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // For linux_syscall_support.h. This makes it safe to call embedded system | 5 // For linux_syscall_support.h. This makes it safe to call embedded system |
| 6 // calls when in seccomp mode. | 6 // calls when in seccomp mode. |
| 7 | 7 |
| 8 #include "chrome/app/breakpad_linux.h" | 8 #include "chrome/app/breakpad_linux_impl.h" |
| 9 | 9 |
| 10 #include <fcntl.h> | 10 #include <fcntl.h> |
| 11 #include <poll.h> | 11 #include <poll.h> |
| 12 #include <signal.h> | 12 #include <signal.h> |
| 13 #include <stdlib.h> | 13 #include <stdlib.h> |
| 14 #include <sys/socket.h> | 14 #include <sys/socket.h> |
| 15 #include <sys/time.h> | 15 #include <sys/time.h> |
| 16 #include <sys/types.h> | 16 #include <sys/types.h> |
| 17 #include <sys/uio.h> | 17 #include <sys/uio.h> |
| 18 #include <sys/wait.h> | 18 #include <sys/wait.h> |
| 19 #include <time.h> | 19 #include <time.h> |
| 20 #include <unistd.h> | 20 #include <unistd.h> |
| 21 | 21 |
| 22 #include <algorithm> | 22 #include <algorithm> |
| 23 #include <string> | 23 #include <string> |
| 24 | 24 |
| 25 #include "base/command_line.h" | 25 #include "base/command_line.h" |
| 26 #include "base/debug/crash_logging.h" | |
| 26 #include "base/files/file_path.h" | 27 #include "base/files/file_path.h" |
| 27 #include "base/linux_util.h" | 28 #include "base/linux_util.h" |
| 28 #include "base/path_service.h" | 29 #include "base/path_service.h" |
| 29 #include "base/platform_file.h" | 30 #include "base/platform_file.h" |
| 30 #include "base/posix/eintr_wrapper.h" | 31 #include "base/posix/eintr_wrapper.h" |
| 31 #include "base/posix/global_descriptors.h" | 32 #include "base/posix/global_descriptors.h" |
| 32 #include "base/process_util.h" | 33 #include "base/process_util.h" |
| 33 #include "base/string_util.h" | 34 #include "base/string_util.h" |
| 34 #include "breakpad/src/client/linux/handler/exception_handler.h" | 35 #include "breakpad/src/client/linux/handler/exception_handler.h" |
| 35 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h" | 36 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h" |
| 36 #include "breakpad/src/common/linux/linux_libc_support.h" | 37 #include "breakpad/src/common/linux/linux_libc_support.h" |
| 37 #include "breakpad/src/common/memory.h" | 38 #include "breakpad/src/common/memory.h" |
| 38 #include "chrome/browser/crash_upload_list.h" | 39 #include "chrome/browser/crash_upload_list.h" |
| 39 #include "chrome/common/child_process_logging.h" | 40 #include "chrome/common/child_process_logging.h" |
| 40 #include "chrome/common/chrome_paths.h" | 41 #include "chrome/common/chrome_paths.h" |
| 41 #include "chrome/common/chrome_switches.h" | 42 #include "chrome/common/chrome_switches.h" |
| 42 #include "chrome/common/chrome_version_info_posix.h" | 43 #include "chrome/common/chrome_version_info_posix.h" |
| 44 #include "chrome/common/crash_keys.h" | |
| 43 #include "chrome/common/dump_without_crashing.h" | 45 #include "chrome/common/dump_without_crashing.h" |
| 44 #include "chrome/common/env_vars.h" | 46 #include "chrome/common/env_vars.h" |
| 45 #include "chrome/common/logging_chrome.h" | 47 #include "chrome/common/logging_chrome.h" |
| 46 #include "content/public/common/content_descriptors.h" | 48 #include "content/public/common/content_descriptors.h" |
| 47 | 49 |
| 48 #if defined(OS_ANDROID) | 50 #if defined(OS_ANDROID) |
| 49 #include <android/log.h> | 51 #include <android/log.h> |
| 50 #include <sys/stat.h> | 52 #include <sys/stat.h> |
| 51 | 53 |
| 52 #include "base/android/build_info.h" | 54 #include "base/android/build_info.h" |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 77 using google_breakpad::MinidumpDescriptor; | 79 using google_breakpad::MinidumpDescriptor; |
| 78 | 80 |
| 79 namespace { | 81 namespace { |
| 80 | 82 |
| 81 const char kUploadURL[] = "https://clients2.google.com/cr/report"; | 83 const char kUploadURL[] = "https://clients2.google.com/cr/report"; |
| 82 | 84 |
| 83 bool g_is_crash_reporter_enabled = false; | 85 bool g_is_crash_reporter_enabled = false; |
| 84 uint64_t g_process_start_time = 0; | 86 uint64_t g_process_start_time = 0; |
| 85 char* g_crash_log_path = NULL; | 87 char* g_crash_log_path = NULL; |
| 86 ExceptionHandler* g_breakpad = NULL; | 88 ExceptionHandler* g_breakpad = NULL; |
| 89 | |
| 87 #if defined(ADDRESS_SANITIZER) | 90 #if defined(ADDRESS_SANITIZER) |
| 88 const char* g_asan_report_str = NULL; | 91 const char* g_asan_report_str = NULL; |
| 89 #endif | 92 #endif |
| 90 #if defined(OS_ANDROID) | 93 #if defined(OS_ANDROID) |
| 91 char* g_process_type = NULL; | 94 char* g_process_type = NULL; |
| 92 #endif | 95 #endif |
| 93 | 96 |
| 97 CrashKeyStorage* g_crash_keys = NULL; | |
| 98 | |
| 94 // Writes the value |v| as 16 hex characters to the memory pointed at by | 99 // Writes the value |v| as 16 hex characters to the memory pointed at by |
| 95 // |output|. | 100 // |output|. |
| 96 void write_uint64_hex(char* output, uint64_t v) { | 101 void write_uint64_hex(char* output, uint64_t v) { |
| 97 static const char hextable[] = "0123456789abcdef"; | 102 static const char hextable[] = "0123456789abcdef"; |
| 98 | 103 |
| 99 for (int i = 15; i >= 0; --i) { | 104 for (int i = 15; i >= 0; --i) { |
| 100 output[i] = hextable[v & 15]; | 105 output[i] = hextable[v & 15]; |
| 101 v >>= 4; | 106 v >>= 4; |
| 102 } | 107 } |
| 103 } | 108 } |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 info.crash_url = NULL; | 481 info.crash_url = NULL; |
| 477 info.crash_url_length = 0; | 482 info.crash_url_length = 0; |
| 478 info.guid = child_process_logging::g_client_id; | 483 info.guid = child_process_logging::g_client_id; |
| 479 info.guid_length = my_strlen(child_process_logging::g_client_id); | 484 info.guid_length = my_strlen(child_process_logging::g_client_id); |
| 480 info.distro = base::g_linux_distro; | 485 info.distro = base::g_linux_distro; |
| 481 info.distro_length = my_strlen(base::g_linux_distro); | 486 info.distro_length = my_strlen(base::g_linux_distro); |
| 482 info.upload = upload; | 487 info.upload = upload; |
| 483 info.process_start_time = g_process_start_time; | 488 info.process_start_time = g_process_start_time; |
| 484 info.oom_size = base::g_oom_size; | 489 info.oom_size = base::g_oom_size; |
| 485 info.pid = 0; | 490 info.pid = 0; |
| 491 info.crash_keys = g_crash_keys; | |
| 486 HandleCrashDump(info); | 492 HandleCrashDump(info); |
| 487 #if defined(OS_ANDROID) | 493 #if defined(OS_ANDROID) |
| 488 return FinalizeCrashDoneAndroid(); | 494 return FinalizeCrashDoneAndroid(); |
| 489 #else | 495 #else |
| 490 return true; | 496 return true; |
| 491 #endif | 497 #endif |
| 492 } | 498 } |
| 493 | 499 |
| 494 // Wrapper function, do not add more code here. | 500 // Wrapper function, do not add more code here. |
| 495 bool CrashDoneNoUpload(const MinidumpDescriptor& minidump, | 501 bool CrashDoneNoUpload(const MinidumpDescriptor& minidump, |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 656 char b; // Dummy variable for sys_read below. | 662 char b; // Dummy variable for sys_read below. |
| 657 const char* b_addr = &b; // Get the address of |b| so we can create the | 663 const char* b_addr = &b; // Get the address of |b| so we can create the |
| 658 // expected /proc/[pid]/syscall content in the | 664 // expected /proc/[pid]/syscall content in the |
| 659 // browser to convert namespace tids. | 665 // browser to convert namespace tids. |
| 660 | 666 |
| 661 // The length of the control message: | 667 // The length of the control message: |
| 662 static const unsigned kControlMsgSize = sizeof(fds); | 668 static const unsigned kControlMsgSize = sizeof(fds); |
| 663 static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize); | 669 static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize); |
| 664 static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize); | 670 static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize); |
| 665 | 671 |
| 666 #if !defined(ADDRESS_SANITIZER) | |
| 667 const size_t kIovSize = 8; | |
| 668 #else | |
| 669 // Additional field to pass the AddressSanitizer log to the crash handler. | |
| 670 const size_t kIovSize = 9; | |
| 671 #endif | |
| 672 struct kernel_msghdr msg; | 672 struct kernel_msghdr msg; |
| 673 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); | 673 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); |
| 674 struct kernel_iovec iov[kIovSize]; | 674 struct kernel_iovec iov[kCrashIovSize]; |
| 675 iov[0].iov_base = const_cast<void*>(crash_context); | 675 iov[0].iov_base = const_cast<void*>(crash_context); |
| 676 iov[0].iov_len = crash_context_size; | 676 iov[0].iov_len = crash_context_size; |
| 677 iov[1].iov_base = guid; | 677 iov[1].iov_base = guid; |
| 678 iov[1].iov_len = kGuidSize + 1; | 678 iov[1].iov_len = kGuidSize + 1; |
| 679 iov[2].iov_base = crash_url; | 679 iov[2].iov_base = crash_url; |
| 680 iov[2].iov_len = kMaxActiveURLSize + 1; | 680 iov[2].iov_len = kMaxActiveURLSize + 1; |
| 681 iov[3].iov_base = distro; | 681 iov[3].iov_base = distro; |
| 682 iov[3].iov_len = kDistroSize + 1; | 682 iov[3].iov_len = kDistroSize + 1; |
| 683 iov[4].iov_base = &b_addr; | 683 iov[4].iov_base = &b_addr; |
| 684 iov[4].iov_len = sizeof(b_addr); | 684 iov[4].iov_len = sizeof(b_addr); |
| 685 iov[5].iov_base = &fds[0]; | 685 iov[5].iov_base = &fds[0]; |
| 686 iov[5].iov_len = sizeof(fds[0]); | 686 iov[5].iov_len = sizeof(fds[0]); |
| 687 iov[6].iov_base = &g_process_start_time; | 687 iov[6].iov_base = &g_process_start_time; |
| 688 iov[6].iov_len = sizeof(g_process_start_time); | 688 iov[6].iov_len = sizeof(g_process_start_time); |
| 689 iov[7].iov_base = &base::g_oom_size; | 689 iov[7].iov_base = &base::g_oom_size; |
| 690 iov[7].iov_len = sizeof(base::g_oom_size); | 690 iov[7].iov_len = sizeof(base::g_oom_size); |
| 691 google_breakpad::SerializedNonAllocatingMap* serialized_map; | |
| 692 iov[8].iov_len = g_crash_keys->Serialize( | |
| 693 const_cast<const google_breakpad::SerializedNonAllocatingMap**>( | |
| 694 &serialized_map)); | |
| 695 iov[8].iov_base = serialized_map; | |
| 691 #if defined(ADDRESS_SANITIZER) | 696 #if defined(ADDRESS_SANITIZER) |
| 692 iov[8].iov_base = const_cast<char*>(g_asan_report_str); | 697 iov[9].iov_base = const_cast<char*>(g_asan_report_str); |
| 693 iov[8].iov_len = kMaxAsanReportSize + 1; | 698 iov[9].iov_len = kMaxAsanReportSize + 1; |
| 694 #endif | 699 #endif |
| 695 | 700 |
| 696 msg.msg_iov = iov; | 701 msg.msg_iov = iov; |
| 697 msg.msg_iovlen = kIovSize; | 702 msg.msg_iovlen = kCrashIovSize; |
| 698 char cmsg[kControlMsgSpaceSize]; | 703 char cmsg[kControlMsgSpaceSize]; |
| 699 my_memset(cmsg, 0, kControlMsgSpaceSize); | 704 my_memset(cmsg, 0, kControlMsgSpaceSize); |
| 700 msg.msg_control = cmsg; | 705 msg.msg_control = cmsg; |
| 701 msg.msg_controllen = sizeof(cmsg); | 706 msg.msg_controllen = sizeof(cmsg); |
| 702 | 707 |
| 703 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); | 708 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); |
| 704 hdr->cmsg_level = SOL_SOCKET; | 709 hdr->cmsg_level = SOL_SOCKET; |
| 705 hdr->cmsg_type = SCM_RIGHTS; | 710 hdr->cmsg_type = SCM_RIGHTS; |
| 706 hdr->cmsg_len = kControlMsgLenSize; | 711 hdr->cmsg_len = kControlMsgLenSize; |
| 707 ((int*) CMSG_DATA(hdr))[0] = fds[0]; | 712 ((int*) CMSG_DATA(hdr))[0] = fds[0]; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 733 MinidumpDescriptor("/tmp"), // Unused but needed or Breakpad will assert. | 738 MinidumpDescriptor("/tmp"), // Unused but needed or Breakpad will assert. |
| 734 NULL, | 739 NULL, |
| 735 NULL, | 740 NULL, |
| 736 reinterpret_cast<void*>(fd), // Param passed to the crash handler. | 741 reinterpret_cast<void*>(fd), // Param passed to the crash handler. |
| 737 true, | 742 true, |
| 738 -1); | 743 -1); |
| 739 g_breakpad->set_crash_handler(NonBrowserCrashHandler); | 744 g_breakpad->set_crash_handler(NonBrowserCrashHandler); |
| 740 } | 745 } |
| 741 #endif // defined(OS_ANDROID) | 746 #endif // defined(OS_ANDROID) |
| 742 | 747 |
| 748 void SetCrashKeyValue(const base::StringPiece& key, | |
| 749 const base::StringPiece& value) { | |
| 750 g_crash_keys->SetKeyValue(key.data(), value.data()); | |
| 751 } | |
| 752 | |
| 753 void ClearCrashKey(const base::StringPiece& key) { | |
| 754 g_crash_keys->RemoveKey(key.data()); | |
| 755 } | |
| 756 | |
| 743 } // namespace | 757 } // namespace |
| 744 | 758 |
| 745 void LoadDataFromFD(google_breakpad::PageAllocator& allocator, | 759 void LoadDataFromFD(google_breakpad::PageAllocator& allocator, |
| 746 int fd, bool close_fd, uint8_t** file_data, size_t* size) { | 760 int fd, bool close_fd, uint8_t** file_data, size_t* size) { |
| 747 STAT_STRUCT st; | 761 STAT_STRUCT st; |
| 748 if (FSTAT_FUNC(fd, &st) != 0) { | 762 if (FSTAT_FUNC(fd, &st) != 0) { |
| 749 static const char msg[] = "Cannot upload crash dump: stat failed\n"; | 763 static const char msg[] = "Cannot upload crash dump: stat failed\n"; |
| 750 WriteLog(msg, sizeof(msg) - 1); | 764 WriteLog(msg, sizeof(msg) - 1); |
| 751 if (close_fd) | 765 if (close_fd) |
| 752 IGNORE_RET(sys_close(fd)); | 766 IGNORE_RET(sys_close(fd)); |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1204 char oom_size_str[kUint64StringSize]; | 1218 char oom_size_str[kUint64StringSize]; |
| 1205 const unsigned oom_size_len = my_uint64_len(info.oom_size); | 1219 const unsigned oom_size_len = my_uint64_len(info.oom_size); |
| 1206 my_uint64tos(oom_size_str, info.oom_size, oom_size_len); | 1220 my_uint64tos(oom_size_str, info.oom_size, oom_size_len); |
| 1207 static const char oom_size_msg[] = "oom-size"; | 1221 static const char oom_size_msg[] = "oom-size"; |
| 1208 writer.AddPairData(oom_size_msg, sizeof(oom_size_msg) - 1, | 1222 writer.AddPairData(oom_size_msg, sizeof(oom_size_msg) - 1, |
| 1209 oom_size_str, oom_size_len); | 1223 oom_size_str, oom_size_len); |
| 1210 writer.AddBoundary(); | 1224 writer.AddBoundary(); |
| 1211 writer.Flush(); | 1225 writer.Flush(); |
| 1212 } | 1226 } |
| 1213 | 1227 |
| 1228 if (info.crash_keys) { | |
| 1229 CrashKeyStorage::Iterator crash_key_iterator(*info.crash_keys); | |
|
Lei Zhang
2013/05/28 22:02:24
Can you update the comment around line 989?
Robert Sesek
2013/05/29 18:39:45
Done.
| |
| 1230 const CrashKeyStorage::Entry* entry; | |
| 1231 while ((entry = crash_key_iterator.Next())) { | |
| 1232 writer.AddPairString(entry->key, entry->value); | |
| 1233 writer.AddBoundary(); | |
| 1234 writer.Flush(); | |
| 1235 } | |
| 1236 } | |
| 1237 | |
| 1214 writer.AddFileContents(g_dump_msg, dump_data, dump_size); | 1238 writer.AddFileContents(g_dump_msg, dump_data, dump_size); |
| 1215 #if defined(ADDRESS_SANITIZER) | 1239 #if defined(ADDRESS_SANITIZER) |
| 1216 // Append a multipart boundary and the contents of the AddressSanitizer log. | 1240 // Append a multipart boundary and the contents of the AddressSanitizer log. |
| 1217 writer.AddBoundary(); | 1241 writer.AddBoundary(); |
| 1218 writer.AddFileContents(g_log_msg, log_data, log_size); | 1242 writer.AddFileContents(g_log_msg, log_data, log_size); |
| 1219 #endif | 1243 #endif |
| 1220 writer.AddEnd(); | 1244 writer.AddEnd(); |
| 1221 writer.Flush(); | 1245 writer.Flush(); |
| 1222 | 1246 |
| 1223 IGNORE_RET(sys_close(temp_file_fd)); | 1247 IGNORE_RET(sys_close(temp_file_fd)); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1466 #endif // #if defined(OS_ANDROID) | 1490 #endif // #if defined(OS_ANDROID) |
| 1467 } | 1491 } |
| 1468 | 1492 |
| 1469 SetProcessStartTime(); | 1493 SetProcessStartTime(); |
| 1470 | 1494 |
| 1471 logging::SetDumpWithoutCrashingFunction(&DumpProcess); | 1495 logging::SetDumpWithoutCrashingFunction(&DumpProcess); |
| 1472 #if defined(ADDRESS_SANITIZER) | 1496 #if defined(ADDRESS_SANITIZER) |
| 1473 // Register the callback for AddressSanitizer error reporting. | 1497 // Register the callback for AddressSanitizer error reporting. |
| 1474 __asan_set_error_report_callback(AsanLinuxBreakpadCallback); | 1498 __asan_set_error_report_callback(AsanLinuxBreakpadCallback); |
| 1475 #endif | 1499 #endif |
| 1500 | |
| 1501 g_crash_keys = new CrashKeyStorage; | |
| 1502 crash_keys::RegisterChromeCrashKeys(); | |
| 1503 base::debug::SetCrashKeyReportingFunctions( | |
| 1504 &SetCrashKeyValue, &ClearCrashKey); | |
| 1476 } | 1505 } |
| 1477 | 1506 |
| 1478 #if defined(OS_ANDROID) | 1507 #if defined(OS_ANDROID) |
| 1479 void InitNonBrowserCrashReporterForAndroid() { | 1508 void InitNonBrowserCrashReporterForAndroid() { |
| 1480 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 1509 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 1481 if (command_line->HasSwitch(switches::kEnableCrashReporter)) { | 1510 if (command_line->HasSwitch(switches::kEnableCrashReporter)) { |
| 1482 // On Android we need to provide a FD to the file where the minidump is | 1511 // On Android we need to provide a FD to the file where the minidump is |
| 1483 // generated as the renderer and browser run with different UIDs | 1512 // generated as the renderer and browser run with different UIDs |
| 1484 // (preventing the browser from inspecting the renderer process). | 1513 // (preventing the browser from inspecting the renderer process). |
| 1485 int minidump_fd = base::GlobalDescriptors::GetInstance()-> | 1514 int minidump_fd = base::GlobalDescriptors::GetInstance()-> |
| 1486 MaybeGet(kAndroidMinidumpDescriptor); | 1515 MaybeGet(kAndroidMinidumpDescriptor); |
| 1487 if (minidump_fd == base::kInvalidPlatformFileValue) { | 1516 if (minidump_fd == base::kInvalidPlatformFileValue) { |
| 1488 NOTREACHED() << "Could not find minidump FD, crash reporting disabled."; | 1517 NOTREACHED() << "Could not find minidump FD, crash reporting disabled."; |
| 1489 } else { | 1518 } else { |
| 1490 EnableNonBrowserCrashDumping(minidump_fd); | 1519 EnableNonBrowserCrashDumping(minidump_fd); |
| 1491 } | 1520 } |
| 1492 } | 1521 } |
| 1493 } | 1522 } |
| 1494 #endif // OS_ANDROID | 1523 #endif // OS_ANDROID |
| 1495 | 1524 |
| 1496 bool IsCrashReporterEnabled() { | 1525 bool IsCrashReporterEnabled() { |
| 1497 return g_is_crash_reporter_enabled; | 1526 return g_is_crash_reporter_enabled; |
| 1498 } | 1527 } |
| OLD | NEW |