Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Side by Side Diff: chrome_elf/breakpad.cc

Issue 154653002: Breakpad coverage for chrome_elf start up (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This module contains the necessary code to register the Breakpad exception 5 // This module contains the necessary code to register the Breakpad exception
6 // handler. This implementation is based on Chrome crash reporting code. See: 6 // handler. This implementation is based on Chrome crash reporting code.
7 // - src/components/breakpad/app/breakpad_win.cc
8 // - src/chrome/installer/setup/setup_main.cc
9 7
10 #include "remoting/base/breakpad.h" 8 #include "chrome_elf/breakpad.h"
11 9
12 #include <windows.h>
13 #include <string> 10 #include <string>
14 11
15 #include "base/atomicops.h" 12 #include "base/atomicops.h"
16 #include "base/file_version_info.h"
17 #include "base/lazy_instance.h" 13 #include "base/lazy_instance.h"
18 #include "base/logging.h"
19 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
20 #include "base/process/memory.h"
21 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
22 #include "base/win/wrapped_window_proc.h" 16 #include "breakpad/src/client/windows/crash_generation/crash_generation_client.h "
23 #include "breakpad/src/client/windows/handler/exception_handler.h" 17 #include "breakpad/src/client/windows/handler/exception_handler.h"
24 18 #include "version.h" // NOLINT
25 namespace remoting {
26 void InitializeCrashReportingForTest(const wchar_t* pipe_name);
27 } // namespace remoting
28 19
29 namespace { 20 namespace {
30 21
31 const wchar_t kBreakpadProductName[] = L"Chromoting"; 22 const wchar_t kBreakpadProductName[] = L"ChromeElf";
32 const wchar_t kBreakpadVersionEntry[] = L"ver"; 23 const wchar_t kBreakpadVersionEntry[] = L"ver";
33 const wchar_t kBreakpadVersionDefault[] = L"0.1.0.0"; 24 const wchar_t kBreakpadVersionDefault[] = L"0.1.0.0";
34 const wchar_t kBreakpadProdEntry[] = L"prod"; 25 const wchar_t kBreakpadProdEntry[] = L"prod";
35 const wchar_t kBreakpadPlatformEntry[] = L"plat"; 26 const wchar_t kBreakpadPlatformEntry[] = L"plat";
36 const wchar_t kBreakpadPlatformWin32[] = L"Win32"; 27 const wchar_t kBreakpadPlatformWin32[] = L"Win32";
37 28
29 // TODO(caitkp): figure out what these should be. Current pipe works with local
30 // instance of crash_service.exe.
38 // The protocol for connecting to the out-of-process Breakpad crash 31 // The protocol for connecting to the out-of-process Breakpad crash
39 // reporter is different for x86-32 and x86-64: the message sizes 32 // reporter is different for x86-32 and x86-64: the message sizes
40 // are different because the message struct contains a pointer. As 33 // are different because the message struct contains a pointer. As
41 // a result, there are two different named pipes to connect to. The 34 // a result, there are two different named pipes to connect to. The
42 // 64-bit one is distinguished with an "-x64" suffix. 35 // 64-bit one is distinguished with an "-x64" suffix.
43 #if defined(_WIN64) 36 #if defined(_WIN64)
44 const wchar_t kGoogleUpdatePipeName[] = 37 const wchar_t kGoogleUpdatePipeName[] =
45 L"\\\\.\\pipe\\GoogleCrashServices\\S-1-5-18-x64"; 38 L"\\\\.\\pipe\\ChromeCrashServices";
39 //L"\\\\.\\pipe\\GoogleCrashServices\\S-1-5-18-x64";
46 #else 40 #else
47 const wchar_t kGoogleUpdatePipeName[] = 41 const wchar_t kGoogleUpdatePipeName[] =
48 L"\\\\.\\pipe\\GoogleCrashServices\\S-1-5-18"; 42 L"\\\\.\\pipe\\ChromeCrashServices";
43 //L"\\\\.\\pipe\\GoogleCrashServices\\S-1-5-18";
49 #endif 44 #endif
50 45
51 using base::subtle::AtomicWord; 46 using base::subtle::AtomicWord;
52 using base::subtle::NoBarrier_CompareAndSwap; 47 using base::subtle::NoBarrier_CompareAndSwap;
53 48
54 class BreakpadWin { 49 class BreakpadWin {
55 public: 50 public:
56 BreakpadWin(); 51 BreakpadWin();
57 ~BreakpadWin(); 52 ~BreakpadWin();
58 53
59 static BreakpadWin* GetInstance(); 54 static BreakpadWin* GetInstance();
60 55
56 // Generates dump on request for given |exinfo|.
57 static int OnDumpRequested(EXCEPTION_POINTERS* exinfo);
58
61 private: 59 private:
62 // Returns the Custom information to be used for crash reporting. 60 // Returns the Custom information to be used for crash reporting.
63 google_breakpad::CustomClientInfo* GetCustomInfo(); 61 google_breakpad::CustomClientInfo* GetCustomInfo();
64 62
65 // This callback is executed when the process has crashed and *before* 63 // This callback is executed when the process has crashed and *before*
66 // the crash dump is created. To prevent duplicate crash reports we 64 // the crash dump is created. To prevent duplicate crash reports we
67 // make every thread calling this method, except the very first one, 65 // make every thread calling this method, except the very first one,
68 // go to sleep. 66 // go to sleep.
69 static bool OnExceptionCallback(void* context, 67 static bool OnExceptionCallback(void* context,
70 EXCEPTION_POINTERS* exinfo, 68 EXCEPTION_POINTERS* exinfo,
71 MDRawAssertionInfo* assertion); 69 MDRawAssertionInfo* assertion);
72 70
73 // Crashes the process after generating a dump for the provided exception.
74 // Note that the crash reporter should be initialized before calling this
75 // function for it to do anything.
76 static int OnWindowProcedureException(EXCEPTION_POINTERS* exinfo);
77
78 // Breakpad's exception handler. 71 // Breakpad's exception handler.
79 scoped_ptr<google_breakpad::ExceptionHandler> breakpad_; 72 scoped_ptr<google_breakpad::ExceptionHandler> breakpad_;
80 73
81 // This flag is used to indicate that an exception is already being handled. 74 // This flag is used to indicate that an exception is already being handled.
82 volatile AtomicWord handling_exception_; 75 volatile AtomicWord handling_exception_;
83 76
84 // The testing hook below allows overriding the crash server pipe name. 77 // The testing hook below allows overriding the crash server pipe name.
85 static const wchar_t* pipe_name_; 78 static const wchar_t* pipe_name_;
86 79
87 friend void ::remoting::InitializeCrashReportingForTest(const wchar_t*);
88
89 DISALLOW_COPY_AND_ASSIGN(BreakpadWin); 80 DISALLOW_COPY_AND_ASSIGN(BreakpadWin);
90 }; 81 };
91 82
92 // |LazyInstance| is used to guarantee that the exception handler will be 83 // |LazyInstance| is used to guarantee that the exception handler will be
93 // initialized exactly once. 84 // initialized exactly once.
94 // N.B. LazyInstance does not allow this to be a static member of the class. 85 // N.B. LazyInstance does not allow this to be a static member of the class.
95 static base::LazyInstance<BreakpadWin>::Leaky g_instance = 86 static base::LazyInstance<BreakpadWin>::Leaky g_instance =
96 LAZY_INSTANCE_INITIALIZER; 87 LAZY_INSTANCE_INITIALIZER;
97 88
98 const wchar_t* BreakpadWin::pipe_name_ = kGoogleUpdatePipeName; 89 const wchar_t* BreakpadWin::pipe_name_ = kGoogleUpdatePipeName;
99 90
100 BreakpadWin::BreakpadWin() : handling_exception_(0) { 91 BreakpadWin::BreakpadWin() : handling_exception_(0) {
101 // Disable the message box for assertions. 92 // Disable the message box for assertions.
102 _CrtSetReportMode(_CRT_ASSERT, 0); 93 _CrtSetReportMode(_CRT_ASSERT, 0);
103 94
104 // Get the alternate dump directory. We use the temp path. 95 // Get the alternate dump directory. We use the temp path.
105 // N.B. We don't use base::GetTempDir() here to avoid running more code then 96 // N.B. We don't use base::GetTempDir() here to avoid running more code then
106 // necessary before crashes can be properly reported. 97 // necessary before crashes can be properly reported.
107 wchar_t temp_directory[MAX_PATH + 1] = { 0 }; 98 wchar_t temp_directory[MAX_PATH + 1] = { 0 };
108 DWORD length = GetTempPath(MAX_PATH, temp_directory); 99 DWORD length = GetTempPath(MAX_PATH, temp_directory);
109 if (length == 0) 100 if (length == 0)
110 return; 101 return;
111 102
112 // Minidump with stacks, PEB, TEBs and unloaded module list. 103 // Minidump with stacks, PEB, TEBs and unloaded module list.
113 MINIDUMP_TYPE dump_type = static_cast<MINIDUMP_TYPE>( 104 MINIDUMP_TYPE dump_type = static_cast<MINIDUMP_TYPE>(
114 MiniDumpWithProcessThreadData | 105 MiniDumpWithProcessThreadData | // Get PEB and TEB.
115 MiniDumpWithUnloadedModules); 106 MiniDumpWithUnloadedModules | // Get unloaded modules when available.
116 breakpad_.reset( 107 MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack.
117 new google_breakpad::ExceptionHandler( 108
118 temp_directory, &OnExceptionCallback, NULL, NULL, 109 breakpad_.reset(new google_breakpad::ExceptionHandler(
119 google_breakpad::ExceptionHandler::HANDLER_ALL, dump_type, 110 temp_directory,
120 pipe_name_, GetCustomInfo())); 111 &OnExceptionCallback,
112 NULL,
113 NULL,
114 google_breakpad::ExceptionHandler::HANDLER_ALL,
115 dump_type,
116 pipe_name_,
117 GetCustomInfo()));
121 118
122 if (breakpad_->IsOutOfProcess()) { 119 if (breakpad_->IsOutOfProcess()) {
123 // Tells breakpad to handle breakpoint and single step exceptions. 120 // Tells breakpad to handle breakpoint and single step exceptions.
124 breakpad_->set_handle_debug_exceptions(true); 121 breakpad_->set_handle_debug_exceptions(true);
125 } 122 }
126
127 // Catch exceptions thrown from a window procedure.
128 base::win::WinProcExceptionFilter exception_filter =
129 base::win::SetWinProcExceptionFilter(&OnWindowProcedureException);
130 CHECK(!exception_filter);
131 } 123 }
132 124
133 BreakpadWin::~BreakpadWin() { 125 BreakpadWin::~BreakpadWin() {
134 // This object should be leaked so that crashes occurred during the process 126 // This object should be leaked so that crashes occurred during the process
135 // shutdown will be caught. 127 // shutdown will be caught.
136 NOTREACHED(); 128 NOTREACHED();
137 } 129 }
138 130
139 // static 131 // static
140 BreakpadWin* BreakpadWin::GetInstance() { 132 BreakpadWin* BreakpadWin::GetInstance() {
141 return &g_instance.Get(); 133 return &g_instance.Get();
142 } 134 }
143 135
136 // static
137 int BreakpadWin::OnDumpRequested(EXCEPTION_POINTERS* exinfo) {
138 BreakpadWin* self = BreakpadWin::GetInstance();
139 if (self->breakpad_.get() != NULL) {
140 self->breakpad_->WriteMinidumpForException(exinfo);
141 // TODO(caitkp): Is terminating the right thing to do here?
Sigurður Ásgeirsson 2014/02/05 13:58:33 It's six of on, half a dozen of the other. If you
Cait (Slow) 2014/02/07 15:32:02 Done -- I'll grab the dump and let the loader take
142 TerminateProcess(GetCurrentProcess(),
143 exinfo->ExceptionRecord->ExceptionCode);
144 }
145 return EXCEPTION_CONTINUE_SEARCH;
146 }
147
144 // Returns the Custom information to be used for crash reporting. 148 // Returns the Custom information to be used for crash reporting.
145 google_breakpad::CustomClientInfo* BreakpadWin::GetCustomInfo() { 149 google_breakpad::CustomClientInfo* BreakpadWin::GetCustomInfo() {
146 HMODULE binary = base::GetModuleFromAddress(
147 reinterpret_cast<void*>(&remoting::InitializeCrashReporting));
148 scoped_ptr<FileVersionInfo> version_info(
149 FileVersionInfo::CreateFileVersionInfoForModule(binary));
150
151 static wchar_t version[64];
152 if (version_info.get()) {
153 wcscpy_s(version,
154 base::UTF16ToWide(version_info->product_version()).c_str());
155 } else {
156 wcscpy_s(version, kBreakpadVersionDefault);
157 }
158
159 static google_breakpad::CustomInfoEntry ver_entry( 150 static google_breakpad::CustomInfoEntry ver_entry(
160 kBreakpadVersionEntry, version); 151 kBreakpadVersionEntry, TEXT(CHROME_VERSION_STRING));
161 static google_breakpad::CustomInfoEntry prod_entry( 152 static google_breakpad::CustomInfoEntry prod_entry(
162 kBreakpadProdEntry, kBreakpadProductName); 153 kBreakpadProdEntry, kBreakpadProductName);
163 static google_breakpad::CustomInfoEntry plat_entry( 154 static google_breakpad::CustomInfoEntry plat_entry(
164 kBreakpadPlatformEntry, kBreakpadPlatformWin32); 155 kBreakpadPlatformEntry, kBreakpadPlatformWin32);
165 static google_breakpad::CustomInfoEntry entries[] = { 156 static google_breakpad::CustomInfoEntry entries[] = {
166 ver_entry, prod_entry, plat_entry }; 157 ver_entry, prod_entry, plat_entry };
167 static google_breakpad::CustomClientInfo custom_info = { 158 static google_breakpad::CustomClientInfo custom_info = {
168 entries, arraysize(entries) }; 159 entries, arraysize(entries) };
169 return &custom_info; 160 return &custom_info;
170 } 161 }
171 162
172 // static 163 // static
173 bool BreakpadWin::OnExceptionCallback(void* /* context */, 164 bool BreakpadWin::OnExceptionCallback(void* /* context */,
174 EXCEPTION_POINTERS* /* exinfo */, 165 EXCEPTION_POINTERS* /* exinfo */,
175 MDRawAssertionInfo* /* assertion */) { 166 MDRawAssertionInfo* /* assertion */) {
176 BreakpadWin* self = BreakpadWin::GetInstance(); 167 BreakpadWin* self = BreakpadWin::GetInstance();
177 if (NoBarrier_CompareAndSwap(&self->handling_exception_, 0, 1) != 0) { 168 if (NoBarrier_CompareAndSwap(&self->handling_exception_, 0, 1) != 0) {
178 // Capture every thread except the first one in the sleep. We don't 169 // Capture every thread except the first one in the sleep. We don't
179 // want multiple threads to concurrently report exceptions. 170 // want multiple threads to concurrently report exceptions.
180 ::Sleep(INFINITE); 171 ::Sleep(INFINITE);
181 } 172 }
182 return true; 173 return true;
183 } 174 }
184 175
185 // static
186 int BreakpadWin::OnWindowProcedureException(EXCEPTION_POINTERS* exinfo) {
187 BreakpadWin* self = BreakpadWin::GetInstance();
188 if (self->breakpad_.get() != NULL) {
189 self->breakpad_->WriteMinidumpForException(exinfo);
190 TerminateProcess(GetCurrentProcess(),
191 exinfo->ExceptionRecord->ExceptionCode);
192 }
193 return EXCEPTION_CONTINUE_SEARCH;
194 }
195
196 } // namespace 176 } // namespace
197 177
198 namespace remoting { 178 int GenerateCrashDump(EXCEPTION_POINTERS* exinfo) {
179 return BreakpadWin::OnDumpRequested(exinfo);
Sigurður Ásgeirsson 2014/02/05 13:58:33 As we discussed, you may want to filter out debug
Cait (Slow) 2014/02/07 15:32:02 I tested under windbg and it seemed fine -- no har
180 }
199 181
200 void InitializeCrashReporting() { 182 void InitializeCrashReporting() {
201 // Touch the object to make sure it is initialized. 183 // Touch the object to make sure it is initialized.
202 BreakpadWin::GetInstance(); 184 BreakpadWin::GetInstance();
203 } 185 }
204
205 void InitializeCrashReportingForTest(const wchar_t* pipe_name) {
206 BreakpadWin::pipe_name_ = pipe_name;
207 InitializeCrashReporting();
208 }
209
210 } // namespace remoting
OLDNEW
« no previous file with comments | « chrome_elf/breakpad.h ('k') | chrome_elf/chrome_elf.gyp » ('j') | chrome_elf/chrome_elf_main.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698