diff options
-rw-r--r-- | chrome/app/breakpad_linux.cc | 163 | ||||
-rw-r--r-- | chrome/app/breakpad_win.cc | 5 | ||||
-rw-r--r-- | chrome/common/child_process_logging.h | 20 | ||||
-rw-r--r-- | chrome/common/child_process_logging_linux.cc | 50 |
4 files changed, 196 insertions, 42 deletions
diff --git a/chrome/app/breakpad_linux.cc b/chrome/app/breakpad_linux.cc index 1e518c7..31294c6 100644 --- a/chrome/app/breakpad_linux.cc +++ b/chrome/app/breakpad_linux.cc @@ -144,12 +144,14 @@ class MimeWriter { } // Append key/value pair, splitting value into chunks no larger than - // kMaxCrashChunkSize. The msg_type string will have a counter suffix to - // distinguish each chunk. + // |chunk_size|. |chunk_size| cannot be greater than |kMaxCrashChunkSize|. + // The msg_type string will have a counter suffix to distinguish each chunk. void AddPairDataInChunks(const char* msg_type, size_t msg_type_size, const char* msg_data, - size_t msg_data_size); + size_t msg_data_size, + size_t chunk_size, + bool strip_trailing_spaces); // Add binary file dump. Currently this is only done once, so the name is // fixed. @@ -168,6 +170,7 @@ class MimeWriter { void AddString(const char* str) { AddItem(str, my_strlen(str)); } + void AddItemWithoutTrailingSpaces(const void* base, size_t size); struct kernel_iovec iov_[kIovCapacity]; int iov_index_; @@ -216,7 +219,12 @@ void MimeWriter::AddPairData(const char* msg_type, void MimeWriter::AddPairDataInChunks(const char* msg_type, size_t msg_type_size, const char* msg_data, - size_t msg_data_size) { + size_t msg_data_size, + size_t chunk_size, + bool strip_trailing_spaces) { + if (chunk_size > kMaxCrashChunkSize) + return; + unsigned i = 0; size_t done = 0, msg_length = msg_data_size; @@ -225,7 +233,7 @@ void MimeWriter::AddPairDataInChunks(const char* msg_type, const unsigned num_len = my_int_len(++i); my_itos(num, i, num_len); - size_t chunk_len = std::min((size_t)kMaxCrashChunkSize, msg_length); + size_t chunk_len = std::min(chunk_size, msg_length); AddString(g_form_data_msg); AddItem(msg_type, msg_type_size); @@ -233,7 +241,11 @@ void MimeWriter::AddPairDataInChunks(const char* msg_type, AddString(g_quote_msg); AddString(g_rn); AddString(g_rn); - AddItem(msg_data + done, chunk_len); + if (strip_trailing_spaces) { + AddItemWithoutTrailingSpaces(msg_data + done, chunk_len); + } else { + AddItem(msg_data + done, chunk_len); + } AddString(g_rn); AddBoundary(); Flush(); @@ -265,6 +277,16 @@ void MimeWriter::AddItem(const void* base, size_t size) { ++iov_index_; } +void MimeWriter::AddItemWithoutTrailingSpaces(const void* base, size_t size) { + while (size > 0) { + const char* c = static_cast<const char*>(base) + size - 1; + if (*c != ' ') + break; + size--; + } + AddItem(base, size); +} + } // namespace pid_t HandleCrashDump(const BreakpadInfo& info) { @@ -389,35 +411,57 @@ pid_t HandleCrashDump(const BreakpadInfo& info) { // abcdef \r\n // BOUNDARY \r\n // + // zero or one: + // Content-Disposition: form-data; name="num-views" \r\n \r\n + // 3 \r\n + // BOUNDARY \r\n + // + // zero or one: + // Content-Disposition: form-data; name="num-extensions" \r\n \r\n + // 5 \r\n + // BOUNDARY \r\n + // + // zero to 10: + // Content-Disposition: form-data; name="extension-1" \r\n \r\n + // abcdefghijklmnopqrstuvwxyzabcdef \r\n + // BOUNDARY \r\n + // + // zero or one: + // Content-Disposition: form-data; name="num-switches" \r\n \r\n + // 5 \r\n + // BOUNDARY \r\n + // + // zero to 15: + // Content-Disposition: form-data; name="switch-1" \r\n \r\n + // --foo \r\n + // BOUNDARY \r\n + // // Content-Disposition: form-data; name="dump"; filename="dump" \r\n // Content-Type: application/octet-stream \r\n \r\n // <dump contents> // \r\n BOUNDARY -- \r\n - #if defined(OS_CHROMEOS) - static const char chrome_product_msg[] = "Chrome_ChromeOS"; - #else // OS_LINUX - static const char chrome_product_msg[] = "Chrome_Linux"; - #endif - static const char version_msg[] = PRODUCT_VERSION; - static const char prod_msg[] = "prod"; - static const char ver_msg[] = "ver"; - static const char guid_msg[] = "guid"; - static const char url_chunk_msg[] = "url-chunk-"; - static const char process_time_msg[] = "ptime"; - static const char process_type_msg[] = "ptype"; - static const char distro_msg[] = "lsb-release"; - MimeWriter writer(fd, mime_boundary); + { +#if defined(OS_CHROMEOS) + static const char chrome_product_msg[] = "Chrome_ChromeOS"; +#else // OS_LINUX + static const char chrome_product_msg[] = "Chrome_Linux"; +#endif + static const char version_msg[] = PRODUCT_VERSION; + static const char prod_msg[] = "prod"; + static const char ver_msg[] = "ver"; + static const char guid_msg[] = "guid"; - writer.AddBoundary(); - writer.AddPairString(prod_msg, chrome_product_msg); - writer.AddBoundary(); - writer.AddPairString(ver_msg, version_msg); - writer.AddBoundary(); - writer.AddPairString(guid_msg, info.guid); - writer.AddBoundary(); - writer.Flush(); + writer.AddBoundary(); + writer.AddPairString(prod_msg, chrome_product_msg); + writer.AddBoundary(); + writer.AddPairString(ver_msg, version_msg); + writer.AddBoundary(); + writer.AddPairString(guid_msg, info.guid); + writer.AddBoundary(); + writer.Flush(); + } if (info.process_start_time > 0) { struct kernel_timeval tv; @@ -429,6 +473,7 @@ pid_t HandleCrashDump(const BreakpadInfo& info) { const unsigned time_len = my_uint64_len(time); my_uint64tos(time_str, time, time_len); + static const char process_time_msg[] = "ptime"; writer.AddPairData(process_time_msg, sizeof(process_time_msg) - 1, time_str, time_len); writer.AddBoundary(); @@ -438,6 +483,7 @@ pid_t HandleCrashDump(const BreakpadInfo& info) { } if (info.process_type_length) { + static const char process_type_msg[] = "ptype"; writer.AddPairString(process_type_msg, info.process_type); writer.AddBoundary(); writer.Flush(); @@ -466,16 +512,73 @@ pid_t HandleCrashDump(const BreakpadInfo& info) { } if (info.distro_length) { + static const char distro_msg[] = "lsb-release"; writer.AddPairString(distro_msg, info.distro); writer.AddBoundary(); writer.Flush(); } - // For rendererers and plugins. + // For renderers and plugins. if (info.crash_url_length) { + static const char url_chunk_msg[] = "url-chunk-"; static const unsigned kMaxUrlLength = 8 * MimeWriter::kMaxCrashChunkSize; writer.AddPairDataInChunks(url_chunk_msg, sizeof(url_chunk_msg) - 1, - info.crash_url, std::min(info.crash_url_length, kMaxUrlLength)); + info.crash_url, std::min(info.crash_url_length, kMaxUrlLength), + MimeWriter::kMaxCrashChunkSize, false /* Don't strip whitespaces. */); + } + + unsigned num_views_len = my_strlen(child_process_logging::g_num_views); + if (num_views_len) { + static const char num_views_msg[] = "num-views"; + writer.AddPairString(num_views_msg, child_process_logging::g_num_views); + writer.AddBoundary(); + writer.Flush(); + } + + unsigned num_extensions_len = + my_strlen(child_process_logging::g_num_extensions); + if (num_extensions_len) { + static const char num_extensions_msg[] = "num-extensions"; + writer.AddPairString(num_extensions_msg, + child_process_logging::g_num_extensions); + writer.AddBoundary(); + writer.Flush(); + } + + unsigned extension_ids_len = + my_strlen(child_process_logging::g_extension_ids); + if (extension_ids_len) { + static const char extension_msg[] = "extension-"; + static const unsigned kMaxExtensionsLen = + kMaxReportedActiveExtensions * child_process_logging::kExtensionLen; + writer.AddPairDataInChunks(extension_msg, sizeof(extension_msg) - 1, + child_process_logging::g_extension_ids, + std::min(extension_ids_len, kMaxExtensionsLen), + child_process_logging::kExtensionLen, + false /* Don't strip whitespace. */); + } + + unsigned num_switches_len = + my_strlen(child_process_logging::g_num_switches); + if (num_switches_len) { + static const char num_switches_msg[] = "num-switches"; + writer.AddPairString(num_switches_msg, + child_process_logging::g_num_switches); + writer.AddBoundary(); + writer.Flush(); + } + + unsigned switches_len = + my_strlen(child_process_logging::g_switches); + if (switches_len) { + static const char switch_msg[] = "switch-"; + static const unsigned kMaxSwitchLen = + kMaxSwitches * child_process_logging::kSwitchLen; + writer.AddPairDataInChunks(switch_msg, sizeof(switch_msg) - 1, + child_process_logging::g_switches, + std::min(switches_len, kMaxSwitchLen), + child_process_logging::kSwitchLen, + true /* Strip whitespace since switches are padded to kSwitchLen. */); } writer.AddFileDump(dump_data, st.st_size); diff --git a/chrome/app/breakpad_win.cc b/chrome/app/breakpad_win.cc index dd1325a..dd1e221 100644 --- a/chrome/app/breakpad_win.cc +++ b/chrome/app/breakpad_win.cc @@ -75,11 +75,6 @@ static size_t g_num_of_views_offset; static size_t g_num_switches_offset; static size_t g_switches_offset; -// The maximum number of command line switches to include in the crash -// report's metadata. Note that the mini-dump itself will also contain the -// (original) command line arguments within the PEB. -const size_t kMaxSwitches = 15; - // Dumps the current process memory. extern "C" void __declspec(dllexport) __cdecl DumpProcess() { if (g_breakpad) diff --git a/chrome/common/child_process_logging.h b/chrome/common/child_process_logging.h index 1269ecf..7117962 100644 --- a/chrome/common/child_process_logging.h +++ b/chrome/common/child_process_logging.h @@ -16,12 +16,17 @@ class CommandLine; struct GPUInfo; -#if defined(OS_WIN) || defined(OS_MACOSX) // The maximum number of active extensions we will report. // Also used in chrome/app, but we define it here to avoid a common->app // dependency. static const int kMaxReportedActiveExtensions = 10; -#endif + +// The maximum number of command line switches to include in the crash +// report's metadata. Note that the mini-dump itself will also contain the +// (original) command line arguments within the PEB. +// Also used in chrome/app, but we define it here to avoid a common->app +// dependency. +static const size_t kMaxSwitches = 15; namespace child_process_logging { @@ -30,11 +35,22 @@ namespace child_process_logging { // compromised context without going through the standard library. extern char g_active_url[]; extern char g_client_id[]; +extern char g_extension_ids[]; extern char g_gpu_vendor_id[]; extern char g_gpu_device_id[]; extern char g_gpu_driver_ver[]; extern char g_gpu_ps_ver[]; extern char g_gpu_vs_ver[]; +extern char g_num_extensions[]; +extern char g_num_switches[]; +extern char g_num_views[]; +extern char g_switches[]; + +// Assume IDs are 32 bytes long. +static const size_t kExtensionLen = 32; + +// Assume command line switches are less than 64 chars. +static const size_t kSwitchLen = 64; #endif // Sets the URL that is logged if the child process crashes. Use GURL() to clear diff --git a/chrome/common/child_process_logging_linux.cc b/chrome/common/child_process_logging_linux.cc index 28b9a2e..37ae5b8 100644 --- a/chrome/common/child_process_logging_linux.cc +++ b/chrome/common/child_process_logging_linux.cc @@ -4,6 +4,8 @@ #include "chrome/common/child_process_logging.h" +#include "base/command_line.h" +#include "base/format_macros.h" #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" @@ -31,6 +33,19 @@ char g_gpu_driver_ver[kGpuStringSize] = ""; char g_gpu_ps_ver[kGpuStringSize] = ""; char g_gpu_vs_ver[kGpuStringSize] = ""; +static const size_t kNumSize = 32; +char g_num_extensions[kNumSize] = ""; +char g_num_switches[kNumSize] = ""; +char g_num_views[kNumSize] = ""; + +static const size_t kMaxExtensionSize = + kExtensionLen * kMaxReportedActiveExtensions + 1; +char g_extension_ids[kMaxExtensionSize] = ""; + +// Assume command line switches are less than 64 chars. +static const size_t kMaxSwitchesSize = kSwitchLen * kMaxSwitches + 1; +char g_switches[kMaxSwitchesSize] = ""; + void SetActiveURL(const GURL& url) { base::strlcpy(g_active_url, url.possibly_invalid_spec().c_str(), @@ -54,7 +69,18 @@ std::string GetClientId() { } void SetActiveExtensions(const std::set<std::string>& extension_ids) { - // TODO(port) + snprintf(g_num_extensions, kNumSize - 1, "%" PRIuS, extension_ids.size()); + g_num_extensions[kNumSize - 1] = '\0'; + + std::string extension_str; + std::set<std::string>::const_iterator iter = extension_ids.begin(); + for (int i = 0; + i < kMaxReportedActiveExtensions && iter != extension_ids.end(); + ++i, ++iter) { + extension_str += *iter; + } + strncpy(g_extension_ids, extension_str.c_str(), kMaxExtensionSize - 1); + g_extension_ids[kMaxExtensionSize - 1] = '\0'; } void SetGpuInfo(const GPUInfo& gpu_info) { @@ -75,12 +101,26 @@ void SetGpuInfo(const GPUInfo& gpu_info) { } void SetNumberOfViews(int number_of_views) { - // TODO(port) + snprintf(g_num_views, kNumSize - 1, "%d", number_of_views); + g_num_views[kNumSize - 1] = '\0'; } -void SetCommandLine(const CommandLine*) { - // TODO: http://crbug.com/60993 - NOTIMPLEMENTED(); +void SetCommandLine(const CommandLine* command_line) { + const CommandLine::StringVector& argv = command_line->argv(); + + snprintf(g_num_switches, kNumSize - 1, "%" PRIuS, argv.size() - 1); + g_num_switches[kNumSize - 1] = '\0'; + + std::string command_line_str; + for (size_t argv_i = 1; + argv_i < argv.size() && argv_i <= kMaxSwitches; + ++argv_i) { + command_line_str += argv[argv_i]; + // Truncate long switches, align short ones with spaces to be trimmed later. + command_line_str.resize(argv_i * kSwitchLen, ' '); + } + strncpy(g_switches, command_line_str.c_str(), kMaxSwitchesSize - 1); + g_switches[kMaxSwitchesSize - 1] = '\0'; } } // namespace child_process_logging |