summaryrefslogtreecommitdiffstats
path: root/components/breakpad/app
diff options
context:
space:
mode:
authorRobert Sesek <rsesek@chromium.org>2014-08-27 12:12:44 -0400
committerRobert Sesek <rsesek@chromium.org>2014-08-27 16:14:41 +0000
commitabcd8100a58d4e5ba55f4ec2e5f394e0aa6a3f33 (patch)
treef502825654e85f9c009a222384cd07a154e2a1e8 /components/breakpad/app
parent6a35b2b82305427017f42a971dc022d154eb127d (diff)
downloadchromium_src-abcd8100a58d4e5ba55f4ec2e5f394e0aa6a3f33.zip
chromium_src-abcd8100a58d4e5ba55f4ec2e5f394e0aa6a3f33.tar.gz
chromium_src-abcd8100a58d4e5ba55f4ec2e5f394e0aa6a3f33.tar.bz2
Rename components/breakpad to components/crash.
In the near future, Crashpad (the new Mac crash reporter) will be integrated, and it should be integrated/exposed transparently to the users of this component. BUG=406410 R=blundell@chromium.org TBR=darin@chromium.org Review URL: https://codereview.chromium.org/485893007 Cr-Commit-Position: refs/heads/master@{#292162}
Diffstat (limited to 'components/breakpad/app')
-rw-r--r--components/breakpad/app/BUILD.gn69
-rw-r--r--components/breakpad/app/DEPS7
-rw-r--r--components/breakpad/app/breakpad_client.cc127
-rw-r--r--components/breakpad/app/breakpad_client.h143
-rw-r--r--components/breakpad/app/breakpad_linux.cc1615
-rw-r--r--components/breakpad/app/breakpad_linux.h32
-rw-r--r--components/breakpad/app/breakpad_linux_impl.h65
-rw-r--r--components/breakpad/app/breakpad_mac.h27
-rw-r--r--components/breakpad/app/breakpad_mac.mm279
-rw-r--r--components/breakpad/app/breakpad_mac_stubs.mm24
-rw-r--r--components/breakpad/app/breakpad_win.cc609
-rw-r--r--components/breakpad/app/breakpad_win.h22
-rw-r--r--components/breakpad/app/crash_keys_win.cc194
-rw-r--r--components/breakpad/app/crash_keys_win.h75
-rw-r--r--components/breakpad/app/crash_keys_win_unittest.cc145
-rw-r--r--components/breakpad/app/hard_error_handler_win.cc118
-rw-r--r--components/breakpad/app/hard_error_handler_win.h34
17 files changed, 0 insertions, 3585 deletions
diff --git a/components/breakpad/app/BUILD.gn b/components/breakpad/app/BUILD.gn
deleted file mode 100644
index b8bd9aa..0000000
--- a/components/breakpad/app/BUILD.gn
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-if (is_android) {
- import("//build/config/android/config.gni")
-}
-
-source_set("lib") {
- sources = [
- "breakpad_client.cc",
- "breakpad_client.h",
- "crash_keys_win.cc",
- "crash_keys_win.h",
- ]
-
- include_dirs = [
- "../../../breakpad/src",
- ]
-}
-
-# Note: if you depend on this target, you need to either link in
-# content.gyp:content_common, or add content/public/common/content_switches.cc
-# to your sources.
-#
-# GYP version: components/breakpad.gyp:breakpad_component
-source_set("app") {
- sources = [
- "breakpad_linux_impl.h",
- "breakpad_mac.h",
- "breakpad_mac.mm",
- "breakpad_win.cc",
- "breakpad_win.h",
- "hard_error_handler_win.cc",
- "hard_error_handler_win.h",
- ]
- if (is_android || is_linux) {
- # Want these files on both Linux and Android.
- set_sources_assignment_filter([])
- sources += [
- "breakpad_linux.cc",
- "breakpad_linux.h",
- ]
- }
-
- defines = [ "BREAKPAD_IMPLEMENTATION" ]
-
- deps = [
- "//base",
- ":lib",
- ]
-
- if (is_mac) {
- deps += [ "//breakpad" ]
- } else if (is_win) {
- deps += [
- "//sandbox",
- "//breakpad:breakpad_handler",
- #'../breakpad/breakpad.gyp:breakpad_sender', TODO(GYP)
- ]
- } else if (is_posix && !is_ios &&
- (!is_android || !is_android_webview_build)) {
- deps += [ "//breakpad:client" ]
- }
-}
-
-source_set("test_support") {
- deps = [ ":lib" ]
-}
diff --git a/components/breakpad/app/DEPS b/components/breakpad/app/DEPS
deleted file mode 100644
index 4080651..0000000
--- a/components/breakpad/app/DEPS
+++ /dev/null
@@ -1,7 +0,0 @@
-include_rules = [
- "+sandbox",
-
- "+content/public/common/content_descriptors.h",
- "+content/public/common/result_codes.h",
- "+third_party/lss/linux_syscall_support.h",
-]
diff --git a/components/breakpad/app/breakpad_client.cc b/components/breakpad/app/breakpad_client.cc
deleted file mode 100644
index 5c763ca..0000000
--- a/components/breakpad/app/breakpad_client.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/breakpad/app/breakpad_client.h"
-
-#include "base/files/file_path.h"
-#include "base/logging.h"
-
-namespace breakpad {
-
-namespace {
-
-BreakpadClient* g_client = NULL;
-
-} // namespace
-
-void SetBreakpadClient(BreakpadClient* client) {
- g_client = client;
-}
-
-BreakpadClient* GetBreakpadClient() {
- DCHECK(g_client);
- return g_client;
-}
-
-BreakpadClient::BreakpadClient() {}
-BreakpadClient::~BreakpadClient() {}
-
-void BreakpadClient::SetBreakpadClientIdFromGUID(
- const std::string& client_guid) {
-}
-
-#if defined(OS_WIN)
-bool BreakpadClient::GetAlternativeCrashDumpLocation(
- base::FilePath* crash_dir) {
- return false;
-}
-
-void BreakpadClient::GetProductNameAndVersion(const base::FilePath& exe_path,
- base::string16* product_name,
- base::string16* version,
- base::string16* special_build,
- base::string16* channel_name) {
-}
-
-bool BreakpadClient::ShouldShowRestartDialog(base::string16* title,
- base::string16* message,
- bool* is_rtl_locale) {
- return false;
-}
-
-bool BreakpadClient::AboutToRestart() {
- return false;
-}
-
-bool BreakpadClient::GetDeferredUploadsSupported(bool is_per_usr_install) {
- return false;
-}
-
-bool BreakpadClient::GetIsPerUserInstall(const base::FilePath& exe_path) {
- return true;
-}
-
-bool BreakpadClient::GetShouldDumpLargerDumps(bool is_per_user_install) {
- return false;
-}
-
-int BreakpadClient::GetResultCodeRespawnFailed() {
- return 0;
-}
-
-void BreakpadClient::InitBrowserCrashDumpsRegKey() {
-}
-
-void BreakpadClient::RecordCrashDumpAttempt(bool is_real_crash) {
-}
-#endif
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
-void BreakpadClient::GetProductNameAndVersion(std::string* product_name,
- std::string* version) {
-}
-
-base::FilePath BreakpadClient::GetReporterLogFilename() {
- return base::FilePath();
-}
-#endif
-
-bool BreakpadClient::GetCrashDumpLocation(base::FilePath* crash_dir) {
- return false;
-}
-
-size_t BreakpadClient::RegisterCrashKeys() {
- return 0;
-}
-
-bool BreakpadClient::IsRunningUnattended() {
- return true;
-}
-
-bool BreakpadClient::GetCollectStatsConsent() {
- return false;
-}
-
-#if defined(OS_WIN) || defined(OS_MACOSX)
-bool BreakpadClient::ReportingIsEnforcedByPolicy(bool* breakpad_enabled) {
- return false;
-}
-#endif
-
-#if defined(OS_ANDROID)
-int BreakpadClient::GetAndroidMinidumpDescriptor() {
- return 0;
-}
-#endif
-
-#if defined(OS_MACOSX)
-void BreakpadClient::InstallAdditionalFilters(BreakpadRef breakpad) {
-}
-#endif
-
-bool BreakpadClient::EnableBreakpadForProcess(const std::string& process_type) {
- return false;
-}
-
-} // namespace breakpad
diff --git a/components/breakpad/app/breakpad_client.h b/components/breakpad/app/breakpad_client.h
deleted file mode 100644
index 7ade184c..0000000
--- a/components/breakpad/app/breakpad_client.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_BREAKPAD_APP_BREAKPAD_CLIENT_H_
-#define COMPONENTS_BREAKPAD_APP_BREAKPAD_CLIENT_H_
-
-#include <string>
-
-#include "base/strings/string16.h"
-#include "build/build_config.h"
-
-namespace base {
-class FilePath;
-}
-
-#if defined(OS_MACOSX)
-// We don't want to directly include
-// breakpad/src/client/mac/Framework/Breakpad.h here, so we repeat the
-// definition of BreakpadRef.
-//
-// On Mac, when compiling without breakpad support, a stub implementation is
-// compiled in. Not having any includes of the breakpad library allows for
-// reusing this header for the stub.
-typedef void* BreakpadRef;
-#endif
-
-namespace breakpad {
-
-class BreakpadClient;
-
-// Setter and getter for the client. The client should be set early, before any
-// breakpad code is called, and should stay alive throughout the entire runtime.
-void SetBreakpadClient(BreakpadClient* client);
-
-#if defined(BREAKPAD_IMPLEMENTATION)
-// Breakpad's embedder API should only be used by breakpad.
-BreakpadClient* GetBreakpadClient();
-#endif
-
-// Interface that the embedder implements.
-class BreakpadClient {
- public:
- BreakpadClient();
- virtual ~BreakpadClient();
-
- // Sets the Breakpad client ID, which is a unique identifier for the client
- // that is sending crash reports. After it is set, it should not be changed.
- // |client_guid| may either be a full GUID or a GUID that was already stripped
- // from its dashes.
- virtual void SetBreakpadClientIdFromGUID(const std::string& client_guid);
-
-#if defined(OS_WIN)
- // Returns true if an alternative location to store the minidump files was
- // specified. Returns true if |crash_dir| was set.
- virtual bool GetAlternativeCrashDumpLocation(base::FilePath* crash_dir);
-
- // Returns a textual description of the product type and version to include
- // in the crash report.
- virtual void GetProductNameAndVersion(const base::FilePath& exe_path,
- base::string16* product_name,
- base::string16* version,
- base::string16* special_build,
- base::string16* channel_name);
-
- // Returns true if a restart dialog should be displayed. In that case,
- // |message| and |title| are set to a message to display in a dialog box with
- // the given title before restarting, and |is_rtl_locale| indicates whether
- // to display the text as RTL.
- virtual bool ShouldShowRestartDialog(base::string16* title,
- base::string16* message,
- bool* is_rtl_locale);
-
- // Returns true if it is ok to restart the application. Invoked right before
- // restarting after a crash.
- virtual bool AboutToRestart();
-
- // Returns true if the crash report uploader supports deferred uploads.
- virtual bool GetDeferredUploadsSupported(bool is_per_user_install);
-
- // Returns true if the running binary is a per-user installation.
- virtual bool GetIsPerUserInstall(const base::FilePath& exe_path);
-
- // Returns true if larger crash dumps should be dumped.
- virtual bool GetShouldDumpLargerDumps(bool is_per_user_install);
-
- // Returns the result code to return when breakpad failed to respawn a
- // crashed process.
- virtual int GetResultCodeRespawnFailed();
-
- // Invoked when initializing breakpad in the browser process.
- virtual void InitBrowserCrashDumpsRegKey();
-
- // Invoked before attempting to write a minidump.
- virtual void RecordCrashDumpAttempt(bool is_real_crash);
-#endif
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
- // Returns a textual description of the product type and version to include
- // in the crash report.
- virtual void GetProductNameAndVersion(std::string* product_name,
- std::string* version);
-
- virtual base::FilePath GetReporterLogFilename();
-#endif
-
- // The location where minidump files should be written. Returns true if
- // |crash_dir| was set.
- virtual bool GetCrashDumpLocation(base::FilePath* crash_dir);
-
- // Register all of the potential crash keys that can be sent to the crash
- // reporting server. Returns the size of the union of all keys.
- virtual size_t RegisterCrashKeys();
-
- // Returns true if running in unattended mode (for automated testing).
- virtual bool IsRunningUnattended();
-
- // Returns true if the user has given consent to collect stats.
- virtual bool GetCollectStatsConsent();
-
-#if defined(OS_WIN) || defined(OS_MACOSX)
- // Returns true if breakpad is enforced via management policies. In that
- // case, |breakpad_enabled| is set to the value enforced by policies.
- virtual bool ReportingIsEnforcedByPolicy(bool* breakpad_enabled);
-#endif
-
-#if defined(OS_ANDROID)
- // Returns the descriptor key of the android minidump global descriptor.
- virtual int GetAndroidMinidumpDescriptor();
-#endif
-
-#if defined(OS_MACOSX)
- // Install additional breakpad filter callbacks.
- virtual void InstallAdditionalFilters(BreakpadRef breakpad);
-#endif
-
- // Returns true if breakpad should run in the given process type.
- virtual bool EnableBreakpadForProcess(const std::string& process_type);
-};
-
-} // namespace breakpad
-
-#endif // COMPONENTS_BREAKPAD_APP_BREAKPAD_CLIENT_H_
diff --git a/components/breakpad/app/breakpad_linux.cc b/components/breakpad/app/breakpad_linux.cc
deleted file mode 100644
index df9d588..0000000
--- a/components/breakpad/app/breakpad_linux.cc
+++ /dev/null
@@ -1,1615 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// For linux_syscall_support.h. This makes it safe to call embedded system
-// calls when in seccomp mode.
-
-#include "components/breakpad/app/breakpad_linux.h"
-
-#include <fcntl.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <string>
-
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/debug/crash_logging.h"
-#include "base/debug/dump_without_crashing.h"
-#include "base/files/file_path.h"
-#include "base/linux_util.h"
-#include "base/path_service.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/posix/global_descriptors.h"
-#include "base/process/memory.h"
-#include "base/strings/string_util.h"
-#include "breakpad/src/client/linux/crash_generation/crash_generation_client.h"
-#include "breakpad/src/client/linux/handler/exception_handler.h"
-#include "breakpad/src/client/linux/minidump_writer/directory_reader.h"
-#include "breakpad/src/common/linux/linux_libc_support.h"
-#include "breakpad/src/common/memory.h"
-#include "components/breakpad/app/breakpad_client.h"
-#include "components/breakpad/app/breakpad_linux_impl.h"
-#include "content/public/common/content_descriptors.h"
-
-#if defined(OS_ANDROID)
-#include <android/log.h>
-#include <sys/stat.h>
-
-#include "base/android/build_info.h"
-#include "base/android/path_utils.h"
-#endif
-#include "third_party/lss/linux_syscall_support.h"
-
-#if defined(ADDRESS_SANITIZER)
-#include <ucontext.h> // for getcontext().
-#endif
-
-#if defined(OS_ANDROID)
-#define STAT_STRUCT struct stat
-#define FSTAT_FUNC fstat
-#else
-#define STAT_STRUCT struct kernel_stat
-#define FSTAT_FUNC sys_fstat
-#endif
-
-// Some versions of gcc are prone to warn about unused return values. In cases
-// where we either a) know the call cannot fail, or b) there is nothing we
-// can do when a call fails, we mark the return code as ignored. This avoids
-// spurious compiler warnings.
-#define IGNORE_RET(x) do { if (x); } while (0)
-
-using google_breakpad::ExceptionHandler;
-using google_breakpad::MinidumpDescriptor;
-
-namespace breakpad {
-
-namespace {
-
-#if !defined(OS_CHROMEOS)
-const char kUploadURL[] = "https://clients2.google.com/cr/report";
-#endif
-
-bool g_is_crash_reporter_enabled = false;
-uint64_t g_process_start_time = 0;
-pid_t g_pid = 0;
-char* g_crash_log_path = NULL;
-ExceptionHandler* g_breakpad = NULL;
-
-#if defined(ADDRESS_SANITIZER)
-const char* g_asan_report_str = NULL;
-#endif
-#if defined(OS_ANDROID)
-char* g_process_type = NULL;
-#endif
-
-CrashKeyStorage* g_crash_keys = NULL;
-
-// Writes the value |v| as 16 hex characters to the memory pointed at by
-// |output|.
-void write_uint64_hex(char* output, uint64_t v) {
- static const char hextable[] = "0123456789abcdef";
-
- for (int i = 15; i >= 0; --i) {
- output[i] = hextable[v & 15];
- v >>= 4;
- }
-}
-
-// The following helper functions are for calculating uptime.
-
-// Converts a struct timeval to milliseconds.
-uint64_t timeval_to_ms(struct timeval *tv) {
- uint64_t ret = tv->tv_sec; // Avoid overflow by explicitly using a uint64_t.
- ret *= 1000;
- ret += tv->tv_usec / 1000;
- return ret;
-}
-
-// Converts a struct timeval to milliseconds.
-uint64_t kernel_timeval_to_ms(struct kernel_timeval *tv) {
- uint64_t ret = tv->tv_sec; // Avoid overflow by explicitly using a uint64_t.
- ret *= 1000;
- ret += tv->tv_usec / 1000;
- return ret;
-}
-
-// String buffer size to use to convert a uint64_t to string.
-const size_t kUint64StringSize = 21;
-
-void SetProcessStartTime() {
- // Set the base process start time value.
- struct timeval tv;
- if (!gettimeofday(&tv, NULL))
- g_process_start_time = timeval_to_ms(&tv);
- else
- g_process_start_time = 0;
-}
-
-// uint64_t version of my_int_len() from
-// breakpad/src/common/linux/linux_libc_support.h. Return the length of the
-// given, non-negative integer when expressed in base 10.
-unsigned my_uint64_len(uint64_t i) {
- if (!i)
- return 1;
-
- unsigned len = 0;
- while (i) {
- len++;
- i /= 10;
- }
-
- return len;
-}
-
-// uint64_t version of my_uitos() from
-// breakpad/src/common/linux/linux_libc_support.h. Convert a non-negative
-// integer to a string (not null-terminated).
-void my_uint64tos(char* output, uint64_t i, unsigned i_len) {
- for (unsigned index = i_len; index; --index, i /= 10)
- output[index - 1] = '0' + (i % 10);
-}
-
-#if defined(OS_ANDROID)
-char* my_strncpy(char* dst, const char* src, size_t len) {
- int i = len;
- char* p = dst;
- if (!dst || !src)
- return dst;
- while (i != 0 && *src != '\0') {
- *p++ = *src++;
- i--;
- }
- while (i != 0) {
- *p++ = '\0';
- i--;
- }
- return dst;
-}
-
-char* my_strncat(char *dest, const char* src, size_t len) {
- char* ret = dest;
- while (*dest)
- dest++;
- while (len--)
- if (!(*dest++ = *src++))
- return ret;
- *dest = 0;
- return ret;
-}
-#endif
-
-#if !defined(OS_CHROMEOS)
-bool my_isxdigit(char c) {
- return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f');
-}
-#endif
-
-size_t LengthWithoutTrailingSpaces(const char* str, size_t len) {
- while (len > 0 && str[len - 1] == ' ') {
- len--;
- }
- return len;
-}
-
-void SetClientIdFromCommandLine(const CommandLine& command_line) {
- // Get the guid from the command line switch.
- std::string switch_value =
- command_line.GetSwitchValueASCII(switches::kEnableCrashReporter);
- GetBreakpadClient()->SetBreakpadClientIdFromGUID(switch_value);
-}
-
-// MIME substrings.
-#if defined(OS_CHROMEOS)
-const char g_sep[] = ":";
-#endif
-const char g_rn[] = "\r\n";
-const char g_form_data_msg[] = "Content-Disposition: form-data; name=\"";
-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.
-class MimeWriter {
- public:
- static const int kIovCapacity = 30;
- static const size_t kMaxCrashChunkSize = 64;
-
- MimeWriter(int fd, const char* const mime_boundary);
- ~MimeWriter();
-
- // Append boundary.
- virtual void AddBoundary();
-
- // Append end of file boundary.
- virtual void AddEnd();
-
- // Append key/value pair with specified sizes.
- virtual void AddPairData(const char* msg_type,
- size_t msg_type_size,
- const char* msg_data,
- size_t msg_data_size);
-
- // Append key/value pair.
- void AddPairString(const char* msg_type,
- const char* msg_data) {
- AddPairData(msg_type, my_strlen(msg_type), msg_data, my_strlen(msg_data));
- }
-
- // Append key/value pair, splitting value into chunks no larger than
- // |chunk_size|. |chunk_size| cannot be greater than |kMaxCrashChunkSize|.
- // The msg_type string will have a counter suffix to distinguish each chunk.
- virtual void AddPairDataInChunks(const char* msg_type,
- size_t msg_type_size,
- const char* msg_data,
- size_t msg_data_size,
- size_t chunk_size,
- bool strip_trailing_spaces);
-
- // Add binary file contents to be uploaded with the specified filename.
- virtual void AddFileContents(const char* filename_msg,
- uint8_t* file_data,
- size_t file_size);
-
- // Flush any pending iovecs to the output file.
- void Flush() {
- IGNORE_RET(sys_writev(fd_, iov_, iov_index_));
- iov_index_ = 0;
- }
-
- protected:
- void AddItem(const void* base, size_t size);
- // Minor performance trade-off for easier-to-maintain code.
- 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_;
-
- // Output file descriptor.
- int fd_;
-
- const char* const mime_boundary_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MimeWriter);
-};
-
-MimeWriter::MimeWriter(int fd, const char* const mime_boundary)
- : iov_index_(0),
- fd_(fd),
- mime_boundary_(mime_boundary) {
-}
-
-MimeWriter::~MimeWriter() {
-}
-
-void MimeWriter::AddBoundary() {
- AddString(mime_boundary_);
- AddString(g_rn);
-}
-
-void MimeWriter::AddEnd() {
- AddString(mime_boundary_);
- AddString(g_dashdash_msg);
- AddString(g_rn);
-}
-
-void MimeWriter::AddPairData(const char* msg_type,
- size_t msg_type_size,
- const char* msg_data,
- size_t msg_data_size) {
- AddString(g_form_data_msg);
- AddItem(msg_type, msg_type_size);
- AddString(g_quote_msg);
- AddString(g_rn);
- AddString(g_rn);
- AddItem(msg_data, msg_data_size);
- AddString(g_rn);
-}
-
-void MimeWriter::AddPairDataInChunks(const char* msg_type,
- size_t msg_type_size,
- const char* msg_data,
- 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;
-
- while (msg_length) {
- char num[kUint64StringSize];
- const unsigned num_len = my_uint_len(++i);
- my_uitos(num, i, num_len);
-
- size_t chunk_len = std::min(chunk_size, msg_length);
-
- AddString(g_form_data_msg);
- AddItem(msg_type, msg_type_size);
- AddItem(num, num_len);
- AddString(g_quote_msg);
- AddString(g_rn);
- AddString(g_rn);
- if (strip_trailing_spaces) {
- AddItemWithoutTrailingSpaces(msg_data + done, chunk_len);
- } else {
- AddItem(msg_data + done, chunk_len);
- }
- AddString(g_rn);
- AddBoundary();
- Flush();
-
- done += chunk_len;
- msg_length -= chunk_len;
- }
-}
-
-void MimeWriter::AddFileContents(const char* filename_msg, uint8_t* file_data,
- size_t file_size) {
- AddString(g_form_data_msg);
- AddString(filename_msg);
- AddString(g_rn);
- AddString(g_content_type_msg);
- AddString(g_rn);
- AddString(g_rn);
- AddItem(file_data, file_size);
- AddString(g_rn);
-}
-
-void MimeWriter::AddItem(const void* base, size_t size) {
- // Check if the iovec is full and needs to be flushed to output file.
- if (iov_index_ == kIovCapacity) {
- Flush();
- }
- iov_[iov_index_].iov_base = const_cast<void*>(base);
- iov_[iov_index_].iov_len = size;
- ++iov_index_;
-}
-
-void MimeWriter::AddItemWithoutTrailingSpaces(const void* base, size_t size) {
- AddItem(base, LengthWithoutTrailingSpaces(static_cast<const char*>(base),
- size));
-}
-
-#if defined(OS_CHROMEOS)
-// This subclass is used on Chromium OS to report crashes in a format easy for
-// the central crash reporting facility to understand.
-// Format is <name>:<data length in decimal>:<data>
-class CrashReporterWriter : public MimeWriter {
- public:
- explicit CrashReporterWriter(int fd);
-
- virtual void AddBoundary() OVERRIDE;
-
- virtual void AddEnd() OVERRIDE;
-
- virtual void AddPairData(const char* msg_type,
- size_t msg_type_size,
- const char* msg_data,
- size_t msg_data_size) OVERRIDE;
-
- virtual void AddPairDataInChunks(const char* msg_type,
- size_t msg_type_size,
- const char* msg_data,
- size_t msg_data_size,
- size_t chunk_size,
- bool strip_trailing_spaces) OVERRIDE;
-
- virtual void AddFileContents(const char* filename_msg,
- uint8_t* file_data,
- size_t file_size) OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CrashReporterWriter);
-};
-
-
-CrashReporterWriter::CrashReporterWriter(int fd) : MimeWriter(fd, "") {}
-
-// No-ops.
-void CrashReporterWriter::AddBoundary() {}
-void CrashReporterWriter::AddEnd() {}
-
-void CrashReporterWriter::AddPairData(const char* msg_type,
- size_t msg_type_size,
- const char* msg_data,
- size_t msg_data_size) {
- char data[kUint64StringSize];
- const unsigned data_len = my_uint_len(msg_data_size);
- my_uitos(data, msg_data_size, data_len);
-
- AddItem(msg_type, msg_type_size);
- AddString(g_sep);
- AddItem(data, data_len);
- AddString(g_sep);
- AddItem(msg_data, msg_data_size);
- Flush();
-}
-
-void CrashReporterWriter::AddPairDataInChunks(const char* msg_type,
- size_t msg_type_size,
- const char* msg_data,
- 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;
- size_t msg_length = msg_data_size;
-
- while (msg_length) {
- char num[kUint64StringSize];
- const unsigned num_len = my_uint_len(++i);
- my_uitos(num, i, num_len);
-
- size_t chunk_len = std::min(chunk_size, msg_length);
-
- size_t write_len = chunk_len;
- if (strip_trailing_spaces) {
- // Take care of this here because we need to know the exact length of
- // what is going to be written.
- write_len = LengthWithoutTrailingSpaces(msg_data + done, write_len);
- }
-
- char data[kUint64StringSize];
- const unsigned data_len = my_uint_len(write_len);
- my_uitos(data, write_len, data_len);
-
- AddItem(msg_type, msg_type_size);
- AddItem(num, num_len);
- AddString(g_sep);
- AddItem(data, data_len);
- AddString(g_sep);
- AddItem(msg_data + done, write_len);
- Flush();
-
- done += chunk_len;
- msg_length -= chunk_len;
- }
-}
-
-void CrashReporterWriter::AddFileContents(const char* filename_msg,
- uint8_t* file_data,
- size_t file_size) {
- char data[kUint64StringSize];
- const unsigned data_len = my_uint_len(file_size);
- my_uitos(data, file_size, data_len);
-
- AddString(filename_msg);
- AddString(g_sep);
- AddItem(data, data_len);
- AddString(g_sep);
- AddItem(file_data, file_size);
- Flush();
-}
-#endif // defined(OS_CHROMEOS)
-
-void DumpProcess() {
- if (g_breakpad)
- g_breakpad->WriteMinidump();
-}
-
-#if defined(OS_ANDROID)
-const char kGoogleBreakpad[] = "google-breakpad";
-#endif
-
-size_t WriteLog(const char* buf, size_t nbytes) {
-#if defined(OS_ANDROID)
- return __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad, buf);
-#else
- return sys_write(2, buf, nbytes);
-#endif
-}
-
-size_t WriteNewline() {
- return WriteLog("\n", 1);
-}
-
-#if defined(OS_ANDROID)
-// Android's native crash handler outputs a diagnostic tombstone to the device
-// log. By returning false from the HandlerCallbacks, breakpad will reinstall
-// the previous (i.e. native) signal handlers before returning from its own
-// handler. A Chrome build fingerprint is written to the log, so that the
-// specific build of Chrome and the location of the archived Chrome symbols can
-// be determined directly from it.
-bool FinalizeCrashDoneAndroid() {
- base::android::BuildInfo* android_build_info =
- base::android::BuildInfo::GetInstance();
-
- __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
- "### ### ### ### ### ### ### ### ### ### ### ### ###");
- __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
- "Chrome build fingerprint:");
- __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
- android_build_info->package_version_name());
- __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
- android_build_info->package_version_code());
- __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
- CHROME_BUILD_ID);
- __android_log_write(ANDROID_LOG_WARN, kGoogleBreakpad,
- "### ### ### ### ### ### ### ### ### ### ### ### ###");
- return false;
-}
-#endif
-
-bool CrashDone(const MinidumpDescriptor& minidump,
- const bool upload,
- const bool succeeded) {
- // WARNING: this code runs in a compromised context. It may not call into
- // libc nor allocate memory normally.
- if (!succeeded) {
- const char msg[] = "Failed to generate minidump.";
- WriteLog(msg, sizeof(msg) - 1);
- return false;
- }
-
- DCHECK(!minidump.IsFD());
-
- BreakpadInfo info = {0};
- info.filename = minidump.path();
- info.fd = minidump.fd();
-#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.distro = base::g_linux_distro;
- info.distro_length = my_strlen(base::g_linux_distro);
- info.upload = upload;
- info.process_start_time = g_process_start_time;
- info.oom_size = base::g_oom_size;
- info.pid = g_pid;
- info.crash_keys = g_crash_keys;
- HandleCrashDump(info);
-#if defined(OS_ANDROID)
- return FinalizeCrashDoneAndroid();
-#else
- return true;
-#endif
-}
-
-// Wrapper function, do not add more code here.
-bool CrashDoneNoUpload(const MinidumpDescriptor& minidump,
- void* context,
- bool succeeded) {
- return CrashDone(minidump, false, succeeded);
-}
-
-#if !defined(OS_ANDROID)
-// Wrapper function, do not add more code here.
-bool CrashDoneUpload(const MinidumpDescriptor& minidump,
- void* context,
- bool succeeded) {
- return CrashDone(minidump, true, succeeded);
-}
-#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 = report;
- // Send minidump here.
- g_breakpad->SimulateSignalDelivery(SIGKILL);
-}
-#endif
-
-void EnableCrashDumping(bool unattended) {
- g_is_crash_reporter_enabled = true;
-
- base::FilePath tmp_path("/tmp");
- PathService::Get(base::DIR_TEMP, &tmp_path);
-
- base::FilePath dumps_path(tmp_path);
- if (GetBreakpadClient()->GetCrashDumpLocation(&dumps_path)) {
- base::FilePath logfile =
- dumps_path.Append(GetBreakpadClient()->GetReporterLogFilename());
- std::string logfile_str = logfile.value();
- const size_t crash_log_path_len = logfile_str.size() + 1;
- g_crash_log_path = new char[crash_log_path_len];
- strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len);
- }
- DCHECK(!g_breakpad);
- MinidumpDescriptor minidump_descriptor(dumps_path.value());
- minidump_descriptor.set_size_limit(kMaxMinidumpFileSize);
-#if defined(OS_ANDROID)
- unattended = true; // Android never uploads directly.
-#endif
- if (unattended) {
- g_breakpad = new ExceptionHandler(
- minidump_descriptor,
- NULL,
- CrashDoneNoUpload,
- NULL,
- true, // Install handlers.
- -1); // Server file descriptor. -1 for in-process.
- return;
- }
-
-#if !defined(OS_ANDROID)
- // Attended mode
- g_breakpad = new ExceptionHandler(
- minidump_descriptor,
- NULL,
- CrashDoneUpload,
- NULL,
- true, // Install handlers.
- -1); // Server file descriptor. -1 for in-process.
-#endif
-}
-
-#if defined(OS_ANDROID)
-bool CrashDoneInProcessNoUpload(
- const google_breakpad::MinidumpDescriptor& descriptor,
- void* context,
- const bool succeeded) {
- // WARNING: this code runs in a compromised context. It may not call into
- // libc nor allocate memory normally.
- if (!succeeded) {
- static const char msg[] = "Crash dump generation failed.\n";
- WriteLog(msg, sizeof(msg) - 1);
- return false;
- }
-
- // Start constructing the message to send to the browser.
- BreakpadInfo info = {0};
- info.filename = NULL;
- info.fd = descriptor.fd();
- info.process_type = g_process_type;
- info.process_type_length = my_strlen(g_process_type);
- info.distro = NULL;
- info.distro_length = 0;
- info.upload = false;
- info.process_start_time = g_process_start_time;
- info.pid = g_pid;
- info.crash_keys = g_crash_keys;
- HandleCrashDump(info);
- bool finalize_result = FinalizeCrashDoneAndroid();
- base::android::BuildInfo* android_build_info =
- base::android::BuildInfo::GetInstance();
- if (android_build_info->sdk_int() >= 18 &&
- my_strcmp(android_build_info->build_type(), "eng") != 0 &&
- my_strcmp(android_build_info->build_type(), "userdebug") != 0) {
- // On JB MR2 and later, the system crash handler displays a dialog. For
- // renderer crashes, this is a bad user experience and so this is disabled
- // for user builds of Android.
- // TODO(cjhopman): There should be some way to recover the crash stack from
- // non-uploading user clients. See http://crbug.com/273706.
- __android_log_write(ANDROID_LOG_WARN,
- kGoogleBreakpad,
- "Tombstones are disabled on JB MR2+ user builds.");
- __android_log_write(ANDROID_LOG_WARN,
- kGoogleBreakpad,
- "### ### ### ### ### ### ### ### ### ### ### ### ###");
- return true;
- } else {
- return finalize_result;
- }
-}
-
-void EnableNonBrowserCrashDumping(const std::string& process_type,
- int minidump_fd) {
- // This will guarantee that the BuildInfo has been initialized and subsequent
- // calls will not require memory allocation.
- base::android::BuildInfo::GetInstance();
- SetClientIdFromCommandLine(*CommandLine::ForCurrentProcess());
-
- // On Android, the current sandboxing uses process isolation, in which the
- // child process runs with a different UID. That breaks the normal crash
- // reporting where the browser process generates the minidump by inspecting
- // the child process. This is because the browser process now does not have
- // the permission to access the states of the child process (as it has a
- // different UID).
- // TODO(jcivelli): http://b/issue?id=6776356 we should use a watchdog
- // process forked from the renderer process that generates the minidump.
- if (minidump_fd == -1) {
- LOG(ERROR) << "Minidump file descriptor not found, crash reporting will "
- " not work.";
- return;
- }
- SetProcessStartTime();
- g_pid = getpid();
-
- g_is_crash_reporter_enabled = true;
- // Save the process type (it is leaked).
- const size_t process_type_len = process_type.size() + 1;
- g_process_type = new char[process_type_len];
- strncpy(g_process_type, process_type.c_str(), process_type_len);
- new google_breakpad::ExceptionHandler(MinidumpDescriptor(minidump_fd),
- NULL, CrashDoneInProcessNoUpload, NULL, true, -1);
-}
-#else
-// Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer
-class NonBrowserCrashHandler : public google_breakpad::CrashGenerationClient {
- public:
- NonBrowserCrashHandler()
- : server_fd_(base::GlobalDescriptors::GetInstance()->Get(
- kCrashDumpSignal)) {
- }
-
- virtual ~NonBrowserCrashHandler() {}
-
- virtual bool RequestDump(const void* crash_context,
- size_t crash_context_size) OVERRIDE {
- int fds[2] = { -1, -1 };
- if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
- static const char msg[] = "Failed to create socket for crash dumping.\n";
- WriteLog(msg, sizeof(msg) - 1);
- return false;
- }
-
- // Start constructing the message to send to the browser.
- char b; // Dummy variable for sys_read below.
- const char* b_addr = &b; // Get the address of |b| so we can create the
- // expected /proc/[pid]/syscall content in the
- // browser to convert namespace tids.
-
- // The length of the control message:
- static const unsigned kControlMsgSize = sizeof(int);
- static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize);
- static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize);
-
- struct kernel_msghdr msg;
- my_memset(&msg, 0, sizeof(struct kernel_msghdr));
- struct kernel_iovec iov[kCrashIovSize];
- iov[0].iov_base = const_cast<void*>(crash_context);
- iov[0].iov_len = crash_context_size;
- iov[1].iov_base = &b_addr;
- iov[1].iov_len = sizeof(b_addr);
- iov[2].iov_base = &fds[0];
- iov[2].iov_len = sizeof(fds[0]);
- iov[3].iov_base = &g_process_start_time;
- iov[3].iov_len = sizeof(g_process_start_time);
- iov[4].iov_base = &base::g_oom_size;
- iov[4].iov_len = sizeof(base::g_oom_size);
- google_breakpad::SerializedNonAllocatingMap* serialized_map;
- iov[5].iov_len = g_crash_keys->Serialize(
- const_cast<const google_breakpad::SerializedNonAllocatingMap**>(
- &serialized_map));
- iov[5].iov_base = serialized_map;
-#if !defined(ADDRESS_SANITIZER)
- COMPILE_ASSERT(5 == kCrashIovSize - 1, Incorrect_Number_Of_Iovec_Members);
-#else
- iov[6].iov_base = const_cast<char*>(g_asan_report_str);
- iov[6].iov_len = kMaxAsanReportSize + 1;
- COMPILE_ASSERT(6 == kCrashIovSize - 1, Incorrect_Number_Of_Iovec_Members);
-#endif
-
- msg.msg_iov = iov;
- msg.msg_iovlen = kCrashIovSize;
- char cmsg[kControlMsgSpaceSize];
- my_memset(cmsg, 0, kControlMsgSpaceSize);
- msg.msg_control = cmsg;
- msg.msg_controllen = sizeof(cmsg);
-
- struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
- hdr->cmsg_level = SOL_SOCKET;
- hdr->cmsg_type = SCM_RIGHTS;
- hdr->cmsg_len = kControlMsgLenSize;
- ((int*)CMSG_DATA(hdr))[0] = fds[1];
-
- if (HANDLE_EINTR(sys_sendmsg(server_fd_, &msg, 0)) < 0) {
- static const char errmsg[] = "Failed to tell parent about crash.\n";
- WriteLog(errmsg, sizeof(errmsg) - 1);
- IGNORE_RET(sys_close(fds[0]));
- IGNORE_RET(sys_close(fds[1]));
- return false;
- }
- IGNORE_RET(sys_close(fds[1]));
-
- if (HANDLE_EINTR(sys_read(fds[0], &b, 1)) != 1) {
- static const char errmsg[] = "Parent failed to complete crash dump.\n";
- WriteLog(errmsg, sizeof(errmsg) - 1);
- }
- IGNORE_RET(sys_close(fds[0]));
-
- return true;
- }
-
- private:
- // The pipe FD to the browser process, which will handle the crash dumping.
- const int server_fd_;
-
- DISALLOW_COPY_AND_ASSIGN(NonBrowserCrashHandler);
-};
-
-void EnableNonBrowserCrashDumping() {
- g_is_crash_reporter_enabled = true;
- // We deliberately leak this object.
- DCHECK(!g_breakpad);
-
- g_breakpad = new ExceptionHandler(
- MinidumpDescriptor("/tmp"), // Unused but needed or Breakpad will assert.
- NULL,
- NULL,
- NULL,
- true,
- -1);
- g_breakpad->set_crash_generation_client(new NonBrowserCrashHandler());
-}
-#endif // defined(OS_ANDROID)
-
-void SetCrashKeyValue(const base::StringPiece& key,
- const base::StringPiece& value) {
- g_crash_keys->SetKeyValue(key.data(), value.data());
-}
-
-void ClearCrashKey(const base::StringPiece& key) {
- g_crash_keys->RemoveKey(key.data());
-}
-
-// GetBreakpadClient() cannot call any Set methods until after InitCrashKeys().
-void InitCrashKeys() {
- g_crash_keys = new CrashKeyStorage;
- GetBreakpadClient()->RegisterCrashKeys();
- base::debug::SetCrashKeyReportingFunctions(&SetCrashKeyValue, &ClearCrashKey);
-}
-
-// Miscellaneous initialization functions to call after Breakpad has been
-// enabled.
-void PostEnableBreakpadInitialization() {
- SetProcessStartTime();
- g_pid = getpid();
-
- base::debug::SetDumpWithoutCrashingFunction(&DumpProcess);
-#if defined(ADDRESS_SANITIZER)
- // Register the callback for AddressSanitizer error reporting.
- __asan_set_error_report_callback(AsanLinuxBreakpadCallback);
-#endif
-}
-
-} // namespace
-
-void LoadDataFromFD(google_breakpad::PageAllocator& allocator,
- int fd, bool close_fd, uint8_t** file_data, size_t* size) {
- STAT_STRUCT st;
- if (FSTAT_FUNC(fd, &st) != 0) {
- static const char msg[] = "Cannot upload crash dump: stat failed\n";
- WriteLog(msg, sizeof(msg) - 1);
- if (close_fd)
- IGNORE_RET(sys_close(fd));
- return;
- }
-
- *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) - 1);
- if (close_fd)
- IGNORE_RET(sys_close(fd));
- return;
- }
- my_memset(*file_data, 0xf, st.st_size);
-
- *size = st.st_size;
- int byte_read = sys_read(fd, *file_data, *size);
- if (byte_read == -1) {
- static const char msg[] = "Cannot upload crash dump: read failed\n";
- WriteLog(msg, sizeof(msg) - 1);
- if (close_fd)
- IGNORE_RET(sys_close(fd));
- return;
- }
-
- if (close_fd)
- IGNORE_RET(sys_close(fd));
-}
-
-void LoadDataFromFile(google_breakpad::PageAllocator& allocator,
- const char* filename,
- int* fd, uint8_t** file_data, size_t* size) {
- // 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;
-
- if (*fd < 0) {
- static const char msg[] = "Cannot upload crash dump: failed to open\n";
- WriteLog(msg, sizeof(msg) - 1);
- return;
- }
-
- LoadDataFromFD(allocator, *fd, true, file_data, size);
-}
-
-// Spawn the appropriate upload process for the current OS:
-// - generic Linux invokes wget.
-// - ChromeOS invokes crash_reporter.
-// |dumpfile| is the path to the dump data file.
-// |mime_boundary| is only used on Linux.
-// |exe_buf| is only used on CrOS and is the crashing process' name.
-void ExecUploadProcessOrTerminate(const BreakpadInfo& info,
- const char* dumpfile,
- const char* mime_boundary,
- const char* exe_buf,
- google_breakpad::PageAllocator* allocator) {
-#if defined(OS_CHROMEOS)
- // CrOS uses crash_reporter instead of wget to report crashes,
- // it needs to know where the crash dump lives and the pid and uid of the
- // crashing process.
- static const char kCrashReporterBinary[] = "/sbin/crash_reporter";
-
- char pid_buf[kUint64StringSize];
- uint64_t pid_str_length = my_uint64_len(info.pid);
- my_uint64tos(pid_buf, info.pid, pid_str_length);
- pid_buf[pid_str_length] = '\0';
-
- char uid_buf[kUint64StringSize];
- uid_t uid = geteuid();
- uint64_t uid_str_length = my_uint64_len(uid);
- my_uint64tos(uid_buf, uid, uid_str_length);
- uid_buf[uid_str_length] = '\0';
- const char* args[] = {
- kCrashReporterBinary,
- "--chrome",
- dumpfile,
- "--pid",
- pid_buf,
- "--uid",
- uid_buf,
- "--exe",
- exe_buf,
- NULL,
- };
- static const char msg[] = "Cannot upload crash dump: cannot exec "
- "/sbin/crash_reporter\n";
-#else
- // The --header argument to wget looks like:
- // --header=Content-Type: multipart/form-data; boundary=XYZ
- // where the boundary has two fewer leading '-' chars
- static const char header_msg[] =
- "--header=Content-Type: multipart/form-data; boundary=";
- char* const header = reinterpret_cast<char*>(allocator->Alloc(
- sizeof(header_msg) - 1 + strlen(mime_boundary) - 2 + 1));
- memcpy(header, header_msg, sizeof(header_msg) - 1);
- memcpy(header + sizeof(header_msg) - 1, mime_boundary + 2,
- strlen(mime_boundary) - 2);
- // We grab the NUL byte from the end of |mime_boundary|.
-
- // The --post-file argument to wget looks like:
- // --post-file=/tmp/...
- static const char post_file_msg[] = "--post-file=";
- char* const post_file = reinterpret_cast<char*>(allocator->Alloc(
- sizeof(post_file_msg) - 1 + strlen(dumpfile) + 1));
- memcpy(post_file, post_file_msg, sizeof(post_file_msg) - 1);
- memcpy(post_file + sizeof(post_file_msg) - 1, dumpfile, strlen(dumpfile));
-
- static const char kWgetBinary[] = "/usr/bin/wget";
- const char* args[] = {
- kWgetBinary,
- header,
- post_file,
- kUploadURL,
- "--timeout=10", // Set a timeout so we don't hang forever.
- "--tries=1", // Don't retry if the upload fails.
- "-O", // output reply to fd 3
- "/dev/fd/3",
- NULL,
- };
- static const char msg[] = "Cannot upload crash dump: cannot exec "
- "/usr/bin/wget\n";
-#endif
- execve(args[0], const_cast<char**>(args), environ);
- WriteLog(msg, sizeof(msg) - 1);
- sys__exit(1);
-}
-
-// Runs in the helper process to wait for the upload process running
-// ExecUploadProcessOrTerminate() to finish. Returns the number of bytes written
-// to |fd| and save the written contents to |buf|.
-// |buf| needs to be big enough to hold |bytes_to_read| + 1 characters.
-size_t WaitForCrashReportUploadProcess(int fd, size_t bytes_to_read,
- char* buf) {
- size_t bytes_read = 0;
-
- // Upload should finish in about 10 seconds. Add a few more 500 ms
- // internals to account for process startup time.
- for (size_t wait_count = 0; wait_count < 24; ++wait_count) {
- struct kernel_pollfd poll_fd;
- poll_fd.fd = fd;
- poll_fd.events = POLLIN | POLLPRI | POLLERR;
- int ret = sys_poll(&poll_fd, 1, 500);
- if (ret < 0) {
- // Error
- break;
- } else if (ret > 0) {
- // There is data to read.
- ssize_t len = HANDLE_EINTR(
- sys_read(fd, buf + bytes_read, bytes_to_read - bytes_read));
- if (len < 0)
- break;
- bytes_read += len;
- if (bytes_read == bytes_to_read)
- break;
- }
- // |ret| == 0 -> timed out, continue waiting.
- // or |bytes_read| < |bytes_to_read| still, keep reading.
- }
- buf[bytes_to_read] = 0; // Always NUL terminate the buffer.
- return bytes_read;
-}
-
-// |buf| should be |expected_len| + 1 characters in size and NULL terminated.
-bool IsValidCrashReportId(const char* buf, size_t bytes_read,
- size_t expected_len) {
- if (bytes_read != expected_len)
- return false;
-#if defined(OS_CHROMEOS)
- return my_strcmp(buf, "_sys_cr_finished") == 0;
-#else
- for (size_t i = 0; i < bytes_read; ++i) {
- if (!my_isxdigit(buf[i]))
- return false;
- }
- return true;
-#endif
-}
-
-// |buf| should be |expected_len| + 1 characters in size and NULL terminated.
-void HandleCrashReportId(const char* buf, size_t bytes_read,
- size_t expected_len) {
- WriteNewline();
- if (!IsValidCrashReportId(buf, bytes_read, expected_len)) {
-#if defined(OS_CHROMEOS)
- static const char msg[] = "Crash_reporter failed to process crash report";
-#else
- static const char msg[] = "Failed to get crash dump id.";
-#endif
- WriteLog(msg, sizeof(msg) - 1);
- WriteNewline();
- return;
- }
-
-#if defined(OS_CHROMEOS)
- static const char msg[] = "Crash dump received by crash_reporter\n";
- WriteLog(msg, sizeof(msg) - 1);
-#else
- // Write crash dump id to stderr.
- static const char msg[] = "Crash dump id: ";
- WriteLog(msg, sizeof(msg) - 1);
- WriteLog(buf, my_strlen(buf));
- WriteNewline();
-
- // Write crash dump id to crash log as: seconds_since_epoch,crash_id
- struct kernel_timeval tv;
- if (g_crash_log_path && !sys_gettimeofday(&tv, NULL)) {
- uint64_t time = kernel_timeval_to_ms(&tv) / 1000;
- char time_str[kUint64StringSize];
- const unsigned time_len = my_uint64_len(time);
- my_uint64tos(time_str, time, time_len);
-
- const int kLogOpenFlags = O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC;
- int log_fd = sys_open(g_crash_log_path, kLogOpenFlags, 0600);
- if (log_fd > 0) {
- sys_write(log_fd, time_str, time_len);
- sys_write(log_fd, ",", 1);
- sys_write(log_fd, buf, my_strlen(buf));
- sys_write(log_fd, "\n", 1);
- IGNORE_RET(sys_close(log_fd));
- }
- }
-#endif
-}
-
-#if defined(OS_CHROMEOS)
-const char* GetCrashingProcessName(const BreakpadInfo& info,
- google_breakpad::PageAllocator* allocator) {
- // Symlink to process binary is at /proc/###/exe.
- char linkpath[kUint64StringSize + sizeof("/proc/") + sizeof("/exe")] =
- "/proc/";
- uint64_t pid_value_len = my_uint64_len(info.pid);
- my_uint64tos(linkpath + sizeof("/proc/") - 1, info.pid, pid_value_len);
- linkpath[sizeof("/proc/") - 1 + pid_value_len] = '\0';
- my_strlcat(linkpath, "/exe", sizeof(linkpath));
-
- const int kMaxSize = 4096;
- char* link = reinterpret_cast<char*>(allocator->Alloc(kMaxSize));
- if (link) {
- ssize_t size = readlink(linkpath, link, kMaxSize);
- if (size < kMaxSize && size > 0) {
- // readlink(2) doesn't add a terminating NUL, so do it now.
- link[size] = '\0';
-
- const char* name = my_strrchr(link, '/');
- if (name)
- return name + 1;
- return link;
- }
- }
- // Either way too long, or a read error.
- return "chrome-crash-unknown-process";
-}
-#endif
-
-void HandleCrashDump(const BreakpadInfo& info) {
- int dumpfd;
- bool keep_fd = false;
- size_t dump_size;
- uint8_t* dump_data;
- google_breakpad::PageAllocator allocator;
- const char* exe_buf = NULL;
-
-#if defined(OS_CHROMEOS)
- // Grab the crashing process' name now, when it should still be available.
- // If we try to do this later in our grandchild the crashing process has
- // already terminated.
- exe_buf = GetCrashingProcessName(info, &allocator);
-#endif
-
- if (info.fd != -1) {
- // Dump is provided with an open FD.
- keep_fd = true;
- dumpfd = info.fd;
-
- // The FD is pointing to the end of the file.
- // Rewind, we'll read the data next.
- if (lseek(dumpfd, 0, SEEK_SET) == -1) {
- static const char msg[] = "Cannot upload crash dump: failed to "
- "reposition minidump FD\n";
- WriteLog(msg, sizeof(msg) - 1);
- IGNORE_RET(sys_close(dumpfd));
- return;
- }
- LoadDataFromFD(allocator, info.fd, false, &dump_data, &dump_size);
- } else {
- // Dump is provided with a path.
- keep_fd = false;
- LoadDataFromFile(allocator, info.filename, &dumpfd, &dump_data, &dump_size);
- }
-
- // TODO(jcivelli): make log work when using FDs.
-#if defined(ADDRESS_SANITIZER)
- int logfd;
- size_t log_size;
- uint8_t* log_data;
- // Load the AddressSanitizer log into log_data.
- LoadDataFromFile(allocator, info.log_filename, &logfd, &log_data, &log_size);
-#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"
- " is missing\n";
- WriteLog(msg, sizeof(msg) - 1);
- return;
- }
-
- static const char temp_file_template[] =
- "/tmp/chromium-upload-XXXXXXXXXXXXXXXX";
- char temp_file[sizeof(temp_file_template)];
- int temp_file_fd = -1;
- if (keep_fd) {
- temp_file_fd = dumpfd;
- // Rewind the destination, we are going to overwrite it.
- if (lseek(dumpfd, 0, SEEK_SET) == -1) {
- static const char msg[] = "Cannot upload crash dump: failed to "
- "reposition minidump FD (2)\n";
- WriteLog(msg, sizeof(msg) - 1);
- IGNORE_RET(sys_close(dumpfd));
- return;
- }
- } else {
- if (info.upload) {
- memcpy(temp_file, temp_file_template, sizeof(temp_file_template));
-
- for (unsigned i = 0; i < 10; ++i) {
- uint64_t t;
- sys_read(ufd, &t, sizeof(t));
- write_uint64_hex(temp_file + sizeof(temp_file) - (16 + 1), t);
-
- temp_file_fd = sys_open(temp_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
- if (temp_file_fd >= 0)
- break;
- }
-
- if (temp_file_fd < 0) {
- static const char msg[] = "Failed to create temporary file in /tmp: "
- "cannot upload crash dump\n";
- WriteLog(msg, sizeof(msg) - 1);
- IGNORE_RET(sys_close(ufd));
- return;
- }
- } else {
- temp_file_fd = sys_open(info.filename, O_WRONLY, 0600);
- if (temp_file_fd < 0) {
- static const char msg[] = "Failed to save crash dump: failed to open\n";
- WriteLog(msg, sizeof(msg) - 1);
- IGNORE_RET(sys_close(ufd));
- return;
- }
- }
- }
-
- // The MIME boundary is 28 hyphens, followed by a 64-bit nonce and a NUL.
- char mime_boundary[28 + 16 + 1];
- my_memset(mime_boundary, '-', 28);
- uint64_t boundary_rand;
- sys_read(ufd, &boundary_rand, sizeof(boundary_rand));
- write_uint64_hex(mime_boundary + 28, boundary_rand);
- mime_boundary[28 + 16] = 0;
- IGNORE_RET(sys_close(ufd));
-
- // The MIME block looks like this:
- // BOUNDARY \r\n
- // Content-Disposition: form-data; name="prod" \r\n \r\n
- // Chrome_Linux \r\n
- // BOUNDARY \r\n
- // Content-Disposition: form-data; name="ver" \r\n \r\n
- // 1.2.3.4 \r\n
- // BOUNDARY \r\n
- //
- // zero or one:
- // Content-Disposition: form-data; name="ptime" \r\n \r\n
- // abcdef \r\n
- // BOUNDARY \r\n
- //
- // zero or one:
- // Content-Disposition: form-data; name="ptype" \r\n \r\n
- // abcdef \r\n
- // BOUNDARY \r\n
- //
- // zero or one:
- // Content-Disposition: form-data; name="lsb-release" \r\n \r\n
- // abcdef \r\n
- // BOUNDARY \r\n
- //
- // zero or one:
- // Content-Disposition: form-data; name="oom-size" \r\n \r\n
- // 1234567890 \r\n
- // BOUNDARY \r\n
- //
- // zero or more (up to CrashKeyStorage::num_entries = 64):
- // Content-Disposition: form-data; name=crash-key-name \r\n
- // crash-key-value \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)
- CrashReporterWriter writer(temp_file_fd);
-#else
- MimeWriter writer(temp_file_fd, mime_boundary);
-#endif
- {
- // TODO(thestig) Do not use this inside a compromised context.
- std::string product_name;
- std::string version;
-
- GetBreakpadClient()->GetProductNameAndVersion(&product_name, &version);
-
- writer.AddBoundary();
- writer.AddPairString("prod", product_name.c_str());
- writer.AddBoundary();
- writer.AddPairString("ver", version.c_str());
- writer.AddBoundary();
- if (info.pid > 0) {
- char pid_value_buf[kUint64StringSize];
- uint64_t pid_value_len = my_uint64_len(info.pid);
- my_uint64tos(pid_value_buf, info.pid, pid_value_len);
- static const char pid_key_name[] = "pid";
- writer.AddPairData(pid_key_name, sizeof(pid_key_name) - 1,
- pid_value_buf, pid_value_len);
- writer.AddBoundary();
- }
-#if defined(OS_ANDROID)
- // Addtional MIME blocks are added for logging on Android devices.
- static const char android_build_id[] = "android_build_id";
- static const char android_build_fp[] = "android_build_fp";
- static const char device[] = "device";
- static const char model[] = "model";
- static const char brand[] = "brand";
- static const char exception_info[] = "exception_info";
-
- base::android::BuildInfo* android_build_info =
- base::android::BuildInfo::GetInstance();
- writer.AddPairString(
- android_build_id, android_build_info->android_build_id());
- writer.AddBoundary();
- writer.AddPairString(
- android_build_fp, android_build_info->android_build_fp());
- writer.AddBoundary();
- writer.AddPairString(device, android_build_info->device());
- writer.AddBoundary();
- writer.AddPairString(model, android_build_info->model());
- writer.AddBoundary();
- writer.AddPairString(brand, android_build_info->brand());
- writer.AddBoundary();
- if (android_build_info->java_exception_info() != NULL) {
- writer.AddPairString(exception_info,
- android_build_info->java_exception_info());
- writer.AddBoundary();
- }
-#endif
- writer.Flush();
- }
-
- if (info.process_start_time > 0) {
- struct kernel_timeval tv;
- if (!sys_gettimeofday(&tv, NULL)) {
- uint64_t time = kernel_timeval_to_ms(&tv);
- if (time > info.process_start_time) {
- time -= info.process_start_time;
- char time_str[kUint64StringSize];
- 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();
- writer.Flush();
- }
- }
- }
-
- if (info.process_type_length) {
- writer.AddPairString("ptype", info.process_type);
- writer.AddBoundary();
- writer.Flush();
- }
-
- if (info.distro_length) {
- static const char distro_msg[] = "lsb-release";
- writer.AddPairString(distro_msg, info.distro);
- writer.AddBoundary();
- writer.Flush();
- }
-
- if (info.oom_size) {
- char oom_size_str[kUint64StringSize];
- const unsigned oom_size_len = my_uint64_len(info.oom_size);
- my_uint64tos(oom_size_str, info.oom_size, oom_size_len);
- static const char oom_size_msg[] = "oom-size";
- writer.AddPairData(oom_size_msg, sizeof(oom_size_msg) - 1,
- oom_size_str, oom_size_len);
- writer.AddBoundary();
- writer.Flush();
- }
-
- if (info.crash_keys) {
- CrashKeyStorage::Iterator crash_key_iterator(*info.crash_keys);
- const CrashKeyStorage::Entry* entry;
- while ((entry = crash_key_iterator.Next())) {
- writer.AddPairString(entry->key, entry->value);
- writer.AddBoundary();
- writer.Flush();
- }
- }
-
- 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();
-
- IGNORE_RET(sys_close(temp_file_fd));
-
-#if defined(OS_ANDROID)
- if (info.filename) {
- int filename_length = my_strlen(info.filename);
-
- // If this was a file, we need to copy it to the right place and use the
- // right file name so it gets uploaded by the browser.
- const char msg[] = "Output crash dump file:";
- WriteLog(msg, sizeof(msg) - 1);
- WriteLog(info.filename, filename_length - 1);
-
- char pid_buf[kUint64StringSize];
- uint64_t pid_str_length = my_uint64_len(info.pid);
- my_uint64tos(pid_buf, info.pid, pid_str_length);
-
- // -1 because we won't need the null terminator on the original filename.
- unsigned done_filename_len = filename_length - 1 + pid_str_length;
- char* done_filename = reinterpret_cast<char*>(
- allocator.Alloc(done_filename_len));
- // Rename the file such that the pid is the suffix in order signal to other
- // processes that the minidump is complete. The advantage of using the pid
- // as the suffix is that it is trivial to associate the minidump with the
- // crashed process.
- // Finally, note strncpy prevents null terminators from
- // being copied. Pad the rest with 0's.
- my_strncpy(done_filename, info.filename, done_filename_len);
- // Append the suffix a null terminator should be added.
- my_strncat(done_filename, pid_buf, pid_str_length);
- // Rename the minidump file to signal that it is complete.
- if (rename(info.filename, done_filename)) {
- const char failed_msg[] = "Failed to rename:";
- WriteLog(failed_msg, sizeof(failed_msg) - 1);
- WriteLog(info.filename, filename_length - 1);
- const char to_msg[] = "to";
- WriteLog(to_msg, sizeof(to_msg) - 1);
- WriteLog(done_filename, done_filename_len - 1);
- }
- }
-#endif
-
- if (!info.upload)
- return;
-
- const pid_t child = sys_fork();
- if (!child) {
- // Spawned helper process.
- //
- // This code is called both when a browser is crashing (in which case,
- // nothing really matters any more) and when a renderer/plugin crashes, in
- // which case we need to continue.
- //
- // Since we are a multithreaded app, if we were just to fork(), we might
- // grab file descriptors which have just been created in another thread and
- // hold them open for too long.
- //
- // Thus, we have to loop and try and close everything.
- const int fd = sys_open("/proc/self/fd", O_DIRECTORY | O_RDONLY, 0);
- if (fd < 0) {
- for (unsigned i = 3; i < 8192; ++i)
- IGNORE_RET(sys_close(i));
- } else {
- google_breakpad::DirectoryReader reader(fd);
- const char* name;
- while (reader.GetNextEntry(&name)) {
- int i;
- if (my_strtoui(&i, name) && i > 2 && i != fd)
- IGNORE_RET(sys_close(i));
- reader.PopEntry();
- }
-
- IGNORE_RET(sys_close(fd));
- }
-
- IGNORE_RET(sys_setsid());
-
- // Leave one end of a pipe in the upload process and watch for it getting
- // closed by the upload process exiting.
- int fds[2];
- if (sys_pipe(fds) >= 0) {
- const pid_t upload_child = sys_fork();
- if (!upload_child) {
- // Upload process.
- IGNORE_RET(sys_close(fds[0]));
- IGNORE_RET(sys_dup2(fds[1], 3));
- ExecUploadProcessOrTerminate(info, temp_file, mime_boundary, exe_buf,
- &allocator);
- }
-
- // Helper process.
- if (upload_child > 0) {
- IGNORE_RET(sys_close(fds[1]));
-
- const size_t kCrashIdLength = 16;
- char id_buf[kCrashIdLength + 1];
- size_t bytes_read =
- WaitForCrashReportUploadProcess(fds[0], kCrashIdLength, id_buf);
- HandleCrashReportId(id_buf, bytes_read, kCrashIdLength);
-
- if (sys_waitpid(upload_child, NULL, WNOHANG) == 0) {
- // Upload process is still around, kill it.
- sys_kill(upload_child, SIGKILL);
- }
- }
- }
-
- // 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);
- }
-
- // Main browser process.
- if (child <= 0)
- return;
- (void) HANDLE_EINTR(sys_waitpid(child, NULL, 0));
-}
-
-void InitCrashReporter(const std::string& process_type) {
-#if defined(OS_ANDROID)
- // This will guarantee that the BuildInfo has been initialized and subsequent
- // calls will not require memory allocation.
- base::android::BuildInfo::GetInstance();
-#endif
- // Determine the process type and take appropriate action.
- const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
- if (parsed_command_line.HasSwitch(switches::kDisableBreakpad))
- return;
-
- if (process_type.empty()) {
- bool enable_breakpad = GetBreakpadClient()->GetCollectStatsConsent() ||
- GetBreakpadClient()->IsRunningUnattended();
- enable_breakpad &=
- !parsed_command_line.HasSwitch(switches::kDisableBreakpad);
- if (!enable_breakpad) {
- enable_breakpad = parsed_command_line.HasSwitch(
- switches::kEnableCrashReporterForTesting);
- }
- if (!enable_breakpad) {
- VLOG(1) << "Breakpad disabled";
- return;
- }
-
- InitCrashKeys();
- EnableCrashDumping(GetBreakpadClient()->IsRunningUnattended());
- } else if (GetBreakpadClient()->EnableBreakpadForProcess(process_type)) {
-#if defined(OS_ANDROID)
- NOTREACHED() << "Breakpad initialized with InitCrashReporter() instead of "
- "InitNonBrowserCrashReporter in " << process_type << " process.";
- return;
-#else
- // We might be chrooted in a zygote or renderer process so we cannot call
- // GetCollectStatsConsent because that needs access the the user's home
- // dir. Instead, we set a command line flag for these processes.
- // Even though plugins are not chrooted, we share the same code path for
- // simplicity.
- if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter))
- return;
- InitCrashKeys();
- SetClientIdFromCommandLine(parsed_command_line);
- EnableNonBrowserCrashDumping();
- VLOG(1) << "Non Browser crash dumping enabled for: " << process_type;
-#endif // #if defined(OS_ANDROID)
- }
-
- PostEnableBreakpadInitialization();
-}
-
-#if defined(OS_ANDROID)
-void InitNonBrowserCrashReporterForAndroid(const std::string& process_type) {
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kEnableCrashReporter)) {
- // On Android we need to provide a FD to the file where the minidump is
- // generated as the renderer and browser run with different UIDs
- // (preventing the browser from inspecting the renderer process).
- int minidump_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(
- GetBreakpadClient()->GetAndroidMinidumpDescriptor());
- if (minidump_fd < 0) {
- NOTREACHED() << "Could not find minidump FD, crash reporting disabled.";
- } else {
- EnableNonBrowserCrashDumping(process_type, minidump_fd);
- }
- }
-}
-#endif // OS_ANDROID
-
-bool IsCrashReporterEnabled() {
- return g_is_crash_reporter_enabled;
-}
-
-} // namespace breakpad
diff --git a/components/breakpad/app/breakpad_linux.h b/components/breakpad/app/breakpad_linux.h
deleted file mode 100644
index b507c92..0000000
--- a/components/breakpad/app/breakpad_linux.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Public interface for enabling Breakpad on Linux systems.
-
-#ifndef COMPONENTS_BREAKPAD_APP_BREAKPAD_LINUX_H_
-#define COMPONENTS_BREAKPAD_APP_BREAKPAD_LINUX_H_
-
-#include <string>
-
-#include "build/build_config.h"
-
-namespace breakpad {
-
-// Turns on the crash reporter in any process.
-extern void InitCrashReporter(const std::string& process_type);
-
-// Enables the crash reporter in child processes.
-#if defined(OS_ANDROID)
-extern void InitNonBrowserCrashReporterForAndroid(
- const std::string& process_type);
-#endif
-
-// Checks if crash reporting is enabled. Note that this is not the same as
-// being opted into metrics reporting (and crash reporting), which controls
-// whether InitCrashReporter() is called.
-bool IsCrashReporterEnabled();
-
-} // namespace breakpad
-
-#endif // COMPONENTS_BREAKPAD_APP_BREAKPAD_LINUX_H_
diff --git a/components/breakpad/app/breakpad_linux_impl.h b/components/breakpad/app/breakpad_linux_impl.h
deleted file mode 100644
index f662236..0000000
--- a/components/breakpad/app/breakpad_linux_impl.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Internal header file for the Linux breakpad implementation. This file is
-// shared between crash_handler_host_linux.cc and breakpad_linux.cc. It should
-// only be used in files compiled with linux_breakpad=1.
-
-#ifndef COMPONENTS_BREAKPAD_APP_BREAKPAD_LINUX_IMPL_H_
-#define COMPONENTS_BREAKPAD_APP_BREAKPAD_LINUX_IMPL_H_
-
-#include <sys/types.h>
-
-#include "base/basictypes.h"
-#include "breakpad/src/common/simple_string_dictionary.h"
-#include "components/breakpad/app/breakpad_linux.h"
-
-namespace breakpad {
-
-typedef google_breakpad::NonAllocatingMap<256, 256, 64> CrashKeyStorage;
-
-#if defined(ADDRESS_SANITIZER)
-static const size_t kMaxAsanReportSize = 1 << 16;
-#endif
-// Define a preferred limit on minidump sizes, because Crash Server currently
-// throws away any larger than 1.2MB (1.2 * 1024 * 1024). A value of -1 means
-// no limit.
-static const off_t kMaxMinidumpFileSize = 1258291;
-
-// The size of the iovec used to transfer crash data from a child back to the
-// browser.
-#if !defined(ADDRESS_SANITIZER)
-const size_t kCrashIovSize = 6;
-#else
-// Additional field to pass the AddressSanitizer log to the crash handler.
-const size_t kCrashIovSize = 7;
-#endif
-
-// BreakpadInfo describes a crash report.
-// The minidump information can either be contained in a file descriptor (fd) or
-// in a file (whose path is in filename).
-struct BreakpadInfo {
- int fd; // File descriptor to the Breakpad dump data.
- const char* filename; // Path to the Breakpad dump data.
-#if defined(ADDRESS_SANITIZER)
- const char* log_filename; // Path to the ASan log file.
- const char* asan_report_str; // ASan report.
- unsigned asan_report_length; // Length of |asan_report_length|.
-#endif
- const char* process_type; // Process type, e.g. "renderer".
- unsigned process_type_length; // Length of |process_type|.
- const char* distro; // Linux distro string.
- unsigned distro_length; // Length of |distro|.
- bool upload; // Whether to upload or save crash dump.
- uint64_t process_start_time; // Uptime of the crashing process.
- size_t oom_size; // Amount of memory requested if OOM.
- uint64_t pid; // PID where applicable.
- CrashKeyStorage* crash_keys;
-};
-
-extern void HandleCrashDump(const BreakpadInfo& info);
-
-} // namespace breakpad
-
-#endif // COMPONENTS_BREAKPAD_APP_BREAKPAD_LINUX_IMPL_H_
diff --git a/components/breakpad/app/breakpad_mac.h b/components/breakpad/app/breakpad_mac.h
deleted file mode 100644
index 1db6d75..0000000
--- a/components/breakpad/app/breakpad_mac.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_BREAKPAD_APP_BREAKPAD_MAC_H_
-#define COMPONENTS_BREAKPAD_APP_BREAKPAD_MAC_H_
-
-#include <string>
-
-// This header defines the entry points for Breakpad integration.
-
-namespace breakpad {
-
-// Initializes Breakpad.
-void InitCrashReporter(const std::string& process_type);
-
-// Give Breakpad a chance to store information about the current process.
-// Extra information requires a parsed command line, so call this after
-// CommandLine::Init has been called.
-void InitCrashProcessInfo(const std::string& process_type_switch);
-
-// Is Breakpad enabled?
-bool IsCrashReporterEnabled();
-
-} // namespace breakpad
-
-#endif // COMPONENTS_BREAKPAD_APP_BREAKPAD_MAC_H_
diff --git a/components/breakpad/app/breakpad_mac.mm b/components/breakpad/app/breakpad_mac.mm
deleted file mode 100644
index 6cb5504..0000000
--- a/components/breakpad/app/breakpad_mac.mm
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "components/breakpad/app/breakpad_mac.h"
-
-#include <CoreFoundation/CoreFoundation.h>
-#import <Foundation/Foundation.h>
-
-#include "base/auto_reset.h"
-#include "base/base_switches.h"
-#import "base/basictypes.h"
-#include "base/command_line.h"
-#include "base/debug/crash_logging.h"
-#include "base/debug/dump_without_crashing.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#import "base/logging.h"
-#include "base/mac/bundle_locations.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_cftyperef.h"
-#import "base/mac/scoped_nsautorelease_pool.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_restrictions.h"
-#import "breakpad/src/client/mac/Framework/Breakpad.h"
-#include "components/breakpad/app/breakpad_client.h"
-
-namespace breakpad {
-
-namespace {
-
-BreakpadRef gBreakpadRef = NULL;
-
-void SetCrashKeyValue(NSString* key, NSString* value) {
- // Comment repeated from header to prevent confusion:
- // IMPORTANT: On OS X, the key/value pairs are sent to the crash server
- // out of bounds and not recorded on disk in the minidump, this means
- // that if you look at the minidump file locally you won't see them!
- if (gBreakpadRef == NULL) {
- return;
- }
-
- BreakpadAddUploadParameter(gBreakpadRef, key, value);
-}
-
-void ClearCrashKeyValue(NSString* key) {
- if (gBreakpadRef == NULL) {
- return;
- }
-
- BreakpadRemoveUploadParameter(gBreakpadRef, key);
-}
-
-void SetCrashKeyValueImpl(const base::StringPiece& key,
- const base::StringPiece& value) {
- SetCrashKeyValue(base::SysUTF8ToNSString(key.as_string()),
- base::SysUTF8ToNSString(value.as_string()));
-}
-
-void ClearCrashKeyValueImpl(const base::StringPiece& key) {
- ClearCrashKeyValue(base::SysUTF8ToNSString(key.as_string()));
-}
-
-bool FatalMessageHandler(int severity, const char* file, int line,
- size_t message_start, const std::string& str) {
- // Do not handle non-FATAL.
- if (severity != logging::LOG_FATAL)
- return false;
-
- // In case of OOM condition, this code could be reentered when
- // constructing and storing the key. Using a static is not
- // thread-safe, but if multiple threads are in the process of a
- // fatal crash at the same time, this should work.
- static bool guarded = false;
- if (guarded)
- return false;
-
- base::AutoReset<bool> guard(&guarded, true);
-
- // Only log last path component. This matches logging.cc.
- if (file) {
- const char* slash = strrchr(file, '/');
- if (slash)
- file = slash + 1;
- }
-
- NSString* fatal_key = @"LOG_FATAL";
- NSString* fatal_value =
- [NSString stringWithFormat:@"%s:%d: %s",
- file, line, str.c_str() + message_start];
- SetCrashKeyValue(fatal_key, fatal_value);
-
- // Rather than including the code to force the crash here, allow the
- // caller to do it.
- return false;
-}
-
-// BreakpadGenerateAndSendReport() does not report the current
-// thread. This class can be used to spin up a thread to run it.
-class DumpHelper : public base::PlatformThread::Delegate {
- public:
- static void DumpWithoutCrashing() {
- DumpHelper dumper;
- base::PlatformThreadHandle handle;
- if (base::PlatformThread::Create(0, &dumper, &handle)) {
- // The entire point of this is to block so that the correct
- // stack is logged.
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- base::PlatformThread::Join(handle);
- }
- }
-
- private:
- DumpHelper() {}
-
- virtual void ThreadMain() OVERRIDE {
- base::PlatformThread::SetName("CrDumpHelper");
- BreakpadGenerateAndSendReport(gBreakpadRef);
- }
-
- DISALLOW_COPY_AND_ASSIGN(DumpHelper);
-};
-
-void SIGABRTHandler(int signal) {
- // The OSX abort() (link below) masks all signals for the process,
- // and all except SIGABRT for the thread. SIGABRT will be masked
- // when the SIGABRT is sent, which means at this point only SIGKILL
- // and SIGSTOP can be delivered. Unmask others so that the code
- // below crashes as desired.
- //
- // http://www.opensource.apple.com/source/Libc/Libc-825.26/stdlib/FreeBSD/abort.c
- sigset_t mask;
- sigemptyset(&mask);
- sigaddset(&mask, signal);
- pthread_sigmask(SIG_SETMASK, &mask, NULL);
-
- // Most interesting operations are not safe in a signal handler, just crash.
- char* volatile death_ptr = NULL;
- *death_ptr = '!';
-}
-
-} // namespace
-
-bool IsCrashReporterEnabled() {
- return gBreakpadRef != NULL;
-}
-
-// Only called for a branded build of Chrome.app.
-void InitCrashReporter(const std::string& process_type) {
- DCHECK(!gBreakpadRef);
- base::mac::ScopedNSAutoreleasePool autorelease_pool;
-
- // Check whether crash reporting should be enabled. If enterprise
- // configuration management controls crash reporting, it takes precedence.
- // Otherwise, check whether the user has consented to stats and crash
- // reporting. The browser process can make this determination directly.
- // Helper processes may not have access to the disk or to the same data as
- // the browser process, so the browser passes the decision to them on the
- // command line.
- NSBundle* main_bundle = base::mac::FrameworkBundle();
- bool is_browser = !base::mac::IsBackgroundOnlyProcess();
- bool enable_breakpad = false;
- CommandLine* command_line = CommandLine::ForCurrentProcess();
-
- if (is_browser) {
- // Since the configuration management infrastructure is possibly not
- // initialized when this code runs, read the policy preference directly.
- if (!GetBreakpadClient()->ReportingIsEnforcedByPolicy(&enable_breakpad)) {
- // Controlled by the user. The crash reporter may be enabled by
- // preference or through an environment variable, but the kDisableBreakpad
- // switch overrides both.
- enable_breakpad = GetBreakpadClient()->GetCollectStatsConsent() ||
- GetBreakpadClient()->IsRunningUnattended();
- enable_breakpad &= !command_line->HasSwitch(switches::kDisableBreakpad);
- }
- } else {
- // This is a helper process, check the command line switch.
- enable_breakpad = command_line->HasSwitch(switches::kEnableCrashReporter);
- }
-
- if (!enable_breakpad) {
- VLOG_IF(1, is_browser) << "Breakpad disabled";
- return;
- }
-
- // Tell Breakpad where crash_inspector and crash_report_sender are.
- NSString* resource_path = [main_bundle resourcePath];
- NSString *inspector_location =
- [resource_path stringByAppendingPathComponent:@"crash_inspector"];
- NSString *reporter_bundle_location =
- [resource_path stringByAppendingPathComponent:@"crash_report_sender.app"];
- NSString *reporter_location =
- [[NSBundle bundleWithPath:reporter_bundle_location] executablePath];
-
- if (!inspector_location || !reporter_location) {
- VLOG_IF(1, is_browser && base::mac::AmIBundled()) << "Breakpad disabled";
- return;
- }
-
- NSDictionary* info_dictionary = [main_bundle infoDictionary];
- NSMutableDictionary *breakpad_config =
- [[info_dictionary mutableCopy] autorelease];
- [breakpad_config setObject:inspector_location
- forKey:@BREAKPAD_INSPECTOR_LOCATION];
- [breakpad_config setObject:reporter_location
- forKey:@BREAKPAD_REPORTER_EXE_LOCATION];
-
- // In the main application (the browser process), crashes can be passed to
- // the system's Crash Reporter. This allows the system to notify the user
- // when the application crashes, and provide the user with the option to
- // restart it.
- if (is_browser)
- [breakpad_config setObject:@"NO" forKey:@BREAKPAD_SEND_AND_EXIT];
-
- base::FilePath dir_crash_dumps;
- GetBreakpadClient()->GetCrashDumpLocation(&dir_crash_dumps);
- [breakpad_config setObject:base::SysUTF8ToNSString(dir_crash_dumps.value())
- forKey:@BREAKPAD_DUMP_DIRECTORY];
-
- // Initialize Breakpad.
- gBreakpadRef = BreakpadCreate(breakpad_config);
- if (!gBreakpadRef) {
- LOG_IF(ERROR, base::mac::AmIBundled()) << "Breakpad initializaiton failed";
- return;
- }
-
- // Initialize the scoped crash key system.
- base::debug::SetCrashKeyReportingFunctions(&SetCrashKeyValueImpl,
- &ClearCrashKeyValueImpl);
- GetBreakpadClient()->RegisterCrashKeys();
-
- // Set Breakpad metadata values. These values are added to Info.plist during
- // the branded Google Chrome.app build.
- SetCrashKeyValue(@"ver", [info_dictionary objectForKey:@BREAKPAD_VERSION]);
- SetCrashKeyValue(@"prod", [info_dictionary objectForKey:@BREAKPAD_PRODUCT]);
- SetCrashKeyValue(@"plat", @"OS X");
-
- if (!is_browser) {
- // Get the guid from the command line switch.
- std::string client_guid =
- command_line->GetSwitchValueASCII(switches::kEnableCrashReporter);
- GetBreakpadClient()->SetBreakpadClientIdFromGUID(client_guid);
- }
-
- logging::SetLogMessageHandler(&FatalMessageHandler);
- base::debug::SetDumpWithoutCrashingFunction(&DumpHelper::DumpWithoutCrashing);
-
- // abort() sends SIGABRT, which breakpad does not intercept.
- // Register a signal handler to crash in a way breakpad will
- // intercept.
- struct sigaction sigact;
- memset(&sigact, 0, sizeof(sigact));
- sigact.sa_handler = SIGABRTHandler;
- CHECK(0 == sigaction(SIGABRT, &sigact, NULL));
-}
-
-void InitCrashProcessInfo(const std::string& process_type_switch) {
- if (gBreakpadRef == NULL) {
- return;
- }
-
- // Determine the process type.
- NSString* process_type = @"browser";
- if (!process_type_switch.empty()) {
- process_type = base::SysUTF8ToNSString(process_type_switch);
- }
-
- GetBreakpadClient()->InstallAdditionalFilters(gBreakpadRef);
-
- // Store process type in crash dump.
- SetCrashKeyValue(@"ptype", process_type);
-
- NSString* pid_value =
- [NSString stringWithFormat:@"%d", static_cast<unsigned int>(getpid())];
- SetCrashKeyValue(@"pid", pid_value);
-}
-
-} // namespace breakpad
diff --git a/components/breakpad/app/breakpad_mac_stubs.mm b/components/breakpad/app/breakpad_mac_stubs.mm
deleted file mode 100644
index a05e150..0000000
--- a/components/breakpad/app/breakpad_mac_stubs.mm
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "components/breakpad/app/breakpad_mac.h"
-
-#import <Foundation/Foundation.h>
-
-// Stubbed out versions of breakpad integration functions so we can compile
-// without linking in Breakpad.
-
-namespace breakpad {
-
-bool IsCrashReporterEnabled() {
- return false;
-}
-
-void InitCrashProcessInfo(const std::string& process_type_switch) {
-}
-
-void InitCrashReporter(const std::string& process_type) {
-}
-
-} // namespace breakpad
diff --git a/components/breakpad/app/breakpad_win.cc b/components/breakpad/app/breakpad_win.cc
deleted file mode 100644
index 5fdf9c2..0000000
--- a/components/breakpad/app/breakpad_win.cc
+++ /dev/null
@@ -1,609 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/breakpad/app/breakpad_win.h"
-
-#include <windows.h>
-#include <shellapi.h>
-#include <tchar.h>
-#include <userenv.h>
-#include <winnt.h>
-
-#include <algorithm>
-#include <map>
-#include <vector>
-
-#include "base/base_switches.h"
-#include "base/basictypes.h"
-#include "base/command_line.h"
-#include "base/debug/crash_logging.h"
-#include "base/debug/dump_without_crashing.h"
-#include "base/environment.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/lock.h"
-#include "base/win/metro.h"
-#include "base/win/pe_image.h"
-#include "base/win/registry.h"
-#include "base/win/win_util.h"
-#include "breakpad/src/client/windows/handler/exception_handler.h"
-#include "components/breakpad/app/breakpad_client.h"
-#include "components/breakpad/app/crash_keys_win.h"
-#include "components/breakpad/app/hard_error_handler_win.h"
-#include "content/public/common/result_codes.h"
-#include "sandbox/win/src/nt_internals.h"
-#include "sandbox/win/src/sidestep/preamble_patcher.h"
-
-// userenv.dll is required for GetProfileType().
-#pragma comment(lib, "userenv.lib")
-
-#pragma intrinsic(_AddressOfReturnAddress)
-#pragma intrinsic(_ReturnAddress)
-
-namespace breakpad {
-
-namespace {
-
-// Minidump with stacks, PEB, TEB, and unloaded module list.
-const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
- MiniDumpWithProcessThreadData | // Get PEB and TEB.
- MiniDumpWithUnloadedModules); // Get unloaded modules when available.
-
-// Minidump with all of the above, plus memory referenced from stack.
-const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
- MiniDumpWithProcessThreadData | // Get PEB and TEB.
- MiniDumpWithUnloadedModules | // Get unloaded modules when available.
- MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack.
-
-// Large dump with all process memory.
-const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
- MiniDumpWithFullMemory | // Full memory from process.
- MiniDumpWithProcessThreadData | // Get PEB and TEB.
- MiniDumpWithHandleData | // Get all handle information.
- MiniDumpWithUnloadedModules); // Get unloaded modules when available.
-
-const char kPipeNameVar[] = "CHROME_BREAKPAD_PIPE_NAME";
-
-const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\";
-const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
-
-// This is the well known SID for the system principal.
-const wchar_t kSystemPrincipalSid[] =L"S-1-5-18";
-
-google_breakpad::ExceptionHandler* g_breakpad = NULL;
-google_breakpad::ExceptionHandler* g_dumphandler_no_crash = NULL;
-
-EXCEPTION_POINTERS g_surrogate_exception_pointers = {0};
-EXCEPTION_RECORD g_surrogate_exception_record = {0};
-CONTEXT g_surrogate_context = {0};
-
-typedef NTSTATUS (WINAPI* NtTerminateProcessPtr)(HANDLE ProcessHandle,
- NTSTATUS ExitStatus);
-char* g_real_terminate_process_stub = NULL;
-
-} // namespace
-
-// Dumps the current process memory.
-extern "C" void __declspec(dllexport) __cdecl DumpProcess() {
- if (g_breakpad) {
- g_breakpad->WriteMinidump();
- }
-}
-
-// Used for dumping a process state when there is no crash.
-extern "C" void __declspec(dllexport) __cdecl DumpProcessWithoutCrash() {
- if (g_dumphandler_no_crash) {
- g_dumphandler_no_crash->WriteMinidump();
- }
-}
-
-namespace {
-
-// We need to prevent ICF from folding DumpForHangDebuggingThread() and
-// DumpProcessWithoutCrashThread() together, since that makes them
-// indistinguishable in crash dumps. We do this by making the function
-// bodies unique, and prevent optimization from shuffling things around.
-MSVC_DISABLE_OPTIMIZE()
-MSVC_PUSH_DISABLE_WARNING(4748)
-
-DWORD WINAPI DumpProcessWithoutCrashThread(void*) {
- DumpProcessWithoutCrash();
- return 0;
-}
-
-// The following two functions do exactly the same thing as the two above. But
-// we want the signatures to be different so that we can easily track them in
-// crash reports.
-// TODO(yzshen): Remove when enough information is collected and the hang rate
-// of pepper/renderer processes is reduced.
-DWORD WINAPI DumpForHangDebuggingThread(void*) {
- DumpProcessWithoutCrash();
- VLOG(1) << "dumped for hang debugging";
- return 0;
-}
-
-MSVC_POP_WARNING()
-MSVC_ENABLE_OPTIMIZE()
-
-} // namespace
-
-// Injects a thread into a remote process to dump state when there is no crash.
-extern "C" HANDLE __declspec(dllexport) __cdecl
-InjectDumpProcessWithoutCrash(HANDLE process) {
- return CreateRemoteThread(process, NULL, 0, DumpProcessWithoutCrashThread,
- 0, 0, NULL);
-}
-
-extern "C" HANDLE __declspec(dllexport) __cdecl
-InjectDumpForHangDebugging(HANDLE process) {
- return CreateRemoteThread(process, NULL, 0, DumpForHangDebuggingThread,
- 0, 0, NULL);
-}
-
-// Returns a string containing a list of all modifiers for the loaded profile.
-std::wstring GetProfileType() {
- std::wstring profile_type;
- DWORD profile_bits = 0;
- if (::GetProfileType(&profile_bits)) {
- static const struct {
- DWORD bit;
- const wchar_t* name;
- } kBitNames[] = {
- { PT_MANDATORY, L"mandatory" },
- { PT_ROAMING, L"roaming" },
- { PT_TEMPORARY, L"temporary" },
- };
- for (size_t i = 0; i < arraysize(kBitNames); ++i) {
- const DWORD this_bit = kBitNames[i].bit;
- if ((profile_bits & this_bit) != 0) {
- profile_type.append(kBitNames[i].name);
- profile_bits &= ~this_bit;
- if (profile_bits != 0)
- profile_type.append(L", ");
- }
- }
- } else {
- DWORD last_error = ::GetLastError();
- base::SStringPrintf(&profile_type, L"error %u", last_error);
- }
- return profile_type;
-}
-
-namespace {
-
-// This callback is used when we want to get a dump without crashing the
-// process.
-bool DumpDoneCallbackWhenNoCrash(const wchar_t*, const wchar_t*, void*,
- EXCEPTION_POINTERS* ex_info,
- MDRawAssertionInfo*, bool) {
- return true;
-}
-
-// This callback is executed when the browser process has crashed, after
-// the crash dump has been created. We need to minimize the amount of work
-// done here since we have potentially corrupted process. Our job is to
-// spawn another instance of chrome which will show a 'chrome has crashed'
-// dialog. This code needs to live in the exe and thus has no access to
-// facilities such as the i18n helpers.
-bool DumpDoneCallback(const wchar_t*, const wchar_t*, void*,
- EXCEPTION_POINTERS* ex_info,
- MDRawAssertionInfo*, bool) {
- // Check if the exception is one of the kind which would not be solved
- // by simply restarting chrome. In this case we show a message box with
- // and exit silently. Remember that chrome is in a crashed state so we
- // can't show our own UI from this process.
- if (HardErrorHandler(ex_info))
- return true;
-
- if (!GetBreakpadClient()->AboutToRestart())
- return true;
-
- // Now we just start chrome browser with the same command line.
- STARTUPINFOW si = {sizeof(si)};
- PROCESS_INFORMATION pi;
- if (::CreateProcessW(NULL, ::GetCommandLineW(), NULL, NULL, FALSE,
- CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &si, &pi)) {
- ::CloseHandle(pi.hProcess);
- ::CloseHandle(pi.hThread);
- }
- // After this return we will be terminated. The actual return value is
- // not used at all.
- return true;
-}
-
-// flag to indicate that we are already handling an exception.
-volatile LONG handling_exception = 0;
-
-// This callback is used when there is no crash. Note: Unlike the
-// |FilterCallback| below this does not do dupe detection. It is upto the caller
-// to implement it.
-bool FilterCallbackWhenNoCrash(
- void*, EXCEPTION_POINTERS*, MDRawAssertionInfo*) {
- GetBreakpadClient()->RecordCrashDumpAttempt(false);
- return true;
-}
-
-// This callback is executed when the Chrome process has crashed and *before*
-// the crash dump is created. To prevent duplicate crash reports we
-// make every thread calling this method, except the very first one,
-// go to sleep.
-bool FilterCallback(void*, EXCEPTION_POINTERS*, MDRawAssertionInfo*) {
- // Capture every thread except the first one in the sleep. We don't
- // want multiple threads to concurrently report exceptions.
- if (::InterlockedCompareExchange(&handling_exception, 1, 0) == 1) {
- ::Sleep(INFINITE);
- }
- GetBreakpadClient()->RecordCrashDumpAttempt(true);
- return true;
-}
-
-// Previous unhandled filter. Will be called if not null when we
-// intercept a crash.
-LPTOP_LEVEL_EXCEPTION_FILTER previous_filter = NULL;
-
-// Exception filter used when breakpad is not enabled. We just display
-// the "Do you want to restart" message and then we call the previous filter.
-long WINAPI ChromeExceptionFilter(EXCEPTION_POINTERS* info) {
- DumpDoneCallback(NULL, NULL, NULL, info, NULL, false);
-
- if (previous_filter)
- return previous_filter(info);
-
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-// Exception filter for the service process used when breakpad is not enabled.
-// We just display the "Do you want to restart" message and then die
-// (without calling the previous filter).
-long WINAPI ServiceExceptionFilter(EXCEPTION_POINTERS* info) {
- DumpDoneCallback(NULL, NULL, NULL, info, NULL, false);
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-} // namespace
-
-// NOTE: This function is used by SyzyASAN to annotate crash reports. If you
-// change the name or signature of this function you will break SyzyASAN
-// instrumented releases of Chrome. Please contact syzygy-team@chromium.org
-// before doing so!
-extern "C" void __declspec(dllexport) __cdecl SetCrashKeyValueImpl(
- const wchar_t* key, const wchar_t* value) {
- CrashKeysWin* keeper = CrashKeysWin::keeper();
- if (!keeper)
- return;
-
- // TODO(siggi): This doesn't look quite right - there's NULL deref potential
- // here, and an implicit std::wstring conversion. Fixme.
- keeper->SetCrashKeyValue(key, value);
-}
-
-extern "C" void __declspec(dllexport) __cdecl ClearCrashKeyValueImpl(
- const wchar_t* key) {
- CrashKeysWin* keeper = CrashKeysWin::keeper();
- if (!keeper)
- return;
-
- // TODO(siggi): This doesn't look quite right - there's NULL deref potential
- // here, and an implicit std::wstring conversion. Fixme.
- keeper->ClearCrashKeyValue(key);
-}
-
-static bool WrapMessageBoxWithSEH(const wchar_t* text, const wchar_t* caption,
- UINT flags, bool* exit_now) {
- // We wrap the call to MessageBoxW with a SEH handler because it some
- // machines with CursorXP, PeaDict or with FontExplorer installed it crashes
- // uncontrollably here. Being this a best effort deal we better go away.
- __try {
- *exit_now = (IDOK != ::MessageBoxW(NULL, text, caption, flags));
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- // Its not safe to continue executing, exit silently here.
- ::TerminateProcess(::GetCurrentProcess(),
- GetBreakpadClient()->GetResultCodeRespawnFailed());
- }
-
- return true;
-}
-
-// This function is executed by the child process that DumpDoneCallback()
-// spawned and basically just shows the 'chrome has crashed' dialog if
-// the CHROME_CRASHED environment variable is present.
-bool ShowRestartDialogIfCrashed(bool* exit_now) {
- // If we are being launched in metro mode don't try to show the dialog.
- if (base::win::IsMetroProcess())
- return false;
-
- base::string16 message;
- base::string16 title;
- bool is_rtl_locale;
- if (!GetBreakpadClient()->ShouldShowRestartDialog(
- &title, &message, &is_rtl_locale)) {
- return false;
- }
-
- // If the UI layout is right-to-left, we need to pass the appropriate MB_XXX
- // flags so that an RTL message box is displayed.
- UINT flags = MB_OKCANCEL | MB_ICONWARNING;
- if (is_rtl_locale)
- flags |= MB_RIGHT | MB_RTLREADING;
-
- return WrapMessageBoxWithSEH(message.c_str(), title.c_str(), flags, exit_now);
-}
-
-// Crashes the process after generating a dump for the provided exception. Note
-// that the crash reporter should be initialized before calling this function
-// for it to do anything.
-// NOTE: This function is used by SyzyASAN to invoke a crash. If you change the
-// the name or signature of this function you will break SyzyASAN instrumented
-// releases of Chrome. Please contact syzygy-team@chromium.org before doing so!
-extern "C" int __declspec(dllexport) CrashForException(
- EXCEPTION_POINTERS* info) {
- if (g_breakpad) {
- g_breakpad->WriteMinidumpForException(info);
- // Patched stub exists based on conditions (See InitCrashReporter).
- // As a side note this function also gets called from
- // WindowProcExceptionFilter.
- if (g_real_terminate_process_stub == NULL) {
- ::TerminateProcess(::GetCurrentProcess(), content::RESULT_CODE_KILLED);
- } else {
- NtTerminateProcessPtr real_terminate_proc =
- reinterpret_cast<NtTerminateProcessPtr>(
- static_cast<char*>(g_real_terminate_process_stub));
- real_terminate_proc(::GetCurrentProcess(), content::RESULT_CODE_KILLED);
- }
- }
- return EXCEPTION_CONTINUE_SEARCH;
-}
-
-static NTSTATUS WINAPI HookNtTerminateProcess(HANDLE ProcessHandle,
- NTSTATUS ExitStatus) {
- if (g_breakpad &&
- (ProcessHandle == ::GetCurrentProcess() || ProcessHandle == NULL)) {
- NT_TIB* tib = reinterpret_cast<NT_TIB*>(NtCurrentTeb());
- void* address_on_stack = _AddressOfReturnAddress();
- if (address_on_stack < tib->StackLimit ||
- address_on_stack > tib->StackBase) {
- g_surrogate_exception_record.ExceptionAddress = _ReturnAddress();
- g_surrogate_exception_record.ExceptionCode = DBG_TERMINATE_PROCESS;
- g_surrogate_exception_record.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
- CrashForException(&g_surrogate_exception_pointers);
- }
- }
-
- NtTerminateProcessPtr real_proc =
- reinterpret_cast<NtTerminateProcessPtr>(
- static_cast<char*>(g_real_terminate_process_stub));
- return real_proc(ProcessHandle, ExitStatus);
-}
-
-static void InitTerminateProcessHooks() {
- NtTerminateProcessPtr terminate_process_func_address =
- reinterpret_cast<NtTerminateProcessPtr>(::GetProcAddress(
- ::GetModuleHandle(L"ntdll.dll"), "NtTerminateProcess"));
- if (terminate_process_func_address == NULL)
- return;
-
- DWORD old_protect = 0;
- if (!::VirtualProtect(terminate_process_func_address, 5,
- PAGE_EXECUTE_READWRITE, &old_protect))
- return;
-
- g_real_terminate_process_stub = reinterpret_cast<char*>(VirtualAllocEx(
- ::GetCurrentProcess(), NULL, sidestep::kMaxPreambleStubSize,
- MEM_COMMIT, PAGE_EXECUTE_READWRITE));
- if (g_real_terminate_process_stub == NULL)
- return;
-
- g_surrogate_exception_pointers.ContextRecord = &g_surrogate_context;
- g_surrogate_exception_pointers.ExceptionRecord =
- &g_surrogate_exception_record;
-
- sidestep::SideStepError patch_result =
- sidestep::PreamblePatcher::Patch(
- terminate_process_func_address, HookNtTerminateProcess,
- g_real_terminate_process_stub, sidestep::kMaxPreambleStubSize);
- if (patch_result != sidestep::SIDESTEP_SUCCESS) {
- CHECK(::VirtualFreeEx(::GetCurrentProcess(), g_real_terminate_process_stub,
- 0, MEM_RELEASE));
- CHECK(::VirtualProtect(terminate_process_func_address, 5, old_protect,
- &old_protect));
- return;
- }
-
- DWORD dummy = 0;
- CHECK(::VirtualProtect(terminate_process_func_address,
- 5,
- old_protect,
- &dummy));
- CHECK(::VirtualProtect(g_real_terminate_process_stub,
- sidestep::kMaxPreambleStubSize,
- old_protect,
- &old_protect));
-}
-
-static void InitPipeNameEnvVar(bool is_per_user_install) {
- scoped_ptr<base::Environment> env(base::Environment::Create());
- if (env->HasVar(kPipeNameVar)) {
- // The Breakpad pipe name is already configured: nothing to do.
- return;
- }
-
- // Check whether configuration management controls crash reporting.
- bool crash_reporting_enabled = true;
- bool controlled_by_policy = GetBreakpadClient()->ReportingIsEnforcedByPolicy(
- &crash_reporting_enabled);
-
- const CommandLine& command = *CommandLine::ForCurrentProcess();
- bool use_crash_service =
- !controlled_by_policy && (command.HasSwitch(switches::kNoErrorDialogs) ||
- GetBreakpadClient()->IsRunningUnattended());
-
- std::wstring pipe_name;
- if (use_crash_service) {
- // Crash reporting is done by crash_service.exe.
- pipe_name = kChromePipeName;
- } else {
- // We want to use the Google Update crash reporting. We need to check if the
- // user allows it first (in case the administrator didn't already decide
- // via policy).
- if (!controlled_by_policy)
- crash_reporting_enabled = GetBreakpadClient()->GetCollectStatsConsent();
-
- if (!crash_reporting_enabled) {
- // Crash reporting is disabled, don't set the environment variable.
- return;
- }
-
- // Build the pipe name. It can be either:
- // System-wide install: "NamedPipe\GoogleCrashServices\S-1-5-18"
- // Per-user install: "NamedPipe\GoogleCrashServices\<user SID>"
- std::wstring user_sid;
- if (is_per_user_install) {
- if (!base::win::GetUserSidString(&user_sid)) {
- return;
- }
- } else {
- user_sid = kSystemPrincipalSid;
- }
-
- pipe_name = kGoogleUpdatePipeName;
- pipe_name += user_sid;
- }
- env->SetVar(kPipeNameVar, base::UTF16ToASCII(pipe_name));
-}
-
-void InitDefaultCrashCallback(LPTOP_LEVEL_EXCEPTION_FILTER filter) {
- previous_filter = SetUnhandledExceptionFilter(filter);
-}
-
-void InitCrashReporter(const std::string& process_type_switch) {
- const CommandLine& command = *CommandLine::ForCurrentProcess();
- if (command.HasSwitch(switches::kDisableBreakpad))
- return;
-
- // Disable the message box for assertions.
- _CrtSetReportMode(_CRT_ASSERT, 0);
-
- std::wstring process_type = base::ASCIIToWide(process_type_switch);
- if (process_type.empty())
- process_type = L"browser";
-
- wchar_t exe_path[MAX_PATH];
- exe_path[0] = 0;
- GetModuleFileNameW(NULL, exe_path, MAX_PATH);
-
- bool is_per_user_install =
- GetBreakpadClient()->GetIsPerUserInstall(base::FilePath(exe_path));
-
- // This is intentionally leaked.
- CrashKeysWin* keeper = new CrashKeysWin();
-
- google_breakpad::CustomClientInfo* custom_info =
- keeper->GetCustomInfo(exe_path, process_type,
- GetProfileType(), CommandLine::ForCurrentProcess(),
- GetBreakpadClient());
-
- google_breakpad::ExceptionHandler::MinidumpCallback callback = NULL;
- LPTOP_LEVEL_EXCEPTION_FILTER default_filter = NULL;
- // We install the post-dump callback only for the browser and service
- // processes. It spawns a new browser/service process.
- if (process_type == L"browser") {
- callback = &DumpDoneCallback;
- default_filter = &ChromeExceptionFilter;
- } else if (process_type == L"service") {
- callback = &DumpDoneCallback;
- default_filter = &ServiceExceptionFilter;
- }
-
- if (process_type == L"browser") {
- InitPipeNameEnvVar(is_per_user_install);
- GetBreakpadClient()->InitBrowserCrashDumpsRegKey();
- }
-
- scoped_ptr<base::Environment> env(base::Environment::Create());
- std::string pipe_name_ascii;
- if (!env->GetVar(kPipeNameVar, &pipe_name_ascii)) {
- // Breakpad is not enabled. Configuration is managed or the user
- // did not allow Google Update to send crashes. We need to use
- // our default crash handler instead, but only for the
- // browser/service processes.
- if (default_filter)
- InitDefaultCrashCallback(default_filter);
- return;
- }
- std::wstring pipe_name = base::ASCIIToWide(pipe_name_ascii);
-
-#ifdef _WIN64
- // The protocol for connecting to the out-of-process Breakpad crash
- // reporter is different for x86-32 and x86-64: the message sizes
- // are different because the message struct contains a pointer. As
- // a result, there are two different named pipes to connect to. The
- // 64-bit one is distinguished with an "-x64" suffix.
- pipe_name += L"-x64";
-#endif
-
- // Get the alternate dump directory. We use the temp path.
- wchar_t temp_dir[MAX_PATH] = {0};
- ::GetTempPathW(MAX_PATH, temp_dir);
-
- MINIDUMP_TYPE dump_type = kSmallDumpType;
- // Capture full memory if explicitly instructed to.
- if (command.HasSwitch(switches::kFullMemoryCrashReport))
- dump_type = kFullDumpType;
- else if (GetBreakpadClient()->GetShouldDumpLargerDumps(is_per_user_install))
- dump_type = kLargerDumpType;
-
- g_breakpad = new google_breakpad::ExceptionHandler(temp_dir, &FilterCallback,
- callback, NULL,
- google_breakpad::ExceptionHandler::HANDLER_ALL,
- dump_type, pipe_name.c_str(), custom_info);
-
- // Now initialize the non crash dump handler.
- g_dumphandler_no_crash = new google_breakpad::ExceptionHandler(temp_dir,
- &FilterCallbackWhenNoCrash,
- &DumpDoneCallbackWhenNoCrash,
- NULL,
- // Set the handler to none so this handler would not be added to
- // |handler_stack_| in |ExceptionHandler| which is a list of exception
- // handlers.
- google_breakpad::ExceptionHandler::HANDLER_NONE,
- dump_type, pipe_name.c_str(), custom_info);
-
- // Set the DumpWithoutCrashingFunction for this instance of base.lib. Other
- // executable images linked with base should set this again for
- // DumpWithoutCrashing to function correctly.
- // See chrome_main.cc for example.
- base::debug::SetDumpWithoutCrashingFunction(&DumpProcessWithoutCrash);
-
- if (g_breakpad->IsOutOfProcess()) {
- // Tells breakpad to handle breakpoint and single step exceptions.
- // This might break JIT debuggers, but at least it will always
- // generate a crashdump for these exceptions.
- g_breakpad->set_handle_debug_exceptions(true);
-
-#ifndef _WIN64
- if (process_type != L"browser" &&
- !GetBreakpadClient()->IsRunningUnattended()) {
- // Initialize the hook TerminateProcess to catch unexpected exits.
- InitTerminateProcessHooks();
- }
-#endif
- }
-}
-
-// If the user has disabled crash reporting uploads and restarted Chrome, the
-// restarted instance will still contain the pipe environment variable, which
-// will allow the restarted process to still upload crash reports. This function
-// clears the environment variable, so that the restarted Chrome, which inherits
-// its environment from the current Chrome, will no longer contain the variable.
-extern "C" void __declspec(dllexport) __cdecl
- ClearBreakpadPipeEnvironmentVariable() {
- scoped_ptr<base::Environment> env(base::Environment::Create());
- env->UnSetVar(kPipeNameVar);
-}
-
-} // namespace breakpad
diff --git a/components/breakpad/app/breakpad_win.h b/components/breakpad/app/breakpad_win.h
deleted file mode 100644
index 926192d..0000000
--- a/components/breakpad/app/breakpad_win.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_BREAKPAD_APP_BREAKPAD_WIN_H_
-#define COMPONENTS_BREAKPAD_APP_BREAKPAD_WIN_H_
-
-#include <windows.h>
-#include <string>
-#include <vector>
-
-namespace breakpad {
-
-void InitCrashReporter(const std::string& process_type_switch);
-
-// If chrome has been restarted because it crashed, this function will display
-// a dialog asking for permission to continue execution or to exit now.
-bool ShowRestartDialogIfCrashed(bool* exit_now);
-
-} // namespace breakpad
-
-#endif // COMPONENTS_BREAKPAD_APP_BREAKPAD_WIN_H_
diff --git a/components/breakpad/app/crash_keys_win.cc b/components/breakpad/app/crash_keys_win.cc
deleted file mode 100644
index 68bbd389d..0000000
--- a/components/breakpad/app/crash_keys_win.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/breakpad/app/crash_keys_win.h"
-
-#include <algorithm>
-
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "components/breakpad/app/breakpad_client.h"
-
-
-namespace breakpad {
-
-namespace {
-
-const size_t kMaxPluginPathLength = 256;
-const size_t kMaxDynamicEntries = 256;
-
-} // namespace
-
-CrashKeysWin* CrashKeysWin::keeper_;
-
-CrashKeysWin::CrashKeysWin() : dynamic_keys_offset_(0) {
- DCHECK_EQ(static_cast<CrashKeysWin*>(NULL), keeper_);
- keeper_ = this;
-}
-
-CrashKeysWin::~CrashKeysWin() {
- DCHECK_EQ(this, keeper_);
- keeper_ = NULL;
-}
-
-// Appends the plugin path to |g_custom_entries|.
-void CrashKeysWin::SetPluginPath(const std::wstring& path) {
- if (path.size() > kMaxPluginPathLength) {
- // If the path is too long, truncate from the start rather than the end,
- // since we want to be able to recover the DLL name.
- SetPluginPath(path.substr(path.size() - kMaxPluginPathLength));
- return;
- }
-
- // The chunk size without terminator.
- const size_t kChunkSize = static_cast<size_t>(
- google_breakpad::CustomInfoEntry::kValueMaxLength - 1);
-
- int chunk_index = 0;
- size_t chunk_start = 0; // Current position inside |path|
-
- for (chunk_start = 0; chunk_start < path.size(); chunk_index++) {
- size_t chunk_length = std::min(kChunkSize, path.size() - chunk_start);
-
- custom_entries_.push_back(google_breakpad::CustomInfoEntry(
- base::StringPrintf(L"plugin-path-chunk-%i", chunk_index + 1).c_str(),
- path.substr(chunk_start, chunk_length).c_str()));
-
- chunk_start += chunk_length;
- }
-}
-
-// Appends the breakpad dump path to |g_custom_entries|.
-void CrashKeysWin::SetBreakpadDumpPath(BreakpadClient* breakpad_client) {
-
- base::FilePath crash_dumps_dir_path;
- if (breakpad_client->GetAlternativeCrashDumpLocation(
- &crash_dumps_dir_path)) {
- custom_entries_.push_back(google_breakpad::CustomInfoEntry(
- L"breakpad-dump-location", crash_dumps_dir_path.value().c_str()));
- }
-}
-
-// Returns the custom info structure based on the dll in parameter and the
-// process type.
-google_breakpad::CustomClientInfo*
-CrashKeysWin::GetCustomInfo(const std::wstring& exe_path,
- const std::wstring& type,
- const std::wstring& profile_type,
- base::CommandLine* cmd_line,
- BreakpadClient* breakpad_client) {
- base::string16 version, product;
- base::string16 special_build;
- base::string16 channel_name;
-
- breakpad_client->GetProductNameAndVersion(
- base::FilePath(exe_path),
- &product,
- &version,
- &special_build,
- &channel_name);
-
- // We only expect this method to be called once per process.
- // Common enties
- custom_entries_.push_back(
- google_breakpad::CustomInfoEntry(L"ver",
- base::UTF16ToWide(version).c_str()));
- custom_entries_.push_back(
- google_breakpad::CustomInfoEntry(L"prod",
- base::UTF16ToWide(product).c_str()));
- custom_entries_.push_back(
- google_breakpad::CustomInfoEntry(L"plat", L"Win32"));
- custom_entries_.push_back(
- google_breakpad::CustomInfoEntry(L"ptype", type.c_str()));
- custom_entries_.push_back(google_breakpad::CustomInfoEntry(
- L"pid", base::StringPrintf(L"%d", ::GetCurrentProcessId()).c_str()));
- custom_entries_.push_back(google_breakpad::CustomInfoEntry(
- L"channel", base::UTF16ToWide(channel_name).c_str()));
- custom_entries_.push_back(google_breakpad::CustomInfoEntry(
- L"profile-type", profile_type.c_str()));
-
- if (!special_build.empty())
- custom_entries_.push_back(google_breakpad::CustomInfoEntry(
- L"special", base::UTF16ToWide(special_build).c_str()));
-
- if (type == L"plugin" || type == L"ppapi") {
- std::wstring plugin_path = cmd_line->GetSwitchValueNative("plugin-path");
- if (!plugin_path.empty())
- SetPluginPath(plugin_path);
- }
-
-
- // Check whether configuration management controls crash reporting.
- bool crash_reporting_enabled = true;
- bool controlled_by_policy = breakpad_client->ReportingIsEnforcedByPolicy(
- &crash_reporting_enabled);
- bool use_crash_service = !controlled_by_policy &&
- (cmd_line->HasSwitch(switches::kNoErrorDialogs) ||
- breakpad_client->IsRunningUnattended());
- if (use_crash_service)
- SetBreakpadDumpPath(breakpad_client);
-
- // Create space for dynamic ad-hoc keys. The names and values are set using
- // the API defined in base/debug/crash_logging.h.
- dynamic_keys_offset_ = custom_entries_.size();
- for (size_t i = 0; i < kMaxDynamicEntries; ++i) {
- // The names will be mutated as they are set. Un-numbered since these are
- // merely placeholders. The name cannot be empty because Breakpad's
- // HTTPUpload will interpret that as an invalid parameter.
- custom_entries_.push_back(
- google_breakpad::CustomInfoEntry(L"unspecified-crash-key", L""));
- }
-
- static google_breakpad::CustomClientInfo custom_client_info;
- custom_client_info.entries = &custom_entries_.front();
- custom_client_info.count = custom_entries_.size();
-
- return &custom_client_info;
-}
-
-void CrashKeysWin::SetCrashKeyValue(
- const std::wstring& key, const std::wstring& value) {
- // CustomInfoEntry limits the length of key and value. If they exceed
- // their maximum length the underlying string handling functions raise
- // an exception and prematurely trigger a crash. Truncate here.
- std::wstring safe_key(std::wstring(key).substr(
- 0, google_breakpad::CustomInfoEntry::kNameMaxLength - 1));
- std::wstring safe_value(std::wstring(value).substr(
- 0, google_breakpad::CustomInfoEntry::kValueMaxLength - 1));
-
- // If we already have a value for this key, update it; otherwise, insert
- // the new value if we have not exhausted the pre-allocated slots for dynamic
- // entries.
- base::AutoLock lock(lock_);
-
- DynamicEntriesMap::iterator it = dynamic_entries_.find(safe_key);
- google_breakpad::CustomInfoEntry* entry = NULL;
- if (it == dynamic_entries_.end()) {
- if (dynamic_entries_.size() >= kMaxDynamicEntries)
- return;
- entry = &custom_entries_[dynamic_keys_offset_++];
- dynamic_entries_.insert(std::make_pair(safe_key, entry));
- } else {
- entry = it->second;
- }
-
- entry->set(safe_key.data(), safe_value.data());
-}
-
-void CrashKeysWin::ClearCrashKeyValue(const std::wstring& key) {
- base::AutoLock lock(lock_);
-
- std::wstring key_string(key);
- DynamicEntriesMap::iterator it = dynamic_entries_.find(key_string);
- if (it == dynamic_entries_.end())
- return;
-
- it->second->set_value(NULL);
-}
-
-} // namespace breakpad
diff --git a/components/breakpad/app/crash_keys_win.h b/components/breakpad/app/crash_keys_win.h
deleted file mode 100644
index 135a31c..0000000
--- a/components/breakpad/app/crash_keys_win.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "breakpad/src/client/windows/common/ipc_protocol.h"
-#include "breakpad/src/client/windows/handler/exception_handler.h"
-
-
-namespace base {
-class CommandLine;
-} // namespace base
-
-namespace breakpad {
-
-class BreakpadClient;
-
-// Manages the breakpad key/value pair stash, there may only be one instance
-// of this class per process at one time.
-class CrashKeysWin {
- public:
- CrashKeysWin();
- ~CrashKeysWin();
-
- // May only be called once.
- // |exe_path| is the path to the executable running, which may be used
- // to figure out whether this is a user or system install.
- // |type| is the process type, or mode this process is running in e.g.
- // something like "browser" or "renderer".
- // |profile_type| is a string describing the kind of the user's Windows
- // profile, e.g. "mandatory", or "roaming" or similar.
- // |cmd_line| is the current process' command line consulted for explicit
- // crash reporting flags.
- // |breakpad_client| is consulted for crash reporting settings.
- google_breakpad::CustomClientInfo* GetCustomInfo(
- const std::wstring& exe_path,
- const std::wstring& type,
- const std::wstring& profile_type,
- base::CommandLine* cmd_line,
- BreakpadClient* breakpad_client);
-
- void SetCrashKeyValue(const std::wstring& key, const std::wstring& value);
- void ClearCrashKeyValue(const std::wstring& key);
-
- static CrashKeysWin* keeper() { return keeper_; }
-
- private:
- // One-time initialization of private key/value pairs.
- void SetPluginPath(const std::wstring& path);
- void SetBreakpadDumpPath(BreakpadClient* breakpad_client);
-
- // Must not be resized after GetCustomInfo is invoked.
- std::vector<google_breakpad::CustomInfoEntry> custom_entries_;
-
- typedef std::map<std::wstring, google_breakpad::CustomInfoEntry*>
- DynamicEntriesMap;
- base::Lock lock_;
- // Keeps track of the next index for a new dynamic entry.
- size_t dynamic_keys_offset_; // Under lock_.
- // Maintains key->entry information for dynamic key/value entries
- // in custom_entries_.
- DynamicEntriesMap dynamic_entries_; // Under lock_.
-
- // Stores the sole instance of this class allowed per process.
- static CrashKeysWin* keeper_;
-
- DISALLOW_COPY_AND_ASSIGN(CrashKeysWin);
-};
-
-} // namespace breakpad
diff --git a/components/breakpad/app/crash_keys_win_unittest.cc b/components/breakpad/app/crash_keys_win_unittest.cc
deleted file mode 100644
index 6574e50..0000000
--- a/components/breakpad/app/crash_keys_win_unittest.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/breakpad/app/crash_keys_win.h"
-
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/strings/stringprintf.h"
-#include "components/breakpad/app/breakpad_client.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace breakpad {
-
-using testing::_;
-using testing::DoAll;
-using testing::Return;
-using testing::SetArgPointee;
-
-class MockBreakpadClient : public BreakpadClient {
- public:
- MOCK_METHOD1(GetAlternativeCrashDumpLocation,
- bool(base::FilePath* crash_dir));
- MOCK_METHOD5(GetProductNameAndVersion, void(const base::FilePath& exe_path,
- base::string16* product_name,
- base::string16* version,
- base::string16* special_build,
- base::string16* channel_name));
- MOCK_METHOD3(ShouldShowRestartDialog, bool(base::string16* title,
- base::string16* message,
- bool* is_rtl_locale));
- MOCK_METHOD0(AboutToRestart, bool());
- MOCK_METHOD1(GetDeferredUploadsSupported, bool(bool is_per_user_install));
- MOCK_METHOD1(GetIsPerUserInstall, bool(const base::FilePath& exe_path));
- MOCK_METHOD1(GetShouldDumpLargerDumps, bool(bool is_per_user_install));
- MOCK_METHOD0(GetResultCodeRespawnFailed, int());
- MOCK_METHOD0(InitBrowserCrashDumpsRegKey, void());
- MOCK_METHOD1(RecordCrashDumpAttempt, void(bool is_real_crash));
-
- MOCK_METHOD2(GetProductNameAndVersion, void(std::string* product_name,
- std::string* version));
- MOCK_METHOD0(GetReporterLogFilename, base::FilePath());
- MOCK_METHOD1(GetCrashDumpLocation, bool(base::FilePath* crash_dir));
- MOCK_METHOD0(RegisterCrashKeys, size_t());
- MOCK_METHOD0(IsRunningUnattended, bool());
- MOCK_METHOD0(GetCollectStatsConsent, bool());
- MOCK_METHOD1(ReportingIsEnforcedByPolicy, bool(bool* breakpad_enabled));
- MOCK_METHOD0(GetAndroidMinidumpDescriptor, int());
-#if defined(OS_MACOSX)
- MOCK_METHOD1(InstallAdditionalFilters, void(BreakpadRef breakpad));
-#endif
- MOCK_METHOD1(EnableBreakpadForProcess, bool(const std::string& process_type));
-};
-
-class CrashKeysWinTest : public testing::Test {
- public:
-
- size_t CountKeyValueOccurences(
- const google_breakpad::CustomClientInfo* client_info,
- const wchar_t* key, const wchar_t* value);
-
- protected:
- testing::StrictMock<MockBreakpadClient> breakpad_client_;
-};
-
-size_t CrashKeysWinTest::CountKeyValueOccurences(
- const google_breakpad::CustomClientInfo* client_info,
- const wchar_t* key, const wchar_t* value) {
- size_t occurrences = 0;
- for (size_t i = 0; i < client_info->count; ++i) {
- if (wcscmp(client_info->entries[i].name, key) == 0 &&
- wcscmp(client_info->entries[i].value, value) == 0) {
- ++occurrences;
- }
- }
-
- return occurrences;
-}
-
-TEST_F(CrashKeysWinTest, RecordsSelf) {
- ASSERT_EQ(static_cast<CrashKeysWin*>(NULL), CrashKeysWin::keeper());
-
- {
- CrashKeysWin crash_keys;
-
- ASSERT_EQ(&crash_keys, CrashKeysWin::keeper());
- }
-
- ASSERT_EQ(static_cast<CrashKeysWin*>(NULL), CrashKeysWin::keeper());
-}
-
-// Tests the crash keys set up for the most common official build consumer
-// scenario. No policy controls, not running unattended and no explicit
-// switches.
-TEST_F(CrashKeysWinTest, OfficialLikeKeys) {
- CrashKeysWin crash_keys;
-
- const base::FilePath kExePath(L"C:\\temp\\exe_path.exe");
- // The exe path ought to get passed through to the breakpad client.
- EXPECT_CALL(breakpad_client_, GetProductNameAndVersion(kExePath, _, _, _, _))
- .WillRepeatedly(DoAll(
- SetArgPointee<1>(L"SomeProdName"),
- SetArgPointee<2>(L"1.2.3.4"),
- SetArgPointee<3>(L""),
- SetArgPointee<4>(L"-devm")));
-
- EXPECT_CALL(breakpad_client_, GetAlternativeCrashDumpLocation(_))
- .WillRepeatedly(DoAll(
- SetArgPointee<0>(base::FilePath(L"C:\\temp")),
- Return(false)));
-
- EXPECT_CALL(breakpad_client_, ReportingIsEnforcedByPolicy(_))
- .WillRepeatedly(Return(false));
-
- EXPECT_CALL(breakpad_client_, IsRunningUnattended())
- .WillRepeatedly(Return(false));
-
- // Provide an empty command line.
- base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM);
- google_breakpad::CustomClientInfo* info =
- crash_keys.GetCustomInfo(kExePath.value(),
- L"made_up_type",
- L"temporary",
- &cmd_line,
- &breakpad_client_);
-
- ASSERT_TRUE(info != NULL);
- ASSERT_TRUE(info->entries != NULL);
-
- // We expect 7 fixed keys and a "freeboard" of 256 keys for dynamic entries.
- EXPECT_EQ(256U + 7U, info->count);
-
- EXPECT_EQ(1, CountKeyValueOccurences(info, L"ver", L"1.2.3.4"));
- EXPECT_EQ(1, CountKeyValueOccurences(info, L"prod", L"SomeProdName"));
- EXPECT_EQ(1, CountKeyValueOccurences(info, L"plat", L"Win32"));
- EXPECT_EQ(1, CountKeyValueOccurences(info, L"ptype", L"made_up_type"));
- std::wstring pid_str(base::StringPrintf(L"%d", ::GetCurrentProcessId()));
- EXPECT_EQ(1, CountKeyValueOccurences(info, L"pid", pid_str.c_str()));
- EXPECT_EQ(1, CountKeyValueOccurences(info, L"channel", L"-devm"));
- EXPECT_EQ(1, CountKeyValueOccurences(info, L"profile-type", L"temporary"));
- EXPECT_EQ(256, CountKeyValueOccurences(info, L"unspecified-crash-key", L""));
-}
-
-} // namespace breakpad
diff --git a/components/breakpad/app/hard_error_handler_win.cc b/components/breakpad/app/hard_error_handler_win.cc
deleted file mode 100644
index cf93adc..0000000
--- a/components/breakpad/app/hard_error_handler_win.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/breakpad/app/hard_error_handler_win.h"
-
-#if defined(_WIN32_WINNT_WIN8) && _MSC_VER < 1700
-// The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h, and in
-// delayimp.h previous to VS2012.
-#undef FACILITY_VISUALCPP
-#endif
-#include <DelayIMP.h>
-#include <winternl.h>
-
-#include "base/basictypes.h"
-#include "base/strings/string_util.h"
-#include "components/breakpad/app/breakpad_client.h"
-
-namespace breakpad {
-
-namespace {
-const DWORD kExceptionModuleNotFound = VcppException(ERROR_SEVERITY_ERROR,
- ERROR_MOD_NOT_FOUND);
-const DWORD kExceptionEntryPtNotFound = VcppException(ERROR_SEVERITY_ERROR,
- ERROR_PROC_NOT_FOUND);
-// This is defined in <ntstatus.h> but we can't include this file here.
-const DWORD FACILITY_GRAPHICS_KERNEL = 0x1E;
-const DWORD NT_STATUS_ENTRYPOINT_NOT_FOUND = 0xC0000139;
-const DWORD NT_STATUS_DLL_NOT_FOUND = 0xC0000135;
-
-// We assume that exception codes are NT_STATUS codes.
-DWORD FacilityFromException(DWORD exception_code) {
- return (exception_code >> 16) & 0x0FFF;
-}
-
-// This is not a generic function. It only works with some |nt_status| values.
-// Check the strings here http://msdn.microsoft.com/en-us/library/cc704588.aspx
-// before attempting to use this function.
-void RaiseHardErrorMsg(long nt_status, const std::string& p1,
- const std::string& p2) {
- // If headless just exit silently.
- if (GetBreakpadClient()->IsRunningUnattended())
- return;
-
- HMODULE ntdll = ::GetModuleHandleA("NTDLL.DLL");
- wchar_t* msg_template = NULL;
- size_t count = ::FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_FROM_HMODULE,
- ntdll,
- nt_status,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- reinterpret_cast<wchar_t*>(&msg_template),
- 0,
- NULL);
-
- if (!count)
- return;
- count += p1.size() + p2.size() + 1;
- base::string16 message;
- ::wsprintf(WriteInto(&message, count), msg_template, p1.c_str(), p2.c_str());
- // The MB_SERVICE_NOTIFICATION causes this message to be displayed by
- // csrss. This means that we are not creating windows or pumping WM messages
- // in this process.
- ::MessageBox(NULL, message.c_str(),
- L"chrome.exe",
- MB_OK | MB_SERVICE_NOTIFICATION);
- ::LocalFree(msg_template);
-}
-
-void ModuleNotFoundHardError(const EXCEPTION_RECORD* ex_record) {
- DelayLoadInfo* dli = reinterpret_cast<DelayLoadInfo*>(
- ex_record->ExceptionInformation[0]);
- if (!dli->szDll)
- return;
- RaiseHardErrorMsg(NT_STATUS_DLL_NOT_FOUND, dli->szDll, std::string());
-}
-
-void EntryPointNotFoundHardError(const EXCEPTION_RECORD* ex_record) {
- DelayLoadInfo* dli = reinterpret_cast<DelayLoadInfo*>(
- ex_record->ExceptionInformation[0]);
- if (!dli->dlp.fImportByName)
- return;
- if (!dli->dlp.szProcName)
- return;
- if (!dli->szDll)
- return;
- RaiseHardErrorMsg(NT_STATUS_ENTRYPOINT_NOT_FOUND,
- dli->dlp.szProcName, dli->szDll);
-}
-
-} // namespace
-
-bool HardErrorHandler(EXCEPTION_POINTERS* ex_info) {
- if (!ex_info)
- return false;
- if (!ex_info->ExceptionRecord)
- return false;
-
- long exception = ex_info->ExceptionRecord->ExceptionCode;
- if (exception == kExceptionModuleNotFound) {
- ModuleNotFoundHardError(ex_info->ExceptionRecord);
- return true;
- } else if (exception == kExceptionEntryPtNotFound) {
- EntryPointNotFoundHardError(ex_info->ExceptionRecord);
- return true;
- } else if (FacilityFromException(exception) == FACILITY_GRAPHICS_KERNEL) {
-#if defined(USE_AURA)
- RaiseHardErrorMsg(exception, std::string(), std::string());
- return true;
-#else
- return false;
-#endif
- }
- return false;
-}
-
-} // namespace breakpad
diff --git a/components/breakpad/app/hard_error_handler_win.h b/components/breakpad/app/hard_error_handler_win.h
deleted file mode 100644
index daf0482..0000000
--- a/components/breakpad/app/hard_error_handler_win.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_BREAKPAD_APP_HARD_ERROR_HANDLER_WIN_H_
-#define COMPONENTS_BREAKPAD_APP_HARD_ERROR_HANDLER_WIN_H_
-
-#include <windows.h>
-
-namespace breakpad {
-
-// This function is in charge of displaying a dialog box that informs the
-// user of a fatal condition in chrome. It is meant to be called from
-// breakpad's unhandled exception handler after the crash dump has been
-// created. The return value will be true if we are to retry launching
-// chrome (and show the 'chrome has crashed' dialog) or to silently exit.
-//
-// This function only handles a few known exceptions, currently:
-// - Failure to load a delayload dll.
-// - Failure to bind to a delayloaded import.
-// - Fatal Graphics card failure (aura build only).
-//
-// If any of these conditions are encountered, a message box shown by
-// the operating system CSRSS process via NtRaiseHardError is invoked.
-// The wording and localization is up to the operating system.
-//
-// Do not call this function for memory related errors like heap corruption
-// or stack exahustion. This function assumes that memory allocations are
-// possible.
-bool HardErrorHandler(EXCEPTION_POINTERS* ex_info);
-
-} // namespace breakpad
-
-#endif // COMPONENTS_BREAKPAD_APP_HARD_ERROR_HANDLER_WIN_H_