Index: chrome/app/breakpad_linux.cc |
=================================================================== |
--- chrome/app/breakpad_linux.cc (revision 20935) |
+++ chrome/app/breakpad_linux.cc (working copy) |
@@ -16,6 +16,7 @@ |
#include "base/eintr_wrapper.h" |
#include "base/file_version_info_linux.h" |
#include "base/global_descriptors_posix.h" |
+#include "base/linux_util.h" |
#include "base/path_service.h" |
#include "base/rand_util.h" |
#include "base/string_util.h" |
@@ -42,17 +43,11 @@ |
} |
} |
-pid_t UploadCrashDump(const char* filename, |
- const char* process_type, |
- unsigned process_type_length, |
- const char* crash_url, |
- unsigned crash_url_length, |
- const char* guid, |
- unsigned guid_length) { |
+pid_t UploadCrashDump(const BreakpadInfo& info) { |
// WARNING: this code runs in a compromised context. It may not call into |
// libc nor allocate memory normally. |
- const int dumpfd = sys_open(filename, O_RDONLY, 0); |
+ const int dumpfd = sys_open(info.filename, O_RDONLY, 0); |
if (dumpfd < 0) { |
static const char msg[] = "Cannot upload crash dump: failed to open\n"; |
sys_write(2, msg, sizeof(msg)); |
@@ -144,6 +139,16 @@ |
// BOUNDARY \r\n (27, 28) |
// |
// zero or more: |
+ // Content-Disposition: form-data; name="ptype" \r\n \r\n (0..4) |
+ // abcdef \r\n (5, 6) |
+ // BOUNDARY \r\n (7, 8) |
+ // |
+ // zero or more: |
+ // Content-Disposition: form-data; name="lsb-release" \r\n \r\n (0..4) |
+ // abcdef \r\n (5, 6) |
+ // BOUNDARY \r\n (7, 8) |
+ // |
+ // zero or more: |
// Content-Disposition: form-data; name="url-chunk-1" \r\n \r\n (0..5) |
// abcdef \r\n (6, 7) |
// BOUNDARY \r\n (8, 9) |
@@ -166,6 +171,7 @@ |
"Content-Type: application/octet-stream"; |
static const char url_chunk_msg[] = "url-chunk-"; |
static const char process_type_msg[] = "ptype"; |
+ static const char distro_msg[] = "lsb-release"; |
struct kernel_iovec iov[29]; |
iov[0].iov_base = mime_boundary; |
@@ -226,8 +232,8 @@ |
iov[24].iov_base = const_cast<char*>(rn); |
iov[24].iov_len = sizeof(rn); |
- iov[25].iov_base = const_cast<char*>(guid); |
- iov[25].iov_len = guid_length; |
+ iov[25].iov_base = const_cast<char*>(info.guid); |
+ iov[25].iov_len = info.guid_length; |
iov[26].iov_base = const_cast<char*>(rn); |
iov[26].iov_len = sizeof(rn); |
@@ -238,7 +244,7 @@ |
sys_writev(fd, iov, 29); |
- if (process_type_length) { |
+ if (info.process_type_length) { |
iov[0].iov_base = const_cast<char*>(form_data_msg); |
iov[0].iov_len = sizeof(form_data_msg) - 1; |
iov[1].iov_base = const_cast<char*>(process_type_msg); |
@@ -250,8 +256,8 @@ |
iov[4].iov_base = const_cast<char*>(rn); |
iov[4].iov_len = sizeof(rn); |
- iov[5].iov_base = const_cast<char*>(process_type); |
- iov[5].iov_len = process_type_length; |
+ iov[5].iov_base = const_cast<char*>(info.process_type); |
+ iov[5].iov_len = info.process_type_length; |
iov[6].iov_base = const_cast<char*>(rn); |
iov[6].iov_len = sizeof(rn); |
iov[7].iov_base = mime_boundary; |
@@ -262,8 +268,32 @@ |
sys_writev(fd, iov, 9); |
} |
- if (crash_url_length) { |
- unsigned i = 0, done = 0; |
+ if (info.distro_length) { |
+ iov[0].iov_base = const_cast<char*>(form_data_msg); |
+ iov[0].iov_len = sizeof(form_data_msg) - 1; |
+ iov[1].iov_base = const_cast<char*>(distro_msg); |
+ iov[1].iov_len = sizeof(distro_msg) - 1; |
+ iov[2].iov_base = const_cast<char*>(quote_msg); |
+ iov[2].iov_len = sizeof(quote_msg); |
+ iov[3].iov_base = const_cast<char*>(rn); |
+ iov[3].iov_len = sizeof(rn); |
+ iov[4].iov_base = const_cast<char*>(rn); |
+ iov[4].iov_len = sizeof(rn); |
+ |
+ iov[5].iov_base = const_cast<char*>(info.distro); |
+ iov[5].iov_len = info.distro_length; |
+ iov[6].iov_base = const_cast<char*>(rn); |
+ iov[6].iov_len = sizeof(rn); |
+ iov[7].iov_base = mime_boundary; |
+ iov[7].iov_len = sizeof(mime_boundary) - 1; |
+ iov[8].iov_base = const_cast<char*>(rn); |
+ iov[8].iov_len = sizeof(rn); |
+ |
+ sys_writev(fd, iov, 9); |
+ } |
+ |
+ if (info.crash_url_length) { |
+ unsigned i = 0, done = 0, crash_url_length = info.crash_url_length; |
static const unsigned kMaxCrashChunkSize = 64; |
static const unsigned kMaxUrlLength = 8 * kMaxCrashChunkSize; |
if (crash_url_length > kMaxUrlLength) |
@@ -289,7 +319,7 @@ |
const unsigned len = crash_url_length > kMaxCrashChunkSize ? |
kMaxCrashChunkSize : crash_url_length; |
- iov[6].iov_base = const_cast<char*>(crash_url + done); |
+ iov[6].iov_base = const_cast<char*>(info.crash_url + done); |
iov[6].iov_len = len; |
iov[7].iov_base = const_cast<char*>(rn); |
iov[7].iov_len = sizeof(rn); |
@@ -402,7 +432,7 @@ |
sys_write(2, id_buf, my_strlen(id_buf)); |
sys_write(2, "\n", 1); |
} |
- sys_unlink(filename); |
+ sys_unlink(info.filename); |
sys_unlink(buf); |
sys__exit(0); |
} |
@@ -437,6 +467,12 @@ |
extern std::string linux_guid; |
} |
+// This is defined in base/linux_util.cc, it's the static string containing the |
+// user's distro info. We send this in the crash report. |
+namespace base { |
+extern std::string linux_distro; |
+} |
+ |
static bool CrashDone(const char* dump_path, |
const char* minidump_id, |
void* context, |
@@ -458,8 +494,17 @@ |
memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); |
path[dump_path_len + 1 + minidump_id_len + 4] = 0; |
- UploadCrashDump(path, "browser", 7, NULL, 0, google_update::linux_guid.data(), |
- google_update::linux_guid.length()); |
+ BreakpadInfo info; |
+ info.filename = path; |
+ info.process_type = "browser"; |
+ info.process_type_length = 7; |
+ info.crash_url = NULL; |
+ info.crash_url_length = 0; |
+ info.guid = google_update::linux_guid.data(); |
+ info.guid_length = google_update::linux_guid.length(); |
+ info.distro = base::linux_distro.data(); |
+ info.distro_length = base::linux_distro.length(); |
+ UploadCrashDump(info); |
return true; |
} |
@@ -481,33 +526,39 @@ |
static bool |
RendererCrashHandler(const void* crash_context, size_t crash_context_size, |
void* context) { |
- const int fd = (int) context; |
+ const int fd = reinterpret_cast<int>(context); |
int fds[2]; |
socketpair(AF_UNIX, SOCK_STREAM, 0, fds); |
char guid[kGuidSize] = {0}; |
char crash_url[kMaxActiveURLSize + 1] = {0}; |
+ char distro[kDistroSize + 1] = {0}; |
const unsigned guid_len = std::min(google_update::linux_guid.size(), |
kGuidSize); |
const unsigned crash_url_len = |
std::min(child_process_logging::active_url.size(), kMaxActiveURLSize); |
+ const unsigned distro_len = |
+ std::min(base::linux_distro.size(), kDistroSize); |
memcpy(guid, google_update::linux_guid.data(), guid_len); |
memcpy(crash_url, child_process_logging::active_url.data(), crash_url_len); |
+ memcpy(distro, base::linux_distro.data(), distro_len); |
// The length of the control message: |
static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int)); |
struct kernel_msghdr msg; |
my_memset(&msg, 0, sizeof(struct kernel_msghdr)); |
- struct kernel_iovec iov[3]; |
+ struct kernel_iovec iov[4]; |
iov[0].iov_base = const_cast<void*>(crash_context); |
iov[0].iov_len = crash_context_size; |
iov[1].iov_base = guid; |
iov[1].iov_len = kGuidSize + 1; |
iov[2].iov_base = crash_url; |
iov[2].iov_len = kMaxActiveURLSize + 1; |
+ iov[3].iov_base = distro; |
+ iov[3].iov_len = kDistroSize + 1; |
msg.msg_iov = iov; |
- msg.msg_iovlen = 3; |
+ msg.msg_iovlen = 4; |
char cmsg[kControlMsgSize]; |
memset(cmsg, 0, kControlMsgSize); |
msg.msg_control = cmsg; |
@@ -545,6 +596,7 @@ |
if (process_type.empty()) { |
if (!GoogleUpdateSettings::GetCollectStatsConsent()) |
return; |
+ base::GetLinuxDistro(); // Initialize base::linux_distro if needed. |
EnableCrashDumping(); |
} else if (process_type == switches::kRendererProcess || |
process_type == switches::kZygoteProcess) { |
@@ -553,8 +605,16 @@ |
// dir. Instead, we set a command line flag for these processes. |
if (!parsed_command_line.HasSwitch(switches::kRendererCrashDump)) |
return; |
- google_update::linux_guid = WideToASCII( |
+ // Get the guid and linux distro from the command line switch. |
+ std::string switch_value = WideToASCII( |
parsed_command_line.GetSwitchValue(switches::kRendererCrashDump)); |
+ size_t separator = switch_value.find(","); |
+ if (separator != std::string::npos) { |
+ google_update::linux_guid = switch_value.substr(0, separator); |
+ base::linux_distro = switch_value.substr(separator + 1); |
+ } else { |
+ google_update::linux_guid = switch_value; |
+ } |
EnableRendererCrashDumping(); |
} |
} |