1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // crash_report.cc : Implementation crash reporting.
6 #include "chrome_frame/crash_reporting/crash_report.h"
8 #include "base/basictypes.h"
9 #include "base/synchronization/lock.h"
10 #include "breakpad/src/client/windows/handler/exception_handler.h"
11 #include "chrome_frame/crash_reporting/crash_metrics.h"
13 // TODO(joshia): factor out common code with chrome used for crash reporting
14 const wchar_t kGoogleUpdatePipeName
[] = L
"\\\\.\\pipe\\GoogleCrashServices\\";
16 // This lock protects against concurrent access to g_breakpad.
17 static base::Lock g_breakpad_lock
;
18 static google_breakpad::ExceptionHandler
* g_breakpad
= NULL
;
20 // These minidump flag combinations have been tested safe against the
21 // DbgHelp.dll version that ships with Windows XP SP2.
22 const MINIDUMP_TYPE kSmallDumpType
= static_cast<MINIDUMP_TYPE
>(
23 MiniDumpWithProcessThreadData
| // Get PEB and TEB.
24 MiniDumpWithUnloadedModules
); // Get unloaded modules when available.
26 const MINIDUMP_TYPE kLargerDumpType
= static_cast<MINIDUMP_TYPE
>(
27 MiniDumpWithProcessThreadData
| // Get PEB and TEB.
28 MiniDumpWithUnloadedModules
| // Get unloaded modules when available.
29 MiniDumpWithIndirectlyReferencedMemory
); // Get memory referenced by stack.
31 // Large dump with all process memory.
32 const MINIDUMP_TYPE kFullDumpType
= static_cast<MINIDUMP_TYPE
>(
33 MiniDumpWithFullMemory
| // Full memory from process.
34 MiniDumpWithProcessThreadData
| // Get PEB and TEB.
35 MiniDumpWithHandleData
| // Get all handle information.
36 MiniDumpWithUnloadedModules
); // Get unloaded modules when available.
38 #pragma code_seg(push, ".text$va")
39 static void veh_segment_start() {}
42 #pragma code_seg(push, ".text$vz")
43 static void veh_segment_end() {}
46 // Place code in .text$veh_m.
47 #pragma code_seg(push, ".text$vm")
48 #include "chrome_frame/crash_reporting/vectored_handler-impl.h"
52 CrashHandler() : veh_id_(NULL
), handler_(&crash_api_
) {}
54 // Note that breakpad_lock is used to protect accesses to breakpad and must
55 // be held when Init() is called.
56 bool Init(google_breakpad::ExceptionHandler
* breakpad
,
57 base::Lock
* breakpad_lock
);
61 VectoredHandlerT
<CrashHandlerTraits
> handler_
;
62 CrashHandlerTraits crash_api_
;
65 static LONG WINAPI
VectoredHandlerEntryPoint(EXCEPTION_POINTERS
* exptrs
);
68 static CrashHandler g_crash_handler
;
70 // Turn off FPO optimization, so ::RtlCaptureStackBackTrace returns sane result.
71 #pragma optimize("y", off)
72 LONG WINAPI
CrashHandler::VectoredHandlerEntryPoint(
73 EXCEPTION_POINTERS
* exptrs
) {
74 return g_crash_handler
.handler_
.Handler(exptrs
);
76 #pragma optimize("y", on)
80 bool CrashHandler::Init(google_breakpad::ExceptionHandler
* breakpad
,
81 base::Lock
* breakpad_lock
) {
83 DCHECK(breakpad_lock
);
84 breakpad_lock
->AssertAcquired();
89 crash_api_
.Init(&veh_segment_start
, &veh_segment_end
,
90 &WriteMinidumpForException
);
92 void* id
= ::AddVectoredExceptionHandler(FALSE
, &VectoredHandlerEntryPoint
);
97 crash_api_
.Shutdown();
102 void CrashHandler::Shutdown() {
104 ::RemoveVectoredExceptionHandler(veh_id_
);
108 crash_api_
.Shutdown();
111 std::wstring
GetCrashServerPipeName(const std::wstring
& user_sid
) {
112 std::wstring pipe_name
= kGoogleUpdatePipeName
;
113 pipe_name
+= user_sid
;
117 bool InitializeVectoredCrashReportingWithPipeName(
119 const wchar_t* pipe_name
,
120 const std::wstring
& dump_path
,
121 google_breakpad::CustomClientInfo
* client_info
) {
122 base::AutoLock
lock(g_breakpad_lock
);
126 if (dump_path
.empty()) {
130 // TODO(siggi): Consider switching to kSmallerDumpType post-beta.
131 MINIDUMP_TYPE dump_type
= full_dump
? kFullDumpType
: kLargerDumpType
;
132 g_breakpad
= new google_breakpad::ExceptionHandler(
133 dump_path
, NULL
, NULL
, NULL
,
134 google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER
|
135 google_breakpad::ExceptionHandler::HANDLER_PURECALL
, dump_type
,
136 pipe_name
, client_info
);
141 if (!g_crash_handler
.Init(g_breakpad
, &g_breakpad_lock
)) {
150 bool InitializeVectoredCrashReporting(
152 const wchar_t* user_sid
,
153 const std::wstring
& dump_path
,
154 google_breakpad::CustomClientInfo
* client_info
) {
158 std::wstring pipe_name
= GetCrashServerPipeName(user_sid
);
160 return InitializeVectoredCrashReportingWithPipeName(full_dump
,
166 bool ShutdownVectoredCrashReporting() {
167 g_crash_handler
.Shutdown();
168 base::AutoLock
lock(g_breakpad_lock
);
174 bool WriteMinidumpForException(EXCEPTION_POINTERS
* p
) {
175 base::AutoLock
lock(g_breakpad_lock
);
176 CrashMetricsReporter::GetInstance()->IncrementMetric(
177 CrashMetricsReporter::CRASH_COUNT
);
178 bool success
= false;
180 success
= g_breakpad
->WriteMinidumpForException(p
);