diff options
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/client/windows')
41 files changed, 0 insertions, 8951 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/breakpad_client.gyp b/toolkit/crashreporter/google-breakpad/src/client/windows/breakpad_client.gyp deleted file mode 100644 index 647975342..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/breakpad_client.gyp +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -{ - 'includes': [ - '../../build/common.gypi', - ], - 'targets': [ - { - 'target_name': 'build_all', - 'type': 'none', - 'dependencies': [ - './crash_generation/crash_generation.gyp:*', - './handler/exception_handler.gyp:*', - './sender/crash_report_sender.gyp:*', - './unittests/client_tests.gyp:*', - './unittests/testing.gyp:*', - './tests/crash_generation_app/crash_generation_app.gyp:*', - ] - }, - { - 'target_name': 'common', - 'type': 'static_library', - 'include_dirs': [ - '<(DEPTH)', - ], - 'direct_dependent_settings': { - 'include_dirs': [ - '<(DEPTH)', - ] - }, - 'sources': [ - '<(DEPTH)/common/windows/guid_string.cc', - '<(DEPTH)/common/windows/guid_string.h', - '<(DEPTH)/common/windows/http_upload.cc', - '<(DEPTH)/common/windows/http_upload.h', - '<(DEPTH)/common/windows/string_utils.cc', - ] - } - ] -} diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/common/auto_critical_section.h b/toolkit/crashreporter/google-breakpad/src/client/windows/common/auto_critical_section.h deleted file mode 100644 index 3fd4b9b7e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/common/auto_critical_section.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__ -#define CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__ - -#include <windows.h> - -namespace google_breakpad { - -// Automatically enters the critical section in the constructor and leaves -// the critical section in the destructor. -class AutoCriticalSection { - public: - // Creates a new instance with the given critical section object - // and enters the critical section immediately. - explicit AutoCriticalSection(CRITICAL_SECTION* cs) : cs_(cs), taken_(false) { - assert(cs_); - Acquire(); - } - - // Destructor: leaves the critical section. - ~AutoCriticalSection() { - if (taken_) { - Release(); - } - } - - // Enters the critical section. Recursive Acquire() calls are not allowed. - void Acquire() { - assert(!taken_); - EnterCriticalSection(cs_); - taken_ = true; - } - - // Leaves the critical section. The caller should not call Release() unless - // the critical seciton has been entered already. - void Release() { - assert(taken_); - taken_ = false; - LeaveCriticalSection(cs_); - } - - private: - // Disable copy ctor and operator=. - AutoCriticalSection(const AutoCriticalSection&); - AutoCriticalSection& operator=(const AutoCriticalSection&); - - CRITICAL_SECTION* cs_; - bool taken_; -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/common/ipc_protocol.h b/toolkit/crashreporter/google-breakpad/src/client/windows/common/ipc_protocol.h deleted file mode 100644 index c74868198..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/common/ipc_protocol.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__ -#define CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__ - -#include <windows.h> -#include <dbghelp.h> -#include <string> -#include <utility> -#include "common/windows/string_utils-inl.h" -#include "google_breakpad/common/minidump_format.h" - -namespace google_breakpad { - -// Name/value pair for custom client information. -struct CustomInfoEntry { - // Maximum length for name and value for client custom info. - static const int kNameMaxLength = 64; - static const int kValueMaxLength = 64; - - CustomInfoEntry() { - // Putting name and value in initializer list makes VC++ show warning 4351. - set_name(NULL); - set_value(NULL); - } - - CustomInfoEntry(const wchar_t* name_arg, const wchar_t* value_arg) { - set_name(name_arg); - set_value(value_arg); - } - - void set_name(const wchar_t* name_arg) { - if (!name_arg) { - name[0] = L'\0'; - return; - } - WindowsStringUtils::safe_wcscpy(name, kNameMaxLength, name_arg); - } - - void set_value(const wchar_t* value_arg) { - if (!value_arg) { - value[0] = L'\0'; - return; - } - - WindowsStringUtils::safe_wcscpy(value, kValueMaxLength, value_arg); - } - - void set(const wchar_t* name_arg, const wchar_t* value_arg) { - set_name(name_arg); - set_value(value_arg); - } - - wchar_t name[kNameMaxLength]; - wchar_t value[kValueMaxLength]; -}; - -// Constants for the protocol between client and the server. - -// Tags sent with each message indicating the purpose of -// the message. -enum MessageTag { - MESSAGE_TAG_NONE = 0, - MESSAGE_TAG_REGISTRATION_REQUEST = 1, - MESSAGE_TAG_REGISTRATION_RESPONSE = 2, - MESSAGE_TAG_REGISTRATION_ACK = 3, - MESSAGE_TAG_UPLOAD_REQUEST = 4 -}; - -struct CustomClientInfo { - const CustomInfoEntry* entries; - size_t count; -}; - -// Message structure for IPC between crash client and crash server. -struct ProtocolMessage { - ProtocolMessage() - : tag(MESSAGE_TAG_NONE), - id(0), - dump_type(MiniDumpNormal), - thread_id(0), - exception_pointers(NULL), - assert_info(NULL), - custom_client_info(), - dump_request_handle(NULL), - dump_generated_handle(NULL), - server_alive_handle(NULL) { - } - - // Creates an instance with the given parameters. - ProtocolMessage(MessageTag arg_tag, - DWORD arg_id, - MINIDUMP_TYPE arg_dump_type, - DWORD* arg_thread_id, - EXCEPTION_POINTERS** arg_exception_pointers, - MDRawAssertionInfo* arg_assert_info, - const CustomClientInfo& custom_info, - HANDLE arg_dump_request_handle, - HANDLE arg_dump_generated_handle, - HANDLE arg_server_alive) - : tag(arg_tag), - id(arg_id), - dump_type(arg_dump_type), - thread_id(arg_thread_id), - exception_pointers(arg_exception_pointers), - assert_info(arg_assert_info), - custom_client_info(custom_info), - dump_request_handle(arg_dump_request_handle), - dump_generated_handle(arg_dump_generated_handle), - server_alive_handle(arg_server_alive) { - } - - // Tag in the message. - MessageTag tag; - - // The id for this message. This may be either a process id or a crash id - // depending on the type of message. - DWORD id; - - // Dump type requested. - MINIDUMP_TYPE dump_type; - - // Client thread id pointer. - DWORD* thread_id; - - // Exception information. - EXCEPTION_POINTERS** exception_pointers; - - // Assert information in case of an invalid parameter or - // pure call failure. - MDRawAssertionInfo* assert_info; - - // Custom client information. - CustomClientInfo custom_client_info; - - // Handle to signal the crash event. - HANDLE dump_request_handle; - - // Handle to check if server is done generating crash. - HANDLE dump_generated_handle; - - // Handle to a mutex that becomes signaled (WAIT_ABANDONED) - // if server process goes down. - HANDLE server_alive_handle; - - private: - // Disable copy ctor and operator=. - ProtocolMessage(const ProtocolMessage& msg); - ProtocolMessage& operator=(const ProtocolMessage& msg); -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/ReadMe.txt b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/ReadMe.txt deleted file mode 100644 index b54d0e11b..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/ReadMe.txt +++ /dev/null @@ -1,58 +0,0 @@ -========================================================================= - State machine transitions for the Crash Generation Server -========================================================================= - -========================================================================= - | - STATE | ACTIONS - | -========================================================================= - ERROR | Clean up resources used to serve clients. - | Always remain in ERROR state. -------------------------------------------------------------------------- - INITIAL | Connect to the pipe asynchronously. - | If connection is successfully queued up asynchronously, - | go into CONNECTING state. - | If connection is done synchronously, go into CONNECTED - | state. - | For any unexpected problems, go into ERROR state. -------------------------------------------------------------------------- - CONNECTING | Get the result of async connection request. - | If I/O is still incomplete, remain in the CONNECTING - | state. - | If connection is complete, go into CONNECTED state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - CONNECTED | Read from the pipe asynchronously. - | If read request is successfully queued up asynchronously, - | go into READING state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - READING | Get the result of async read request. - | If read is done, go into READ_DONE state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - READ_DONE | Register the client, prepare the reply and write the - | reply to the pipe asynchronously. - | If write request is successfully queued up asynchronously, - | go into WRITING state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - WRITING | Get the result of the async write request. - | If write is done, go into WRITE_DONE state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - WRITE_DONE | Read from the pipe asynchronously (for an ACK). - | If read request is successfully queued up asynchonously, - | go into READING_ACK state. - | For any unexpected problems, go into DISCONNECTING state. -------------------------------------------------------------------------- - READING_ACK | Get the result of the async read request. - | If read is done, perform action for successful client - | connection. - | Go into DISCONNECTING state. -------------------------------------------------------------------------- - DISCONNECTING | Disconnect from the pipe, reset the event and go into - | INITIAL state and signal the event again. If anything - | fails, go into ERROR state. -========================================================================= diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.cc deleted file mode 100644 index ed3126381..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.cc +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "client/windows/crash_generation/client_info.h" -#include "client/windows/common/ipc_protocol.h" - -static const wchar_t kCustomInfoProcessUptimeName[] = L"ptime"; -static const size_t kMaxCustomInfoEntries = 4096; - -namespace google_breakpad { - -ClientInfo::ClientInfo(CrashGenerationServer* crash_server, - DWORD pid, - MINIDUMP_TYPE dump_type, - DWORD* thread_id, - EXCEPTION_POINTERS** ex_info, - MDRawAssertionInfo* assert_info, - const CustomClientInfo& custom_client_info) - : crash_server_(crash_server), - pid_(pid), - dump_type_(dump_type), - ex_info_(ex_info), - assert_info_(assert_info), - custom_client_info_(custom_client_info), - thread_id_(thread_id), - process_handle_(NULL), - dump_requested_handle_(NULL), - dump_generated_handle_(NULL), - dump_request_wait_handle_(NULL), - process_exit_wait_handle_(NULL), - crash_id_(NULL) { - GetSystemTimeAsFileTime(&start_time_); -} - -bool ClientInfo::Initialize() { - process_handle_ = OpenProcess(GENERIC_ALL, FALSE, pid_); - if (!process_handle_) { - return false; - } - - // The crash_id will be the low order word of the process creation time. - FILETIME creation_time, exit_time, kernel_time, user_time; - if (GetProcessTimes(process_handle_, &creation_time, &exit_time, - &kernel_time, &user_time)) { - start_time_ = creation_time; - } - crash_id_ = start_time_.dwLowDateTime; - - dump_requested_handle_ = CreateEvent(NULL, // Security attributes. - TRUE, // Manual reset. - FALSE, // Initial state. - NULL); // Name. - if (!dump_requested_handle_) { - return false; - } - - dump_generated_handle_ = CreateEvent(NULL, // Security attributes. - TRUE, // Manual reset. - FALSE, // Initial state. - NULL); // Name. - return dump_generated_handle_ != NULL; -} - -void ClientInfo::UnregisterDumpRequestWaitAndBlockUntilNoPending() { - if (dump_request_wait_handle_) { - // Wait for callbacks that might already be running to finish. - UnregisterWaitEx(dump_request_wait_handle_, INVALID_HANDLE_VALUE); - dump_request_wait_handle_ = NULL; - } -} - -void ClientInfo::UnregisterProcessExitWait(bool block_until_no_pending) { - if (process_exit_wait_handle_) { - if (block_until_no_pending) { - // Wait for the callback that might already be running to finish. - UnregisterWaitEx(process_exit_wait_handle_, INVALID_HANDLE_VALUE); - } else { - UnregisterWait(process_exit_wait_handle_); - } - process_exit_wait_handle_ = NULL; - } -} - -ClientInfo::~ClientInfo() { - // Waiting for the callback to finish here is safe because ClientInfo's are - // never destroyed from the dump request handling callback. - UnregisterDumpRequestWaitAndBlockUntilNoPending(); - - // This is a little tricky because ClientInfo's may be destroyed by the same - // callback (OnClientEnd) and waiting for it to finish will cause a deadlock. - // Regardless of this complication, wait for any running callbacks to finish - // so that the common case is properly handled. In order to avoid deadlocks, - // the OnClientEnd callback must call UnregisterProcessExitWait(false) - // before deleting the ClientInfo. - UnregisterProcessExitWait(true); - - if (process_handle_) { - CloseHandle(process_handle_); - } - - if (dump_requested_handle_) { - CloseHandle(dump_requested_handle_); - } - - if (dump_generated_handle_) { - CloseHandle(dump_generated_handle_); - } -} - -bool ClientInfo::GetClientExceptionInfo(EXCEPTION_POINTERS** ex_info) const { - SIZE_T bytes_count = 0; - if (!ReadProcessMemory(process_handle_, - ex_info_, - ex_info, - sizeof(*ex_info), - &bytes_count)) { - return false; - } - - return bytes_count == sizeof(*ex_info); -} - -bool ClientInfo::GetClientThreadId(DWORD* thread_id) const { - SIZE_T bytes_count = 0; - if (!ReadProcessMemory(process_handle_, - thread_id_, - thread_id, - sizeof(*thread_id), - &bytes_count)) { - return false; - } - - return bytes_count == sizeof(*thread_id); -} - -void ClientInfo::SetProcessUptime() { - FILETIME now = {0}; - GetSystemTimeAsFileTime(&now); - - ULARGE_INTEGER time_start; - time_start.HighPart = start_time_.dwHighDateTime; - time_start.LowPart = start_time_.dwLowDateTime; - - ULARGE_INTEGER time_now; - time_now.HighPart = now.dwHighDateTime; - time_now.LowPart = now.dwLowDateTime; - - // Calculate the delay and convert it from 100-nanoseconds to milliseconds. - __int64 delay = (time_now.QuadPart - time_start.QuadPart) / 10 / 1000; - - // Convert it to a string. - wchar_t* value = custom_info_entries_.get()[custom_client_info_.count].value; - _i64tow_s(delay, value, CustomInfoEntry::kValueMaxLength, 10); -} - -bool ClientInfo::PopulateCustomInfo() { - if (custom_client_info_.count > kMaxCustomInfoEntries) - return false; - - SIZE_T bytes_count = 0; - SIZE_T read_count = sizeof(CustomInfoEntry) * custom_client_info_.count; - - // If the scoped array for custom info already has an array, it will be - // the same size as what we need. This is because the number of custom info - // entries is always the same. So allocate memory only if scoped array has - // a NULL pointer. - if (!custom_info_entries_.get()) { - // Allocate an extra entry for reporting uptime for the client process. - custom_info_entries_.reset( - new CustomInfoEntry[custom_client_info_.count + 1]); - // Use the last element in the array for uptime. - custom_info_entries_.get()[custom_client_info_.count].set_name( - kCustomInfoProcessUptimeName); - } - - if (!ReadProcessMemory(process_handle_, - custom_client_info_.entries, - custom_info_entries_.get(), - read_count, - &bytes_count)) { - return false; - } - - SetProcessUptime(); - return (bytes_count == read_count); -} - -CustomClientInfo ClientInfo::GetCustomInfo() const { - CustomClientInfo custom_info; - custom_info.entries = custom_info_entries_.get(); - // Add 1 to the count from the client process to account for extra entry for - // process uptime. - custom_info.count = custom_client_info_.count + 1; - return custom_info; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.h b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.h deleted file mode 100644 index 6a8fba31f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/client_info.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ -#define CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ - -#include <windows.h> -#include <dbghelp.h> -#include "client/windows/common/ipc_protocol.h" -#include "common/scoped_ptr.h" -#include "google_breakpad/common/minidump_format.h" - -namespace google_breakpad { - -class CrashGenerationServer; - -// Abstraction for a crash client process. -class ClientInfo { - public: - // Creates an instance with the given values. Gets the process - // handle for the given process id and creates necessary event - // objects. - ClientInfo(CrashGenerationServer* crash_server, - DWORD pid, - MINIDUMP_TYPE dump_type, - DWORD* thread_id, - EXCEPTION_POINTERS** ex_info, - MDRawAssertionInfo* assert_info, - const CustomClientInfo& custom_client_info); - - ~ClientInfo(); - - CrashGenerationServer* crash_server() const { return crash_server_; } - DWORD pid() const { return pid_; } - MINIDUMP_TYPE dump_type() const { return dump_type_; } - EXCEPTION_POINTERS** ex_info() const { return ex_info_; } - MDRawAssertionInfo* assert_info() const { return assert_info_; } - DWORD* thread_id() const { return thread_id_; } - HANDLE process_handle() const { return process_handle_; } - HANDLE dump_requested_handle() const { return dump_requested_handle_; } - HANDLE dump_generated_handle() const { return dump_generated_handle_; } - DWORD crash_id() const { return crash_id_; } - const CustomClientInfo& custom_client_info() const { - return custom_client_info_; - } - - void set_dump_request_wait_handle(HANDLE value) { - dump_request_wait_handle_ = value; - } - - void set_process_exit_wait_handle(HANDLE value) { - process_exit_wait_handle_ = value; - } - - // Unregister the dump request wait operation and wait for all callbacks - // that might already be running to complete before returning. - void UnregisterDumpRequestWaitAndBlockUntilNoPending(); - - // Unregister the process exit wait operation. If block_until_no_pending is - // true, wait for all callbacks that might already be running to complete - // before returning. - void UnregisterProcessExitWait(bool block_until_no_pending); - - bool Initialize(); - bool GetClientExceptionInfo(EXCEPTION_POINTERS** ex_info) const; - bool GetClientThreadId(DWORD* thread_id) const; - - // Reads the custom information from the client process address space. - bool PopulateCustomInfo(); - - // Returns the client custom information. - CustomClientInfo GetCustomInfo() const; - - private: - // Calcualtes the uptime for the client process, converts it to a string and - // stores it in the last entry of client custom info. - void SetProcessUptime(); - - // Crash generation server. - CrashGenerationServer* crash_server_; - - // Client process ID. - DWORD pid_; - - // Dump type requested by the client. - MINIDUMP_TYPE dump_type_; - - // Address of an EXCEPTION_POINTERS* variable in the client - // process address space that will point to an instance of - // EXCEPTION_POINTERS containing information about crash. - // - // WARNING: Do not dereference these pointers as they are pointers - // in the address space of another process. - EXCEPTION_POINTERS** ex_info_; - - // Address of an instance of MDRawAssertionInfo in the client - // process address space that will contain information about - // non-exception related crashes like invalid parameter assertion - // failures and pure calls. - // - // WARNING: Do not dereference these pointers as they are pointers - // in the address space of another process. - MDRawAssertionInfo* assert_info_; - - // Custom information about the client. - CustomClientInfo custom_client_info_; - - // Contains the custom client info entries read from the client process - // memory. This will be populated only if the method GetClientCustomInfo - // is called. - scoped_array<CustomInfoEntry> custom_info_entries_; - - // Address of a variable in the client process address space that - // will contain the thread id of the crashing client thread. - // - // WARNING: Do not dereference these pointers as they are pointers - // in the address space of another process. - DWORD* thread_id_; - - // Client process handle. - HANDLE process_handle_; - - // Dump request event handle. - HANDLE dump_requested_handle_; - - // Dump generated event handle. - HANDLE dump_generated_handle_; - - // Wait handle for dump request event. - HANDLE dump_request_wait_handle_; - - // Wait handle for process exit event. - HANDLE process_exit_wait_handle_; - - // Time when the client process started. It is used to determine the uptime - // for the client process when it signals a crash. - FILETIME start_time_; - - // The crash id which can be used to request an upload. This will be the - // value of the low order dword of the process creation time for the process - // being dumped. - DWORD crash_id_; - - // Disallow copy ctor and operator=. - ClientInfo(const ClientInfo& client_info); - ClientInfo& operator=(const ClientInfo& client_info); -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation.gyp b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation.gyp deleted file mode 100644 index ba343768a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation.gyp +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -{ - 'includes': [ - '../../../build/common.gypi', - ], - 'targets': [ - { - 'target_name': 'crash_generation_server', - 'type': 'static_library', - 'sources': [ - 'client_info.cc', - 'crash_generation_server.cc', - 'minidump_generator.cc', - 'client_info.h', - 'crash_generation_client.h', - 'crash_generation_server.h', - 'minidump_generator.h', - ], - 'dependencies': [ - '../breakpad_client.gyp:common' - ], - }, - { - 'target_name': 'crash_generation_client', - 'type': 'static_library', - 'include_dirs': [ - '<(DEPTH)', - ], - 'sources': [ - 'crash_generation_client.h', - 'crash_generation_client.cc', - 'crash_generation_server.h', - ], - }, - ], -} diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.cc deleted file mode 100644 index 3ba5d4e4f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.cc +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "client/windows/crash_generation/crash_generation_client.h" -#include <cassert> -#include <utility> -#include "client/windows/common/ipc_protocol.h" - -namespace google_breakpad { - -const int kPipeBusyWaitTimeoutMs = 2000; - -#ifdef _DEBUG -const DWORD kWaitForServerTimeoutMs = INFINITE; -#else -const DWORD kWaitForServerTimeoutMs = 15000; -#endif - -const int kPipeConnectMaxAttempts = 2; - -const DWORD kPipeDesiredAccess = FILE_READ_DATA | - FILE_WRITE_DATA | - FILE_WRITE_ATTRIBUTES; - -const DWORD kPipeFlagsAndAttributes = SECURITY_IDENTIFICATION | - SECURITY_SQOS_PRESENT; - -const DWORD kPipeMode = PIPE_READMODE_MESSAGE; - -const size_t kWaitEventCount = 2; - -// This function is orphan for production code. It can be used -// for debugging to help repro some scenarios like the client -// is slow in writing to the pipe after connecting, the client -// is slow in reading from the pipe after writing, etc. The parameter -// overlapped below is not used and it is present to match the signature -// of this function to TransactNamedPipe Win32 API. Uncomment if needed -// for debugging. -/** -static bool TransactNamedPipeDebugHelper(HANDLE pipe, - const void* in_buffer, - DWORD in_size, - void* out_buffer, - DWORD out_size, - DWORD* bytes_count, - LPOVERLAPPED) { - // Uncomment the next sleep to create a gap before writing - // to pipe. - // Sleep(5000); - - if (!WriteFile(pipe, - in_buffer, - in_size, - bytes_count, - NULL)) { - return false; - } - - // Uncomment the next sleep to create a gap between write - // and read. - // Sleep(5000); - - return ReadFile(pipe, out_buffer, out_size, bytes_count, NULL) != FALSE; -} -**/ - -CrashGenerationClient::CrashGenerationClient( - const wchar_t* pipe_name, - MINIDUMP_TYPE dump_type, - const CustomClientInfo* custom_info) - : pipe_name_(pipe_name), - pipe_handle_(NULL), - custom_info_(), - dump_type_(dump_type), - crash_event_(NULL), - crash_generated_(NULL), - server_alive_(NULL), - server_process_id_(0), - thread_id_(0), - exception_pointers_(NULL) { - memset(&assert_info_, 0, sizeof(assert_info_)); - if (custom_info) { - custom_info_ = *custom_info; - } -} - -CrashGenerationClient::CrashGenerationClient( - HANDLE pipe_handle, - MINIDUMP_TYPE dump_type, - const CustomClientInfo* custom_info) - : pipe_name_(), - pipe_handle_(pipe_handle), - custom_info_(), - dump_type_(dump_type), - crash_event_(NULL), - crash_generated_(NULL), - server_alive_(NULL), - server_process_id_(0), - thread_id_(0), - exception_pointers_(NULL) { - memset(&assert_info_, 0, sizeof(assert_info_)); - if (custom_info) { - custom_info_ = *custom_info; - } -} - -CrashGenerationClient::~CrashGenerationClient() { - if (crash_event_) { - CloseHandle(crash_event_); - } - - if (crash_generated_) { - CloseHandle(crash_generated_); - } - - if (server_alive_) { - CloseHandle(server_alive_); - } -} - -// Performs the registration step with the server process. -// The registration step involves communicating with the server -// via a named pipe. The client sends the following pieces of -// data to the server: -// -// * Message tag indicating the client is requesting registration. -// * Process id of the client process. -// * Address of a DWORD variable in the client address space -// that will contain the thread id of the client thread that -// caused the crash. -// * Address of a EXCEPTION_POINTERS* variable in the client -// address space that will point to an instance of EXCEPTION_POINTERS -// when the crash happens. -// * Address of an instance of MDRawAssertionInfo that will contain -// relevant information in case of non-exception crashes like assertion -// failures and pure calls. -// -// In return the client expects the following information from the server: -// -// * Message tag indicating successful registration. -// * Server process id. -// * Handle to an object that client can signal to request dump -// generation from the server. -// * Handle to an object that client can wait on after requesting -// dump generation for the server to finish dump generation. -// * Handle to a mutex object that client can wait on to make sure -// server is still alive. -// -// If any step of the expected behavior mentioned above fails, the -// registration step is not considered successful and hence out-of-process -// dump generation service is not available. -// -// Returns true if the registration is successful; false otherwise. -bool CrashGenerationClient::Register() { - if (IsRegistered()) { - return true; - } - - HANDLE pipe = ConnectToServer(); - if (!pipe) { - return false; - } - - bool success = RegisterClient(pipe); - CloseHandle(pipe); - return success; -} - -bool CrashGenerationClient::RequestUpload(DWORD crash_id) { - HANDLE pipe = ConnectToServer(); - if (!pipe) { - return false; - } - - CustomClientInfo custom_info = {NULL, 0}; - ProtocolMessage msg(MESSAGE_TAG_UPLOAD_REQUEST, crash_id, - static_cast<MINIDUMP_TYPE>(NULL), NULL, NULL, NULL, - custom_info, NULL, NULL, NULL); - DWORD bytes_count = 0; - bool success = WriteFile(pipe, &msg, sizeof(msg), &bytes_count, NULL) != 0; - - CloseHandle(pipe); - return success; -} - -HANDLE CrashGenerationClient::ConnectToServer() { - HANDLE pipe = ConnectToPipe(pipe_name_.c_str(), - kPipeDesiredAccess, - kPipeFlagsAndAttributes); - if (!pipe) { - return NULL; - } - - DWORD mode = kPipeMode; - if (!SetNamedPipeHandleState(pipe, &mode, NULL, NULL)) { - CloseHandle(pipe); - pipe = NULL; - } - - return pipe; -} - -bool CrashGenerationClient::RegisterClient(HANDLE pipe) { - ProtocolMessage msg(MESSAGE_TAG_REGISTRATION_REQUEST, - GetCurrentProcessId(), - dump_type_, - &thread_id_, - &exception_pointers_, - &assert_info_, - custom_info_, - NULL, - NULL, - NULL); - ProtocolMessage reply; - DWORD bytes_count = 0; - // The call to TransactNamedPipe below can be changed to a call - // to TransactNamedPipeDebugHelper to help repro some scenarios. - // For details see comments for TransactNamedPipeDebugHelper. - if (!TransactNamedPipe(pipe, - &msg, - sizeof(msg), - &reply, - sizeof(ProtocolMessage), - &bytes_count, - NULL)) { - return false; - } - - if (!ValidateResponse(reply)) { - return false; - } - - ProtocolMessage ack_msg; - ack_msg.tag = MESSAGE_TAG_REGISTRATION_ACK; - - if (!WriteFile(pipe, &ack_msg, sizeof(ack_msg), &bytes_count, NULL)) { - return false; - } - crash_event_ = reply.dump_request_handle; - crash_generated_ = reply.dump_generated_handle; - server_alive_ = reply.server_alive_handle; - server_process_id_ = reply.id; - - return true; -} - -HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name, - DWORD pipe_access, - DWORD flags_attrs) { - if (pipe_handle_) { - HANDLE t = pipe_handle_; - pipe_handle_ = NULL; - return t; - } - - for (int i = 0; i < kPipeConnectMaxAttempts; ++i) { - HANDLE pipe = CreateFile(pipe_name, - pipe_access, - 0, - NULL, - OPEN_EXISTING, - flags_attrs, - NULL); - if (pipe != INVALID_HANDLE_VALUE) { - return pipe; - } - - // Cannot continue retrying if error is something other than - // ERROR_PIPE_BUSY. - if (GetLastError() != ERROR_PIPE_BUSY) { - break; - } - - // Cannot continue retrying if wait on pipe fails. - if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) { - break; - } - } - - return NULL; -} - -bool CrashGenerationClient::ValidateResponse( - const ProtocolMessage& msg) const { - return (msg.tag == MESSAGE_TAG_REGISTRATION_RESPONSE) && - (msg.id != 0) && - (msg.dump_request_handle != NULL) && - (msg.dump_generated_handle != NULL) && - (msg.server_alive_handle != NULL); -} - -bool CrashGenerationClient::IsRegistered() const { - return crash_event_ != NULL; -} - -bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info, - MDRawAssertionInfo* assert_info) { - if (!IsRegistered()) { - return false; - } - - exception_pointers_ = ex_info; - thread_id_ = GetCurrentThreadId(); - - if (assert_info) { - memcpy(&assert_info_, assert_info, sizeof(assert_info_)); - } else { - memset(&assert_info_, 0, sizeof(assert_info_)); - } - - return SignalCrashEventAndWait(); -} - -bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info) { - return RequestDump(ex_info, NULL); -} - -bool CrashGenerationClient::RequestDump(MDRawAssertionInfo* assert_info) { - return RequestDump(NULL, assert_info); -} - -bool CrashGenerationClient::SignalCrashEventAndWait() { - assert(crash_event_); - assert(crash_generated_); - assert(server_alive_); - - // Reset the dump generated event before signaling the crash - // event so that the server can set the dump generated event - // once it is done generating the event. - if (!ResetEvent(crash_generated_)) { - return false; - } - - if (!SetEvent(crash_event_)) { - return false; - } - - HANDLE wait_handles[kWaitEventCount] = {crash_generated_, server_alive_}; - - DWORD result = WaitForMultipleObjects(kWaitEventCount, - wait_handles, - FALSE, - kWaitForServerTimeoutMs); - - // Crash dump was successfully generated only if the server - // signaled the crash generated event. - return result == WAIT_OBJECT_0; -} - -HANDLE CrashGenerationClient::DuplicatePipeToClientProcess(const wchar_t* pipe_name, - HANDLE hProcess) { - for (int i = 0; i < kPipeConnectMaxAttempts; ++i) { - HANDLE local_pipe = CreateFile(pipe_name, kPipeDesiredAccess, - 0, NULL, OPEN_EXISTING, - kPipeFlagsAndAttributes, NULL); - if (local_pipe != INVALID_HANDLE_VALUE) { - HANDLE remotePipe = INVALID_HANDLE_VALUE; - if (DuplicateHandle(GetCurrentProcess(), local_pipe, - hProcess, &remotePipe, 0, FALSE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { - return remotePipe; - } else { - return INVALID_HANDLE_VALUE; - } - } - - // Cannot continue retrying if the error wasn't a busy pipe. - if (GetLastError() != ERROR_PIPE_BUSY) { - return INVALID_HANDLE_VALUE; - } - - if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) { - return INVALID_HANDLE_VALUE; - } - } - return INVALID_HANDLE_VALUE; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.h b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.h deleted file mode 100644 index 457f73195..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_client.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_ -#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_ - -#include <windows.h> -#include <dbghelp.h> -#include <string> -#include <utility> -#include "client/windows/common/ipc_protocol.h" -#include "common/scoped_ptr.h" - -namespace google_breakpad { - -struct CustomClientInfo; - -// Abstraction of client-side implementation of out of process -// crash generation. -// -// The process that desires to have out-of-process crash dump -// generation service can use this class in the following way: -// -// * Create an instance. -// * Call Register method so that the client tries to register -// with the server process and check the return value. If -// registration is not successful, out-of-process crash dump -// generation will not be available -// * Request dump generation by calling either of the two -// overloaded RequestDump methods - one in case of exceptions -// and the other in case of assertion failures -// -// Note that it is the responsibility of the client code of -// this class to set the unhandled exception filter with the -// system by calling the SetUnhandledExceptionFilter function -// and the client code should explicitly request dump generation. -class CrashGenerationClient { - public: - CrashGenerationClient(const wchar_t* pipe_name, - MINIDUMP_TYPE dump_type, - const CustomClientInfo* custom_info); - - CrashGenerationClient(HANDLE pipe_handle, - MINIDUMP_TYPE dump_type, - const CustomClientInfo* custom_info); - - ~CrashGenerationClient(); - - // Registers the client process with the crash server. - // - // Returns true if the registration is successful; false otherwise. - bool Register(); - - // Requests the crash server to upload a previous dump with the - // given crash id. - bool RequestUpload(DWORD crash_id); - - bool RequestDump(EXCEPTION_POINTERS* ex_info, - MDRawAssertionInfo* assert_info); - - // Requests the crash server to generate a dump with the given - // exception information. - // - // Returns true if the dump was successful; false otherwise. Note that - // if the registration step was not performed or it was not successful, - // false will be returned. - bool RequestDump(EXCEPTION_POINTERS* ex_info); - - // Requests the crash server to generate a dump with the given - // assertion information. - // - // Returns true if the dump was successful; false otherwise. Note that - // if the registration step was not performed or it was not successful, - // false will be returned. - bool RequestDump(MDRawAssertionInfo* assert_info); - - // If the crash generation client is running in a sandbox that prevents it - // from opening the named pipe directly, the server process may open the - // handle and duplicate it into the client process with this helper method. - // Returns INVALID_HANDLE_VALUE on failure. The process must have been opened - // with the PROCESS_DUP_HANDLE access right. - static HANDLE DuplicatePipeToClientProcess(const wchar_t* pipe_name, - HANDLE hProcess); - - private: - // Connects to the appropriate pipe and sets the pipe handle state. - // - // Returns the pipe handle if everything goes well; otherwise Returns NULL. - HANDLE ConnectToServer(); - - // Performs a handshake with the server over the given pipe which should be - // already connected to the server. - // - // Returns true if handshake with the server was successful; false otherwise. - bool RegisterClient(HANDLE pipe); - - // Validates the given server response. - bool ValidateResponse(const ProtocolMessage& msg) const; - - // Returns true if the registration step succeeded; false otherwise. - bool IsRegistered() const; - - // Connects to the given named pipe with given parameters. - // - // Returns true if the connection is successful; false otherwise. - HANDLE ConnectToPipe(const wchar_t* pipe_name, - DWORD pipe_access, - DWORD flags_attrs); - - // Signals the crash event and wait for the server to generate crash. - bool SignalCrashEventAndWait(); - - // Pipe name to use to talk to server. - std::wstring pipe_name_; - - // Pipe handle duplicated from server process. Only valid before - // Register is called. - HANDLE pipe_handle_; - - // Custom client information - CustomClientInfo custom_info_; - - // Type of dump to generate. - MINIDUMP_TYPE dump_type_; - - // Event to signal in case of a crash. - HANDLE crash_event_; - - // Handle to wait on after signaling a crash for the server - // to finish generating crash dump. - HANDLE crash_generated_; - - // Handle to a mutex that will become signaled with WAIT_ABANDONED - // if the server process goes down. - HANDLE server_alive_; - - // Server process id. - DWORD server_process_id_; - - // Id of the thread that caused the crash. - DWORD thread_id_; - - // Exception pointers for an exception crash. - EXCEPTION_POINTERS* exception_pointers_; - - // Assertion info for an invalid parameter or pure call crash. - MDRawAssertionInfo assert_info_; - - // Disable copy ctor and operator=. - CrashGenerationClient(const CrashGenerationClient& crash_client); - CrashGenerationClient& operator=(const CrashGenerationClient& crash_client); -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc deleted file mode 100644 index bb0968fe0..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc +++ /dev/null @@ -1,931 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "client/windows/crash_generation/crash_generation_server.h" -#include <windows.h> -#include <cassert> -#include <list> -#include "client/windows/common/auto_critical_section.h" -#include "common/scoped_ptr.h" - -#include "client/windows/crash_generation/client_info.h" - -namespace google_breakpad { - -// Output buffer size. -static const size_t kOutBufferSize = 64; - -// Input buffer size. -static const size_t kInBufferSize = 64; - -// Access flags for the client on the dump request event. -static const DWORD kDumpRequestEventAccess = EVENT_MODIFY_STATE; - -// Access flags for the client on the dump generated event. -static const DWORD kDumpGeneratedEventAccess = EVENT_MODIFY_STATE | - SYNCHRONIZE; - -// Access flags for the client on the mutex. -static const DWORD kMutexAccess = SYNCHRONIZE; - -// Attribute flags for the pipe. -static const DWORD kPipeAttr = FILE_FLAG_FIRST_PIPE_INSTANCE | - PIPE_ACCESS_DUPLEX | - FILE_FLAG_OVERLAPPED; - -// Mode for the pipe. -static const DWORD kPipeMode = PIPE_TYPE_MESSAGE | - PIPE_READMODE_MESSAGE | - PIPE_WAIT; - -// For pipe I/O, execute the callback in the wait thread itself, -// since the callback does very little work. The callback executes -// the code for one of the states of the server state machine and -// the code for all of the states perform async I/O and hence -// finish very quickly. -static const ULONG kPipeIOThreadFlags = WT_EXECUTEINWAITTHREAD; - -// Dump request threads will, most likely, generate dumps. That may -// take some time to finish, so specify WT_EXECUTELONGFUNCTION flag. -static const ULONG kDumpRequestThreadFlags = WT_EXECUTEINWAITTHREAD | - WT_EXECUTELONGFUNCTION; - -static bool IsClientRequestValid(const ProtocolMessage& msg) { - return msg.tag == MESSAGE_TAG_UPLOAD_REQUEST || - (msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST && - msg.id != 0 && - msg.thread_id != NULL && - msg.exception_pointers != NULL && - msg.assert_info != NULL); -} - -#ifndef NDEBUG -static bool CheckForIOIncomplete(bool success) { - // We should never get an I/O incomplete since we should not execute this - // unless the operation has finished and the overlapped event is signaled. If - // we do get INCOMPLETE, we have a bug in our code. - return success ? false : (GetLastError() == ERROR_IO_INCOMPLETE); -} -#endif - -CrashGenerationServer::CrashGenerationServer( - const std::wstring& pipe_name, - SECURITY_ATTRIBUTES* pipe_sec_attrs, - OnClientConnectedCallback connect_callback, - void* connect_context, - OnClientDumpRequestCallback dump_callback, - void* dump_context, - OnClientExitedCallback exit_callback, - void* exit_context, - OnClientUploadRequestCallback upload_request_callback, - void* upload_context, - bool generate_dumps, - const std::wstring* dump_path) - : pipe_name_(pipe_name), - pipe_sec_attrs_(pipe_sec_attrs), - pipe_(NULL), - pipe_wait_handle_(NULL), - server_alive_handle_(NULL), - connect_callback_(connect_callback), - connect_context_(connect_context), - dump_callback_(dump_callback), - dump_context_(dump_context), - exit_callback_(exit_callback), - exit_context_(exit_context), - upload_request_callback_(upload_request_callback), - upload_context_(upload_context), - generate_dumps_(generate_dumps), - pre_fetch_custom_info_(true), - dump_path_(dump_path ? *dump_path : L""), - server_state_(IPC_SERVER_STATE_UNINITIALIZED), - shutting_down_(false), - overlapped_(), - client_info_(NULL) { - InitializeCriticalSection(&sync_); -} - -// This should never be called from the OnPipeConnected callback. -// Otherwise the UnregisterWaitEx call below will cause a deadlock. -CrashGenerationServer::~CrashGenerationServer() { - // New scope to release the lock automatically. - { - // Make sure no clients are added or removed beyond this point. - // Before adding or removing any clients, the critical section - // must be entered and the shutting_down_ flag checked. The - // critical section is then exited only after the clients_ list - // modifications are done and the list is in a consistent state. - AutoCriticalSection lock(&sync_); - - // Indicate to existing threads that server is shutting down. - shutting_down_ = true; - } - // No one will modify the clients_ list beyond this point - - // not even from another thread. - - // Even if there are no current worker threads running, it is possible that - // an I/O request is pending on the pipe right now but not yet done. - // In fact, it's very likely this is the case unless we are in an ERROR - // state. If we don't wait for the pending I/O to be done, then when the I/O - // completes, it may write to invalid memory. AppVerifier will flag this - // problem too. So we disconnect from the pipe and then wait for the server - // to get into error state so that the pending I/O will fail and get - // cleared. - DisconnectNamedPipe(pipe_); - int num_tries = 100; - while (num_tries-- && server_state_ != IPC_SERVER_STATE_ERROR) { - Sleep(10); - } - - // Unregister wait on the pipe. - if (pipe_wait_handle_) { - // Wait for already executing callbacks to finish. - UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE); - } - - // Close the pipe to avoid further client connections. - if (pipe_) { - CloseHandle(pipe_); - } - - // Request all ClientInfo objects to unregister all waits. - // No need to enter the critical section because no one is allowed to modify - // the clients_ list once the shutting_down_ flag is set. - std::list<ClientInfo*>::iterator iter; - for (iter = clients_.begin(); iter != clients_.end(); ++iter) { - ClientInfo* client_info = *iter; - // Unregister waits. Wait for already executing callbacks to finish. - // Unregister the client process exit wait first and only then unregister - // the dump request wait. The reason is that the OnClientExit callback - // also unregisters the dump request wait and such a race (doing the same - // unregistration from two threads) is undesirable. - client_info->UnregisterProcessExitWait(true); - client_info->UnregisterDumpRequestWaitAndBlockUntilNoPending(); - - // Destroying the ClientInfo here is safe because all wait operations for - // this ClientInfo were unregistered and no pending or running callbacks - // for this ClientInfo can possible exist (block_until_no_pending option - // was used). - delete client_info; - } - - if (server_alive_handle_) { - // Release the mutex before closing the handle so that clients requesting - // dumps wait for a long time for the server to generate a dump. - ReleaseMutex(server_alive_handle_); - CloseHandle(server_alive_handle_); - } - - if (overlapped_.hEvent) { - CloseHandle(overlapped_.hEvent); - } - - DeleteCriticalSection(&sync_); -} - -bool CrashGenerationServer::Start() { - if (server_state_ != IPC_SERVER_STATE_UNINITIALIZED) { - return false; - } - - server_state_ = IPC_SERVER_STATE_INITIAL; - - server_alive_handle_ = CreateMutex(NULL, TRUE, NULL); - if (!server_alive_handle_) { - return false; - } - - // Event to signal the client connection and pipe reads and writes. - overlapped_.hEvent = CreateEvent(NULL, // Security descriptor. - TRUE, // Manual reset. - FALSE, // Initially nonsignaled. - NULL); // Name. - if (!overlapped_.hEvent) { - return false; - } - - // Register a callback with the thread pool for the client connection. - if (!RegisterWaitForSingleObject(&pipe_wait_handle_, - overlapped_.hEvent, - OnPipeConnected, - this, - INFINITE, - kPipeIOThreadFlags)) { - return false; - } - - pipe_ = CreateNamedPipe(pipe_name_.c_str(), - kPipeAttr, - kPipeMode, - 1, - kOutBufferSize, - kInBufferSize, - 0, - pipe_sec_attrs_); - if (pipe_ == INVALID_HANDLE_VALUE) { - return false; - } - - // Kick-start the state machine. This will initiate an asynchronous wait - // for client connections. - if (!SetEvent(overlapped_.hEvent)) { - server_state_ = IPC_SERVER_STATE_ERROR; - return false; - } - - // If we are in error state, it's because we failed to start listening. - return true; -} - -// If the server thread serving clients ever gets into the -// ERROR state, reset the event, close the pipe and remain -// in the error state forever. Error state means something -// that we didn't account for has happened, and it's dangerous -// to do anything unknowingly. -void CrashGenerationServer::HandleErrorState() { - assert(server_state_ == IPC_SERVER_STATE_ERROR); - - // If the server is shutting down anyway, don't clean up - // here since shut down process will clean up. - if (shutting_down_) { - return; - } - - if (pipe_wait_handle_) { - UnregisterWait(pipe_wait_handle_); - pipe_wait_handle_ = NULL; - } - - if (pipe_) { - CloseHandle(pipe_); - pipe_ = NULL; - } - - if (overlapped_.hEvent) { - CloseHandle(overlapped_.hEvent); - overlapped_.hEvent = NULL; - } -} - -// When the server thread serving clients is in the INITIAL state, -// try to connect to the pipe asynchronously. If the connection -// finishes synchronously, directly go into the CONNECTED state; -// otherwise go into the CONNECTING state. For any problems, go -// into the ERROR state. -void CrashGenerationServer::HandleInitialState() { - assert(server_state_ == IPC_SERVER_STATE_INITIAL); - - if (!ResetEvent(overlapped_.hEvent)) { - EnterErrorState(); - return; - } - - bool success = ConnectNamedPipe(pipe_, &overlapped_) != FALSE; - DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); - - // From MSDN, it is not clear that when ConnectNamedPipe is used - // in an overlapped mode, will it ever return non-zero value, and - // if so, in what cases. - assert(!success); - - switch (error_code) { - case ERROR_IO_PENDING: - EnterStateWhenSignaled(IPC_SERVER_STATE_CONNECTING); - break; - - case ERROR_PIPE_CONNECTED: - EnterStateImmediately(IPC_SERVER_STATE_CONNECTED); - break; - - default: - EnterErrorState(); - break; - } -} - -// When the server thread serving the clients is in the CONNECTING state, -// try to get the result of the asynchronous connection request using -// the OVERLAPPED object. If the result indicates the connection is done, -// go into the CONNECTED state. If the result indicates I/O is still -// INCOMPLETE, remain in the CONNECTING state. For any problems, -// go into the DISCONNECTING state. -void CrashGenerationServer::HandleConnectingState() { - assert(server_state_ == IPC_SERVER_STATE_CONNECTING); - - DWORD bytes_count = 0; - bool success = GetOverlappedResult(pipe_, - &overlapped_, - &bytes_count, - FALSE) != FALSE; - DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); - - if (success) { - EnterStateImmediately(IPC_SERVER_STATE_CONNECTED); - } else if (error_code != ERROR_IO_INCOMPLETE) { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - } else { - // remain in CONNECTING state - } -} - -// When the server thread serving the clients is in the CONNECTED state, -// try to issue an asynchronous read from the pipe. If read completes -// synchronously or if I/O is pending then go into the READING state. -// For any problems, go into the DISCONNECTING state. -void CrashGenerationServer::HandleConnectedState() { - assert(server_state_ == IPC_SERVER_STATE_CONNECTED); - - DWORD bytes_count = 0; - memset(&msg_, 0, sizeof(msg_)); - bool success = ReadFile(pipe_, - &msg_, - sizeof(msg_), - &bytes_count, - &overlapped_) != FALSE; - DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); - - // Note that the asynchronous read issued above can finish before the - // code below executes. But, it is okay to change state after issuing - // the asynchronous read. This is because even if the asynchronous read - // is done, the callback for it would not be executed until the current - // thread finishes its execution. - if (success || error_code == ERROR_IO_PENDING) { - EnterStateWhenSignaled(IPC_SERVER_STATE_READING); - } else { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - } -} - -// When the server thread serving the clients is in the READING state, -// try to get the result of the async read. If async read is done, -// go into the READ_DONE state. For any problems, go into the -// DISCONNECTING state. -void CrashGenerationServer::HandleReadingState() { - assert(server_state_ == IPC_SERVER_STATE_READING); - - DWORD bytes_count = 0; - bool success = GetOverlappedResult(pipe_, - &overlapped_, - &bytes_count, - FALSE) != FALSE; - if (success && bytes_count == sizeof(ProtocolMessage)) { - EnterStateImmediately(IPC_SERVER_STATE_READ_DONE); - return; - } - - assert(!CheckForIOIncomplete(success)); - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); -} - -// When the server thread serving the client is in the READ_DONE state, -// validate the client's request message, register the client by -// creating appropriate objects and prepare the response. Then try to -// write the response to the pipe asynchronously. If that succeeds, -// go into the WRITING state. For any problems, go into the DISCONNECTING -// state. -void CrashGenerationServer::HandleReadDoneState() { - assert(server_state_ == IPC_SERVER_STATE_READ_DONE); - - if (!IsClientRequestValid(msg_)) { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - return; - } - - if (msg_.tag == MESSAGE_TAG_UPLOAD_REQUEST) { - if (upload_request_callback_) - upload_request_callback_(upload_context_, msg_.id); - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - return; - } - - scoped_ptr<ClientInfo> client_info( - new ClientInfo(this, - msg_.id, - msg_.dump_type, - msg_.thread_id, - msg_.exception_pointers, - msg_.assert_info, - msg_.custom_client_info)); - - if (!client_info->Initialize()) { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - return; - } - - // Issues an asynchronous WriteFile call if successful. - // Iff successful, assigns ownership of the client_info pointer to the server - // instance, in which case we must be sure not to free it in this function. - if (!RespondToClient(client_info.get())) { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - return; - } - - // This is only valid as long as it can be found in the clients_ list - client_info_ = client_info.release(); - - // Note that the asynchronous write issued by RespondToClient function - // can finish before the code below executes. But it is okay to change - // state after issuing the asynchronous write. This is because even if - // the asynchronous write is done, the callback for it would not be - // executed until the current thread finishes its execution. - EnterStateWhenSignaled(IPC_SERVER_STATE_WRITING); -} - -// When the server thread serving the clients is in the WRITING state, -// try to get the result of the async write. If the async write is done, -// go into the WRITE_DONE state. For any problems, go into the -// DISONNECTING state. -void CrashGenerationServer::HandleWritingState() { - assert(server_state_ == IPC_SERVER_STATE_WRITING); - - DWORD bytes_count = 0; - bool success = GetOverlappedResult(pipe_, - &overlapped_, - &bytes_count, - FALSE) != FALSE; - if (success) { - EnterStateImmediately(IPC_SERVER_STATE_WRITE_DONE); - return; - } - - assert(!CheckForIOIncomplete(success)); - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); -} - -// When the server thread serving the clients is in the WRITE_DONE state, -// try to issue an async read on the pipe. If the read completes synchronously -// or if I/O is still pending then go into the READING_ACK state. For any -// issues, go into the DISCONNECTING state. -void CrashGenerationServer::HandleWriteDoneState() { - assert(server_state_ == IPC_SERVER_STATE_WRITE_DONE); - - DWORD bytes_count = 0; - bool success = ReadFile(pipe_, - &msg_, - sizeof(msg_), - &bytes_count, - &overlapped_) != FALSE; - DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); - - if (success) { - EnterStateImmediately(IPC_SERVER_STATE_READING_ACK); - } else if (error_code == ERROR_IO_PENDING) { - EnterStateWhenSignaled(IPC_SERVER_STATE_READING_ACK); - } else { - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); - } -} - -// When the server thread serving the clients is in the READING_ACK state, -// try to get result of async read. Go into the DISCONNECTING state. -void CrashGenerationServer::HandleReadingAckState() { - assert(server_state_ == IPC_SERVER_STATE_READING_ACK); - - DWORD bytes_count = 0; - bool success = GetOverlappedResult(pipe_, - &overlapped_, - &bytes_count, - FALSE) != FALSE; - if (success) { - // The connection handshake with the client is now complete; perform - // the callback. - if (connect_callback_) { - // Note that there is only a single copy of the ClientInfo of the - // currently connected client. However it is being referenced from - // two different places: - // - the client_info_ member - // - the clients_ list - // The lifetime of this ClientInfo depends on the lifetime of the - // client process - basically it can go away at any time. - // However, as long as it is referenced by the clients_ list it - // is guaranteed to be valid. Enter the critical section and check - // to see whether the client_info_ can be found in the list. - // If found, execute the callback and only then leave the critical - // section. - AutoCriticalSection lock(&sync_); - - bool client_is_still_alive = false; - std::list<ClientInfo*>::iterator iter; - for (iter = clients_.begin(); iter != clients_.end(); ++iter) { - if (client_info_ == *iter) { - client_is_still_alive = true; - break; - } - } - - if (client_is_still_alive) { - connect_callback_(connect_context_, client_info_); - } - } - } else { - assert(!CheckForIOIncomplete(success)); - } - - EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING); -} - -// When the server thread serving the client is in the DISCONNECTING state, -// disconnect from the pipe and reset the event. If anything fails, go into -// the ERROR state. If it goes well, go into the INITIAL state and set the -// event to start all over again. -void CrashGenerationServer::HandleDisconnectingState() { - assert(server_state_ == IPC_SERVER_STATE_DISCONNECTING); - - // Done serving the client. - client_info_ = NULL; - - overlapped_.Internal = NULL; - overlapped_.InternalHigh = NULL; - overlapped_.Offset = 0; - overlapped_.OffsetHigh = 0; - overlapped_.Pointer = NULL; - - if (!ResetEvent(overlapped_.hEvent)) { - EnterErrorState(); - return; - } - - if (!DisconnectNamedPipe(pipe_)) { - EnterErrorState(); - return; - } - - // If the server is shutting down do not connect to the - // next client. - if (shutting_down_) { - return; - } - - EnterStateImmediately(IPC_SERVER_STATE_INITIAL); -} - -void CrashGenerationServer::EnterErrorState() { - SetEvent(overlapped_.hEvent); - server_state_ = IPC_SERVER_STATE_ERROR; -} - -void CrashGenerationServer::EnterStateWhenSignaled(IPCServerState state) { - server_state_ = state; -} - -void CrashGenerationServer::EnterStateImmediately(IPCServerState state) { - server_state_ = state; - - if (!SetEvent(overlapped_.hEvent)) { - server_state_ = IPC_SERVER_STATE_ERROR; - } -} - -bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info, - ProtocolMessage* reply) const { - reply->tag = MESSAGE_TAG_REGISTRATION_RESPONSE; - reply->id = GetCurrentProcessId(); - - if (CreateClientHandles(client_info, reply)) { - return true; - } - - // Closing of remote handles (belonging to a different process) can - // only be done through DuplicateHandle. - if (reply->dump_request_handle) { - DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle - reply->dump_request_handle, // hSourceHandle - NULL, // hTargetProcessHandle - 0, // lpTargetHandle - 0, // dwDesiredAccess - FALSE, // bInheritHandle - DUPLICATE_CLOSE_SOURCE); // dwOptions - reply->dump_request_handle = NULL; - } - - if (reply->dump_generated_handle) { - DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle - reply->dump_generated_handle, // hSourceHandle - NULL, // hTargetProcessHandle - 0, // lpTargetHandle - 0, // dwDesiredAccess - FALSE, // bInheritHandle - DUPLICATE_CLOSE_SOURCE); // dwOptions - reply->dump_generated_handle = NULL; - } - - if (reply->server_alive_handle) { - DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle - reply->server_alive_handle, // hSourceHandle - NULL, // hTargetProcessHandle - 0, // lpTargetHandle - 0, // dwDesiredAccess - FALSE, // bInheritHandle - DUPLICATE_CLOSE_SOURCE); // dwOptions - reply->server_alive_handle = NULL; - } - - return false; -} - -bool CrashGenerationServer::CreateClientHandles(const ClientInfo& client_info, - ProtocolMessage* reply) const { - HANDLE current_process = GetCurrentProcess(); - if (!DuplicateHandle(current_process, - client_info.dump_requested_handle(), - client_info.process_handle(), - &reply->dump_request_handle, - kDumpRequestEventAccess, - FALSE, - 0)) { - return false; - } - - if (!DuplicateHandle(current_process, - client_info.dump_generated_handle(), - client_info.process_handle(), - &reply->dump_generated_handle, - kDumpGeneratedEventAccess, - FALSE, - 0)) { - return false; - } - - if (!DuplicateHandle(current_process, - server_alive_handle_, - client_info.process_handle(), - &reply->server_alive_handle, - kMutexAccess, - FALSE, - 0)) { - return false; - } - - return true; -} - -bool CrashGenerationServer::RespondToClient(ClientInfo* client_info) { - ProtocolMessage reply; - if (!PrepareReply(*client_info, &reply)) { - return false; - } - - DWORD bytes_count = 0; - bool success = WriteFile(pipe_, - &reply, - sizeof(reply), - &bytes_count, - &overlapped_) != FALSE; - DWORD error_code = success ? ERROR_SUCCESS : GetLastError(); - - if (!success && error_code != ERROR_IO_PENDING) { - return false; - } - - // Takes over ownership of client_info. We MUST return true if AddClient - // succeeds. - return AddClient(client_info); -} - -// The server thread servicing the clients runs this method. The method -// implements the state machine described in ReadMe.txt along with the -// helper methods HandleXXXState. -void CrashGenerationServer::HandleConnectionRequest() { - // If the server is shutting down, get into ERROR state, reset the event so - // more workers don't run and return immediately. - if (shutting_down_) { - server_state_ = IPC_SERVER_STATE_ERROR; - ResetEvent(overlapped_.hEvent); - return; - } - - switch (server_state_) { - case IPC_SERVER_STATE_ERROR: - HandleErrorState(); - break; - - case IPC_SERVER_STATE_INITIAL: - HandleInitialState(); - break; - - case IPC_SERVER_STATE_CONNECTING: - HandleConnectingState(); - break; - - case IPC_SERVER_STATE_CONNECTED: - HandleConnectedState(); - break; - - case IPC_SERVER_STATE_READING: - HandleReadingState(); - break; - - case IPC_SERVER_STATE_READ_DONE: - HandleReadDoneState(); - break; - - case IPC_SERVER_STATE_WRITING: - HandleWritingState(); - break; - - case IPC_SERVER_STATE_WRITE_DONE: - HandleWriteDoneState(); - break; - - case IPC_SERVER_STATE_READING_ACK: - HandleReadingAckState(); - break; - - case IPC_SERVER_STATE_DISCONNECTING: - HandleDisconnectingState(); - break; - - default: - assert(false); - // This indicates that we added one more state without - // adding handling code. - server_state_ = IPC_SERVER_STATE_ERROR; - break; - } -} - -bool CrashGenerationServer::AddClient(ClientInfo* client_info) { - HANDLE request_wait_handle = NULL; - if (!RegisterWaitForSingleObject(&request_wait_handle, - client_info->dump_requested_handle(), - OnDumpRequest, - client_info, - INFINITE, - kDumpRequestThreadFlags)) { - return false; - } - - client_info->set_dump_request_wait_handle(request_wait_handle); - - // OnClientEnd will be called when the client process terminates. - HANDLE process_wait_handle = NULL; - if (!RegisterWaitForSingleObject(&process_wait_handle, - client_info->process_handle(), - OnClientEnd, - client_info, - INFINITE, - WT_EXECUTEONLYONCE)) { - return false; - } - - client_info->set_process_exit_wait_handle(process_wait_handle); - - // New scope to hold the lock for the shortest time. - { - AutoCriticalSection lock(&sync_); - if (shutting_down_) { - // If server is shutting down, don't add new clients - return false; - } - clients_.push_back(client_info); - } - - return true; -} - -// static -void CALLBACK CrashGenerationServer::OnPipeConnected(void* context, BOOLEAN) { - assert(context); - - CrashGenerationServer* obj = - reinterpret_cast<CrashGenerationServer*>(context); - obj->HandleConnectionRequest(); -} - -// static -void CALLBACK CrashGenerationServer::OnDumpRequest(void* context, BOOLEAN) { - assert(context); - ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context); - - CrashGenerationServer* crash_server = client_info->crash_server(); - assert(crash_server); - if (crash_server->pre_fetch_custom_info_) { - client_info->PopulateCustomInfo(); - } - crash_server->HandleDumpRequest(*client_info); - - ResetEvent(client_info->dump_requested_handle()); -} - -// static -void CALLBACK CrashGenerationServer::OnClientEnd(void* context, BOOLEAN) { - assert(context); - ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context); - - CrashGenerationServer* crash_server = client_info->crash_server(); - assert(crash_server); - - crash_server->HandleClientProcessExit(client_info); -} - -void CrashGenerationServer::HandleClientProcessExit(ClientInfo* client_info) { - assert(client_info); - - // Must unregister the dump request wait operation and wait for any - // dump requests that might be pending to finish before proceeding - // with the client_info cleanup. - client_info->UnregisterDumpRequestWaitAndBlockUntilNoPending(); - - if (exit_callback_) { - exit_callback_(exit_context_, client_info); - } - - // Start a new scope to release lock automatically. - { - AutoCriticalSection lock(&sync_); - if (shutting_down_) { - // The crash generation server is shutting down and as part of the - // shutdown process it will delete all clients from the clients_ list. - return; - } - clients_.remove(client_info); - } - - // Explicitly unregister the process exit wait using the non-blocking method. - // Otherwise, the destructor will attempt to unregister it using the blocking - // method which will lead to a deadlock because it is being called from the - // callback of the same wait operation - client_info->UnregisterProcessExitWait(false); - - delete client_info; -} - -void CrashGenerationServer::HandleDumpRequest(const ClientInfo& client_info) { - bool execute_callback = true; - // Generate the dump only if it's explicitly requested by the - // server application; otherwise the server might want to generate - // dump in the callback. - std::wstring dump_path; - if (generate_dumps_) { - if (!GenerateDump(client_info, &dump_path)) { - // client proccess terminated or some other error - execute_callback = false; - } - } - - if (dump_callback_ && execute_callback) { - std::wstring* ptr_dump_path = (dump_path == L"") ? NULL : &dump_path; - dump_callback_(dump_context_, &client_info, ptr_dump_path); - } - - SetEvent(client_info.dump_generated_handle()); -} - -bool CrashGenerationServer::GenerateDump(const ClientInfo& client, - std::wstring* dump_path) { - assert(client.pid() != 0); - assert(client.process_handle()); - - // We have to get the address of EXCEPTION_INFORMATION from - // the client process address space. - EXCEPTION_POINTERS* client_ex_info = NULL; - if (!client.GetClientExceptionInfo(&client_ex_info)) { - return false; - } - - DWORD client_thread_id = 0; - if (!client.GetClientThreadId(&client_thread_id)) { - return false; - } - - MinidumpGenerator dump_generator(dump_path_, - client.process_handle(), - client.pid(), - client_thread_id, - GetCurrentThreadId(), - client_ex_info, - client.assert_info(), - client.dump_type(), - true); - if (!dump_generator.GenerateDumpFile(dump_path)) { - return false; - } - return dump_generator.WriteMinidump(); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h deleted file mode 100644 index 0ea90e510..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ -#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ - -#include <list> -#include <string> -#include "client/windows/common/ipc_protocol.h" -#include "client/windows/crash_generation/minidump_generator.h" -#include "common/scoped_ptr.h" - -namespace google_breakpad { -class ClientInfo; - -// Abstraction for server side implementation of out-of-process crash -// generation protocol for Windows platform only. It generates Windows -// minidump files for client processes that request dump generation. When -// the server is requested to start listening for clients (by calling the -// Start method), it creates a named pipe and waits for the clients to -// register. In response, it hands them event handles that the client can -// signal to request dump generation. When the clients request dump -// generation in this way, the server generates Windows minidump files. -class CrashGenerationServer { - public: - typedef void (*OnClientConnectedCallback)(void* context, - const ClientInfo* client_info); - - typedef void (*OnClientDumpRequestCallback)(void* context, - const ClientInfo* client_info, - const std::wstring* file_path); - - typedef void (*OnClientExitedCallback)(void* context, - const ClientInfo* client_info); - - typedef void (*OnClientUploadRequestCallback)(void* context, - const DWORD crash_id); - - // Creates an instance with the given parameters. - // - // Parameter pipe_name: Name of the Windows named pipe - // Parameter pipe_sec_attrs Security attributes to set on the pipe. Pass - // NULL to use default security on the pipe. By default, the pipe created - // allows Local System, Administrators and the Creator full control and - // the Everyone group read access on the pipe. - // Parameter connect_callback: Callback for a new client connection. - // Parameter connect_context: Context for client connection callback. - // Parameter crash_callback: Callback for a client crash dump request. - // Parameter crash_context: Context for client crash dump request callback. - // Parameter exit_callback: Callback for client process exit. - // Parameter exit_context: Context for client exit callback. - // Parameter generate_dumps: Whether to automatically generate dumps. - // Client code of this class might want to generate dumps explicitly in the - // crash dump request callback. In that case, false can be passed for this - // parameter. - // Parameter dump_path: Path for generating dumps; required only if true is - // passed for generateDumps parameter; NULL can be passed otherwise. - CrashGenerationServer(const std::wstring& pipe_name, - SECURITY_ATTRIBUTES* pipe_sec_attrs, - OnClientConnectedCallback connect_callback, - void* connect_context, - OnClientDumpRequestCallback dump_callback, - void* dump_context, - OnClientExitedCallback exit_callback, - void* exit_context, - OnClientUploadRequestCallback upload_request_callback, - void* upload_context, - bool generate_dumps, - const std::wstring* dump_path); - - ~CrashGenerationServer(); - - // Performs initialization steps needed to start listening to clients. Upon - // successful return clients may connect to this server's pipe. - // - // Returns true if initialization is successful; false otherwise. - bool Start(); - - void pre_fetch_custom_info(bool do_pre_fetch) { - pre_fetch_custom_info_ = do_pre_fetch; - } - - private: - // Various states the client can be in during the handshake with - // the server. - enum IPCServerState { - // Server starts in this state. - IPC_SERVER_STATE_UNINITIALIZED, - - // Server is in error state and it cannot serve any clients. - IPC_SERVER_STATE_ERROR, - - // Server starts in this state. - IPC_SERVER_STATE_INITIAL, - - // Server has issued an async connect to the pipe and it is waiting - // for the connection to be established. - IPC_SERVER_STATE_CONNECTING, - - // Server is connected successfully. - IPC_SERVER_STATE_CONNECTED, - - // Server has issued an async read from the pipe and it is waiting for - // the read to finish. - IPC_SERVER_STATE_READING, - - // Server is done reading from the pipe. - IPC_SERVER_STATE_READ_DONE, - - // Server has issued an async write to the pipe and it is waiting for - // the write to finish. - IPC_SERVER_STATE_WRITING, - - // Server is done writing to the pipe. - IPC_SERVER_STATE_WRITE_DONE, - - // Server has issued an async read from the pipe for an ack and it - // is waiting for the read to finish. - IPC_SERVER_STATE_READING_ACK, - - // Server is done writing to the pipe and it is now ready to disconnect - // and reconnect. - IPC_SERVER_STATE_DISCONNECTING - }; - - // - // Helper methods to handle various server IPC states. - // - void HandleErrorState(); - void HandleInitialState(); - void HandleConnectingState(); - void HandleConnectedState(); - void HandleReadingState(); - void HandleReadDoneState(); - void HandleWritingState(); - void HandleWriteDoneState(); - void HandleReadingAckState(); - void HandleDisconnectingState(); - - // Prepares reply for a client from the given parameters. - bool PrepareReply(const ClientInfo& client_info, - ProtocolMessage* reply) const; - - // Duplicates various handles in the ClientInfo object for the client - // process and stores them in the given ProtocolMessage instance. If - // creating any handle fails, ProtocolMessage will contain the handles - // already created successfully, which should be closed by the caller. - bool CreateClientHandles(const ClientInfo& client_info, - ProtocolMessage* reply) const; - - // Response to the given client. Return true if all steps of - // responding to the client succeed, false otherwise. - bool RespondToClient(ClientInfo* client_info); - - // Handles a connection request from the client. - void HandleConnectionRequest(); - - // Handles a dump request from the client. - void HandleDumpRequest(const ClientInfo& client_info); - - // Callback for pipe connected event. - static void CALLBACK OnPipeConnected(void* context, BOOLEAN timer_or_wait); - - // Callback for a dump request. - static void CALLBACK OnDumpRequest(void* context, BOOLEAN timer_or_wait); - - // Callback for client process exit event. - static void CALLBACK OnClientEnd(void* context, BOOLEAN timer_or_wait); - - // Handles client process exit. - void HandleClientProcessExit(ClientInfo* client_info); - - // Adds the given client to the list of registered clients. - bool AddClient(ClientInfo* client_info); - - // Generates dump for the given client. - bool GenerateDump(const ClientInfo& client, std::wstring* dump_path); - - // Puts the server in a permanent error state and sets a signal such that - // the state will be immediately entered after the current state transition - // is complete. - void EnterErrorState(); - - // Puts the server in the specified state and sets a signal such that the - // state is immediately entered after the current state transition is - // complete. - void EnterStateImmediately(IPCServerState state); - - // Puts the server in the specified state. No signal will be set, so the state - // transition will only occur when signaled manually or by completion of an - // asynchronous IO operation. - void EnterStateWhenSignaled(IPCServerState state); - - // Sync object for thread-safe access to the shared list of clients. - CRITICAL_SECTION sync_; - - // List of clients. - std::list<ClientInfo*> clients_; - - // Pipe name. - std::wstring pipe_name_; - - // Pipe security attributes - SECURITY_ATTRIBUTES* pipe_sec_attrs_; - - // Handle to the pipe used for handshake with clients. - HANDLE pipe_; - - // Pipe wait handle. - HANDLE pipe_wait_handle_; - - // Handle to server-alive mutex. - HANDLE server_alive_handle_; - - // Callback for a successful client connection. - OnClientConnectedCallback connect_callback_; - - // Context for client connected callback. - void* connect_context_; - - // Callback for a client dump request. - OnClientDumpRequestCallback dump_callback_; - - // Context for client dump request callback. - void* dump_context_; - - // Callback for client process exit. - OnClientExitedCallback exit_callback_; - - // Context for client process exit callback. - void* exit_context_; - - // Callback for upload request. - OnClientUploadRequestCallback upload_request_callback_; - - // Context for upload request callback. - void* upload_context_; - - // Whether to generate dumps. - bool generate_dumps_; - - // Wether to populate custom information up-front. - bool pre_fetch_custom_info_; - - // The dump path for the server. - const std::wstring dump_path_; - - // State of the server in performing the IPC with the client. - // Note that since we restrict the pipe to one instance, we - // only need to keep one state of the server. Otherwise, server - // would have one state per client it is talking to. - IPCServerState server_state_; - - // Whether the server is shutting down. - bool shutting_down_; - - // Overlapped instance for async I/O on the pipe. - OVERLAPPED overlapped_; - - // Message object used in IPC with the client. - ProtocolMessage msg_; - - // Client Info for the client that's connecting to the server. - ClientInfo* client_info_; - - // Disable copy ctor and operator=. - CrashGenerationServer(const CrashGenerationServer& crash_server); - CrashGenerationServer& operator=(const CrashGenerationServer& crash_server); -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.cc deleted file mode 100644 index 786c9b937..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.cc +++ /dev/null @@ -1,579 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "client/windows/crash_generation/minidump_generator.h" - -#include <assert.h> -#include <avrfsdk.h> - -#include <algorithm> -#include <iterator> -#include <list> -#include <vector> - -#include "client/windows/common/auto_critical_section.h" -#include "common/scoped_ptr.h" -#include "common/windows/guid_string.h" - -using std::wstring; - -namespace { - -// A helper class used to collect handle operations data. Unlike -// |MiniDumpWithHandleData| it records the operations for a single handle value -// only, making it possible to include this information to a minidump. -class HandleTraceData { - public: - HandleTraceData(); - ~HandleTraceData(); - - // Collects the handle operations data and formats a user stream to be added - // to the minidump. - bool CollectHandleData(HANDLE process_handle, - EXCEPTION_POINTERS* exception_pointers); - - // Fills the user dump entry with a pointer to the collected handle operations - // data. Returns |true| if the entry was initialized successfully, or |false| - // if no trace data is available. - bool GetUserStream(MINIDUMP_USER_STREAM* user_stream); - - private: - // Reads the exception code from the client process's address space. - // This routine assumes that the client process's pointer width matches ours. - static bool ReadExceptionCode(HANDLE process_handle, - EXCEPTION_POINTERS* exception_pointers, - DWORD* exception_code); - - // Stores handle operations retrieved by VerifierEnumerateResource(). - static ULONG CALLBACK RecordHandleOperations(void* resource_description, - void* enumeration_context, - ULONG* enumeration_level); - - // Function pointer type for VerifierEnumerateResource, which is looked up - // dynamically. - typedef BOOL (WINAPI* VerifierEnumerateResourceType)( - HANDLE Process, - ULONG Flags, - ULONG ResourceType, - AVRF_RESOURCE_ENUMERATE_CALLBACK ResourceCallback, - PVOID EnumerationContext); - - // Handle to dynamically loaded verifier.dll. - HMODULE verifier_module_; - - // Pointer to the VerifierEnumerateResource function. - VerifierEnumerateResourceType enumerate_resource_; - - // Handle value to look for. - ULONG64 handle_; - - // List of handle operations for |handle_|. - std::list<AVRF_HANDLE_OPERATION> operations_; - - // Minidump stream data. - std::vector<char> stream_; -}; - -HandleTraceData::HandleTraceData() - : verifier_module_(NULL), - enumerate_resource_(NULL), - handle_(NULL) { -} - -HandleTraceData::~HandleTraceData() { - if (verifier_module_) { - FreeLibrary(verifier_module_); - } -} - -bool HandleTraceData::CollectHandleData( - HANDLE process_handle, - EXCEPTION_POINTERS* exception_pointers) { - DWORD exception_code; - if (!ReadExceptionCode(process_handle, exception_pointers, &exception_code)) { - return false; - } - - // Verify whether the execption is STATUS_INVALID_HANDLE. Do not record any - // handle information if it is a different exception to keep the minidump - // small. - if (exception_code != STATUS_INVALID_HANDLE) { - return true; - } - - // Load verifier!VerifierEnumerateResource() dynamically. - verifier_module_ = LoadLibrary(TEXT("verifier.dll")); - if (!verifier_module_) { - return false; - } - - enumerate_resource_ = reinterpret_cast<VerifierEnumerateResourceType>( - GetProcAddress(verifier_module_, "VerifierEnumerateResource")); - if (!enumerate_resource_) { - return false; - } - - // STATUS_INVALID_HANDLE does not provide the offending handle value in - // the exception parameters so we have to guess. At the moment we scan - // the handle operations trace looking for the last invalid handle operation - // and record only the operations for that handle value. - if (enumerate_resource_(process_handle, - 0, - AvrfResourceHandleTrace, - &RecordHandleOperations, - this) != ERROR_SUCCESS) { - // The handle tracing must have not been enabled. - return true; - } - - // Now that |handle_| is initialized, purge all irrelevant operations. - std::list<AVRF_HANDLE_OPERATION>::iterator i = operations_.begin(); - std::list<AVRF_HANDLE_OPERATION>::iterator i_end = operations_.end(); - while (i != i_end) { - if (i->Handle == handle_) { - ++i; - } else { - i = operations_.erase(i); - } - } - - // Convert the list of recorded operations to a minidump stream. - stream_.resize(sizeof(MINIDUMP_HANDLE_OPERATION_LIST) + - sizeof(AVRF_HANDLE_OPERATION) * operations_.size()); - - MINIDUMP_HANDLE_OPERATION_LIST* stream_data = - reinterpret_cast<MINIDUMP_HANDLE_OPERATION_LIST*>( - &stream_.front()); - stream_data->SizeOfHeader = sizeof(MINIDUMP_HANDLE_OPERATION_LIST); - stream_data->SizeOfEntry = sizeof(AVRF_HANDLE_OPERATION); - stream_data->NumberOfEntries = static_cast<ULONG32>(operations_.size()); - stream_data->Reserved = 0; - std::copy(operations_.begin(), - operations_.end(), -#ifdef _MSC_VER - stdext::checked_array_iterator<AVRF_HANDLE_OPERATION*>( - reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1), - operations_.size()) -#else - reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1) -#endif - ); - - return true; -} - -bool HandleTraceData::GetUserStream(MINIDUMP_USER_STREAM* user_stream) { - if (stream_.empty()) { - return false; - } else { - user_stream->Type = HandleOperationListStream; - user_stream->BufferSize = static_cast<ULONG>(stream_.size()); - user_stream->Buffer = &stream_.front(); - return true; - } -} - -bool HandleTraceData::ReadExceptionCode( - HANDLE process_handle, - EXCEPTION_POINTERS* exception_pointers, - DWORD* exception_code) { - EXCEPTION_POINTERS pointers; - if (!ReadProcessMemory(process_handle, - exception_pointers, - &pointers, - sizeof(pointers), - NULL)) { - return false; - } - - if (!ReadProcessMemory(process_handle, - pointers.ExceptionRecord, - exception_code, - sizeof(*exception_code), - NULL)) { - return false; - } - - return true; -} - -ULONG CALLBACK HandleTraceData::RecordHandleOperations( - void* resource_description, - void* enumeration_context, - ULONG* enumeration_level) { - AVRF_HANDLE_OPERATION* description = - reinterpret_cast<AVRF_HANDLE_OPERATION*>(resource_description); - HandleTraceData* self = - reinterpret_cast<HandleTraceData*>(enumeration_context); - - // Remember the last invalid handle operation. - if (description->OperationType == OperationDbBADREF) { - self->handle_ = description->Handle; - } - - // Record all handle operations. - self->operations_.push_back(*description); - - *enumeration_level = HeapEnumerationEverything; - return ERROR_SUCCESS; -} - -} // namespace - -namespace google_breakpad { - -MinidumpGenerator::MinidumpGenerator( - const std::wstring& dump_path, - const HANDLE process_handle, - const DWORD process_id, - const DWORD thread_id, - const DWORD requesting_thread_id, - EXCEPTION_POINTERS* exception_pointers, - MDRawAssertionInfo* assert_info, - const MINIDUMP_TYPE dump_type, - const bool is_client_pointers) - : dbghelp_module_(NULL), - write_dump_(NULL), - rpcrt4_module_(NULL), - create_uuid_(NULL), - process_handle_(process_handle), - process_id_(process_id), - thread_id_(thread_id), - requesting_thread_id_(requesting_thread_id), - exception_pointers_(exception_pointers), - assert_info_(assert_info), - dump_type_(dump_type), - is_client_pointers_(is_client_pointers), - dump_path_(dump_path), - dump_file_(INVALID_HANDLE_VALUE), - full_dump_file_(INVALID_HANDLE_VALUE), - dump_file_is_internal_(false), - full_dump_file_is_internal_(false), - additional_streams_(NULL), - callback_info_(NULL) { - InitializeCriticalSection(&module_load_sync_); - InitializeCriticalSection(&get_proc_address_sync_); -} - -MinidumpGenerator::~MinidumpGenerator() { - if (dump_file_is_internal_ && dump_file_ != INVALID_HANDLE_VALUE) { - CloseHandle(dump_file_); - } - - if (full_dump_file_is_internal_ && full_dump_file_ != INVALID_HANDLE_VALUE) { - CloseHandle(full_dump_file_); - } - - if (dbghelp_module_) { - FreeLibrary(dbghelp_module_); - } - - if (rpcrt4_module_) { - FreeLibrary(rpcrt4_module_); - } - - DeleteCriticalSection(&get_proc_address_sync_); - DeleteCriticalSection(&module_load_sync_); -} - -bool MinidumpGenerator::WriteMinidump() { - bool full_memory_dump = (dump_type_ & MiniDumpWithFullMemory) != 0; - if (dump_file_ == INVALID_HANDLE_VALUE || - (full_memory_dump && full_dump_file_ == INVALID_HANDLE_VALUE)) { - return false; - } - - MiniDumpWriteDumpType write_dump = GetWriteDump(); - if (!write_dump) { - return false; - } - - MINIDUMP_EXCEPTION_INFORMATION* dump_exception_pointers = NULL; - MINIDUMP_EXCEPTION_INFORMATION dump_exception_info; - - // Setup the exception information object only if it's a dump - // due to an exception. - if (exception_pointers_) { - dump_exception_pointers = &dump_exception_info; - dump_exception_info.ThreadId = thread_id_; - dump_exception_info.ExceptionPointers = exception_pointers_; - dump_exception_info.ClientPointers = is_client_pointers_; - } - - // Add an MDRawBreakpadInfo stream to the minidump, to provide additional - // information about the exception handler to the Breakpad processor. - // The information will help the processor determine which threads are - // relevant. The Breakpad processor does not require this information but - // can function better with Breakpad-generated dumps when it is present. - // The native debugger is not harmed by the presence of this information. - MDRawBreakpadInfo breakpad_info = {0}; - if (!is_client_pointers_) { - // Set the dump thread id and requesting thread id only in case of - // in-process dump generation. - breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | - MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; - breakpad_info.dump_thread_id = thread_id_; - breakpad_info.requesting_thread_id = requesting_thread_id_; - } - - int additional_streams_count = additional_streams_ ? - additional_streams_->UserStreamCount : 0; - scoped_array<MINIDUMP_USER_STREAM> user_stream_array( - new MINIDUMP_USER_STREAM[3 + additional_streams_count]); - user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM; - user_stream_array[0].BufferSize = sizeof(breakpad_info); - user_stream_array[0].Buffer = &breakpad_info; - - MINIDUMP_USER_STREAM_INFORMATION user_streams; - user_streams.UserStreamCount = 1; - user_streams.UserStreamArray = user_stream_array.get(); - - MDRawAssertionInfo* actual_assert_info = assert_info_; - MDRawAssertionInfo client_assert_info = {{0}}; - - if (assert_info_) { - // If the assertion info object lives in the client process, - // read the memory of the client process. - if (is_client_pointers_) { - SIZE_T bytes_read = 0; - if (!ReadProcessMemory(process_handle_, - assert_info_, - &client_assert_info, - sizeof(client_assert_info), - &bytes_read)) { - if (dump_file_is_internal_) - CloseHandle(dump_file_); - if (full_dump_file_is_internal_ && - full_dump_file_ != INVALID_HANDLE_VALUE) - CloseHandle(full_dump_file_); - return false; - } - - if (bytes_read != sizeof(client_assert_info)) { - if (dump_file_is_internal_) - CloseHandle(dump_file_); - if (full_dump_file_is_internal_ && - full_dump_file_ != INVALID_HANDLE_VALUE) - CloseHandle(full_dump_file_); - return false; - } - - actual_assert_info = &client_assert_info; - } - - user_stream_array[1].Type = MD_ASSERTION_INFO_STREAM; - user_stream_array[1].BufferSize = sizeof(MDRawAssertionInfo); - user_stream_array[1].Buffer = actual_assert_info; - ++user_streams.UserStreamCount; - } - - if (additional_streams_) { - for (size_t i = 0; - i < additional_streams_->UserStreamCount; - i++, user_streams.UserStreamCount++) { - user_stream_array[user_streams.UserStreamCount].Type = - additional_streams_->UserStreamArray[i].Type; - user_stream_array[user_streams.UserStreamCount].BufferSize = - additional_streams_->UserStreamArray[i].BufferSize; - user_stream_array[user_streams.UserStreamCount].Buffer = - additional_streams_->UserStreamArray[i].Buffer; - } - } - - // If the process is terminated by STATUS_INVALID_HANDLE exception store - // the trace of operations for the offending handle value. Do nothing special - // if the client already requested the handle trace to be stored in the dump. - HandleTraceData handle_trace_data; - if (exception_pointers_ && (dump_type_ & MiniDumpWithHandleData) == 0) { - if (!handle_trace_data.CollectHandleData(process_handle_, - exception_pointers_)) { - if (dump_file_is_internal_) - CloseHandle(dump_file_); - if (full_dump_file_is_internal_ && - full_dump_file_ != INVALID_HANDLE_VALUE) - CloseHandle(full_dump_file_); - return false; - } - } - - bool result_full_memory = true; - if (full_memory_dump) { - result_full_memory = write_dump( - process_handle_, - process_id_, - full_dump_file_, - static_cast<MINIDUMP_TYPE>((dump_type_ & (~MiniDumpNormal)) - | MiniDumpWithHandleData), - exception_pointers_ ? &dump_exception_info : NULL, - &user_streams, - NULL) != FALSE; - } - - // Add handle operations trace stream to the minidump if it was collected. - if (handle_trace_data.GetUserStream( - &user_stream_array[user_streams.UserStreamCount])) { - ++user_streams.UserStreamCount; - } - - bool result_minidump = write_dump( - process_handle_, - process_id_, - dump_file_, - static_cast<MINIDUMP_TYPE>((dump_type_ & (~MiniDumpWithFullMemory)) - | MiniDumpNormal), - exception_pointers_ ? &dump_exception_info : NULL, - &user_streams, - callback_info_) != FALSE; - - return result_minidump && result_full_memory; -} - -bool MinidumpGenerator::GenerateDumpFile(wstring* dump_path) { - // The dump file was already set by handle or this function was previously - // called. - if (dump_file_ != INVALID_HANDLE_VALUE) { - return false; - } - - wstring dump_file_path; - if (!GenerateDumpFilePath(&dump_file_path)) { - return false; - } - - dump_file_ = CreateFile(dump_file_path.c_str(), - GENERIC_WRITE, - 0, - NULL, - CREATE_NEW, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (dump_file_ == INVALID_HANDLE_VALUE) { - return false; - } - - dump_file_is_internal_ = true; - *dump_path = dump_file_path; - return true; -} - -bool MinidumpGenerator::GenerateFullDumpFile(wstring* full_dump_path) { - // A full minidump was not requested. - if ((dump_type_ & MiniDumpWithFullMemory) == 0) { - return false; - } - - // The dump file was already set by handle or this function was previously - // called. - if (full_dump_file_ != INVALID_HANDLE_VALUE) { - return false; - } - - wstring full_dump_file_path; - if (!GenerateDumpFilePath(&full_dump_file_path)) { - return false; - } - full_dump_file_path.resize(full_dump_file_path.size() - 4); // strip .dmp - full_dump_file_path.append(TEXT("-full.dmp")); - - full_dump_file_ = CreateFile(full_dump_file_path.c_str(), - GENERIC_WRITE, - 0, - NULL, - CREATE_NEW, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (full_dump_file_ == INVALID_HANDLE_VALUE) { - return false; - } - - full_dump_file_is_internal_ = true; - *full_dump_path = full_dump_file_path; - return true; -} - -HMODULE MinidumpGenerator::GetDbghelpModule() { - AutoCriticalSection lock(&module_load_sync_); - if (!dbghelp_module_) { - dbghelp_module_ = LoadLibrary(TEXT("dbghelp.dll")); - } - - return dbghelp_module_; -} - -MinidumpGenerator::MiniDumpWriteDumpType MinidumpGenerator::GetWriteDump() { - AutoCriticalSection lock(&get_proc_address_sync_); - if (!write_dump_) { - HMODULE module = GetDbghelpModule(); - if (module) { - FARPROC proc = GetProcAddress(module, "MiniDumpWriteDump"); - write_dump_ = reinterpret_cast<MiniDumpWriteDumpType>(proc); - } - } - - return write_dump_; -} - -HMODULE MinidumpGenerator::GetRpcrt4Module() { - AutoCriticalSection lock(&module_load_sync_); - if (!rpcrt4_module_) { - rpcrt4_module_ = LoadLibrary(TEXT("rpcrt4.dll")); - } - - return rpcrt4_module_; -} - -MinidumpGenerator::UuidCreateType MinidumpGenerator::GetCreateUuid() { - AutoCriticalSection lock(&module_load_sync_); - if (!create_uuid_) { - HMODULE module = GetRpcrt4Module(); - if (module) { - FARPROC proc = GetProcAddress(module, "UuidCreate"); - create_uuid_ = reinterpret_cast<UuidCreateType>(proc); - } - } - - return create_uuid_; -} - -bool MinidumpGenerator::GenerateDumpFilePath(wstring* file_path) { - UUID id = {0}; - - UuidCreateType create_uuid = GetCreateUuid(); - if (!create_uuid) { - return false; - } - - create_uuid(&id); - wstring id_str = GUIDString::GUIDToWString(&id); - - *file_path = dump_path_ + TEXT("\\") + id_str + TEXT(".dmp"); - return true; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.h b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.h deleted file mode 100644 index a3c123056..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/minidump_generator.h +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATOR_H_ -#define CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATOR_H_ - -#include <windows.h> -#include <dbghelp.h> -#include <rpc.h> -#include <list> -#include <string> -#include "google_breakpad/common/minidump_format.h" - -namespace google_breakpad { - -// Abstraction for various objects and operations needed to generate -// minidump on Windows. This abstraction is useful to hide all the gory -// details for minidump generation and provide a clean interface to -// the clients to generate minidumps. -class MinidumpGenerator { - public: - // Creates an instance with the given parameters. - // is_client_pointers specifies whether the exception_pointers and - // assert_info point into the process that is being dumped. - // Before calling WriteMinidump on the returned instance a dump file muct be - // specified by a call to either SetDumpFile() or GenerateDumpFile(). - // If a full dump file will be requested via a subsequent call to either - // SetFullDumpFile or GenerateFullDumpFile() dump_type must include - // MiniDumpWithFullMemory. - MinidumpGenerator(const std::wstring& dump_path, - const HANDLE process_handle, - const DWORD process_id, - const DWORD thread_id, - const DWORD requesting_thread_id, - EXCEPTION_POINTERS* exception_pointers, - MDRawAssertionInfo* assert_info, - const MINIDUMP_TYPE dump_type, - const bool is_client_pointers); - - ~MinidumpGenerator(); - - void SetDumpFile(const HANDLE dump_file) { dump_file_ = dump_file; } - void SetFullDumpFile(const HANDLE full_dump_file) { - full_dump_file_ = full_dump_file; - } - - // Generate the name for the dump file that will be written to once - // WriteMinidump() is called. Can only be called once and cannot be called - // if the dump file is set via SetDumpFile(). - bool GenerateDumpFile(std::wstring* dump_path); - - // Generate the name for the full dump file that will be written to once - // WriteMinidump() is called. Cannot be called unless the minidump type - // includes MiniDumpWithFullMemory. Can only be called once and cannot be - // called if the dump file is set via SetFullDumpFile(). - bool GenerateFullDumpFile(std::wstring* full_dump_path); - - void SetAdditionalStreams( - MINIDUMP_USER_STREAM_INFORMATION* additional_streams) { - additional_streams_ = additional_streams; - } - - void SetCallback(MINIDUMP_CALLBACK_INFORMATION* callback_info) { - callback_info_ = callback_info; - } - - // Writes the minidump with the given parameters. Stores the - // dump file path in the dump_path parameter if dump generation - // succeeds. - bool WriteMinidump(); - - private: - // Function pointer type for MiniDumpWriteDump, which is looked up - // dynamically. - typedef BOOL (WINAPI* MiniDumpWriteDumpType)( - HANDLE hProcess, - DWORD ProcessId, - HANDLE hFile, - MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); - - // Function pointer type for UuidCreate, which is looked up dynamically. - typedef RPC_STATUS (RPC_ENTRY* UuidCreateType)(UUID* Uuid); - - // Loads the appropriate DLL lazily in a thread safe way. - HMODULE GetDbghelpModule(); - - // Loads the appropriate DLL and gets a pointer to the MiniDumpWriteDump - // function lazily and in a thread-safe manner. - MiniDumpWriteDumpType GetWriteDump(); - - // Loads the appropriate DLL lazily in a thread safe way. - HMODULE GetRpcrt4Module(); - - // Loads the appropriate DLL and gets a pointer to the UuidCreate - // function lazily and in a thread-safe manner. - UuidCreateType GetCreateUuid(); - - // Returns the path for the file to write dump to. - bool GenerateDumpFilePath(std::wstring* file_path); - - // Handle to dynamically loaded DbgHelp.dll. - HMODULE dbghelp_module_; - - // Pointer to the MiniDumpWriteDump function. - MiniDumpWriteDumpType write_dump_; - - // Handle to dynamically loaded rpcrt4.dll. - HMODULE rpcrt4_module_; - - // Pointer to the UuidCreate function. - UuidCreateType create_uuid_; - - // Handle for the process to dump. - HANDLE process_handle_; - - // Process ID for the process to dump. - DWORD process_id_; - - // The crashing thread ID. - DWORD thread_id_; - - // The thread ID which is requesting the dump. - DWORD requesting_thread_id_; - - // Pointer to the exception information for the crash. This may point to an - // address in the crashing process so it should not be dereferenced. - EXCEPTION_POINTERS* exception_pointers_; - - // Assertion info for the report. - MDRawAssertionInfo* assert_info_; - - // Type of minidump to generate. - MINIDUMP_TYPE dump_type_; - - // Specifies whether the exception_pointers_ reference memory in the crashing - // process. - bool is_client_pointers_; - - // Folder path to store dump files. - std::wstring dump_path_; - - // The file where the dump will be written. - HANDLE dump_file_; - - // The file where the full dump will be written. - HANDLE full_dump_file_; - - // Tracks whether the dump file handle is managed externally. - bool dump_file_is_internal_; - - // Tracks whether the full dump file handle is managed externally. - bool full_dump_file_is_internal_; - - // Additional streams to be written to the dump. - MINIDUMP_USER_STREAM_INFORMATION* additional_streams_; - - // The user defined callback for the various stages of the dump process. - MINIDUMP_CALLBACK_INFORMATION* callback_info_; - - // Critical section to sychronize action of loading modules dynamically. - CRITICAL_SECTION module_load_sync_; - - // Critical section to synchronize action of dynamically getting function - // addresses from modules. - CRITICAL_SECTION get_proc_address_sync_; -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATOR_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/objs.mozbuild b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/objs.mozbuild deleted file mode 100644 index 549c14e10..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/objs.mozbuild +++ /dev/null @@ -1,17 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -lobjs_crash_generation = [ - 'client_info.cc', - 'crash_generation_client.cc', - 'crash_generation_server.cc', - 'minidump_generator.cc', -] - -subdir = 'toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation' -objs_crash_generation = [ - '/%s/%s' % (subdir, s) for s in lobjs_crash_generation -] diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc deleted file mode 100644 index 1f7b19f9a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc +++ /dev/null @@ -1,1073 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <objbase.h> - -#include <algorithm> -#include <cassert> -#include <cstdio> - -#include "common/windows/string_utils-inl.h" - -#include "client/windows/common/ipc_protocol.h" -#include "client/windows/handler/exception_handler.h" -#include "common/windows/guid_string.h" - -namespace google_breakpad { - -// This is passed as the context to the MinidumpWriteDump callback. -typedef struct { - AppMemoryList::const_iterator iter; - AppMemoryList::const_iterator end; -} MinidumpCallbackContext; - -vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL; -LONG ExceptionHandler::handler_stack_index_ = 0; -CRITICAL_SECTION ExceptionHandler::handler_stack_critical_section_; -volatile LONG ExceptionHandler::instance_count_ = 0; - -ExceptionHandler::ExceptionHandler(const wstring& dump_path, - FilterCallback filter, - MinidumpCallback callback, - void* callback_context, - int handler_types, - MINIDUMP_TYPE dump_type, - const wchar_t* pipe_name, - const CustomClientInfo* custom_info) { - Initialize(dump_path, - filter, - callback, - callback_context, - handler_types, - dump_type, - pipe_name, - NULL, // pipe_handle - NULL, // crash_generation_client - custom_info); -} - -ExceptionHandler::ExceptionHandler(const wstring& dump_path, - FilterCallback filter, - MinidumpCallback callback, - void* callback_context, - int handler_types, - MINIDUMP_TYPE dump_type, - HANDLE pipe_handle, - const CustomClientInfo* custom_info) { - Initialize(dump_path, - filter, - callback, - callback_context, - handler_types, - dump_type, - NULL, // pipe_name - pipe_handle, - NULL, // crash_generation_client - custom_info); -} - -ExceptionHandler::ExceptionHandler( - const wstring& dump_path, - FilterCallback filter, - MinidumpCallback callback, - void* callback_context, - int handler_types, - CrashGenerationClient* crash_generation_client) { - // The dump_type, pipe_name and custom_info that are passed in to Initialize() - // are not used. The ones set in crash_generation_client are used instead. - Initialize(dump_path, - filter, - callback, - callback_context, - handler_types, - MiniDumpNormal, // dump_type - not used - NULL, // pipe_name - not used - NULL, // pipe_handle - crash_generation_client, - NULL); // custom_info - not used -} - -ExceptionHandler::ExceptionHandler(const wstring &dump_path, - FilterCallback filter, - MinidumpCallback callback, - void* callback_context, - int handler_types) { - Initialize(dump_path, - filter, - callback, - callback_context, - handler_types, - MiniDumpNormal, - NULL, // pipe_name - NULL, // pipe_handle - NULL, // crash_generation_client - NULL); // custom_info -} - -void ExceptionHandler::Initialize( - const wstring& dump_path, - FilterCallback filter, - MinidumpCallback callback, - void* callback_context, - int handler_types, - MINIDUMP_TYPE dump_type, - const wchar_t* pipe_name, - HANDLE pipe_handle, - CrashGenerationClient* crash_generation_client, - const CustomClientInfo* custom_info) { - LONG instance_count = InterlockedIncrement(&instance_count_); - filter_ = filter; - callback_ = callback; - callback_context_ = callback_context; - dump_path_c_ = NULL; - next_minidump_id_c_ = NULL; - next_minidump_path_c_ = NULL; - dbghelp_module_ = NULL; - minidump_write_dump_ = NULL; - dump_type_ = dump_type; - rpcrt4_module_ = NULL; - uuid_create_ = NULL; - handler_types_ = handler_types; - previous_filter_ = NULL; -#if _MSC_VER >= 1400 // MSVC 2005/8 - previous_iph_ = NULL; -#endif // _MSC_VER >= 1400 - previous_pch_ = NULL; - handler_thread_ = NULL; - is_shutdown_ = false; - handler_start_semaphore_ = NULL; - handler_finish_semaphore_ = NULL; - requesting_thread_id_ = 0; - exception_info_ = NULL; - assertion_ = NULL; - handler_return_value_ = false; - handle_debug_exceptions_ = false; - consume_invalid_handle_exceptions_ = false; - - // Attempt to use out-of-process if user has specified a pipe or a - // crash generation client. - scoped_ptr<CrashGenerationClient> client; - if (crash_generation_client) { - client.reset(crash_generation_client); - } else if (pipe_name) { - client.reset( - new CrashGenerationClient(pipe_name, dump_type_, custom_info)); - } else if (pipe_handle) { - client.reset( - new CrashGenerationClient(pipe_handle, dump_type_, custom_info)); - } - - if (client.get() != NULL) { - // If successful in registering with the monitoring process, - // there is no need to setup in-process crash generation. - if (client->Register()) { - crash_generation_client_.reset(client.release()); - } - } - - if (!IsOutOfProcess()) { - // Either client did not ask for out-of-process crash generation - // or registration with the server process failed. In either case, - // setup to do in-process crash generation. - - // Set synchronization primitives and the handler thread. Each - // ExceptionHandler object gets its own handler thread because that's the - // only way to reliably guarantee sufficient stack space in an exception, - // and it allows an easy way to get a snapshot of the requesting thread's - // context outside of an exception. - InitializeCriticalSection(&handler_critical_section_); - handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); - assert(handler_start_semaphore_ != NULL); - - handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); - assert(handler_finish_semaphore_ != NULL); - - // Don't attempt to create the thread if we could not create the semaphores. - if (handler_finish_semaphore_ != NULL && handler_start_semaphore_ != NULL) { - DWORD thread_id; - const int kExceptionHandlerThreadInitialStackSize = 64 * 1024; - handler_thread_ = CreateThread(NULL, // lpThreadAttributes - kExceptionHandlerThreadInitialStackSize, - ExceptionHandlerThreadMain, - this, // lpParameter - 0, // dwCreationFlags - &thread_id); - assert(handler_thread_ != NULL); - } - - dbghelp_module_ = LoadLibrary(L"dbghelp.dll"); - if (dbghelp_module_) { - minidump_write_dump_ = reinterpret_cast<MiniDumpWriteDump_type>( - GetProcAddress(dbghelp_module_, "MiniDumpWriteDump")); - } - - // Load this library dynamically to not affect existing projects. Most - // projects don't link against this directly, it's usually dynamically - // loaded by dependent code. - rpcrt4_module_ = LoadLibrary(L"rpcrt4.dll"); - if (rpcrt4_module_) { - uuid_create_ = reinterpret_cast<UuidCreate_type>( - GetProcAddress(rpcrt4_module_, "UuidCreate")); - } - - // set_dump_path calls UpdateNextID. This sets up all of the path and id - // strings, and their equivalent c_str pointers. - set_dump_path(dump_path); - } - - // Reserve one element for the instruction memory - AppMemory instruction_memory; - instruction_memory.ptr = NULL; - instruction_memory.length = 0; - app_memory_info_.push_back(instruction_memory); - - // There is a race condition here. If the first instance has not yet - // initialized the critical section, the second (and later) instances may - // try to use uninitialized critical section object. The feature of multiple - // instances in one module is not used much, so leave it as is for now. - // One way to solve this in the current design (that is, keeping the static - // handler stack) is to use spin locks with volatile bools to synchronize - // the handler stack. This works only if the compiler guarantees to generate - // cache coherent code for volatile. - // TODO(munjal): Fix this in a better way by changing the design if possible. - - // Lazy initialization of the handler_stack_critical_section_ - if (instance_count == 1) { - InitializeCriticalSection(&handler_stack_critical_section_); - } - - if (handler_types != HANDLER_NONE) { - EnterCriticalSection(&handler_stack_critical_section_); - - // The first time an ExceptionHandler that installs a handler is - // created, set up the handler stack. - if (!handler_stack_) { - handler_stack_ = new vector<ExceptionHandler*>(); - } - handler_stack_->push_back(this); - - if (handler_types & HANDLER_EXCEPTION) - previous_filter_ = SetUnhandledExceptionFilter(HandleException); - -#if _MSC_VER >= 1400 // MSVC 2005/8 - if (handler_types & HANDLER_INVALID_PARAMETER) - previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter); -#endif // _MSC_VER >= 1400 - - if (handler_types & HANDLER_PURECALL) - previous_pch_ = _set_purecall_handler(HandlePureVirtualCall); - - LeaveCriticalSection(&handler_stack_critical_section_); - } -} - -ExceptionHandler::~ExceptionHandler() { - if (dbghelp_module_) { - FreeLibrary(dbghelp_module_); - } - - if (rpcrt4_module_) { - FreeLibrary(rpcrt4_module_); - } - - if (handler_types_ != HANDLER_NONE) { - EnterCriticalSection(&handler_stack_critical_section_); - - if (handler_types_ & HANDLER_EXCEPTION) - SetUnhandledExceptionFilter(previous_filter_); - -#if _MSC_VER >= 1400 // MSVC 2005/8 - if (handler_types_ & HANDLER_INVALID_PARAMETER) - _set_invalid_parameter_handler(previous_iph_); -#endif // _MSC_VER >= 1400 - - if (handler_types_ & HANDLER_PURECALL) - _set_purecall_handler(previous_pch_); - - if (handler_stack_->back() == this) { - handler_stack_->pop_back(); - } else { - // TODO(mmentovai): use advapi32!ReportEvent to log the warning to the - // system's application event log. - fprintf(stderr, "warning: removing Breakpad handler out of order\n"); - vector<ExceptionHandler*>::iterator iterator = handler_stack_->begin(); - while (iterator != handler_stack_->end()) { - if (*iterator == this) { - iterator = handler_stack_->erase(iterator); - } else { - ++iterator; - } - } - } - - if (handler_stack_->empty()) { - // When destroying the last ExceptionHandler that installed a handler, - // clean up the handler stack. - delete handler_stack_; - handler_stack_ = NULL; - } - - LeaveCriticalSection(&handler_stack_critical_section_); - } - - // Some of the objects were only initialized if out of process - // registration was not done. - if (!IsOutOfProcess()) { -#ifdef BREAKPAD_NO_TERMINATE_THREAD - // Clean up the handler thread and synchronization primitives. The handler - // thread is either waiting on the semaphore to handle a crash or it is - // handling a crash. Coming out of the wait is fast but wait more in the - // eventuality a crash is handled. This compilation option results in a - // deadlock if the exception handler is destroyed while executing code - // inside DllMain. - is_shutdown_ = true; - ReleaseSemaphore(handler_start_semaphore_, 1, NULL); - const int kWaitForHandlerThreadMs = 60000; - WaitForSingleObject(handler_thread_, kWaitForHandlerThreadMs); -#else - TerminateThread(handler_thread_, 1); -#endif // BREAKPAD_NO_TERMINATE_THREAD - - CloseHandle(handler_thread_); - handler_thread_ = NULL; - DeleteCriticalSection(&handler_critical_section_); - CloseHandle(handler_start_semaphore_); - CloseHandle(handler_finish_semaphore_); - } - - // There is a race condition in the code below: if this instance is - // deleting the static critical section and a new instance of the class - // is created, then there is a possibility that the critical section be - // initialized while the same critical section is being deleted. Given the - // usage pattern for the code, this race condition is unlikely to hit, but it - // is a race condition nonetheless. - if (InterlockedDecrement(&instance_count_) == 0) { - DeleteCriticalSection(&handler_stack_critical_section_); - } -} - -bool ExceptionHandler::RequestUpload(DWORD crash_id) { - return crash_generation_client_->RequestUpload(crash_id); -} - -// static -DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) { - ExceptionHandler* self = reinterpret_cast<ExceptionHandler *>(lpParameter); - assert(self); - assert(self->handler_start_semaphore_ != NULL); - assert(self->handler_finish_semaphore_ != NULL); - - while (true) { - if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) == - WAIT_OBJECT_0) { - // Perform the requested action. - if (self->is_shutdown_) { - // The instance of the exception handler is being destroyed. - break; - } else { - self->handler_return_value_ = - self->WriteMinidumpWithException(self->requesting_thread_id_, - self->exception_info_, - self->assertion_); - } - - // Allow the requesting thread to proceed. - ReleaseSemaphore(self->handler_finish_semaphore_, 1, NULL); - } - } - - // This statement is not reached when the thread is unconditionally - // terminated by the ExceptionHandler destructor. - return 0; -} - -// HandleException and HandleInvalidParameter must create an -// AutoExceptionHandler object to maintain static state and to determine which -// ExceptionHandler instance to use. The constructor locates the correct -// instance, and makes it available through get_handler(). The destructor -// restores the state in effect prior to allocating the AutoExceptionHandler. -class AutoExceptionHandler { - public: - AutoExceptionHandler() { - // Increment handler_stack_index_ so that if another Breakpad handler is - // registered using this same HandleException function, and it needs to be - // called while this handler is running (either because this handler - // declines to handle the exception, or an exception occurs during - // handling), HandleException will find the appropriate ExceptionHandler - // object in handler_stack_ to deliver the exception to. - // - // Because handler_stack_ is addressed in reverse (as |size - index|), - // preincrementing handler_stack_index_ avoids needing to subtract 1 from - // the argument to |at|. - // - // The index is maintained instead of popping elements off of the handler - // stack and pushing them at the end of this method. This avoids ruining - // the order of elements in the stack in the event that some other thread - // decides to manipulate the handler stack (such as creating a new - // ExceptionHandler object) while an exception is being handled. - EnterCriticalSection(&ExceptionHandler::handler_stack_critical_section_); - handler_ = ExceptionHandler::handler_stack_->at( - ExceptionHandler::handler_stack_->size() - - ++ExceptionHandler::handler_stack_index_); - - // In case another exception occurs while this handler is doing its thing, - // it should be delivered to the previous filter. - SetUnhandledExceptionFilter(handler_->previous_filter_); -#if _MSC_VER >= 1400 // MSVC 2005/8 - _set_invalid_parameter_handler(handler_->previous_iph_); -#endif // _MSC_VER >= 1400 - _set_purecall_handler(handler_->previous_pch_); - } - - ~AutoExceptionHandler() { - // Put things back the way they were before entering this handler. - SetUnhandledExceptionFilter(ExceptionHandler::HandleException); -#if _MSC_VER >= 1400 // MSVC 2005/8 - _set_invalid_parameter_handler(ExceptionHandler::HandleInvalidParameter); -#endif // _MSC_VER >= 1400 - _set_purecall_handler(ExceptionHandler::HandlePureVirtualCall); - - --ExceptionHandler::handler_stack_index_; - LeaveCriticalSection(&ExceptionHandler::handler_stack_critical_section_); - } - - ExceptionHandler* get_handler() const { return handler_; } - - private: - ExceptionHandler* handler_; -}; - -// static -LONG ExceptionHandler::HandleException(EXCEPTION_POINTERS* exinfo) { - AutoExceptionHandler auto_exception_handler; - ExceptionHandler* current_handler = auto_exception_handler.get_handler(); - - // Ignore EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP exceptions. This - // logic will short-circuit before calling WriteMinidumpOnHandlerThread, - // allowing something else to handle the breakpoint without incurring the - // overhead transitioning to and from the handler thread. This behavior - // can be overridden by calling ExceptionHandler::set_handle_debug_exceptions. - DWORD code = exinfo->ExceptionRecord->ExceptionCode; - LONG action; - bool is_debug_exception = (code == EXCEPTION_BREAKPOINT) || - (code == EXCEPTION_SINGLE_STEP); - - if (code == EXCEPTION_INVALID_HANDLE && - current_handler->consume_invalid_handle_exceptions_) { - return EXCEPTION_CONTINUE_EXECUTION; - } - - bool success = false; - - if (!is_debug_exception || - current_handler->get_handle_debug_exceptions()) { - // If out-of-proc crash handler client is available, we have to use that - // to generate dump and we cannot fall back on in-proc dump generation - // because we never prepared for an in-proc dump generation - - // In case of out-of-process dump generation, directly call - // WriteMinidumpWithException since there is no separate thread running. - if (current_handler->IsOutOfProcess()) { - success = current_handler->WriteMinidumpWithException( - GetCurrentThreadId(), - exinfo, - NULL); - } else { - success = current_handler->WriteMinidumpOnHandlerThread(exinfo, NULL); - } - } - - // The handler fully handled the exception. Returning - // EXCEPTION_EXECUTE_HANDLER indicates this to the system, and usually - // results in the application being terminated. - // - // Note: If the application was launched from within the Cygwin - // environment, returning EXCEPTION_EXECUTE_HANDLER seems to cause the - // application to be restarted. - if (success) { - action = EXCEPTION_EXECUTE_HANDLER; - } else { - // There was an exception, it was a breakpoint or something else ignored - // above, or it was passed to the handler, which decided not to handle it. - // This could be because the filter callback didn't want it, because - // minidump writing failed for some reason, or because the post-minidump - // callback function indicated failure. Give the previous handler a - // chance to do something with the exception. If there is no previous - // handler, return EXCEPTION_CONTINUE_SEARCH, which will allow a debugger - // or native "crashed" dialog to handle the exception. - if (current_handler->previous_filter_) { - action = current_handler->previous_filter_(exinfo); - } else { - action = EXCEPTION_CONTINUE_SEARCH; - } - } - - return action; -} - -#if _MSC_VER >= 1400 // MSVC 2005/8 -// static -void ExceptionHandler::HandleInvalidParameter(const wchar_t* expression, - const wchar_t* function, - const wchar_t* file, - unsigned int line, - uintptr_t reserved) { - // This is an invalid parameter, not an exception. It's safe to play with - // sprintf here. - AutoExceptionHandler auto_exception_handler; - ExceptionHandler* current_handler = auto_exception_handler.get_handler(); - - MDRawAssertionInfo assertion; - memset(&assertion, 0, sizeof(assertion)); - _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.expression), - sizeof(assertion.expression) / sizeof(assertion.expression[0]), - _TRUNCATE, L"%s", expression); - _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.function), - sizeof(assertion.function) / sizeof(assertion.function[0]), - _TRUNCATE, L"%s", function); - _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.file), - sizeof(assertion.file) / sizeof(assertion.file[0]), - _TRUNCATE, L"%s", file); - assertion.line = line; - assertion.type = MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER; - - // Make up an exception record for the current thread and CPU context - // to make it possible for the crash processor to classify these - // as do regular crashes, and to make it humane for developers to - // analyze them. - EXCEPTION_RECORD exception_record = {}; - CONTEXT exception_context = {}; - EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context }; - - ::RtlCaptureContext(&exception_context); - - exception_record.ExceptionCode = STATUS_INVALID_PARAMETER; - - // We store pointers to the the expression and function strings, - // and the line as exception parameters to make them easy to - // access by the developer on the far side. - exception_record.NumberParameters = 3; - exception_record.ExceptionInformation[0] = - reinterpret_cast<ULONG_PTR>(&assertion.expression); - exception_record.ExceptionInformation[1] = - reinterpret_cast<ULONG_PTR>(&assertion.file); - exception_record.ExceptionInformation[2] = assertion.line; - - bool success = false; - // In case of out-of-process dump generation, directly call - // WriteMinidumpWithException since there is no separate thread running. - if (current_handler->IsOutOfProcess()) { - success = current_handler->WriteMinidumpWithException( - GetCurrentThreadId(), - &exception_ptrs, - &assertion); - } else { - success = current_handler->WriteMinidumpOnHandlerThread(&exception_ptrs, - &assertion); - } - - if (!success) { - if (current_handler->previous_iph_) { - // The handler didn't fully handle the exception. Give it to the - // previous invalid parameter handler. - current_handler->previous_iph_(expression, - function, - file, - line, - reserved); - } else { - // If there's no previous handler, pass the exception back in to the - // invalid parameter handler's core. That's the routine that called this - // function, but now, since this function is no longer registered (and in - // fact, no function at all is registered), this will result in the - // default code path being taken: _CRT_DEBUGGER_HOOK and _invoke_watson. - // Use _invalid_parameter where it exists (in _DEBUG builds) as it passes - // more information through. In non-debug builds, it is not available, - // so fall back to using _invalid_parameter_noinfo. See invarg.c in the - // CRT source. -#ifdef _DEBUG - _invalid_parameter(expression, function, file, line, reserved); -#else // _DEBUG - _invalid_parameter_noinfo(); -#endif // _DEBUG - } - } - - // The handler either took care of the invalid parameter problem itself, - // or passed it on to another handler. "Swallow" it by exiting, paralleling - // the behavior of "swallowing" exceptions. - exit(0); -} -#endif // _MSC_VER >= 1400 - -// static -void ExceptionHandler::HandlePureVirtualCall() { - // This is an pure virtual function call, not an exception. It's safe to - // play with sprintf here. - AutoExceptionHandler auto_exception_handler; - ExceptionHandler* current_handler = auto_exception_handler.get_handler(); - - MDRawAssertionInfo assertion; - memset(&assertion, 0, sizeof(assertion)); - assertion.type = MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL; - - // Make up an exception record for the current thread and CPU context - // to make it possible for the crash processor to classify these - // as do regular crashes, and to make it humane for developers to - // analyze them. - EXCEPTION_RECORD exception_record = {}; - CONTEXT exception_context = {}; - EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context }; - - ::RtlCaptureContext(&exception_context); - - exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; - - // We store pointers to the the expression and function strings, - // and the line as exception parameters to make them easy to - // access by the developer on the far side. - exception_record.NumberParameters = 3; - exception_record.ExceptionInformation[0] = - reinterpret_cast<ULONG_PTR>(&assertion.expression); - exception_record.ExceptionInformation[1] = - reinterpret_cast<ULONG_PTR>(&assertion.file); - exception_record.ExceptionInformation[2] = assertion.line; - - bool success = false; - // In case of out-of-process dump generation, directly call - // WriteMinidumpWithException since there is no separate thread running. - - if (current_handler->IsOutOfProcess()) { - success = current_handler->WriteMinidumpWithException( - GetCurrentThreadId(), - &exception_ptrs, - &assertion); - } else { - success = current_handler->WriteMinidumpOnHandlerThread(&exception_ptrs, - &assertion); - } - - if (!success) { - if (current_handler->previous_pch_) { - // The handler didn't fully handle the exception. Give it to the - // previous purecall handler. - current_handler->previous_pch_(); - } else { - // If there's no previous handler, return and let _purecall handle it. - // This will just put up an assertion dialog. - return; - } - } - - // The handler either took care of the invalid parameter problem itself, - // or passed it on to another handler. "Swallow" it by exiting, paralleling - // the behavior of "swallowing" exceptions. - exit(0); -} - -bool ExceptionHandler::WriteMinidumpOnHandlerThread( - EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) { - EnterCriticalSection(&handler_critical_section_); - - // There isn't much we can do if the handler thread - // was not successfully created. - if (handler_thread_ == NULL) { - LeaveCriticalSection(&handler_critical_section_); - return false; - } - - // The handler thread should only be created when the semaphores are valid. - assert(handler_start_semaphore_ != NULL); - assert(handler_finish_semaphore_ != NULL); - - // Set up data to be passed in to the handler thread. - requesting_thread_id_ = GetCurrentThreadId(); - exception_info_ = exinfo; - assertion_ = assertion; - - // This causes the handler thread to call WriteMinidumpWithException. - ReleaseSemaphore(handler_start_semaphore_, 1, NULL); - - // Wait until WriteMinidumpWithException is done and collect its return value. - WaitForSingleObject(handler_finish_semaphore_, INFINITE); - bool status = handler_return_value_; - - // Clean up. - requesting_thread_id_ = 0; - exception_info_ = NULL; - assertion_ = NULL; - - LeaveCriticalSection(&handler_critical_section_); - - return status; -} - -bool ExceptionHandler::WriteMinidump() { - // Make up an exception record for the current thread and CPU context - // to make it possible for the crash processor to classify these - // as do regular crashes, and to make it humane for developers to - // analyze them. - EXCEPTION_RECORD exception_record = {}; - CONTEXT exception_context = {}; - EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context }; - - ::RtlCaptureContext(&exception_context); - exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; - - return WriteMinidumpForException(&exception_ptrs); -} - -bool ExceptionHandler::WriteMinidumpForException(EXCEPTION_POINTERS* exinfo) { - // In case of out-of-process dump generation, directly call - // WriteMinidumpWithException since there is no separate thread running. - if (IsOutOfProcess()) { - return WriteMinidumpWithException(GetCurrentThreadId(), - exinfo, - NULL); - } - - bool success = WriteMinidumpOnHandlerThread(exinfo, NULL); - UpdateNextID(); - return success; -} - -// static -bool ExceptionHandler::WriteMinidump(const wstring &dump_path, - MinidumpCallback callback, - void* callback_context, - MINIDUMP_TYPE dump_type) { - ExceptionHandler handler(dump_path, NULL, callback, callback_context, - HANDLER_NONE, dump_type, (HANDLE)NULL, NULL); - return handler.WriteMinidump(); -} - -// static -bool ExceptionHandler::WriteMinidumpForChild(HANDLE child, - DWORD child_blamed_thread, - const wstring& dump_path, - MinidumpCallback callback, - void* callback_context, - MINIDUMP_TYPE dump_type) { - EXCEPTION_RECORD ex; - CONTEXT ctx; - EXCEPTION_POINTERS exinfo = { NULL, NULL }; - // As documented on MSDN, on failure SuspendThread returns (DWORD) -1 - const DWORD kFailedToSuspendThread = static_cast<DWORD>(-1); - DWORD last_suspend_count = kFailedToSuspendThread; - HANDLE child_thread_handle = OpenThread(THREAD_GET_CONTEXT | - THREAD_QUERY_INFORMATION | - THREAD_SUSPEND_RESUME, - FALSE, - child_blamed_thread); - // This thread may have died already, so not opening the handle is a - // non-fatal error. - if (child_thread_handle != NULL) { - last_suspend_count = SuspendThread(child_thread_handle); - if (last_suspend_count != kFailedToSuspendThread) { - ctx.ContextFlags = CONTEXT_ALL; - if (GetThreadContext(child_thread_handle, &ctx)) { - memset(&ex, 0, sizeof(ex)); - ex.ExceptionCode = EXCEPTION_BREAKPOINT; -#if defined(_M_IX86) - ex.ExceptionAddress = reinterpret_cast<PVOID>(ctx.Eip); -#elif defined(_M_X64) - ex.ExceptionAddress = reinterpret_cast<PVOID>(ctx.Rip); -#endif - exinfo.ExceptionRecord = &ex; - exinfo.ContextRecord = &ctx; - } - } - } - - ExceptionHandler handler(dump_path, NULL, callback, callback_context, - HANDLER_NONE, dump_type, (HANDLE)NULL, NULL); - bool success = handler.WriteMinidumpWithExceptionForProcess( - child_blamed_thread, - exinfo.ExceptionRecord ? &exinfo : NULL, - NULL, child, false); - - if (last_suspend_count != kFailedToSuspendThread) { - ResumeThread(child_thread_handle); - } - - CloseHandle(child_thread_handle); - - if (callback) { - success = callback(handler.dump_path_c_, handler.next_minidump_id_c_, - callback_context, NULL, NULL, success); - } - - return success; -} - -bool ExceptionHandler::WriteMinidumpWithException( - DWORD requesting_thread_id, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion) { - // Give user code a chance to approve or prevent writing a minidump. If the - // filter returns false, don't handle the exception at all. If this method - // was called as a result of an exception, returning false will cause - // HandleException to call any previous handler or return - // EXCEPTION_CONTINUE_SEARCH on the exception thread, allowing it to appear - // as though this handler were not present at all. - if (filter_ && !filter_(callback_context_, exinfo, assertion)) { - return false; - } - - bool success = false; - if (IsOutOfProcess()) { - success = crash_generation_client_->RequestDump(exinfo, assertion); - } else { - success = WriteMinidumpWithExceptionForProcess(requesting_thread_id, - exinfo, - assertion, - GetCurrentProcess(), - true); - } - - if (callback_) { - // TODO(munjal): In case of out-of-process dump generation, both - // dump_path_c_ and next_minidump_id_ will be NULL. For out-of-process - // scenario, the server process ends up creating the dump path and dump - // id so they are not known to the client. - success = callback_(dump_path_c_, next_minidump_id_c_, callback_context_, - exinfo, assertion, success); - } - - return success; -} - -// static -BOOL CALLBACK ExceptionHandler::MinidumpWriteDumpCallback( - PVOID context, - const PMINIDUMP_CALLBACK_INPUT callback_input, - PMINIDUMP_CALLBACK_OUTPUT callback_output) { - switch (callback_input->CallbackType) { - case MemoryCallback: { - MinidumpCallbackContext* callback_context = - reinterpret_cast<MinidumpCallbackContext*>(context); - if (callback_context->iter == callback_context->end) - return FALSE; - - // Include the specified memory region. - callback_output->MemoryBase = callback_context->iter->ptr; - callback_output->MemorySize = callback_context->iter->length; - callback_context->iter++; - return TRUE; - } - - // Include all modules. - case IncludeModuleCallback: - case ModuleCallback: - return TRUE; - - // Include all threads. - case IncludeThreadCallback: - case ThreadCallback: - return TRUE; - - // Stop receiving cancel callbacks. - case CancelCallback: - callback_output->CheckCancel = FALSE; - callback_output->Cancel = FALSE; - return TRUE; - } - // Ignore other callback types. - return FALSE; -} - -bool ExceptionHandler::WriteMinidumpWithExceptionForProcess( - DWORD requesting_thread_id, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - HANDLE process, - bool write_requester_stream) { - bool success = false; - if (minidump_write_dump_) { - HANDLE dump_file = CreateFile(next_minidump_path_c_, - GENERIC_WRITE, - 0, // no sharing - NULL, - CREATE_NEW, // fail if exists - FILE_ATTRIBUTE_NORMAL, - NULL); - if (dump_file != INVALID_HANDLE_VALUE) { - MINIDUMP_EXCEPTION_INFORMATION except_info; - except_info.ThreadId = requesting_thread_id; - except_info.ExceptionPointers = exinfo; - except_info.ClientPointers = FALSE; - - // Leave room in user_stream_array for possible breakpad and - // assertion info streams. - MINIDUMP_USER_STREAM user_stream_array[2]; - MINIDUMP_USER_STREAM_INFORMATION user_streams; - user_streams.UserStreamCount = 0; - user_streams.UserStreamArray = user_stream_array; - - if (write_requester_stream) { - // Add an MDRawBreakpadInfo stream to the minidump, to provide - // additional information about the exception handler to the Breakpad - // processor. The information will help the processor determine which - // threads are relevant. The Breakpad processor does not require this - // information but can function better with Breakpad-generated dumps - // when it is present. The native debugger is not harmed by the - // presence of this information. - MDRawBreakpadInfo breakpad_info; - breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | - MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; - breakpad_info.dump_thread_id = GetCurrentThreadId(); - breakpad_info.requesting_thread_id = requesting_thread_id; - - int index = user_streams.UserStreamCount; - user_stream_array[index].Type = MD_BREAKPAD_INFO_STREAM; - user_stream_array[index].BufferSize = sizeof(breakpad_info); - user_stream_array[index].Buffer = &breakpad_info; - ++user_streams.UserStreamCount; - } - - if (assertion) { - int index = user_streams.UserStreamCount; - user_stream_array[index].Type = MD_ASSERTION_INFO_STREAM; - user_stream_array[index].BufferSize = sizeof(MDRawAssertionInfo); - user_stream_array[index].Buffer = assertion; - ++user_streams.UserStreamCount; - } - - // Older versions of DbgHelp.dll don't correctly put the memory around - // the faulting instruction pointer into the minidump. This - // callback will ensure that it gets included. - if (exinfo) { - // Find a memory region of 256 bytes centered on the - // faulting instruction pointer. - const ULONG64 instruction_pointer = -#if defined(_M_IX86) - exinfo->ContextRecord->Eip; -#elif defined(_M_AMD64) - exinfo->ContextRecord->Rip; -#else -#error Unsupported platform -#endif - - MEMORY_BASIC_INFORMATION info; - if (VirtualQueryEx(process, - reinterpret_cast<LPCVOID>(instruction_pointer), - &info, - sizeof(MEMORY_BASIC_INFORMATION)) != 0 && - info.State == MEM_COMMIT) { - // Attempt to get 128 bytes before and after the instruction - // pointer, but settle for whatever's available up to the - // boundaries of the memory region. - const ULONG64 kIPMemorySize = 256; - ULONG64 base = - (std::max)(reinterpret_cast<ULONG64>(info.BaseAddress), - instruction_pointer - (kIPMemorySize / 2)); - ULONG64 end_of_range = - (std::min)(instruction_pointer + (kIPMemorySize / 2), - reinterpret_cast<ULONG64>(info.BaseAddress) - + info.RegionSize); - ULONG size = static_cast<ULONG>(end_of_range - base); - - AppMemory& elt = app_memory_info_.front(); - elt.ptr = base; - elt.length = size; - } - } - - MinidumpCallbackContext context; - context.iter = app_memory_info_.begin(); - context.end = app_memory_info_.end(); - - // Skip the reserved element if there was no instruction memory - if (context.iter->ptr == 0) { - context.iter++; - } - - MINIDUMP_CALLBACK_INFORMATION callback; - callback.CallbackRoutine = MinidumpWriteDumpCallback; - callback.CallbackParam = reinterpret_cast<void*>(&context); - - // The explicit comparison to TRUE avoids a warning (C4800). - success = (minidump_write_dump_(process, - GetProcessId(process), - dump_file, - dump_type_, - exinfo ? &except_info : NULL, - &user_streams, - &callback) == TRUE); - - CloseHandle(dump_file); - } - } - - return success; -} - -void ExceptionHandler::UpdateNextID() { - assert(uuid_create_); - UUID id = {0}; - if (uuid_create_) { - uuid_create_(&id); - } - next_minidump_id_ = GUIDString::GUIDToWString(&id); - next_minidump_id_c_ = next_minidump_id_.c_str(); - - wchar_t minidump_path[MAX_PATH]; - swprintf(minidump_path, MAX_PATH, L"%s\\%s.dmp", - dump_path_c_, next_minidump_id_c_); - - // remove when VC++7.1 is no longer supported - minidump_path[MAX_PATH - 1] = L'\0'; - - next_minidump_path_ = minidump_path; - next_minidump_path_c_ = next_minidump_path_.c_str(); -} - -void ExceptionHandler::RegisterAppMemory(void* ptr, size_t length) { - AppMemoryList::iterator iter = - std::find(app_memory_info_.begin(), app_memory_info_.end(), ptr); - if (iter != app_memory_info_.end()) { - // Don't allow registering the same pointer twice. - return; - } - - AppMemory app_memory; - app_memory.ptr = reinterpret_cast<ULONG64>(ptr); - app_memory.length = static_cast<ULONG>(length); - app_memory_info_.push_back(app_memory); -} - -void ExceptionHandler::UnregisterAppMemory(void* ptr) { - AppMemoryList::iterator iter = - std::find(app_memory_info_.begin(), app_memory_info_.end(), ptr); - if (iter != app_memory_info_.end()) { - app_memory_info_.erase(iter); - } -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.gyp b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.gyp deleted file mode 100644 index c5733277d..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.gyp +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -{ - 'includes': [ - '../../../build/common.gypi', - ], - 'targets': [ - { - 'target_name': 'exception_handler', - 'type': 'static_library', - 'sources': [ - "exception_handler.cc", - "exception_handler.h", - ], - 'dependencies': [ - '../breakpad_client.gyp:common', - '../crash_generation/crash_generation.gyp:crash_generation_server', - ] - }, - ], -} diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h deleted file mode 100644 index 11babe513..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h +++ /dev/null @@ -1,524 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ExceptionHandler can write a minidump file when an exception occurs, -// or when WriteMinidump() is called explicitly by your program. -// -// To have the exception handler write minidumps when an uncaught exception -// (crash) occurs, you should create an instance early in the execution -// of your program, and keep it around for the entire time you want to -// have crash handling active (typically, until shutdown). -// -// If you want to write minidumps without installing the exception handler, -// you can create an ExceptionHandler with install_handler set to false, -// then call WriteMinidump. You can also use this technique if you want to -// use different minidump callbacks for different call sites. -// -// In either case, a callback function is called when a minidump is written, -// which receives the unqiue id of the minidump. The caller can use this -// id to collect and write additional application state, and to launch an -// external crash-reporting application. -// -// It is important that creation and destruction of ExceptionHandler objects -// be nested cleanly, when using install_handler = true. -// Avoid the following pattern: -// ExceptionHandler *e = new ExceptionHandler(...); -// ExceptionHandler *f = new ExceptionHandler(...); -// delete e; -// This will put the exception filter stack into an inconsistent state. - -#ifndef CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ -#define CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ - -#include <stdlib.h> -#include <windows.h> -#include <dbghelp.h> -#include <rpc.h> - -#pragma warning(push) -// Disable exception handler warnings. -#pragma warning(disable:4530) - -#include <list> -#include <string> -#include <vector> - -#include "client/windows/common/ipc_protocol.h" -#include "client/windows/crash_generation/crash_generation_client.h" -#include "common/scoped_ptr.h" -#include "google_breakpad/common/minidump_format.h" - -namespace google_breakpad { - -using std::vector; -using std::wstring; - -// These entries store a list of memory regions that the client wants included -// in the minidump. -struct AppMemory { - ULONG64 ptr; - ULONG length; - - bool operator==(const struct AppMemory& other) const { - return ptr == other.ptr; - } - - bool operator==(const void* other) const { - return ptr == reinterpret_cast<ULONG64>(other); - } -}; -typedef std::list<AppMemory> AppMemoryList; - -class ExceptionHandler { - public: - // A callback function to run before Breakpad performs any substantial - // processing of an exception. A FilterCallback is called before writing - // a minidump. context is the parameter supplied by the user as - // callback_context when the handler was created. exinfo points to the - // exception record, if any; assertion points to assertion information, - // if any. - // - // If a FilterCallback returns true, Breakpad will continue processing, - // attempting to write a minidump. If a FilterCallback returns false, - // Breakpad will immediately report the exception as unhandled without - // writing a minidump, allowing another handler the opportunity to handle it. - typedef bool (*FilterCallback)(void* context, EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion); - - // A callback function to run after the minidump has been written. - // minidump_id is a unique id for the dump, so the minidump - // file is <dump_path>\<minidump_id>.dmp. context is the parameter supplied - // by the user as callback_context when the handler was created. exinfo - // points to the exception record, or NULL if no exception occurred. - // succeeded indicates whether a minidump file was successfully written. - // assertion points to information about an assertion if the handler was - // invoked by an assertion. - // - // If an exception occurred and the callback returns true, Breakpad will treat - // the exception as fully-handled, suppressing any other handlers from being - // notified of the exception. If the callback returns false, Breakpad will - // treat the exception as unhandled, and allow another handler to handle it. - // If there are no other handlers, Breakpad will report the exception to the - // system as unhandled, allowing a debugger or native crash dialog the - // opportunity to handle the exception. Most callback implementations - // should normally return the value of |succeeded|, or when they wish to - // not report an exception of handled, false. Callbacks will rarely want to - // return true directly (unless |succeeded| is true). - // - // For out-of-process dump generation, dump path and minidump ID will always - // be NULL. In case of out-of-process dump generation, the dump path and - // minidump id are controlled by the server process and are not communicated - // back to the crashing process. - typedef bool (*MinidumpCallback)(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded); - - // HandlerType specifies which types of handlers should be installed, if - // any. Use HANDLER_NONE for an ExceptionHandler that remains idle, - // without catching any failures on its own. This type of handler may - // still be triggered by calling WriteMinidump. Otherwise, use a - // combination of the other HANDLER_ values, or HANDLER_ALL to install - // all handlers. - enum HandlerType { - HANDLER_NONE = 0, - HANDLER_EXCEPTION = 1 << 0, // SetUnhandledExceptionFilter - HANDLER_INVALID_PARAMETER = 1 << 1, // _set_invalid_parameter_handler - HANDLER_PURECALL = 1 << 2, // _set_purecall_handler - HANDLER_ALL = HANDLER_EXCEPTION | - HANDLER_INVALID_PARAMETER | - HANDLER_PURECALL - }; - - // Creates a new ExceptionHandler instance to handle writing minidumps. - // Before writing a minidump, the optional filter callback will be called. - // Its return value determines whether or not Breakpad should write a - // minidump. Minidump files will be written to dump_path, and the optional - // callback is called after writing the dump file, as described above. - // handler_types specifies the types of handlers that should be installed. - ExceptionHandler(const wstring& dump_path, - FilterCallback filter, - MinidumpCallback callback, - void* callback_context, - int handler_types); - - // Creates a new ExceptionHandler instance that can attempt to perform - // out-of-process dump generation if pipe_name is not NULL. If pipe_name is - // NULL, or if out-of-process dump generation registration step fails, - // in-process dump generation will be used. This also allows specifying - // the dump type to generate. - ExceptionHandler(const wstring& dump_path, - FilterCallback filter, - MinidumpCallback callback, - void* callback_context, - int handler_types, - MINIDUMP_TYPE dump_type, - const wchar_t* pipe_name, - const CustomClientInfo* custom_info); - - // As above, creates a new ExceptionHandler instance to perform - // out-of-process dump generation if the given pipe_handle is not NULL. - ExceptionHandler(const wstring& dump_path, - FilterCallback filter, - MinidumpCallback callback, - void* callback_context, - int handler_types, - MINIDUMP_TYPE dump_type, - HANDLE pipe_handle, - const CustomClientInfo* custom_info); - - // ExceptionHandler that ENSURES out-of-process dump generation. Expects a - // crash generation client that is already registered with a crash generation - // server. Takes ownership of the passed-in crash_generation_client. - // - // Usage example: - // crash_generation_client = new CrashGenerationClient(..); - // if (crash_generation_client->Register()) { - // // Registration with the crash generation server succeeded. - // // Out-of-process dump generation is guaranteed. - // g_handler = new ExceptionHandler(.., crash_generation_client, ..); - // return true; - // } - ExceptionHandler(const wstring& dump_path, - FilterCallback filter, - MinidumpCallback callback, - void* callback_context, - int handler_types, - CrashGenerationClient* crash_generation_client); - - ~ExceptionHandler(); - - // Get and set the minidump path. - wstring dump_path() const { return dump_path_; } - void set_dump_path(const wstring &dump_path) { - dump_path_ = dump_path; - dump_path_c_ = dump_path_.c_str(); - UpdateNextID(); // Necessary to put dump_path_ in next_minidump_path_. - } - - // Requests that a previously reported crash be uploaded. - bool RequestUpload(DWORD crash_id); - - // Writes a minidump immediately. This can be used to capture the - // execution state independently of a crash. Returns true on success. - bool WriteMinidump(); - - // Writes a minidump immediately, with the user-supplied exception - // information. - bool WriteMinidumpForException(EXCEPTION_POINTERS* exinfo); - - // Convenience form of WriteMinidump which does not require an - // ExceptionHandler instance. - static bool WriteMinidump(const wstring &dump_path, - MinidumpCallback callback, void* callback_context, - MINIDUMP_TYPE dump_type = MiniDumpNormal); - - // Write a minidump of |child| immediately. This can be used to - // capture the execution state of |child| independently of a crash. - // Pass a meaningful |child_blamed_thread| to make that thread in - // the child process the one from which a crash signature is - // extracted. - static bool WriteMinidumpForChild(HANDLE child, - DWORD child_blamed_thread, - const wstring& dump_path, - MinidumpCallback callback, - void* callback_context, - MINIDUMP_TYPE dump_type = MiniDumpNormal); - - // Get the thread ID of the thread requesting the dump (either the exception - // thread or any other thread that called WriteMinidump directly). This - // may be useful if you want to include additional thread state in your - // dumps. - DWORD get_requesting_thread_id() const { return requesting_thread_id_; } - - // Controls behavior of EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP. - bool get_handle_debug_exceptions() const { return handle_debug_exceptions_; } - void set_handle_debug_exceptions(bool handle_debug_exceptions) { - handle_debug_exceptions_ = handle_debug_exceptions; - } - - // Controls behavior of EXCEPTION_INVALID_HANDLE. - bool get_consume_invalid_handle_exceptions() const { - return consume_invalid_handle_exceptions_; - } - void set_consume_invalid_handle_exceptions( - bool consume_invalid_handle_exceptions) { - consume_invalid_handle_exceptions_ = consume_invalid_handle_exceptions; - } - - // Returns whether out-of-process dump generation is used or not. - bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; } - - // Calling RegisterAppMemory(p, len) causes len bytes starting - // at address p to be copied to the minidump when a crash happens. - void RegisterAppMemory(void* ptr, size_t length); - void UnregisterAppMemory(void* ptr); - - private: - friend class AutoExceptionHandler; - - // Initializes the instance with given values. - void Initialize(const wstring& dump_path, - FilterCallback filter, - MinidumpCallback callback, - void* callback_context, - int handler_types, - MINIDUMP_TYPE dump_type, - const wchar_t* pipe_name, - HANDLE pipe_handle, - CrashGenerationClient* crash_generation_client, - const CustomClientInfo* custom_info); - - // Function pointer type for MiniDumpWriteDump, which is looked up - // dynamically. - typedef BOOL (WINAPI *MiniDumpWriteDump_type)( - HANDLE hProcess, - DWORD dwPid, - HANDLE hFile, - MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); - - // Function pointer type for UuidCreate, which is looked up dynamically. - typedef RPC_STATUS (RPC_ENTRY *UuidCreate_type)(UUID* Uuid); - - // Runs the main loop for the exception handler thread. - static DWORD WINAPI ExceptionHandlerThreadMain(void* lpParameter); - - // Called on the exception thread when an unhandled exception occurs. - // Signals the exception handler thread to handle the exception. - static LONG WINAPI HandleException(EXCEPTION_POINTERS* exinfo); - -#if _MSC_VER >= 1400 // MSVC 2005/8 - // This function will be called by some CRT functions when they detect - // that they were passed an invalid parameter. Note that in _DEBUG builds, - // the CRT may display an assertion dialog before calling this function, - // and the function will not be called unless the assertion dialog is - // dismissed by clicking "Ignore." - static void HandleInvalidParameter(const wchar_t* expression, - const wchar_t* function, - const wchar_t* file, - unsigned int line, - uintptr_t reserved); -#endif // _MSC_VER >= 1400 - - // This function will be called by the CRT when a pure virtual - // function is called. - static void HandlePureVirtualCall(); - - // This is called on the exception thread or on another thread that - // the user wishes to produce a dump from. It calls - // WriteMinidumpWithException on the handler thread, avoiding stack - // overflows and inconsistent dumps due to writing the dump from - // the exception thread. If the dump is requested as a result of an - // exception, exinfo contains exception information, otherwise, it - // is NULL. If the dump is requested as a result of an assertion - // (such as an invalid parameter being passed to a CRT function), - // assertion contains data about the assertion, otherwise, it is NULL. - bool WriteMinidumpOnHandlerThread(EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion); - - // This function is called on the handler thread. It calls into - // WriteMinidumpWithExceptionForProcess() with a handle to the - // current process. requesting_thread_id is the ID of the thread - // that requested the dump. If the dump is requested as a result of - // an exception, exinfo contains exception information, otherwise, - // it is NULL. - bool WriteMinidumpWithException(DWORD requesting_thread_id, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion); - - // This function is used as a callback when calling MinidumpWriteDump, - // in order to add additional memory regions to the dump. - static BOOL CALLBACK MinidumpWriteDumpCallback( - PVOID context, - const PMINIDUMP_CALLBACK_INPUT callback_input, - PMINIDUMP_CALLBACK_OUTPUT callback_output); - - // This function does the actual writing of a minidump. It is - // called on the handler thread. requesting_thread_id is the ID of - // the thread that requested the dump, if that information is - // meaningful. If the dump is requested as a result of an - // exception, exinfo contains exception information, otherwise, it - // is NULL. process is the one that will be dumped. If - // requesting_thread_id is meaningful and should be added to the - // minidump, write_requester_stream is |true|. - bool WriteMinidumpWithExceptionForProcess(DWORD requesting_thread_id, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - HANDLE process, - bool write_requester_stream); - - // Generates a new ID and stores it in next_minidump_id_, and stores the - // path of the next minidump to be written in next_minidump_path_. - void UpdateNextID(); - - FilterCallback filter_; - MinidumpCallback callback_; - void* callback_context_; - - scoped_ptr<CrashGenerationClient> crash_generation_client_; - - // The directory in which a minidump will be written, set by the dump_path - // argument to the constructor, or set_dump_path. - wstring dump_path_; - - // The basename of the next minidump to be written, without the extension. - wstring next_minidump_id_; - - // The full pathname of the next minidump to be written, including the file - // extension. - wstring next_minidump_path_; - - // Pointers to C-string representations of the above. These are set when - // the above wstring versions are set in order to avoid calling c_str during - // an exception, as c_str may attempt to allocate heap memory. These - // pointers are not owned by the ExceptionHandler object, but their lifetimes - // should be equivalent to the lifetimes of the associated wstring, provided - // that the wstrings are not altered. - const wchar_t* dump_path_c_; - const wchar_t* next_minidump_id_c_; - const wchar_t* next_minidump_path_c_; - - HMODULE dbghelp_module_; - MiniDumpWriteDump_type minidump_write_dump_; - MINIDUMP_TYPE dump_type_; - - HMODULE rpcrt4_module_; - UuidCreate_type uuid_create_; - - // Tracks the handler types that were installed according to the - // handler_types constructor argument. - int handler_types_; - - // When installed_handler_ is true, previous_filter_ is the unhandled - // exception filter that was set prior to installing ExceptionHandler as - // the unhandled exception filter and pointing it to |this|. NULL indicates - // that there is no previous unhandled exception filter. - LPTOP_LEVEL_EXCEPTION_FILTER previous_filter_; - -#if _MSC_VER >= 1400 // MSVC 2005/8 - // Beginning in VC 8, the CRT provides an invalid parameter handler that will - // be called when some CRT functions are passed invalid parameters. In - // earlier CRTs, the same conditions would cause unexpected behavior or - // crashes. - _invalid_parameter_handler previous_iph_; -#endif // _MSC_VER >= 1400 - - // The CRT allows you to override the default handler for pure - // virtual function calls. - _purecall_handler previous_pch_; - - // The exception handler thread. - HANDLE handler_thread_; - - // True if the exception handler is being destroyed. - // Starting with MSVC 2005, Visual C has stronger guarantees on volatile vars. - // It has release semantics on write and acquire semantics on reads. - // See the msdn documentation. - volatile bool is_shutdown_; - - // The critical section enforcing the requirement that only one exception be - // handled by a handler at a time. - CRITICAL_SECTION handler_critical_section_; - - // Semaphores used to move exception handling between the exception thread - // and the handler thread. handler_start_semaphore_ is signalled by the - // exception thread to wake up the handler thread when an exception occurs. - // handler_finish_semaphore_ is signalled by the handler thread to wake up - // the exception thread when handling is complete. - HANDLE handler_start_semaphore_; - HANDLE handler_finish_semaphore_; - - // The next 2 fields contain data passed from the requesting thread to - // the handler thread. - - // The thread ID of the thread requesting the dump (either the exception - // thread or any other thread that called WriteMinidump directly). - DWORD requesting_thread_id_; - - // The exception info passed to the exception handler on the exception - // thread, if an exception occurred. NULL for user-requested dumps. - EXCEPTION_POINTERS* exception_info_; - - // If the handler is invoked due to an assertion, this will contain a - // pointer to the assertion information. It is NULL at other times. - MDRawAssertionInfo* assertion_; - - // The return value of the handler, passed from the handler thread back to - // the requesting thread. - bool handler_return_value_; - - // If true, the handler will intercept EXCEPTION_BREAKPOINT and - // EXCEPTION_SINGLE_STEP exceptions. Leave this false (the default) - // to not interfere with debuggers. - bool handle_debug_exceptions_; - - // If true, the handler will consume any EXCEPTION_INVALID_HANDLE exceptions. - // Leave this false (the default) to handle these exceptions as normal. - bool consume_invalid_handle_exceptions_; - - // Callers can request additional memory regions to be included in - // the dump. - AppMemoryList app_memory_info_; - - // A stack of ExceptionHandler objects that have installed unhandled - // exception filters. This vector is used by HandleException to determine - // which ExceptionHandler object to route an exception to. When an - // ExceptionHandler is created with install_handler true, it will append - // itself to this list. - static vector<ExceptionHandler*>* handler_stack_; - - // The index of the ExceptionHandler in handler_stack_ that will handle the - // next exception. Note that 0 means the last entry in handler_stack_, 1 - // means the next-to-last entry, and so on. This is used by HandleException - // to support multiple stacked Breakpad handlers. - static LONG handler_stack_index_; - - // handler_stack_critical_section_ guards operations on handler_stack_ and - // handler_stack_index_. The critical section is initialized by the - // first instance of the class and destroyed by the last instance of it. - static CRITICAL_SECTION handler_stack_critical_section_; - - // The number of instances of this class. - static volatile LONG instance_count_; - - // disallow copy ctor and operator= - explicit ExceptionHandler(const ExceptionHandler &); - void operator=(const ExceptionHandler &); -}; - -} // namespace google_breakpad - -#pragma warning(pop) - -#endif // CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/objs.mozbuild b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/objs.mozbuild deleted file mode 100644 index 6cabb09b7..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/objs.mozbuild +++ /dev/null @@ -1,14 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -lobjs_handler = [ - 'exception_handler.cc', -] - -subdir = 'toolkit/crashreporter/google-breakpad/src/client/windows/handler' -objs_handler = [ - '/%s/%s' % (subdir, s) for s in lobjs_handler -] diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.cc deleted file mode 100644 index 70c36b0e2..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.cc +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Disable exception handler warnings. -#pragma warning( disable : 4530 ) - -#include <errno.h> - -#include "client/windows/sender/crash_report_sender.h" -#include "common/windows/http_upload.h" - -#if _MSC_VER < 1400 // MSVC 2005/8 -// Older MSVC doesn't have fscanf_s, but they are compatible as long as -// we don't use the string conversions (%s/%c/%S/%C). -#define fscanf_s fscanf -#endif - -namespace google_breakpad { - -static const char kCheckpointSignature[] = "GBP1\n"; - -CrashReportSender::CrashReportSender(const wstring &checkpoint_file) - : checkpoint_file_(checkpoint_file), - max_reports_per_day_(-1), - last_sent_date_(-1), - reports_sent_(0) { - FILE *fd; - if (OpenCheckpointFile(L"r", &fd) == 0) { - ReadCheckpoint(fd); - fclose(fd); - } -} - -ReportResult CrashReportSender::SendCrashReport( - const wstring &url, const map<wstring, wstring> ¶meters, - const map<wstring, wstring> &files, wstring *report_code) { - int today = GetCurrentDate(); - if (today == last_sent_date_ && - max_reports_per_day_ != -1 && - reports_sent_ >= max_reports_per_day_) { - return RESULT_THROTTLED; - } - - int http_response = 0; - bool result = HTTPUpload::SendRequest( - url, parameters, files, NULL, report_code, - &http_response); - - if (result) { - ReportSent(today); - return RESULT_SUCCEEDED; - } else if (http_response >= 400 && http_response < 500) { - return RESULT_REJECTED; - } else { - return RESULT_FAILED; - } -} - -void CrashReportSender::ReadCheckpoint(FILE *fd) { - char buf[128]; - if (!fgets(buf, sizeof(buf), fd) || - strcmp(buf, kCheckpointSignature) != 0) { - return; - } - - if (fscanf_s(fd, "%d\n", &last_sent_date_) != 1) { - last_sent_date_ = -1; - return; - } - if (fscanf_s(fd, "%d\n", &reports_sent_) != 1) { - reports_sent_ = 0; - return; - } -} - -void CrashReportSender::ReportSent(int today) { - // Update the report stats - if (today != last_sent_date_) { - last_sent_date_ = today; - reports_sent_ = 0; - } - ++reports_sent_; - - // Update the checkpoint file - FILE *fd; - if (OpenCheckpointFile(L"w", &fd) == 0) { - fputs(kCheckpointSignature, fd); - fprintf(fd, "%d\n", last_sent_date_); - fprintf(fd, "%d\n", reports_sent_); - fclose(fd); - } -} - -int CrashReportSender::GetCurrentDate() const { - SYSTEMTIME system_time; - GetSystemTime(&system_time); - return (system_time.wYear * 10000) + (system_time.wMonth * 100) + - system_time.wDay; -} - -int CrashReportSender::OpenCheckpointFile(const wchar_t *mode, FILE **fd) { - if (checkpoint_file_.empty()) { - return ENOENT; - } -#if _MSC_VER >= 1400 // MSVC 2005/8 - return _wfopen_s(fd, checkpoint_file_.c_str(), mode); -#else - *fd = _wfopen(checkpoint_file_.c_str(), mode); - if (*fd == NULL) { - return errno; - } - return 0; -#endif -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.gyp b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.gyp deleted file mode 100644 index dc8583a0a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.gyp +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -{ - 'includes': [ - '../../../build/common.gypi', - ], - 'targets': [ - { - 'target_name': 'crash_report_sender', - 'type': 'static_library', - 'sources': [ - 'crash_report_sender.cc', - 'crash_report_sender.h', - ], - 'dependencies': [ - '../breakpad_client.gyp:common' - ], - }, - ], -} diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.h b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.h deleted file mode 100644 index 7786cc699..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__ -#define CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__ - -// CrashReportSender is a "static" class which provides an API to upload -// crash reports via HTTP(S). A crash report is formatted as a multipart POST -// request, which contains a set of caller-supplied string key/value pairs, -// and a minidump file to upload. -// -// To use this library in your project, you will need to link against -// wininet.lib. - -#pragma warning( push ) -// Disable exception handler warnings. -#pragma warning( disable : 4530 ) - -#include <map> -#include <string> - -namespace google_breakpad { - -using std::wstring; -using std::map; - -typedef enum { - RESULT_FAILED = 0, // Failed to communicate with the server; try later. - RESULT_REJECTED, // Successfully sent the crash report, but the - // server rejected it; don't resend this report. - RESULT_SUCCEEDED, // The server accepted the crash report. - RESULT_THROTTLED // No attempt was made to send the crash report, because - // we exceeded the maximum reports per day. -} ReportResult; - -class CrashReportSender { - public: - // Initializes a CrashReportSender instance. - // If checkpoint_file is non-empty, breakpad will persist crash report - // state to this file. A checkpoint file is required for - // set_max_reports_per_day() to function properly. - explicit CrashReportSender(const wstring &checkpoint_file); - ~CrashReportSender() {} - - // Sets the maximum number of crash reports that will be sent in a 24-hour - // period. This uses the state persisted to the checkpoint file. - // The default value of -1 means that there is no limit on reports sent. - void set_max_reports_per_day(int reports) { - max_reports_per_day_ = reports; - } - - int max_reports_per_day() const { return max_reports_per_day_; } - - // Sends the specified files, along with the map of - // name value pairs, as a multipart POST request to the given URL. - // Parameter names must contain only printable ASCII characters, - // and may not contain a quote (") character. - // Only HTTP(S) URLs are currently supported. The return value indicates - // the result of the operation (see above for possible results). - // If report_code is non-NULL and the report is sent successfully (that is, - // the return value is RESULT_SUCCEEDED), a code uniquely identifying the - // report will be returned in report_code. - // (Otherwise, report_code will be unchanged.) - ReportResult SendCrashReport(const wstring &url, - const map<wstring, wstring> ¶meters, - const map<wstring, wstring> &files, - wstring *report_code); - - private: - // Reads persistent state from a checkpoint file. - void ReadCheckpoint(FILE *fd); - - // Called when a new report has been sent, to update the checkpoint state. - void ReportSent(int today); - - // Returns today's date (UTC) formatted as YYYYMMDD. - int GetCurrentDate() const; - - // Opens the checkpoint file with the specified mode. - // Returns zero on success, or an error code on failure. - int OpenCheckpointFile(const wchar_t *mode, FILE **fd); - - wstring checkpoint_file_; - int max_reports_per_day_; - // The last date on which we sent a report, expressed as YYYYMMDD. - int last_sent_date_; - // Number of reports sent on last_sent_date_ - int reports_sent_; - - // Disallow copy constructor and operator= - explicit CrashReportSender(const CrashReportSender &); - void operator=(const CrashReportSender &); -}; - -} // namespace google_breakpad - -#pragma warning( pop ) - -#endif // CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/objs.mozbuild b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/objs.mozbuild deleted file mode 100644 index 7b519328d..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/objs.mozbuild +++ /dev/null @@ -1,14 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -lobjs_sender = [ - 'crash_report_sender.cc', -] - -subdir = 'toolkit/crashreporter/google-breakpad/src/client/windows/sender' -objs_sender = [ - '/%s/%s' % (subdir, s) for s in lobjs_sender -] diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/abstract_class.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/abstract_class.cc deleted file mode 100644 index 32f78f2b9..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/abstract_class.cc +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "client/windows/tests/crash_generation_app/abstract_class.h" - -namespace google_breakpad { - -Base::Base(Derived* derived) - : derived_(derived) { -} - -Base::~Base() { - derived_->DoSomething(); -} - -#pragma warning(push) -#pragma warning(disable:4355) -// Disable warning C4355: 'this' : used in base member initializer list. -Derived::Derived() - : Base(this) { // C4355 -} -#pragma warning(pop) - -void Derived::DoSomething() { -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/abstract_class.h b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/abstract_class.h deleted file mode 100644 index e3f2a4f37..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/abstract_class.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_ABSTRACT_CLASS_H__ -#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_ABSTRACT_CLASS_H__ - -namespace google_breakpad { - -// Dummy classes to help generate a pure call violation. - -class Derived; - -class Base { - public: - Base(Derived* derived); - virtual ~Base(); - virtual void DoSomething() = 0; - - private: - Derived* derived_; -}; - -class Derived : public Base { - public: - Derived(); - virtual void DoSomething(); -}; - -} // namespace google_breakpad - -#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.cc deleted file mode 100644 index 0d837e521..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.cc +++ /dev/null @@ -1,522 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// crash_generation_app.cpp : Defines the entry point for the application. -// - -#include "client/windows/tests/crash_generation_app/crash_generation_app.h" - -#include <windows.h> -#include <tchar.h> - -#include "client/windows/crash_generation/client_info.h" -#include "client/windows/crash_generation/crash_generation_server.h" -#include "client/windows/handler/exception_handler.h" -#include "client/windows/common/ipc_protocol.h" - -#include "client/windows/tests/crash_generation_app/abstract_class.h" - -namespace google_breakpad { - -const int kMaxLoadString = 100; -const wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashServices\\TestServer"; - -const DWORD kEditBoxStyles = WS_CHILD | - WS_VISIBLE | - WS_VSCROLL | - ES_LEFT | - ES_MULTILINE | - ES_AUTOVSCROLL | - ES_READONLY; - -// Maximum length of a line in the edit box. -const size_t kMaximumLineLength = 256; - -// CS to access edit control in a thread safe way. -static CRITICAL_SECTION* cs_edit = NULL; - -// Edit control. -static HWND client_status_edit_box; - -HINSTANCE current_instance; // Current instance. -TCHAR title[kMaxLoadString]; // Title bar text. -TCHAR window_class[kMaxLoadString]; // Main window class name. - -ATOM MyRegisterClass(HINSTANCE instance); -BOOL InitInstance(HINSTANCE, int); -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); -INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); - -static size_t kCustomInfoCount = 2; -static CustomInfoEntry kCustomInfoEntries[] = { - CustomInfoEntry(L"prod", L"CrashTestApp"), - CustomInfoEntry(L"ver", L"1.0"), -}; - -static ExceptionHandler* handler = NULL; -static CrashGenerationServer* crash_server = NULL; - -// Registers the window class. -// -// This function and its usage are only necessary if you want this code -// to be compatible with Win32 systems prior to the 'RegisterClassEx' -// function that was added to Windows 95. It is important to call this -// function so that the application will get 'well formed' small icons -// associated with it. -ATOM MyRegisterClass(HINSTANCE instance) { - WNDCLASSEX wcex; - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = WndProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = instance; - wcex.hIcon = LoadIcon(instance, - MAKEINTRESOURCE(IDI_CRASHGENERATIONAPP)); - wcex.hCursor = LoadCursor(NULL, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.lpszMenuName = MAKEINTRESOURCE(IDC_CRASHGENERATIONAPP); - wcex.lpszClassName = window_class; - wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); - - return RegisterClassEx(&wcex); -} - -// Saves instance handle and creates main window -// -// In this function, we save the instance handle in a global variable and -// create and display the main program window. -BOOL InitInstance(HINSTANCE instance, int command_show) { - current_instance = instance; - HWND wnd = CreateWindow(window_class, - title, - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - 0, - CW_USEDEFAULT, - 0, - NULL, - NULL, - instance, - NULL); - - if (!wnd) { - return FALSE; - } - - ShowWindow(wnd, command_show); - UpdateWindow(wnd); - - return TRUE; -} - -static void AppendTextToEditBox(TCHAR* text) { - EnterCriticalSection(cs_edit); - SYSTEMTIME current_time; - GetLocalTime(¤t_time); - TCHAR line[kMaximumLineLength]; - int result = swprintf_s(line, - kMaximumLineLength, - L"[%.2d-%.2d-%.4d %.2d:%.2d:%.2d] %s", - current_time.wMonth, - current_time.wDay, - current_time.wYear, - current_time.wHour, - current_time.wMinute, - current_time.wSecond, - text); - - if (result == -1) { - return; - } - - int length = GetWindowTextLength(client_status_edit_box); - SendMessage(client_status_edit_box, - EM_SETSEL, - (WPARAM)length, - (LPARAM)length); - SendMessage(client_status_edit_box, - EM_REPLACESEL, - (WPARAM)FALSE, - (LPARAM)line); - LeaveCriticalSection(cs_edit); -} - -static DWORD WINAPI AppendTextWorker(void* context) { - TCHAR* text = reinterpret_cast<TCHAR*>(context); - - AppendTextToEditBox(text); - delete[] text; - - return 0; -} - -bool ShowDumpResults(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded) { - TCHAR* text = new TCHAR[kMaximumLineLength]; - text[0] = _T('\0'); - int result = swprintf_s(text, - kMaximumLineLength, - TEXT("Dump generation request %s\r\n"), - succeeded ? TEXT("succeeded") : TEXT("failed")); - if (result == -1) { - delete [] text; - } - - QueueUserWorkItem(AppendTextWorker, text, WT_EXECUTEDEFAULT); - return succeeded; -} - -static void ShowClientConnected(void* context, - const ClientInfo* client_info) { - TCHAR* line = new TCHAR[kMaximumLineLength]; - line[0] = _T('\0'); - int result = swprintf_s(line, - kMaximumLineLength, - L"Client connected:\t\t%d\r\n", - client_info->pid()); - - if (result == -1) { - delete[] line; - return; - } - - QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT); -} - -static void ShowClientCrashed(void* context, - const ClientInfo* client_info, - const wstring* dump_path) { - TCHAR* line = new TCHAR[kMaximumLineLength]; - line[0] = _T('\0'); - int result = swprintf_s(line, - kMaximumLineLength, - TEXT("Client requested dump:\t%d\r\n"), - client_info->pid()); - - if (result == -1) { - delete[] line; - return; - } - - QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT); - - CustomClientInfo custom_info = client_info->GetCustomInfo(); - if (custom_info.count <= 0) { - return; - } - - wstring str_line; - for (size_t i = 0; i < custom_info.count; ++i) { - if (i > 0) { - str_line += L", "; - } - str_line += custom_info.entries[i].name; - str_line += L": "; - str_line += custom_info.entries[i].value; - } - - line = new TCHAR[kMaximumLineLength]; - line[0] = _T('\0'); - result = swprintf_s(line, - kMaximumLineLength, - L"%s\n", - str_line.c_str()); - if (result == -1) { - delete[] line; - return; - } - QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT); -} - -static void ShowClientExited(void* context, - const ClientInfo* client_info) { - TCHAR* line = new TCHAR[kMaximumLineLength]; - line[0] = _T('\0'); - int result = swprintf_s(line, - kMaximumLineLength, - TEXT("Client exited:\t\t%d\r\n"), - client_info->pid()); - - if (result == -1) { - delete[] line; - return; - } - - QueueUserWorkItem(AppendTextWorker, line, WT_EXECUTEDEFAULT); -} - -void CrashServerStart() { - // Do not create another instance of the server. - if (crash_server) { - return; - } - - std::wstring dump_path = L"C:\\Dumps\\"; - - if (_wmkdir(dump_path.c_str()) && (errno != EEXIST)) { - MessageBoxW(NULL, L"Unable to create dump directory", L"Dumper", MB_OK); - return; - } - - crash_server = new CrashGenerationServer(kPipeName, - NULL, - ShowClientConnected, - NULL, - ShowClientCrashed, - NULL, - ShowClientExited, - NULL, - NULL, - NULL, - true, - &dump_path); - - if (!crash_server->Start()) { - MessageBoxW(NULL, L"Unable to start server", L"Dumper", MB_OK); - delete crash_server; - crash_server = NULL; - } -} - -void CrashServerStop() { - delete crash_server; - crash_server = NULL; -} - -void DerefZeroCrash() { - int* x = 0; - *x = 1; -} - -void InvalidParamCrash() { - printf(NULL); -} - -void PureCallCrash() { - Derived derived; -} - -void RequestDump() { - if (!handler->WriteMinidump()) { - MessageBoxW(NULL, L"Dump request failed", L"Dumper", MB_OK); - } - kCustomInfoEntries[1].set_value(L"1.1"); -} - -void CleanUp() { - if (cs_edit) { - DeleteCriticalSection(cs_edit); - delete cs_edit; - } - - if (handler) { - delete handler; - } - - if (crash_server) { - delete crash_server; - } -} - -// Processes messages for the main window. -// -// WM_COMMAND - process the application menu. -// WM_PAINT - Paint the main window. -// WM_DESTROY - post a quit message and return. -LRESULT CALLBACK WndProc(HWND wnd, - UINT message, - WPARAM w_param, - LPARAM l_param) { - int message_id; - int message_event; - PAINTSTRUCT ps; - HDC hdc; - - HINSTANCE instance = (HINSTANCE)GetWindowLongPtr(wnd, GWLP_HINSTANCE); - - switch (message) { - case WM_COMMAND: - // Parse the menu selections. - message_id = LOWORD(w_param); - message_event = HIWORD(w_param); - switch (message_id) { - case IDM_ABOUT: - DialogBox(current_instance, - MAKEINTRESOURCE(IDD_ABOUTBOX), - wnd, - About); - break; - case IDM_EXIT: - DestroyWindow(wnd); - break; - case ID_SERVER_START: - CrashServerStart(); - break; - case ID_SERVER_STOP: - CrashServerStop(); - break; - case ID_CLIENT_DEREFZERO: - DerefZeroCrash(); - break; - case ID_CLIENT_INVALIDPARAM: - InvalidParamCrash(); - break; - case ID_CLIENT_PURECALL: - PureCallCrash(); - break; - case ID_CLIENT_REQUESTEXPLICITDUMP: - RequestDump(); - break; - default: - return DefWindowProc(wnd, message, w_param, l_param); - } - break; - case WM_CREATE: - client_status_edit_box = CreateWindow(TEXT("EDIT"), - NULL, - kEditBoxStyles, - 0, - 0, - 0, - 0, - wnd, - NULL, - instance, - NULL); - break; - case WM_SIZE: - // Make the edit control the size of the window's client area. - MoveWindow(client_status_edit_box, - 0, - 0, - LOWORD(l_param), // width of client area. - HIWORD(l_param), // height of client area. - TRUE); // repaint window. - break; - case WM_SETFOCUS: - SetFocus(client_status_edit_box); - break; - case WM_PAINT: - hdc = BeginPaint(wnd, &ps); - EndPaint(wnd, &ps); - break; - case WM_DESTROY: - CleanUp(); - PostQuitMessage(0); - break; - default: - return DefWindowProc(wnd, message, w_param, l_param); - } - - return 0; -} - -// Message handler for about box. -INT_PTR CALLBACK About(HWND dlg, - UINT message, - WPARAM w_param, - LPARAM l_param) { - UNREFERENCED_PARAMETER(l_param); - switch (message) { - case WM_INITDIALOG: - return (INT_PTR)TRUE; - - case WM_COMMAND: - if (LOWORD(w_param) == IDOK || LOWORD(w_param) == IDCANCEL) { - EndDialog(dlg, LOWORD(w_param)); - return (INT_PTR)TRUE; - } - break; - } - - return (INT_PTR)FALSE; -} - -} // namespace google_breakpad - -int APIENTRY _tWinMain(HINSTANCE instance, - HINSTANCE previous_instance, - LPTSTR command_line, - int command_show) { - using namespace google_breakpad; - - UNREFERENCED_PARAMETER(previous_instance); - UNREFERENCED_PARAMETER(command_line); - - cs_edit = new CRITICAL_SECTION(); - InitializeCriticalSection(cs_edit); - - CustomClientInfo custom_info = {kCustomInfoEntries, kCustomInfoCount}; - - CrashServerStart(); - // This is needed for CRT to not show dialog for invalid param - // failures and instead let the code handle it. - _CrtSetReportMode(_CRT_ASSERT, 0); - handler = new ExceptionHandler(L"C:\\dumps\\", - NULL, - google_breakpad::ShowDumpResults, - NULL, - ExceptionHandler::HANDLER_ALL, - MiniDumpNormal, - kPipeName, - &custom_info); - - // Initialize global strings. - LoadString(instance, IDS_APP_TITLE, title, kMaxLoadString); - LoadString(instance, - IDC_CRASHGENERATIONAPP, - window_class, - kMaxLoadString); - MyRegisterClass(instance); - - // Perform application initialization. - if (!InitInstance(instance, command_show)) { - return FALSE; - } - - HACCEL accel_table = LoadAccelerators( - instance, - MAKEINTRESOURCE(IDC_CRASHGENERATIONAPP)); - - // Main message loop. - MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) { - if (!TranslateAccelerator(msg.hwnd, accel_table, &msg)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - return static_cast<int>(msg.wParam); -} diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.gyp b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.gyp deleted file mode 100644 index 3ce307da0..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.gyp +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -{ - 'includes': [ - '../../../../build/common.gypi', - ], - 'targets': [ - { - 'target_name': 'crash_generation_app', - 'type': 'executable', - 'sources': [ - 'abstract_class.cc', - 'abstract_class.h', - 'crash_generation_app.cc', - 'crash_generation_app.h', - 'crash_generation_app.ico', - 'crash_generation_app.rc', - 'resource.h', - 'small.ico', - ], - 'libraries': [ - 'user32.lib', - ], - 'dependencies': [ - '../../breakpad_client.gyp:common', - '../../crash_generation/crash_generation.gyp:crash_generation_server', - '../../crash_generation/crash_generation.gyp:crash_generation_client', - '../../handler/exception_handler.gyp:exception_handler', - ], - 'msvs_settings': { - 'VCLinkerTool': { - 'SubSystem': '2', # Windows Subsystem as opposed to a console app - }, - }, - } - ] -} diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.h b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.h deleted file mode 100644 index 4d3bb6eb2..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__ -#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__ - -#include "resource.h" - -#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_CRASH_GENERATION_APP_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.ico b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.ico Binary files differdeleted file mode 100644 index d551aa3aa..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.ico +++ /dev/null diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.rc b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.rc deleted file mode 100644 index a362562b9..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.rc +++ /dev/null @@ -1,144 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#define APSTUDIO_HIDDEN_SYMBOLS -#include "windows.h" -#undef APSTUDIO_HIDDEN_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_CRASHGENERATIONAPP ICON "crash_generation_app.ico" -IDI_SMALL ICON "small.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDC_CRASHGENERATIONAPP MENU -BEGIN - POPUP "&File" - BEGIN - MENUITEM "E&xit", IDM_EXIT - END - POPUP "&Server" - BEGIN - MENUITEM "&Start", ID_SERVER_START - MENUITEM "S&top", ID_SERVER_STOP - END - POPUP "&Client" - BEGIN - MENUITEM "&Deref Zero", ID_CLIENT_DEREFZERO - MENUITEM "&Invalid Param", ID_CLIENT_INVALIDPARAM - MENUITEM "&Pure Call", ID_CLIENT_PURECALL - MENUITEM "&Request Dump", ID_CLIENT_REQUESTEXPLICITDUMP - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Accelerator -// - -IDC_CRASHGENERATIONAPP ACCELERATORS -BEGIN - "?", IDM_ABOUT, ASCII, ALT - "/", IDM_ABOUT, ASCII, ALT -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_ABOUTBOX DIALOG 22, 17, 230, 75 -STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "About" -FONT 8, "System" -BEGIN - ICON IDI_CRASHGENERATIONAPP,IDC_MYICON,14,9,16,16 - LTEXT "CrashGenerationApp Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX - LTEXT "Copyright (C) 2008",IDC_STATIC,49,20,119,8 - DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP -END - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""windows.h""\r\n" - "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN - IDS_APP_TITLE "CrashGenerationApp" - IDC_CRASHGENERATIONAPP "CRASHGENERATIONAPP" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/resource.h b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/resource.h deleted file mode 100644 index 8c7f6570a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/resource.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// PreCompile.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#ifndef CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_RESOURCE_H__ -#define CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_RESOURCE_H__ - -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by crash_generation_app.rc -// -#define IDC_MYICON 2 -#define IDD_CRASHGENERATIONAPP_DIALOG 102 -#define IDS_APP_TITLE 103 -#define IDD_ABOUTBOX 103 -#define IDM_ABOUT 104 -#define IDM_EXIT 105 -#define IDI_CRASHGENERATIONAPP 107 -#define IDI_SMALL 108 -#define IDC_CRASHGENERATIONAPP 109 -#define IDR_MAINFRAME 128 -#define ID_SERVER_START 32771 -#define ID_SERVER_STOP 32772 -#define ID_CLIENT_INVALIDPARAM 32773 -#define ID_CLIENT_ASSERTFAILURE 32774 -#define ID_CLIENT_DEREFZERO 32775 -#define ID_CLIENT_PURECALL 32777 -#define ID_CLIENT_REQUESTEXPLICITDUMP 32778 -#define IDC_STATIC -1 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 129 -#define _APS_NEXT_COMMAND_VALUE 32780 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 110 -#endif -#endif - -#endif // CLIENT_WINDOWS_TESTS_CRASH_GENERATION_APP_RESOURCE_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/small.ico b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/small.ico Binary files differdeleted file mode 100644 index d551aa3aa..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/small.ico +++ /dev/null diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/client_tests.gyp b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/client_tests.gyp deleted file mode 100644 index b13603ef4..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/client_tests.gyp +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -{ - 'includes': [ - '../../../build/common.gypi', - ], - 'targets': [ - { - 'target_name': 'client_tests', - 'type': 'executable', - 'sources': [ - 'exception_handler_test.h', - 'exception_handler_test.cc', - 'exception_handler_death_test.cc', - 'exception_handler_nesting_test.cc', - 'minidump_test.cc', - 'dump_analysis.cc', - 'dump_analysis.h', - 'crash_generation_server_test.cc' - ], - 'dependencies': [ - 'testing.gyp:gtest', - 'testing.gyp:gmock', - '../breakpad_client.gyp:common', - '../crash_generation/crash_generation.gyp:crash_generation_server', - '../crash_generation/crash_generation.gyp:crash_generation_client', - '../handler/exception_handler.gyp:exception_handler', - 'processor_bits', - ] - }, - { - 'target_name': 'processor_bits', - 'type': 'static_library', - 'include_dirs': [ - '<(DEPTH)', - ], - 'direct_dependent_settings': { - 'include_dirs': [ - '<(DEPTH)', - ] - }, - 'sources': [ - '<(DEPTH)/common/string_conversion.cc', - '<(DEPTH)/processor/basic_code_modules.cc', - '<(DEPTH)/processor/dump_context.cc', - '<(DEPTH)/processor/dump_object.cc', - '<(DEPTH)/processor/logging.cc', - '<(DEPTH)/processor/minidump.cc', - '<(DEPTH)/processor/pathname_stripper.cc', - '<(DEPTH)/processor/proc_maps_linux.cc', - ] - } - ], -} diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/crash_generation_server_test.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/crash_generation_server_test.cc deleted file mode 100644 index b7b2b84f2..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/crash_generation_server_test.cc +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/include/gmock/gmock.h" - -#include "client/windows/crash_generation/crash_generation_server.h" -#include "client/windows/common/ipc_protocol.h" - -using testing::_; - -namespace { - -const wchar_t kPipeName[] = - L"\\\\.\\pipe\\CrashGenerationServerTest\\TestCaseServer"; - -const DWORD kPipeDesiredAccess = FILE_READ_DATA | - FILE_WRITE_DATA | - FILE_WRITE_ATTRIBUTES; - -const DWORD kPipeFlagsAndAttributes = SECURITY_IDENTIFICATION | - SECURITY_SQOS_PRESENT; - -const DWORD kPipeMode = PIPE_READMODE_MESSAGE; - -#define arraysize(f) (sizeof(f) / sizeof(*f)) -const google_breakpad::CustomInfoEntry kCustomInfoEntries[] = { - google_breakpad::CustomInfoEntry(L"prod", L"CrashGenerationServerTest"), - google_breakpad::CustomInfoEntry(L"ver", L"1.0"), -}; - -class CrashGenerationServerTest : public ::testing::Test { - public: - CrashGenerationServerTest() - : crash_generation_server_(kPipeName, - NULL, - CallOnClientConnected, &mock_callbacks_, - CallOnClientDumpRequested, &mock_callbacks_, - CallOnClientExited, &mock_callbacks_, - CallOnClientUploadRequested, &mock_callbacks_, - false, - NULL), - thread_id_(0), - exception_pointers_(NULL) { - memset(&assert_info_, 0, sizeof(assert_info_)); - } - - protected: - class MockCrashGenerationServerCallbacks { - public: - MOCK_METHOD1(OnClientConnected, - void(const google_breakpad::ClientInfo* client_info)); - MOCK_METHOD2(OnClientDumpRequested, - void(const google_breakpad::ClientInfo* client_info, - const std::wstring* file_path)); - MOCK_METHOD1(OnClientExited, - void(const google_breakpad::ClientInfo* client_info)); - MOCK_METHOD1(OnClientUploadRequested, - void(const DWORD crash_id)); - }; - - enum ClientFault { - NO_FAULT, - CLOSE_AFTER_CONNECT, - SEND_INVALID_REGISTRATION, - TRUNCATE_REGISTRATION, - CLOSE_AFTER_REGISTRATION, - RESPONSE_BUFFER_TOO_SMALL, - CLOSE_AFTER_RESPONSE, - SEND_INVALID_ACK - }; - - void SetUp() { - ASSERT_TRUE(crash_generation_server_.Start()); - } - - void FaultyClient(ClientFault fault_type) { - HANDLE pipe = CreateFile(kPipeName, - kPipeDesiredAccess, - 0, - NULL, - OPEN_EXISTING, - kPipeFlagsAndAttributes, - NULL); - - if (pipe == INVALID_HANDLE_VALUE) { - ASSERT_EQ(ERROR_PIPE_BUSY, GetLastError()); - - // Cannot continue retrying if wait on pipe fails. - ASSERT_TRUE(WaitNamedPipe(kPipeName, 500)); - - pipe = CreateFile(kPipeName, - kPipeDesiredAccess, - 0, - NULL, - OPEN_EXISTING, - kPipeFlagsAndAttributes, - NULL); - } - - ASSERT_NE(pipe, INVALID_HANDLE_VALUE); - - DWORD mode = kPipeMode; - ASSERT_TRUE(SetNamedPipeHandleState(pipe, &mode, NULL, NULL)); - - DoFaultyClient(fault_type, pipe); - - CloseHandle(pipe); - } - - void DoTestFault(ClientFault fault) { - EXPECT_CALL(mock_callbacks_, OnClientConnected(_)).Times(0); - ASSERT_NO_FATAL_FAILURE(FaultyClient(fault)); - ASSERT_NO_FATAL_FAILURE(FaultyClient(fault)); - ASSERT_NO_FATAL_FAILURE(FaultyClient(fault)); - - EXPECT_CALL(mock_callbacks_, OnClientConnected(_)); - - ASSERT_NO_FATAL_FAILURE(FaultyClient(NO_FAULT)); - - // Slight hack. The OnClientConnected is only invoked after the ack is - // received by the server. At that point, the FaultyClient call has already - // returned. The best way to wait until the server is done handling that is - // to send one more ping, whose processing will be blocked by delivery of - // the OnClientConnected message. - ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT)); - } - - MockCrashGenerationServerCallbacks mock_callbacks_; - - private: - // Depends on the caller to successfully open the pipe before invocation and - // to close it immediately afterwards. - void DoFaultyClient(ClientFault fault_type, HANDLE pipe) { - if (fault_type == CLOSE_AFTER_CONNECT) { - return; - } - - google_breakpad::CustomClientInfo custom_info = {kCustomInfoEntries, - arraysize(kCustomInfoEntries)}; - - google_breakpad::ProtocolMessage msg( - fault_type == SEND_INVALID_REGISTRATION ? - google_breakpad::MESSAGE_TAG_NONE : - google_breakpad::MESSAGE_TAG_REGISTRATION_REQUEST, - GetCurrentProcessId(), - MiniDumpNormal, - &thread_id_, - &exception_pointers_, - &assert_info_, - custom_info, - NULL, - NULL, - NULL); - - DWORD bytes_count = 0; - - ASSERT_TRUE(WriteFile(pipe, - &msg, - fault_type == TRUNCATE_REGISTRATION ? - sizeof(msg) / 2 : sizeof(msg), - &bytes_count, - NULL)); - - if (fault_type == CLOSE_AFTER_REGISTRATION) { - return; - } - - google_breakpad::ProtocolMessage reply; - - if (!ReadFile(pipe, - &reply, - fault_type == RESPONSE_BUFFER_TOO_SMALL ? - sizeof(google_breakpad::ProtocolMessage) / 2 : - sizeof(google_breakpad::ProtocolMessage), - &bytes_count, - NULL)) { - switch (fault_type) { - case TRUNCATE_REGISTRATION: - case RESPONSE_BUFFER_TOO_SMALL: - case SEND_INVALID_REGISTRATION: - return; - - default: - FAIL() << "Unexpectedly failed to register."; - } - } - - if (fault_type == CLOSE_AFTER_RESPONSE) { - return; - } - - google_breakpad::ProtocolMessage ack_msg; - ack_msg.tag = google_breakpad::MESSAGE_TAG_REGISTRATION_ACK; - - ASSERT_TRUE(WriteFile(pipe, - &ack_msg, - SEND_INVALID_ACK ? - sizeof(ack_msg) : sizeof(ack_msg) / 2, - &bytes_count, - NULL)); - - return; - } - - static void CallOnClientConnected( - void* context, const google_breakpad::ClientInfo* client_info) { - static_cast<MockCrashGenerationServerCallbacks*>(context)-> - OnClientConnected(client_info); - } - - static void CallOnClientDumpRequested( - void* context, - const google_breakpad::ClientInfo* client_info, - const std::wstring* file_path) { - static_cast<MockCrashGenerationServerCallbacks*>(context)-> - OnClientDumpRequested(client_info, file_path); - } - - static void CallOnClientExited( - void* context, const google_breakpad::ClientInfo* client_info) { - static_cast<MockCrashGenerationServerCallbacks*>(context)-> - OnClientExited(client_info); - } - - static void CallOnClientUploadRequested(void* context, const DWORD crash_id) { - static_cast<MockCrashGenerationServerCallbacks*>(context)-> - OnClientUploadRequested(crash_id); - } - - DWORD thread_id_; - EXCEPTION_POINTERS* exception_pointers_; - MDRawAssertionInfo assert_info_; - - google_breakpad::CrashGenerationServer crash_generation_server_; -}; - -TEST_F(CrashGenerationServerTest, PingServerTest) { - DoTestFault(CLOSE_AFTER_CONNECT); -} - -TEST_F(CrashGenerationServerTest, InvalidRegistration) { - DoTestFault(SEND_INVALID_REGISTRATION); -} - -TEST_F(CrashGenerationServerTest, TruncateRegistration) { - DoTestFault(TRUNCATE_REGISTRATION); -} - -TEST_F(CrashGenerationServerTest, CloseAfterRegistration) { - DoTestFault(CLOSE_AFTER_REGISTRATION); -} - -TEST_F(CrashGenerationServerTest, ResponseBufferTooSmall) { - DoTestFault(RESPONSE_BUFFER_TOO_SMALL); -} - -TEST_F(CrashGenerationServerTest, CloseAfterResponse) { - DoTestFault(CLOSE_AFTER_RESPONSE); -} - -// It turns out that, as long as you send one byte, the ACK is accepted and -// registration succeeds. -TEST_F(CrashGenerationServerTest, SendInvalidAck) { - EXPECT_CALL(mock_callbacks_, OnClientConnected(_)); - ASSERT_NO_FATAL_FAILURE(FaultyClient(SEND_INVALID_ACK)); - - // See DoTestFault for an explanation of this line - ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT)); - - EXPECT_CALL(mock_callbacks_, OnClientConnected(_)); - ASSERT_NO_FATAL_FAILURE(FaultyClient(NO_FAULT)); - - // See DoTestFault for an explanation of this line - ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT)); -} - -} // anonymous namespace diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/dump_analysis.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/dump_analysis.cc deleted file mode 100644 index 6bf854719..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/dump_analysis.cc +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <windows.h> -#include <objbase.h> -#include <dbghelp.h> - -#include "client/windows/unittests/dump_analysis.h" // NOLINT -#include "testing/gtest/include/gtest/gtest.h" - -DumpAnalysis::~DumpAnalysis() { - if (dump_file_view_ != NULL) { - EXPECT_TRUE(::UnmapViewOfFile(dump_file_view_)); - ::CloseHandle(dump_file_mapping_); - dump_file_mapping_ = NULL; - } - - if (dump_file_handle_ != NULL) { - ::CloseHandle(dump_file_handle_); - dump_file_handle_ = NULL; - } -} - -void DumpAnalysis::EnsureDumpMapped() { - if (dump_file_view_ == NULL) { - dump_file_handle_ = ::CreateFile(dump_file_.c_str(), - GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - 0, - NULL); - ASSERT_TRUE(dump_file_handle_ != NULL); - ASSERT_TRUE(dump_file_mapping_ == NULL); - - dump_file_mapping_ = ::CreateFileMapping(dump_file_handle_, - NULL, - PAGE_READONLY, - 0, - 0, - NULL); - ASSERT_TRUE(dump_file_mapping_ != NULL); - - dump_file_view_ = ::MapViewOfFile(dump_file_mapping_, - FILE_MAP_READ, - 0, - 0, - 0); - ASSERT_TRUE(dump_file_view_ != NULL); - } -} - -bool DumpAnalysis::HasTebs() const { - MINIDUMP_THREAD_LIST* thread_list = NULL; - size_t thread_list_size = GetStream(ThreadListStream, &thread_list); - - if (thread_list_size > 0 && thread_list != NULL) { - for (ULONG i = 0; i < thread_list->NumberOfThreads; ++i) { - if (!HasMemory(thread_list->Threads[i].Teb)) - return false; - } - - return true; - } - - // No thread list, no TEB info. - return false; -} - -bool DumpAnalysis::HasPeb() const { - MINIDUMP_THREAD_LIST* thread_list = NULL; - size_t thread_list_size = GetStream(ThreadListStream, &thread_list); - - if (thread_list_size > 0 && thread_list != NULL && - thread_list->NumberOfThreads > 0) { - FakeTEB* teb = NULL; - if (!HasMemory(thread_list->Threads[0].Teb, &teb)) - return false; - - return HasMemory(teb->peb); - } - - return false; -} - -bool DumpAnalysis::HasStream(ULONG stream_number) const { - void* stream = NULL; - size_t stream_size = GetStreamImpl(stream_number, &stream); - return stream_size > 0 && stream != NULL; -} - -size_t DumpAnalysis::GetStreamImpl(ULONG stream_number, void** stream) const { - MINIDUMP_DIRECTORY* directory = NULL; - ULONG memory_list_size = 0; - BOOL ret = ::MiniDumpReadDumpStream(dump_file_view_, - stream_number, - &directory, - stream, - &memory_list_size); - - return ret ? memory_list_size : 0; -} - -bool DumpAnalysis::HasMemoryImpl(const void *addr_in, size_t structuresize, - void **structure) const { - uintptr_t address = reinterpret_cast<uintptr_t>(addr_in); - MINIDUMP_MEMORY_LIST* memory_list = NULL; - size_t memory_list_size = GetStream(MemoryListStream, &memory_list); - if (memory_list_size > 0 && memory_list != NULL) { - for (ULONG i = 0; i < memory_list->NumberOfMemoryRanges; ++i) { - MINIDUMP_MEMORY_DESCRIPTOR& descr = memory_list->MemoryRanges[i]; - const uintptr_t range_start = - static_cast<uintptr_t>(descr.StartOfMemoryRange); - uintptr_t range_end = range_start + descr.Memory.DataSize; - - if (address >= range_start && - address + structuresize < range_end) { - // The start address falls in the range, and the end address is - // in bounds, return a pointer to the structure if requested. - if (structure != NULL) - *structure = RVA_TO_ADDR(dump_file_view_, descr.Memory.Rva); - - return true; - } - } - } - - // We didn't find the range in a MINIDUMP_MEMORY_LIST, so maybe this - // is a full dump using MINIDUMP_MEMORY64_LIST with all the memory at the - // end of the dump file. - MINIDUMP_MEMORY64_LIST* memory64_list = NULL; - memory_list_size = GetStream(Memory64ListStream, &memory64_list); - if (memory_list_size > 0 && memory64_list != NULL) { - // Keep track of where the current descriptor maps to. - RVA64 curr_rva = memory64_list->BaseRva; - for (ULONG i = 0; i < memory64_list->NumberOfMemoryRanges; ++i) { - MINIDUMP_MEMORY_DESCRIPTOR64& descr = memory64_list->MemoryRanges[i]; - uintptr_t range_start = - static_cast<uintptr_t>(descr.StartOfMemoryRange); - uintptr_t range_end = range_start + static_cast<size_t>(descr.DataSize); - - if (address >= range_start && - address + structuresize < range_end) { - // The start address falls in the range, and the end address is - // in bounds, return a pointer to the structure if requested. - if (structure != NULL) - *structure = RVA_TO_ADDR(dump_file_view_, curr_rva); - - return true; - } - - // Advance the current RVA. - curr_rva += descr.DataSize; - } - } - - return false; -} diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/dump_analysis.h b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/dump_analysis.h deleted file mode 100644 index 6cef48d81..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/dump_analysis.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_UNITTESTS_DUMP_ANALYSIS_H_ -#define CLIENT_WINDOWS_UNITTESTS_DUMP_ANALYSIS_H_ - -#include "client/windows/crash_generation/minidump_generator.h" - -// Convenience to get to the PEB pointer in a TEB. -struct FakeTEB { - char dummy[0x30]; - void* peb; -}; - -class DumpAnalysis { - public: - explicit DumpAnalysis(const std::wstring& file_path) - : dump_file_(file_path), dump_file_view_(NULL), dump_file_mapping_(NULL), - dump_file_handle_(NULL) { - EnsureDumpMapped(); - } - ~DumpAnalysis(); - - bool HasStream(ULONG stream_number) const; - - // This is template to keep type safety in the front, but we end up casting - // to void** inside the implementation to pass the pointer to Win32. So - // casting here is considered safe. - template <class StreamType> - size_t GetStream(ULONG stream_number, StreamType** stream) const { - return GetStreamImpl(stream_number, reinterpret_cast<void**>(stream)); - } - - bool HasTebs() const; - bool HasPeb() const; - bool HasMemory(ULONG64 address) const { - return HasMemory<BYTE>(address, NULL); - } - - bool HasMemory(const void* address) const { - return HasMemory<BYTE>(address, NULL); - } - - template <class StructureType> - bool HasMemory(ULONG64 address, StructureType** structure = NULL) const { - // We can't cope with 64 bit addresses for now. - if (address > 0xFFFFFFFFUL) - return false; - - return HasMemory(reinterpret_cast<void*>(address), structure); - } - - template <class StructureType> - bool HasMemory(const void* addr_in, StructureType** structure = NULL) const { - return HasMemoryImpl(addr_in, sizeof(StructureType), - reinterpret_cast<void**>(structure)); - } - - protected: - void EnsureDumpMapped(); - - HANDLE dump_file_mapping_; - HANDLE dump_file_handle_; - void* dump_file_view_; - std::wstring dump_file_; - - private: - // This is the implementation of GetStream<>. - size_t GetStreamImpl(ULONG stream_number, void** stream) const; - - // This is the implementation of HasMemory<>. - bool HasMemoryImpl(const void* addr_in, size_t pointersize, - void** structure) const; -}; - -#endif // CLIENT_WINDOWS_UNITTESTS_DUMP_ANALYSIS_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_death_test.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_death_test.cc deleted file mode 100644 index 079ca3d6f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_death_test.cc +++ /dev/null @@ -1,582 +0,0 @@ -// Copyright 2009, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <windows.h> -#include <dbghelp.h> -#include <strsafe.h> -#include <objbase.h> -#include <shellapi.h> - -#include <string> - -#include "breakpad_googletest_includes.h" -#include "client/windows/crash_generation/crash_generation_server.h" -#include "client/windows/handler/exception_handler.h" -#include "client/windows/unittests/exception_handler_test.h" -#include "common/windows/string_utils-inl.h" -#include "google_breakpad/processor/minidump.h" - -namespace { - -using std::wstring; -using namespace google_breakpad; - -const wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashTest\\TestCaseServer"; -const char kSuccessIndicator[] = "success"; -const char kFailureIndicator[] = "failure"; - -// Utility function to test for a path's existence. -BOOL DoesPathExist(const TCHAR *path_name); - -enum OutOfProcGuarantee { - OUT_OF_PROC_GUARANTEED, - OUT_OF_PROC_BEST_EFFORT, -}; - -class ExceptionHandlerDeathTest : public ::testing::Test { - protected: - // Member variable for each test that they can use - // for temporary storage. - TCHAR temp_path_[MAX_PATH]; - // Actually constructs a temp path name. - virtual void SetUp(); - // A helper method that tests can use to crash. - void DoCrashAccessViolation(const OutOfProcGuarantee out_of_proc_guarantee); - void DoCrashPureVirtualCall(); -}; - -void ExceptionHandlerDeathTest::SetUp() { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - TCHAR temp_path[MAX_PATH] = { '\0' }; - TCHAR test_name_wide[MAX_PATH] = { '\0' }; - // We want the temporary directory to be what the OS returns - // to us, + the test case name. - GetTempPath(MAX_PATH, temp_path); - // The test case name is exposed as a c-style string, - // convert it to a wchar_t string. - int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(), - strlen(test_info->name()), - test_name_wide, - MAX_PATH); - if (!dwRet) { - assert(false); - } - StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide); - CreateDirectory(temp_path_, NULL); -} - -BOOL DoesPathExist(const TCHAR *path_name) { - DWORD flags = GetFileAttributes(path_name); - if (flags == INVALID_FILE_ATTRIBUTES) { - return FALSE; - } - return TRUE; -} - -bool MinidumpWrittenCallback(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded) { - if (succeeded && DoesPathExist(dump_path)) { - fprintf(stderr, kSuccessIndicator); - } else { - fprintf(stderr, kFailureIndicator); - } - // If we don't flush, the output doesn't get sent before - // this process dies. - fflush(stderr); - return succeeded; -} - -TEST_F(ExceptionHandlerDeathTest, InProcTest) { - // For the in-proc test, we just need to instantiate an exception - // handler in in-proc mode, and crash. Since the entire test is - // reexecuted in the child process, we don't have to worry about - // the semantics of the exception handler being inherited/not - // inherited across CreateProcess(). - ASSERT_TRUE(DoesPathExist(temp_path_)); - scoped_ptr<google_breakpad::ExceptionHandler> exc( - new google_breakpad::ExceptionHandler( - temp_path_, - NULL, - &MinidumpWrittenCallback, - NULL, - google_breakpad::ExceptionHandler::HANDLER_ALL)); - - // Disable GTest SEH handler - testing::DisableExceptionHandlerInScope disable_exception_handler; - - int *i = NULL; - ASSERT_DEATH((*i)++, kSuccessIndicator); -} - -static bool gDumpCallbackCalled = false; - -void clientDumpCallback(void *dump_context, - const google_breakpad::ClientInfo *client_info, - const std::wstring *dump_path) { - gDumpCallbackCalled = true; -} - -void ExceptionHandlerDeathTest::DoCrashAccessViolation( - const OutOfProcGuarantee out_of_proc_guarantee) { - scoped_ptr<google_breakpad::ExceptionHandler> exc; - - if (out_of_proc_guarantee == OUT_OF_PROC_GUARANTEED) { - google_breakpad::CrashGenerationClient *client = - new google_breakpad::CrashGenerationClient(kPipeName, - MiniDumpNormal, - NULL); // custom_info - ASSERT_TRUE(client->Register()); - exc.reset(new google_breakpad::ExceptionHandler( - temp_path_, - NULL, // filter - NULL, // callback - NULL, // callback_context - google_breakpad::ExceptionHandler::HANDLER_ALL, - client)); - } else { - ASSERT_TRUE(out_of_proc_guarantee == OUT_OF_PROC_BEST_EFFORT); - exc.reset(new google_breakpad::ExceptionHandler( - temp_path_, - NULL, // filter - NULL, // callback - NULL, // callback_context - google_breakpad::ExceptionHandler::HANDLER_ALL, - MiniDumpNormal, - kPipeName, - NULL)); // custom_info - } - - // Disable GTest SEH handler - testing::DisableExceptionHandlerInScope disable_exception_handler; - - // Although this is executing in the child process of the death test, - // if it's not true we'll still get an error rather than the crash - // being expected. - ASSERT_TRUE(exc->IsOutOfProcess()); - int *i = NULL; - printf("%d\n", (*i)++); -} - -TEST_F(ExceptionHandlerDeathTest, OutOfProcTest) { - // We can take advantage of a detail of google test here to save some - // complexity in testing: when you do a death test, it actually forks. - // So we can make the main test harness the crash generation server, - // and call ASSERT_DEATH on a NULL dereference, it to expecting test - // the out of process scenario, since it's happening in a different - // process! This is different from the above because, above, we pass - // a NULL pipe name, and we also don't start a crash generation server. - - ASSERT_TRUE(DoesPathExist(temp_path_)); - std::wstring dump_path(temp_path_); - google_breakpad::CrashGenerationServer server( - kPipeName, NULL, NULL, NULL, &clientDumpCallback, NULL, NULL, NULL, NULL, - NULL, true, &dump_path); - - // This HAS to be EXPECT_, because when this test case is executed in the - // child process, the server registration will fail due to the named pipe - // being the same. - EXPECT_TRUE(server.Start()); - gDumpCallbackCalled = false; - ASSERT_DEATH(this->DoCrashAccessViolation(OUT_OF_PROC_BEST_EFFORT), ""); - EXPECT_TRUE(gDumpCallbackCalled); -} - -TEST_F(ExceptionHandlerDeathTest, OutOfProcGuaranteedTest) { - // This is similar to the previous test (OutOfProcTest). The only difference - // is that in this test, the crash generation client is created and registered - // with the crash generation server outside of the ExceptionHandler - // constructor which allows breakpad users to opt out of the default - // in-process dump generation when the registration with the crash generation - // server fails. - - ASSERT_TRUE(DoesPathExist(temp_path_)); - std::wstring dump_path(temp_path_); - google_breakpad::CrashGenerationServer server( - kPipeName, NULL, NULL, NULL, &clientDumpCallback, NULL, NULL, NULL, NULL, - NULL, true, &dump_path); - - // This HAS to be EXPECT_, because when this test case is executed in the - // child process, the server registration will fail due to the named pipe - // being the same. - EXPECT_TRUE(server.Start()); - gDumpCallbackCalled = false; - ASSERT_DEATH(this->DoCrashAccessViolation(OUT_OF_PROC_GUARANTEED), ""); - EXPECT_TRUE(gDumpCallbackCalled); -} - -TEST_F(ExceptionHandlerDeathTest, InvalidParameterTest) { - using google_breakpad::ExceptionHandler; - - ASSERT_TRUE(DoesPathExist(temp_path_)); - ExceptionHandler handler(temp_path_, NULL, NULL, NULL, - ExceptionHandler::HANDLER_INVALID_PARAMETER); - - // Disable the message box for assertions - _CrtSetReportMode(_CRT_ASSERT, 0); - - // Call with a bad argument. The invalid parameter will be swallowed - // and a dump will be generated, the process will exit(0). - ASSERT_EXIT(printf(NULL), ::testing::ExitedWithCode(0), ""); -} - - -struct PureVirtualCallBase { - PureVirtualCallBase() { - // We have to reinterpret so the linker doesn't get confused because the - // method isn't defined. - reinterpret_cast<PureVirtualCallBase*>(this)->PureFunction(); - } - virtual ~PureVirtualCallBase() {} - virtual void PureFunction() const = 0; -}; -struct PureVirtualCall : public PureVirtualCallBase { - PureVirtualCall() { PureFunction(); } - virtual void PureFunction() const {} -}; - -void ExceptionHandlerDeathTest::DoCrashPureVirtualCall() { - PureVirtualCall instance; -} - -TEST_F(ExceptionHandlerDeathTest, PureVirtualCallTest) { - using google_breakpad::ExceptionHandler; - - ASSERT_TRUE(DoesPathExist(temp_path_)); - ExceptionHandler handler(temp_path_, NULL, NULL, NULL, - ExceptionHandler::HANDLER_PURECALL); - - // Disable the message box for assertions - _CrtSetReportMode(_CRT_ASSERT, 0); - - // Calls a pure virtual function. - EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), ""); -} - -wstring find_minidump_in_directory(const wstring &directory) { - wstring search_path = directory + L"\\*"; - WIN32_FIND_DATA find_data; - HANDLE find_handle = FindFirstFileW(search_path.c_str(), &find_data); - if (find_handle == INVALID_HANDLE_VALUE) - return wstring(); - - wstring filename; - do { - const wchar_t extension[] = L".dmp"; - const int extension_length = sizeof(extension) / sizeof(extension[0]) - 1; - const int filename_length = wcslen(find_data.cFileName); - if (filename_length > extension_length && - wcsncmp(extension, - find_data.cFileName + filename_length - extension_length, - extension_length) == 0) { - filename = directory + L"\\" + find_data.cFileName; - break; - } - } while (FindNextFile(find_handle, &find_data)); - FindClose(find_handle); - return filename; -} - -#ifndef ADDRESS_SANITIZER - -TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemory) { - ASSERT_TRUE(DoesPathExist(temp_path_)); - scoped_ptr<google_breakpad::ExceptionHandler> exc( - new google_breakpad::ExceptionHandler( - temp_path_, - NULL, - NULL, - NULL, - google_breakpad::ExceptionHandler::HANDLER_ALL)); - - // Disable GTest SEH handler - testing::DisableExceptionHandlerInScope disable_exception_handler; - - // Get some executable memory. - const uint32_t kMemorySize = 256; // bytes - const int kOffset = kMemorySize / 2; - // This crashes with SIGILL on x86/x86-64/arm. - const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff }; - char* memory = reinterpret_cast<char*>(VirtualAlloc(NULL, - kMemorySize, - MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE)); - ASSERT_TRUE(memory); - - // Write some instructions that will crash. Put them - // in the middle of the block of memory, because the - // minidump should contain 128 bytes on either side of the - // instruction pointer. - memcpy(memory + kOffset, instructions, sizeof(instructions)); - - // Now execute the instructions, which should crash. - typedef void (*void_function)(void); - void_function memory_function = - reinterpret_cast<void_function>(memory + kOffset); - ASSERT_DEATH(memory_function(), ""); - - // free the memory. - VirtualFree(memory, 0, MEM_RELEASE); - - // Verify that the resulting minidump contains the memory around the IP - wstring minidump_filename_wide = find_minidump_in_directory(temp_path_); - ASSERT_FALSE(minidump_filename_wide.empty()); - string minidump_filename; - ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(minidump_filename_wide, - &minidump_filename)); - - // Read the minidump. Locate the exception record and the - // memory list, and then ensure that there is a memory region - // in the memory list that covers the instruction pointer from - // the exception record. - { - Minidump minidump(minidump_filename); - ASSERT_TRUE(minidump.Read()); - - MinidumpException* exception = minidump.GetException(); - MinidumpMemoryList* memory_list = minidump.GetMemoryList(); - ASSERT_TRUE(exception); - ASSERT_TRUE(memory_list); - ASSERT_LT((unsigned)0, memory_list->region_count()); - - MinidumpContext* context = exception->GetContext(); - ASSERT_TRUE(context); - - uint64_t instruction_pointer; - ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); - - MinidumpMemoryRegion* region = - memory_list->GetMemoryRegionForAddress(instruction_pointer); - ASSERT_TRUE(region); - - EXPECT_EQ(kMemorySize, region->GetSize()); - const uint8_t* bytes = region->GetMemory(); - ASSERT_TRUE(bytes); - - uint8_t prefix_bytes[kOffset]; - uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(instructions)]; - memset(prefix_bytes, 0, sizeof(prefix_bytes)); - memset(suffix_bytes, 0, sizeof(suffix_bytes)); - EXPECT_EQ(0, memcmp(bytes, prefix_bytes, sizeof(prefix_bytes))); - EXPECT_EQ(0, memcmp(bytes + kOffset, instructions, sizeof(instructions))); - EXPECT_EQ(0, memcmp(bytes + kOffset + sizeof(instructions), - suffix_bytes, sizeof(suffix_bytes))); - } - - DeleteFileW(minidump_filename_wide.c_str()); -} - -TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMinBound) { - ASSERT_TRUE(DoesPathExist(temp_path_)); - scoped_ptr<google_breakpad::ExceptionHandler> exc( - new google_breakpad::ExceptionHandler( - temp_path_, - NULL, - NULL, - NULL, - google_breakpad::ExceptionHandler::HANDLER_ALL)); - - // Disable GTest SEH handler - testing::DisableExceptionHandlerInScope disable_exception_handler; - - SYSTEM_INFO sSysInfo; // Useful information about the system - GetSystemInfo(&sSysInfo); // Initialize the structure. - - const uint32_t kMemorySize = 256; // bytes - const DWORD kPageSize = sSysInfo.dwPageSize; - const int kOffset = 0; - // This crashes with SIGILL on x86/x86-64/arm. - const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff }; - // Get some executable memory. Specifically, reserve two pages, - // but only commit the second. - char* all_memory = reinterpret_cast<char*>(VirtualAlloc(NULL, - kPageSize * 2, - MEM_RESERVE, - PAGE_NOACCESS)); - ASSERT_TRUE(all_memory); - char* memory = all_memory + kPageSize; - ASSERT_TRUE(VirtualAlloc(memory, kPageSize, - MEM_COMMIT, PAGE_EXECUTE_READWRITE)); - - // Write some instructions that will crash. Put them - // in the middle of the block of memory, because the - // minidump should contain 128 bytes on either side of the - // instruction pointer. - memcpy(memory + kOffset, instructions, sizeof(instructions)); - - // Now execute the instructions, which should crash. - typedef void (*void_function)(void); - void_function memory_function = - reinterpret_cast<void_function>(memory + kOffset); - ASSERT_DEATH(memory_function(), ""); - - // free the memory. - VirtualFree(memory, 0, MEM_RELEASE); - - // Verify that the resulting minidump contains the memory around the IP - wstring minidump_filename_wide = find_minidump_in_directory(temp_path_); - ASSERT_FALSE(minidump_filename_wide.empty()); - string minidump_filename; - ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(minidump_filename_wide, - &minidump_filename)); - - // Read the minidump. Locate the exception record and the - // memory list, and then ensure that there is a memory region - // in the memory list that covers the instruction pointer from - // the exception record. - { - Minidump minidump(minidump_filename); - ASSERT_TRUE(minidump.Read()); - - MinidumpException* exception = minidump.GetException(); - MinidumpMemoryList* memory_list = minidump.GetMemoryList(); - ASSERT_TRUE(exception); - ASSERT_TRUE(memory_list); - ASSERT_LT((unsigned)0, memory_list->region_count()); - - MinidumpContext* context = exception->GetContext(); - ASSERT_TRUE(context); - - uint64_t instruction_pointer; - ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); - - MinidumpMemoryRegion* region = - memory_list->GetMemoryRegionForAddress(instruction_pointer); - ASSERT_TRUE(region); - - EXPECT_EQ(kMemorySize / 2, region->GetSize()); - const uint8_t* bytes = region->GetMemory(); - ASSERT_TRUE(bytes); - - uint8_t suffix_bytes[kMemorySize / 2 - sizeof(instructions)]; - memset(suffix_bytes, 0, sizeof(suffix_bytes)); - EXPECT_TRUE(memcmp(bytes + kOffset, - instructions, sizeof(instructions)) == 0); - EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(instructions), - suffix_bytes, sizeof(suffix_bytes)) == 0); - } - - DeleteFileW(minidump_filename_wide.c_str()); -} - -TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMaxBound) { - ASSERT_TRUE(DoesPathExist(temp_path_)); - scoped_ptr<google_breakpad::ExceptionHandler> exc( - new google_breakpad::ExceptionHandler( - temp_path_, - NULL, - NULL, - NULL, - google_breakpad::ExceptionHandler::HANDLER_ALL)); - - // Disable GTest SEH handler - testing::DisableExceptionHandlerInScope disable_exception_handler; - - SYSTEM_INFO sSysInfo; // Useful information about the system - GetSystemInfo(&sSysInfo); // Initialize the structure. - - const DWORD kPageSize = sSysInfo.dwPageSize; - // This crashes with SIGILL on x86/x86-64/arm. - const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff }; - const int kOffset = kPageSize - sizeof(instructions); - // Get some executable memory. Specifically, reserve two pages, - // but only commit the first. - char* memory = reinterpret_cast<char*>(VirtualAlloc(NULL, - kPageSize * 2, - MEM_RESERVE, - PAGE_NOACCESS)); - ASSERT_TRUE(memory); - ASSERT_TRUE(VirtualAlloc(memory, kPageSize, - MEM_COMMIT, PAGE_EXECUTE_READWRITE)); - - // Write some instructions that will crash. - memcpy(memory + kOffset, instructions, sizeof(instructions)); - - // Now execute the instructions, which should crash. - typedef void (*void_function)(void); - void_function memory_function = - reinterpret_cast<void_function>(memory + kOffset); - ASSERT_DEATH(memory_function(), ""); - - // free the memory. - VirtualFree(memory, 0, MEM_RELEASE); - - // Verify that the resulting minidump contains the memory around the IP - wstring minidump_filename_wide = find_minidump_in_directory(temp_path_); - ASSERT_FALSE(minidump_filename_wide.empty()); - string minidump_filename; - ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(minidump_filename_wide, - &minidump_filename)); - - // Read the minidump. Locate the exception record and the - // memory list, and then ensure that there is a memory region - // in the memory list that covers the instruction pointer from - // the exception record. - { - Minidump minidump(minidump_filename); - ASSERT_TRUE(minidump.Read()); - - MinidumpException* exception = minidump.GetException(); - MinidumpMemoryList* memory_list = minidump.GetMemoryList(); - ASSERT_TRUE(exception); - ASSERT_TRUE(memory_list); - ASSERT_LT((unsigned)0, memory_list->region_count()); - - MinidumpContext* context = exception->GetContext(); - ASSERT_TRUE(context); - - uint64_t instruction_pointer; - ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer)); - - MinidumpMemoryRegion* region = - memory_list->GetMemoryRegionForAddress(instruction_pointer); - ASSERT_TRUE(region); - - const size_t kPrefixSize = 128; // bytes - EXPECT_EQ(kPrefixSize + sizeof(instructions), region->GetSize()); - const uint8_t* bytes = region->GetMemory(); - ASSERT_TRUE(bytes); - - uint8_t prefix_bytes[kPrefixSize]; - memset(prefix_bytes, 0, sizeof(prefix_bytes)); - EXPECT_EQ(0, memcmp(bytes, prefix_bytes, sizeof(prefix_bytes))); - EXPECT_EQ(0, memcmp(bytes + kPrefixSize, - instructions, sizeof(instructions))); - } - - DeleteFileW(minidump_filename_wide.c_str()); -} - -#endif // !ADDRESS_SANITIZER - -} // namespace diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_nesting_test.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_nesting_test.cc deleted file mode 100644 index 3ae1d7cd0..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_nesting_test.cc +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2012, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <windows.h> - -#include <string> - -#include "breakpad_googletest_includes.h" -#include "client/windows/handler/exception_handler.h" -#include "client/windows/unittests/exception_handler_test.h" - -namespace { - -const char kFoo[] = "foo"; -const char kBar[] = "bar"; - -const char kStartOfLine[] = "^"; -const char kEndOfLine[] = "$"; - -const char kFilterReturnsTrue[] = "filter_returns_true"; -const char kFilterReturnsFalse[] = "filter_returns_false"; - -const char kCallbackReturnsTrue[] = "callback_returns_true"; -const char kCallbackReturnsFalse[] = "callback_returns_false"; - -bool DoesPathExist(const wchar_t *path_name) { - DWORD flags = GetFileAttributes(path_name); - if (flags == INVALID_FILE_ATTRIBUTES) { - return false; - } - return true; -} - -// A callback function to run before Breakpad performs any substantial -// processing of an exception. A FilterCallback is called before writing -// a minidump. context is the parameter supplied by the user as -// callback_context when the handler was created. exinfo points to the -// exception record, if any; assertion points to assertion information, -// if any. -// -// If a FilterCallback returns true, Breakpad will continue processing, -// attempting to write a minidump. If a FilterCallback returns false, -// Breakpad will immediately report the exception as unhandled without -// writing a minidump, allowing another handler the opportunity to handle it. -template <bool filter_return_value> -bool CrashHandlerFilter(void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion) { - if (filter_return_value) { - fprintf(stderr, kFilterReturnsTrue); - } else { - fprintf(stderr, kFilterReturnsFalse); - } - fflush(stderr); - - return filter_return_value; -} - -// A callback function to run after the minidump has been written. -// minidump_id is a unique id for the dump, so the minidump -// file is <dump_path>\<minidump_id>.dmp. context is the parameter supplied -// by the user as callback_context when the handler was created. exinfo -// points to the exception record, or NULL if no exception occurred. -// succeeded indicates whether a minidump file was successfully written. -// assertion points to information about an assertion if the handler was -// invoked by an assertion. -// -// If an exception occurred and the callback returns true, Breakpad will treat -// the exception as fully-handled, suppressing any other handlers from being -// notified of the exception. If the callback returns false, Breakpad will -// treat the exception as unhandled, and allow another handler to handle it. -// If there are no other handlers, Breakpad will report the exception to the -// system as unhandled, allowing a debugger or native crash dialog the -// opportunity to handle the exception. Most callback implementations -// should normally return the value of |succeeded|, or when they wish to -// not report an exception of handled, false. Callbacks will rarely want to -// return true directly (unless |succeeded| is true). -// -// For out-of-process dump generation, dump path and minidump ID will always -// be NULL. In case of out-of-process dump generation, the dump path and -// minidump id are controlled by the server process and are not communicated -// back to the crashing process. -template <bool callback_return_value> -bool MinidumpWrittenCallback(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded) { - bool rv = false; - if (callback_return_value && - succeeded && - DoesPathExist(dump_path)) { - rv = true; - fprintf(stderr, kCallbackReturnsTrue); - } else { - fprintf(stderr, kCallbackReturnsFalse); - } - fflush(stderr); - - return rv; -} - - -void DoCrash(const char *message) { - if (message) { - fprintf(stderr, "%s", message); - fflush(stderr); - } - int *i = NULL; - (*i)++; - - ASSERT_TRUE(false); -} - -void InstallExceptionHandlerAndCrash(bool install_filter, - bool filter_return_value, - bool install_callback, - bool callback_return_value) { - wchar_t temp_path[MAX_PATH] = { '\0' }; - GetTempPath(MAX_PATH, temp_path); - - ASSERT_TRUE(DoesPathExist(temp_path)); - google_breakpad::ExceptionHandler exc( - temp_path, - install_filter ? - (filter_return_value ? - &CrashHandlerFilter<true> : - &CrashHandlerFilter<false>) : - NULL, - install_callback ? - (callback_return_value ? - &MinidumpWrittenCallback<true> : - &MinidumpWrittenCallback<false>) : - NULL, - NULL, // callback_context - google_breakpad::ExceptionHandler::HANDLER_EXCEPTION); - - // Disable GTest SEH handler - testing::DisableExceptionHandlerInScope disable_exception_handler; - - DoCrash(NULL); -} - -TEST(AssertDeathSanity, Simple) { - ASSERT_DEATH(DoCrash(NULL), ""); -} - -TEST(AssertDeathSanity, Regex) { - ASSERT_DEATH(DoCrash(kFoo), - std::string(kStartOfLine) + - std::string(kFoo) + - std::string(kEndOfLine)); - - ASSERT_DEATH(DoCrash(kBar), - std::string(kStartOfLine) + - std::string(kBar) + - std::string(kEndOfLine)); -} - -TEST(ExceptionHandlerCallbacks, FilterTrue_No_Callback) { - ASSERT_DEATH( - InstallExceptionHandlerAndCrash(true, // install_filter - true, // filter_return_value - false, // install_callback - false), // callback_return_value - std::string(kStartOfLine) + - std::string(kFilterReturnsTrue) + - std::string(kEndOfLine)); -} - -TEST(ExceptionHandlerCallbacks, FilterTrue_Callback) { - ASSERT_DEATH( - InstallExceptionHandlerAndCrash(true, // install_filter - true, // filter_return_value - true, // install_callback - false), // callback_return_value - std::string(kStartOfLine) + - std::string(kFilterReturnsTrue) + - std::string(kCallbackReturnsFalse) + - std::string(kEndOfLine)); -} - -TEST(ExceptionHandlerCallbacks, FilterFalse_No_Callback) { - ASSERT_DEATH( - InstallExceptionHandlerAndCrash(true, // install_filter - false, // filter_return_value - false, // install_callback - false), // callback_return_value - std::string(kStartOfLine) + - std::string(kFilterReturnsFalse) + - std::string(kEndOfLine)); -} - -// Callback shouldn't be executed when filter returns false -TEST(ExceptionHandlerCallbacks, FilterFalse_Callback) { - ASSERT_DEATH( - InstallExceptionHandlerAndCrash(true, // install_filter - false, // filter_return_value - true, // install_callback - false), // callback_return_value - std::string(kStartOfLine) + - std::string(kFilterReturnsFalse) + - std::string(kEndOfLine)); -} - -TEST(ExceptionHandlerCallbacks, No_Filter_No_Callback) { - ASSERT_DEATH( - InstallExceptionHandlerAndCrash(false, // install_filter - true, // filter_return_value - false, // install_callback - false), // callback_return_value - std::string(kStartOfLine) + - std::string(kEndOfLine)); -} - -TEST(ExceptionHandlerCallbacks, No_Filter_Callback) { - ASSERT_DEATH( - InstallExceptionHandlerAndCrash(false, // install_filter - true, // filter_return_value - true, // install_callback - false), // callback_return_value - std::string(kStartOfLine) + - std::string(kCallbackReturnsFalse) + - std::string(kEndOfLine)); -} - - -TEST(ExceptionHandlerNesting, Skip_From_Inner_Filter) { - wchar_t temp_path[MAX_PATH] = { '\0' }; - GetTempPath(MAX_PATH, temp_path); - - ASSERT_TRUE(DoesPathExist(temp_path)); - google_breakpad::ExceptionHandler exc( - temp_path, - &CrashHandlerFilter<true>, - &MinidumpWrittenCallback<false>, - NULL, // callback_context - google_breakpad::ExceptionHandler::HANDLER_EXCEPTION); - - ASSERT_DEATH( - InstallExceptionHandlerAndCrash(true, // install_filter - false, // filter_return_value - true, // install_callback - true), // callback_return_value - std::string(kStartOfLine) + - std::string(kFilterReturnsFalse) + // inner filter - std::string(kFilterReturnsTrue) + // outer filter - std::string(kCallbackReturnsFalse) + // outer callback - std::string(kEndOfLine)); -} - -TEST(ExceptionHandlerNesting, Skip_From_Inner_Callback) { - wchar_t temp_path[MAX_PATH] = { '\0' }; - GetTempPath(MAX_PATH, temp_path); - - ASSERT_TRUE(DoesPathExist(temp_path)); - google_breakpad::ExceptionHandler exc( - temp_path, - &CrashHandlerFilter<true>, - &MinidumpWrittenCallback<false>, - NULL, // callback_context - google_breakpad::ExceptionHandler::HANDLER_EXCEPTION); - - ASSERT_DEATH( - InstallExceptionHandlerAndCrash(true, // install_filter - true, // filter_return_value - true, // install_callback - false), // callback_return_value - std::string(kStartOfLine) + - std::string(kFilterReturnsTrue) + // inner filter - std::string(kCallbackReturnsFalse) + // inner callback - std::string(kFilterReturnsTrue) + // outer filter - std::string(kCallbackReturnsFalse) + // outer callback - std::string(kEndOfLine)); -} - -TEST(ExceptionHandlerNesting, Handled_By_Inner_Handler) { - wchar_t temp_path[MAX_PATH] = { '\0' }; - GetTempPath(MAX_PATH, temp_path); - - ASSERT_TRUE(DoesPathExist(temp_path)); - google_breakpad::ExceptionHandler exc( - temp_path, - &CrashHandlerFilter<true>, - &MinidumpWrittenCallback<true>, - NULL, // callback_context - google_breakpad::ExceptionHandler::HANDLER_EXCEPTION); - - ASSERT_DEATH( - InstallExceptionHandlerAndCrash(true, // install_filter - true, // filter_return_value - true, // install_callback - true), // callback_return_value - std::string(kStartOfLine) + - std::string(kFilterReturnsTrue) + // inner filter - std::string(kCallbackReturnsTrue) + // inner callback - std::string(kEndOfLine)); -} - -} // namespace diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.cc deleted file mode 100644 index 55275323e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.cc +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2009, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "client/windows/unittests/exception_handler_test.h" - -#include <windows.h> -#include <dbghelp.h> -#include <strsafe.h> -#include <objbase.h> -#include <shellapi.h> - -#include <string> - -#include "breakpad_googletest_includes.h" -#include "client/windows/crash_generation/crash_generation_server.h" -#include "client/windows/handler/exception_handler.h" -#include "client/windows/unittests/dump_analysis.h" // NOLINT -#include "common/windows/string_utils-inl.h" -#include "google_breakpad/processor/minidump.h" - -namespace testing { - -DisableExceptionHandlerInScope::DisableExceptionHandlerInScope() { - catch_exceptions_ = GTEST_FLAG(catch_exceptions); - GTEST_FLAG(catch_exceptions) = false; -} - -DisableExceptionHandlerInScope::~DisableExceptionHandlerInScope() { - GTEST_FLAG(catch_exceptions) = catch_exceptions_; -} - -} // namespace testing - -namespace { - -using std::wstring; -using namespace google_breakpad; - -const wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashTest\\TestCaseServer"; -const char kSuccessIndicator[] = "success"; -const char kFailureIndicator[] = "failure"; - -const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>( - MiniDumpWithFullMemory | // Full memory from process. - MiniDumpWithProcessThreadData | // Get PEB and TEB. - MiniDumpWithHandleData); // Get all handle information. - -class ExceptionHandlerTest : public ::testing::Test { - protected: - // Member variable for each test that they can use - // for temporary storage. - TCHAR temp_path_[MAX_PATH]; - - // Actually constructs a temp path name. - virtual void SetUp(); - - // Deletes temporary files. - virtual void TearDown(); - - void DoCrashInvalidParameter(); - void DoCrashPureVirtualCall(); - - // Utility function to test for a path's existence. - static BOOL DoesPathExist(const TCHAR *path_name); - - // Client callback. - static void ClientDumpCallback( - void *dump_context, - const google_breakpad::ClientInfo *client_info, - const std::wstring *dump_path); - - static bool DumpCallback(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded); - - static std::wstring dump_file; - static std::wstring full_dump_file; -}; - -std::wstring ExceptionHandlerTest::dump_file; -std::wstring ExceptionHandlerTest::full_dump_file; - -void ExceptionHandlerTest::SetUp() { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - TCHAR temp_path[MAX_PATH] = { '\0' }; - TCHAR test_name_wide[MAX_PATH] = { '\0' }; - // We want the temporary directory to be what the OS returns - // to us, + the test case name. - GetTempPath(MAX_PATH, temp_path); - // THe test case name is exposed to use as a c-style string, - // But we might be working in UNICODE here on Windows. - int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(), - strlen(test_info->name()), - test_name_wide, - MAX_PATH); - if (!dwRet) { - assert(false); - } - StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide); - CreateDirectory(temp_path_, NULL); -} - -void ExceptionHandlerTest::TearDown() { - if (!dump_file.empty()) { - ::DeleteFile(dump_file.c_str()); - dump_file = L""; - } - if (!full_dump_file.empty()) { - ::DeleteFile(full_dump_file.c_str()); - full_dump_file = L""; - } -} - -BOOL ExceptionHandlerTest::DoesPathExist(const TCHAR *path_name) { - DWORD flags = GetFileAttributes(path_name); - if (flags == INVALID_FILE_ATTRIBUTES) { - return FALSE; - } - return TRUE; -} - -// static -void ExceptionHandlerTest::ClientDumpCallback( - void *dump_context, - const google_breakpad::ClientInfo *client_info, - const wstring *dump_path) { - dump_file = *dump_path; - // Create the full dump file name from the dump path. - full_dump_file = dump_file.substr(0, dump_file.length() - 4) + L"-full.dmp"; -} - -// static -bool ExceptionHandlerTest::DumpCallback(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded) { - dump_file = dump_path; - dump_file += L"\\"; - dump_file += minidump_id; - dump_file += L".dmp"; - return succeeded; -} - -void ExceptionHandlerTest::DoCrashInvalidParameter() { - google_breakpad::ExceptionHandler *exc = - new google_breakpad::ExceptionHandler( - temp_path_, NULL, NULL, NULL, - google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER, - kFullDumpType, kPipeName, NULL); - - // Disable the message box for assertions - _CrtSetReportMode(_CRT_ASSERT, 0); - - // Although this is executing in the child process of the death test, - // if it's not true we'll still get an error rather than the crash - // being expected. - ASSERT_TRUE(exc->IsOutOfProcess()); - printf(NULL); -} - - -struct PureVirtualCallBase { - PureVirtualCallBase() { - // We have to reinterpret so the linker doesn't get confused because the - // method isn't defined. - reinterpret_cast<PureVirtualCallBase*>(this)->PureFunction(); - } - virtual ~PureVirtualCallBase() {} - virtual void PureFunction() const = 0; -}; -struct PureVirtualCall : public PureVirtualCallBase { - PureVirtualCall() { PureFunction(); } - virtual void PureFunction() const {} -}; - -void ExceptionHandlerTest::DoCrashPureVirtualCall() { - google_breakpad::ExceptionHandler *exc = - new google_breakpad::ExceptionHandler( - temp_path_, NULL, NULL, NULL, - google_breakpad::ExceptionHandler::HANDLER_PURECALL, - kFullDumpType, kPipeName, NULL); - - // Disable the message box for assertions - _CrtSetReportMode(_CRT_ASSERT, 0); - - // Although this is executing in the child process of the death test, - // if it's not true we'll still get an error rather than the crash - // being expected. - ASSERT_TRUE(exc->IsOutOfProcess()); - - // Create a new frame to ensure PureVirtualCall is not optimized to some - // other line in this function. - { - PureVirtualCall instance; - } -} - -// This test validates that the minidump is written correctly. -TEST_F(ExceptionHandlerTest, InvalidParameterMiniDumpTest) { - ASSERT_TRUE(DoesPathExist(temp_path_)); - - // Call with a bad argument - ASSERT_TRUE(DoesPathExist(temp_path_)); - wstring dump_path(temp_path_); - google_breakpad::CrashGenerationServer server( - kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL, - NULL, true, &dump_path); - - ASSERT_TRUE(dump_file.empty() && full_dump_file.empty()); - - // This HAS to be EXPECT_, because when this test case is executed in the - // child process, the server registration will fail due to the named pipe - // being the same. - EXPECT_TRUE(server.Start()); - EXPECT_EXIT(DoCrashInvalidParameter(), ::testing::ExitedWithCode(0), ""); - ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty()); - ASSERT_TRUE(DoesPathExist(dump_file.c_str())); - - // Verify the dump for infos. - DumpAnalysis mini(dump_file); - DumpAnalysis full(full_dump_file); - - // The dump should have all of these streams. - EXPECT_TRUE(mini.HasStream(ThreadListStream)); - EXPECT_TRUE(full.HasStream(ThreadListStream)); - EXPECT_TRUE(mini.HasStream(ModuleListStream)); - EXPECT_TRUE(full.HasStream(ModuleListStream)); - EXPECT_TRUE(mini.HasStream(ExceptionStream)); - EXPECT_TRUE(full.HasStream(ExceptionStream)); - EXPECT_TRUE(mini.HasStream(SystemInfoStream)); - EXPECT_TRUE(full.HasStream(SystemInfoStream)); - EXPECT_TRUE(mini.HasStream(MiscInfoStream)); - EXPECT_TRUE(full.HasStream(MiscInfoStream)); - EXPECT_TRUE(mini.HasStream(HandleDataStream)); - EXPECT_TRUE(full.HasStream(HandleDataStream)); - - // We expect PEB and TEBs in this dump. - EXPECT_TRUE(mini.HasTebs() || full.HasTebs()); - EXPECT_TRUE(mini.HasPeb() || full.HasPeb()); - - // Minidump should have a memory listing, but no 64-bit memory. - EXPECT_TRUE(mini.HasStream(MemoryListStream)); - EXPECT_FALSE(mini.HasStream(Memory64ListStream)); - - EXPECT_FALSE(full.HasStream(MemoryListStream)); - EXPECT_TRUE(full.HasStream(Memory64ListStream)); - - // This is the only place we don't use OR because we want both not - // to have the streams. - EXPECT_FALSE(mini.HasStream(ThreadExListStream)); - EXPECT_FALSE(full.HasStream(ThreadExListStream)); - EXPECT_FALSE(mini.HasStream(CommentStreamA)); - EXPECT_FALSE(full.HasStream(CommentStreamA)); - EXPECT_FALSE(mini.HasStream(CommentStreamW)); - EXPECT_FALSE(full.HasStream(CommentStreamW)); - EXPECT_FALSE(mini.HasStream(FunctionTableStream)); - EXPECT_FALSE(full.HasStream(FunctionTableStream)); - EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); - EXPECT_FALSE(full.HasStream(MemoryInfoListStream)); - EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); - EXPECT_FALSE(full.HasStream(ThreadInfoListStream)); - EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); - EXPECT_FALSE(full.HasStream(HandleOperationListStream)); - EXPECT_FALSE(mini.HasStream(TokenStream)); - EXPECT_FALSE(full.HasStream(TokenStream)); -} - - -// This test validates that the minidump is written correctly. -TEST_F(ExceptionHandlerTest, PureVirtualCallMiniDumpTest) { - ASSERT_TRUE(DoesPathExist(temp_path_)); - - // Call with a bad argument - ASSERT_TRUE(DoesPathExist(temp_path_)); - wstring dump_path(temp_path_); - google_breakpad::CrashGenerationServer server( - kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL, - NULL, true, &dump_path); - - ASSERT_TRUE(dump_file.empty() && full_dump_file.empty()); - - // This HAS to be EXPECT_, because when this test case is executed in the - // child process, the server registration will fail due to the named pipe - // being the same. - EXPECT_TRUE(server.Start()); - EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), ""); - ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty()); - ASSERT_TRUE(DoesPathExist(dump_file.c_str())); - - // Verify the dump for infos. - DumpAnalysis mini(dump_file); - DumpAnalysis full(full_dump_file); - - // The dump should have all of these streams. - EXPECT_TRUE(mini.HasStream(ThreadListStream)); - EXPECT_TRUE(full.HasStream(ThreadListStream)); - EXPECT_TRUE(mini.HasStream(ModuleListStream)); - EXPECT_TRUE(full.HasStream(ModuleListStream)); - EXPECT_TRUE(mini.HasStream(ExceptionStream)); - EXPECT_TRUE(full.HasStream(ExceptionStream)); - EXPECT_TRUE(mini.HasStream(SystemInfoStream)); - EXPECT_TRUE(full.HasStream(SystemInfoStream)); - EXPECT_TRUE(mini.HasStream(MiscInfoStream)); - EXPECT_TRUE(full.HasStream(MiscInfoStream)); - EXPECT_TRUE(mini.HasStream(HandleDataStream)); - EXPECT_TRUE(full.HasStream(HandleDataStream)); - - // We expect PEB and TEBs in this dump. - EXPECT_TRUE(mini.HasTebs() || full.HasTebs()); - EXPECT_TRUE(mini.HasPeb() || full.HasPeb()); - - // Minidump should have a memory listing, but no 64-bit memory. - EXPECT_TRUE(mini.HasStream(MemoryListStream)); - EXPECT_FALSE(mini.HasStream(Memory64ListStream)); - - EXPECT_FALSE(full.HasStream(MemoryListStream)); - EXPECT_TRUE(full.HasStream(Memory64ListStream)); - - // This is the only place we don't use OR because we want both not - // to have the streams. - EXPECT_FALSE(mini.HasStream(ThreadExListStream)); - EXPECT_FALSE(full.HasStream(ThreadExListStream)); - EXPECT_FALSE(mini.HasStream(CommentStreamA)); - EXPECT_FALSE(full.HasStream(CommentStreamA)); - EXPECT_FALSE(mini.HasStream(CommentStreamW)); - EXPECT_FALSE(full.HasStream(CommentStreamW)); - EXPECT_FALSE(mini.HasStream(FunctionTableStream)); - EXPECT_FALSE(full.HasStream(FunctionTableStream)); - EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); - EXPECT_FALSE(full.HasStream(MemoryInfoListStream)); - EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); - EXPECT_FALSE(full.HasStream(ThreadInfoListStream)); - EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); - EXPECT_FALSE(full.HasStream(HandleOperationListStream)); - EXPECT_FALSE(mini.HasStream(TokenStream)); - EXPECT_FALSE(full.HasStream(TokenStream)); -} - -// Test that writing a minidump produces a valid minidump containing -// some expected structures. -TEST_F(ExceptionHandlerTest, WriteMinidumpTest) { - ExceptionHandler handler(temp_path_, - NULL, - DumpCallback, - NULL, - ExceptionHandler::HANDLER_ALL); - - // Disable GTest SEH handler - testing::DisableExceptionHandlerInScope disable_exception_handler; - - ASSERT_TRUE(handler.WriteMinidump()); - ASSERT_FALSE(dump_file.empty()); - - string minidump_filename; - ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file, - &minidump_filename)); - - // Read the minidump and verify some info. - Minidump minidump(minidump_filename); - ASSERT_TRUE(minidump.Read()); - // TODO(ted): more comprehensive tests... -} - -// Test that an additional memory region can be included in the minidump. -TEST_F(ExceptionHandlerTest, AdditionalMemory) { - SYSTEM_INFO si; - GetSystemInfo(&si); - const uint32_t kMemorySize = si.dwPageSize; - - // Get some heap memory. - uint8_t* memory = new uint8_t[kMemorySize]; - const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory); - ASSERT_TRUE(memory); - - // Stick some data into the memory so the contents can be verified. - for (uint32_t i = 0; i < kMemorySize; ++i) { - memory[i] = i % 255; - } - - ExceptionHandler handler(temp_path_, - NULL, - DumpCallback, - NULL, - ExceptionHandler::HANDLER_ALL); - - // Disable GTest SEH handler - testing::DisableExceptionHandlerInScope disable_exception_handler; - - // Add the memory region to the list of memory to be included. - handler.RegisterAppMemory(memory, kMemorySize); - ASSERT_TRUE(handler.WriteMinidump()); - ASSERT_FALSE(dump_file.empty()); - - string minidump_filename; - ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file, - &minidump_filename)); - - // Read the minidump. Ensure that the memory region is present - Minidump minidump(minidump_filename); - ASSERT_TRUE(minidump.Read()); - - MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList(); - ASSERT_TRUE(dump_memory_list); - const MinidumpMemoryRegion* region = - dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress); - ASSERT_TRUE(region); - - EXPECT_EQ(kMemoryAddress, region->GetBase()); - EXPECT_EQ(kMemorySize, region->GetSize()); - - // Verify memory contents. - EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize)); - - delete[] memory; -} - -// Test that a memory region that was previously registered -// can be unregistered. -TEST_F(ExceptionHandlerTest, AdditionalMemoryRemove) { - SYSTEM_INFO si; - GetSystemInfo(&si); - const uint32_t kMemorySize = si.dwPageSize; - - // Get some heap memory. - uint8_t* memory = new uint8_t[kMemorySize]; - const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory); - ASSERT_TRUE(memory); - - // Stick some data into the memory so the contents can be verified. - for (uint32_t i = 0; i < kMemorySize; ++i) { - memory[i] = i % 255; - } - - ExceptionHandler handler(temp_path_, - NULL, - DumpCallback, - NULL, - ExceptionHandler::HANDLER_ALL); - - // Disable GTest SEH handler - testing::DisableExceptionHandlerInScope disable_exception_handler; - - // Add the memory region to the list of memory to be included. - handler.RegisterAppMemory(memory, kMemorySize); - - // ...and then remove it - handler.UnregisterAppMemory(memory); - - ASSERT_TRUE(handler.WriteMinidump()); - ASSERT_FALSE(dump_file.empty()); - - string minidump_filename; - ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file, - &minidump_filename)); - - // Read the minidump. Ensure that the memory region is not present. - Minidump minidump(minidump_filename); - ASSERT_TRUE(minidump.Read()); - - MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList(); - ASSERT_TRUE(dump_memory_list); - const MinidumpMemoryRegion* region = - dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress); - EXPECT_FALSE(region); - - delete[] memory; -} - -} // namespace diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.h b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.h deleted file mode 100644 index ef973e539..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/exception_handler_test.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2012, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CLIENT_WINDOWS_UNITTESTS_EXCEPTION_HANDLER_TEST_H_ -#define CLIENT_WINDOWS_UNITTESTS_EXCEPTION_HANDLER_TEST_H_ - -namespace testing { - -// By default, GTest (on Windows) installs a SEH filter (and a handler) before -// starting to run all the tests in order to avoid test interruptions is some -// of the tests are crashing. Unfortunately, this functionality prevents the -// execution to reach the UnhandledExceptionFilter installed by Google-Breakpad -// ExceptionHandler so in order to test the Google-Breakpad exception handling -// code the exception handling done by GTest must be disabled. -// Usage: -// -// google_breakpad::ExceptionHandler exc(...); -// -// // Disable GTest SEH handler -// testing::DisableExceptionHandlerInScope disable_exception_handler; -// ... -// ASSERT_DEATH( ... some crash ...); -// -class DisableExceptionHandlerInScope { - public: - DisableExceptionHandlerInScope(); - ~DisableExceptionHandlerInScope(); - - private: - bool catch_exceptions_; -}; - -} // namespace testing - -#endif // CLIENT_WINDOWS_UNITTESTS_EXCEPTION_HANDLER_TEST_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/minidump_test.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/minidump_test.cc deleted file mode 100644 index 8d2d726c4..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/minidump_test.cc +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <windows.h> -#include <objbase.h> -#include <dbghelp.h> - -#include "client/windows/crash_generation/minidump_generator.h" -#include "client/windows/unittests/dump_analysis.h" // NOLINT - -#include "gtest/gtest.h" - -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. - -class MinidumpTest: public testing::Test { - public: - MinidumpTest() { - wchar_t temp_dir_path[ MAX_PATH ] = {0}; - ::GetTempPath(MAX_PATH, temp_dir_path); - dump_path_ = temp_dir_path; - } - - virtual void SetUp() { - // Make sure URLMon isn't loaded into our process. - ASSERT_EQ(NULL, ::GetModuleHandle(L"urlmon.dll")); - - // Then load and unload it to ensure we have something to - // stock the unloaded module list with. - HMODULE urlmon = ::LoadLibrary(L"urlmon.dll"); - ASSERT_TRUE(urlmon != NULL); - ASSERT_TRUE(::FreeLibrary(urlmon)); - } - - virtual void TearDown() { - if (!dump_file_.empty()) { - ::DeleteFile(dump_file_.c_str()); - dump_file_ = L""; - } - if (!full_dump_file_.empty()) { - ::DeleteFile(full_dump_file_.c_str()); - full_dump_file_ = L""; - } - } - - bool WriteDump(ULONG flags) { - using google_breakpad::MinidumpGenerator; - - // Fake exception is access violation on write to this. - EXCEPTION_RECORD ex_record = { - STATUS_ACCESS_VIOLATION, // ExceptionCode - 0, // ExceptionFlags - NULL, // ExceptionRecord; - reinterpret_cast<void*>(0xCAFEBABE), // ExceptionAddress; - 2, // NumberParameters; - { EXCEPTION_WRITE_FAULT, reinterpret_cast<ULONG_PTR>(this) } - }; - CONTEXT ctx_record = {}; - EXCEPTION_POINTERS ex_ptrs = { - &ex_record, - &ctx_record, - }; - - MinidumpGenerator generator(dump_path_, - ::GetCurrentProcess(), - ::GetCurrentProcessId(), - ::GetCurrentThreadId(), - ::GetCurrentThreadId(), - &ex_ptrs, - NULL, - static_cast<MINIDUMP_TYPE>(flags), - TRUE); - generator.GenerateDumpFile(&dump_file_); - generator.GenerateFullDumpFile(&full_dump_file_); - // And write a dump - bool result = generator.WriteMinidump(); - return result == TRUE; - } - - protected: - std::wstring dump_file_; - std::wstring full_dump_file_; - - std::wstring dump_path_; -}; - -// We need to be able to get file information from Windows -bool HasFileInfo(const std::wstring& file_path) { - DWORD dummy; - const wchar_t* path = file_path.c_str(); - DWORD length = ::GetFileVersionInfoSize(path, &dummy); - if (length == 0) - return NULL; - - void* data = calloc(length, 1); - if (!data) - return false; - - if (!::GetFileVersionInfo(path, dummy, length, data)) { - free(data); - return false; - } - - void* translate = NULL; - UINT page_count; - BOOL query_result = VerQueryValue( - data, - L"\\VarFileInfo\\Translation", - static_cast<void**>(&translate), - &page_count); - - free(data); - if (query_result && translate) { - return true; - } else { - return false; - } -} - -TEST_F(MinidumpTest, Version) { - // Loads DbgHelp.dll in process - ImagehlpApiVersion(); - - HMODULE dbg_help = ::GetModuleHandle(L"dbghelp.dll"); - ASSERT_TRUE(dbg_help != NULL); - - wchar_t dbg_help_file[1024] = {}; - ASSERT_TRUE(::GetModuleFileName(dbg_help, - dbg_help_file, - sizeof(dbg_help_file) / - sizeof(*dbg_help_file))); - ASSERT_TRUE(HasFileInfo(std::wstring(dbg_help_file)) != NULL); - -// LOG(INFO) << "DbgHelp.dll version: " << file_info->file_version(); -} - -TEST_F(MinidumpTest, Normal) { - EXPECT_TRUE(WriteDump(MiniDumpNormal)); - DumpAnalysis mini(dump_file_); - - // We expect threads, modules and some memory. - EXPECT_TRUE(mini.HasStream(ThreadListStream)); - EXPECT_TRUE(mini.HasStream(ModuleListStream)); - EXPECT_TRUE(mini.HasStream(MemoryListStream)); - EXPECT_TRUE(mini.HasStream(ExceptionStream)); - EXPECT_TRUE(mini.HasStream(SystemInfoStream)); - EXPECT_TRUE(mini.HasStream(MiscInfoStream)); - - EXPECT_FALSE(mini.HasStream(ThreadExListStream)); - EXPECT_FALSE(mini.HasStream(Memory64ListStream)); - EXPECT_FALSE(mini.HasStream(CommentStreamA)); - EXPECT_FALSE(mini.HasStream(CommentStreamW)); - EXPECT_FALSE(mini.HasStream(HandleDataStream)); - EXPECT_FALSE(mini.HasStream(FunctionTableStream)); - EXPECT_FALSE(mini.HasStream(UnloadedModuleListStream)); - EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); - EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); - EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); - EXPECT_FALSE(mini.HasStream(TokenStream)); - - // We expect no PEB nor TEBs in this dump. - EXPECT_FALSE(mini.HasTebs()); - EXPECT_FALSE(mini.HasPeb()); - - // We expect no off-stack memory in this dump. - EXPECT_FALSE(mini.HasMemory(this)); -} - -TEST_F(MinidumpTest, SmallDump) { - ASSERT_TRUE(WriteDump(kSmallDumpType)); - DumpAnalysis mini(dump_file_); - - EXPECT_TRUE(mini.HasStream(ThreadListStream)); - EXPECT_TRUE(mini.HasStream(ModuleListStream)); - EXPECT_TRUE(mini.HasStream(MemoryListStream)); - EXPECT_TRUE(mini.HasStream(ExceptionStream)); - EXPECT_TRUE(mini.HasStream(SystemInfoStream)); - EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream)); - EXPECT_TRUE(mini.HasStream(MiscInfoStream)); - - // We expect PEB and TEBs in this dump. - EXPECT_TRUE(mini.HasTebs()); - EXPECT_TRUE(mini.HasPeb()); - - EXPECT_FALSE(mini.HasStream(ThreadExListStream)); - EXPECT_FALSE(mini.HasStream(Memory64ListStream)); - EXPECT_FALSE(mini.HasStream(CommentStreamA)); - EXPECT_FALSE(mini.HasStream(CommentStreamW)); - EXPECT_FALSE(mini.HasStream(HandleDataStream)); - EXPECT_FALSE(mini.HasStream(FunctionTableStream)); - EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); - EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); - EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); - EXPECT_FALSE(mini.HasStream(TokenStream)); - - // We expect no off-stack memory in this dump. - EXPECT_FALSE(mini.HasMemory(this)); -} - -TEST_F(MinidumpTest, LargerDump) { - ASSERT_TRUE(WriteDump(kLargerDumpType)); - DumpAnalysis mini(dump_file_); - - // The dump should have all of these streams. - EXPECT_TRUE(mini.HasStream(ThreadListStream)); - EXPECT_TRUE(mini.HasStream(ModuleListStream)); - EXPECT_TRUE(mini.HasStream(MemoryListStream)); - EXPECT_TRUE(mini.HasStream(ExceptionStream)); - EXPECT_TRUE(mini.HasStream(SystemInfoStream)); - EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream)); - EXPECT_TRUE(mini.HasStream(MiscInfoStream)); - - // We expect memory referenced by stack in this dump. - EXPECT_TRUE(mini.HasMemory(this)); - - // We expect PEB and TEBs in this dump. - EXPECT_TRUE(mini.HasTebs()); - EXPECT_TRUE(mini.HasPeb()); - - EXPECT_FALSE(mini.HasStream(ThreadExListStream)); - EXPECT_FALSE(mini.HasStream(Memory64ListStream)); - EXPECT_FALSE(mini.HasStream(CommentStreamA)); - EXPECT_FALSE(mini.HasStream(CommentStreamW)); - EXPECT_FALSE(mini.HasStream(HandleDataStream)); - EXPECT_FALSE(mini.HasStream(FunctionTableStream)); - EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); - EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); - EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); - EXPECT_FALSE(mini.HasStream(TokenStream)); -} - -TEST_F(MinidumpTest, FullDump) { - ASSERT_TRUE(WriteDump(kFullDumpType)); - ASSERT_TRUE(dump_file_ != L""); - ASSERT_TRUE(full_dump_file_ != L""); - DumpAnalysis mini(dump_file_); - DumpAnalysis full(full_dump_file_); - - // Either dumps can contain part of the information. - - // The dump should have all of these streams. - EXPECT_TRUE(mini.HasStream(ThreadListStream)); - EXPECT_TRUE(full.HasStream(ThreadListStream)); - EXPECT_TRUE(mini.HasStream(ModuleListStream)); - EXPECT_TRUE(full.HasStream(ModuleListStream)); - EXPECT_TRUE(mini.HasStream(ExceptionStream)); - EXPECT_TRUE(full.HasStream(ExceptionStream)); - EXPECT_TRUE(mini.HasStream(SystemInfoStream)); - EXPECT_TRUE(full.HasStream(SystemInfoStream)); - EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream)); - EXPECT_TRUE(full.HasStream(UnloadedModuleListStream)); - EXPECT_TRUE(mini.HasStream(MiscInfoStream)); - EXPECT_TRUE(full.HasStream(MiscInfoStream)); - EXPECT_TRUE(mini.HasStream(HandleDataStream)); - EXPECT_TRUE(full.HasStream(HandleDataStream)); - - // We expect memory referenced by stack in this dump. - EXPECT_FALSE(mini.HasMemory(this)); - EXPECT_TRUE(full.HasMemory(this)); - - // We expect PEB and TEBs in this dump. - EXPECT_TRUE(mini.HasTebs() || full.HasTebs()); - EXPECT_TRUE(mini.HasPeb() || full.HasPeb()); - - EXPECT_TRUE(mini.HasStream(MemoryListStream)); - EXPECT_TRUE(full.HasStream(Memory64ListStream)); - EXPECT_FALSE(mini.HasStream(Memory64ListStream)); - EXPECT_FALSE(full.HasStream(MemoryListStream)); - - // This is the only place we don't use OR because we want both not - // to have the streams. - EXPECT_FALSE(mini.HasStream(ThreadExListStream)); - EXPECT_FALSE(full.HasStream(ThreadExListStream)); - EXPECT_FALSE(mini.HasStream(CommentStreamA)); - EXPECT_FALSE(full.HasStream(CommentStreamA)); - EXPECT_FALSE(mini.HasStream(CommentStreamW)); - EXPECT_FALSE(full.HasStream(CommentStreamW)); - EXPECT_FALSE(mini.HasStream(FunctionTableStream)); - EXPECT_FALSE(full.HasStream(FunctionTableStream)); - EXPECT_FALSE(mini.HasStream(MemoryInfoListStream)); - EXPECT_FALSE(full.HasStream(MemoryInfoListStream)); - EXPECT_FALSE(mini.HasStream(ThreadInfoListStream)); - EXPECT_FALSE(full.HasStream(ThreadInfoListStream)); - EXPECT_FALSE(mini.HasStream(HandleOperationListStream)); - EXPECT_FALSE(full.HasStream(HandleOperationListStream)); - EXPECT_FALSE(mini.HasStream(TokenStream)); - EXPECT_FALSE(full.HasStream(TokenStream)); -} - -} // namespace diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/testing.gyp b/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/testing.gyp deleted file mode 100644 index 141d0ed0c..000000000 --- a/toolkit/crashreporter/google-breakpad/src/client/windows/unittests/testing.gyp +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -{ - 'includes': [ - '../../../build/common.gypi', - ], - 'target_defaults': { - }, - 'targets': [ - { - 'target_name': 'gtest', - 'type': 'static_library', - 'include_dirs': [ - '<(DEPTH)/testing/include', - '<(DEPTH)/testing/gtest', - '<(DEPTH)/testing/gtest/include', - ], - 'sources': [ - '<(DEPTH)/testing/gtest/src/gtest-all.cc', - ], - 'direct_dependent_settings': { - 'include_dirs': [ - '<(DEPTH)/testing/include', - '<(DEPTH)/testing/gtest/include', - ], - # Visual C++ implements variadic templates strangely, and - # VC++2012 broke Google Test by lowering this value. See - # http://stackoverflow.com/questions/12558327/google-test-in-visual-studio-2012 - 'defines': ['_VARIADIC_MAX=10'], - }, - 'defines': ['_VARIADIC_MAX=10'], - }, - { - 'target_name': 'gmock', - 'type': 'static_library', - 'include_dirs': [ - '<(DEPTH)/testing/include', - '<(DEPTH)/testing/', - '<(DEPTH)/testing/gtest', - '<(DEPTH)/testing/gtest/include', - ], - 'sources': [ - '<(DEPTH)/testing/src/gmock-all.cc', - '<(DEPTH)/testing/src/gmock_main.cc', - ], - 'direct_dependent_settings': { - 'include_dirs': [ - '<(DEPTH)/testing/include', - '<(DEPTH)/testing/gtest/include', - ], - 'defines': ['_VARIADIC_MAX=10'], - }, - 'defines': ['_VARIADIC_MAX=10'], - }, - - ], -} |