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

Side by Side Diff: chrome/app/breakpad_win.cc

Issue 9432033: Add experiments info to crash dumps. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 9 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) 2012 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 #include "chrome/app/breakpad_win.h" 5 #include "chrome/app/breakpad_win.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <shellapi.h> 8 #include <shellapi.h>
9 #include <tchar.h> 9 #include <tchar.h>
10 10
11 #include <algorithm> 11 #include <algorithm>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/base_switches.h" 14 #include "base/base_switches.h"
15 #include "base/command_line.h" 15 #include "base/command_line.h"
16 #include "base/environment.h" 16 #include "base/environment.h"
17 #include "base/file_util.h" 17 #include "base/file_util.h"
18 #include "base/file_version_info.h" 18 #include "base/file_version_info.h"
19 #include "base/memory/scoped_ptr.h" 19 #include "base/memory/scoped_ptr.h"
20 #include "base/string_split.h" 20 #include "base/string_split.h"
21 #include "base/string_util.h" 21 #include "base/string_util.h"
22 #include "base/string16.h"
22 #include "base/stringprintf.h" 23 #include "base/stringprintf.h"
23 #include "base/utf_string_conversions.h" 24 #include "base/utf_string_conversions.h"
24 #include "base/win/registry.h" 25 #include "base/win/registry.h"
25 #include "base/win/win_util.h" 26 #include "base/win/win_util.h"
26 #include "breakpad/src/client/windows/handler/exception_handler.h" 27 #include "breakpad/src/client/windows/handler/exception_handler.h"
28 #include "chrome/app/breakpad_field_trial_win.h"
27 #include "chrome/app/hard_error_handler_win.h" 29 #include "chrome/app/hard_error_handler_win.h"
28 #include "chrome/common/child_process_logging.h" 30 #include "chrome/common/child_process_logging.h"
29 #include "chrome/common/chrome_result_codes.h" 31 #include "chrome/common/chrome_result_codes.h"
30 #include "chrome/common/chrome_switches.h" 32 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/env_vars.h" 33 #include "chrome/common/env_vars.h"
32 #include "chrome/installer/util/google_chrome_sxs_distribution.h" 34 #include "chrome/installer/util/google_chrome_sxs_distribution.h"
33 #include "chrome/installer/util/google_update_settings.h" 35 #include "chrome/installer/util/google_update_settings.h"
34 #include "chrome/installer/util/install_util.h" 36 #include "chrome/installer/util/install_util.h"
35 #include "policy/policy_constants.h" 37 #include "policy/policy_constants.h"
36 38
39 using breakpad_win::g_custom_entries;
40
37 namespace { 41 namespace {
38 42
39 // Minidump with stacks, PEB, TEB, and unloaded module list. 43 // Minidump with stacks, PEB, TEB, and unloaded module list.
40 const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>( 44 const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
41 MiniDumpWithProcessThreadData | // Get PEB and TEB. 45 MiniDumpWithProcessThreadData | // Get PEB and TEB.
42 MiniDumpWithUnloadedModules); // Get unloaded modules when available. 46 MiniDumpWithUnloadedModules); // Get unloaded modules when available.
43 47
44 // Minidump with all of the above, plus memory referenced from stack. 48 // Minidump with all of the above, plus memory referenced from stack.
45 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>( 49 const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
46 MiniDumpWithProcessThreadData | // Get PEB and TEB. 50 MiniDumpWithProcessThreadData | // Get PEB and TEB.
(...skipping 11 matching lines...) Expand all
58 62
59 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; 63 const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\";
60 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices"; 64 const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
61 65
62 // This is the well known SID for the system principal. 66 // This is the well known SID for the system principal.
63 const wchar_t kSystemPrincipalSid[] =L"S-1-5-18"; 67 const wchar_t kSystemPrincipalSid[] =L"S-1-5-18";
64 68
65 google_breakpad::ExceptionHandler* g_breakpad = NULL; 69 google_breakpad::ExceptionHandler* g_breakpad = NULL;
66 google_breakpad::ExceptionHandler* g_dumphandler_no_crash = NULL; 70 google_breakpad::ExceptionHandler* g_dumphandler_no_crash = NULL;
67 71
68 // A pointer to the custom entries that we send in the event of a crash. We need 72 static size_t g_url_chunks_offset = 0;
69 // this pointer, along with the offsets into it below, so that we can keep the 73 static size_t g_num_of_extensions_offset = 0;
70 // data updated as the state of the browser changes. 74 static size_t g_extension_ids_offset = 0;
71 static std::vector<google_breakpad::CustomInfoEntry>* g_custom_entries = NULL; 75 static size_t g_client_id_offset = 0;
72 static size_t g_url_chunks_offset; 76 static size_t g_gpu_info_offset = 0;
73 static size_t g_num_of_extensions_offset; 77 static size_t g_printer_info_offset = 0;
74 static size_t g_extension_ids_offset; 78 static size_t g_num_of_views_offset = 0;
75 static size_t g_client_id_offset; 79 static size_t g_num_switches_offset = 0;
76 static size_t g_gpu_info_offset; 80 static size_t g_switches_offset = 0;
77 static size_t g_printer_info_offset;
78 static size_t g_num_of_views_offset;
79 static size_t g_num_switches_offset;
80 static size_t g_switches_offset;
81 81
82 // Maximum length for plugin path to include in plugin crash reports. 82 // Maximum length for plugin path to include in plugin crash reports.
83 const size_t kMaxPluginPathLength = 256; 83 const size_t kMaxPluginPathLength = 256;
84 84
85 // Dumps the current process memory. 85 // Dumps the current process memory.
86 extern "C" void __declspec(dllexport) __cdecl DumpProcess() { 86 extern "C" void __declspec(dllexport) __cdecl DumpProcess() {
87 if (g_breakpad) 87 if (g_breakpad)
88 g_breakpad->WriteMinidump(); 88 g_breakpad->WriteMinidump();
89 } 89 }
90 90
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 246
247 if (!special_build.empty()) 247 if (!special_build.empty())
248 g_custom_entries->push_back( 248 g_custom_entries->push_back(
249 google_breakpad::CustomInfoEntry(L"special", special_build.c_str())); 249 google_breakpad::CustomInfoEntry(L"special", special_build.c_str()));
250 250
251 g_num_of_extensions_offset = g_custom_entries->size(); 251 g_num_of_extensions_offset = g_custom_entries->size();
252 g_custom_entries->push_back( 252 g_custom_entries->push_back(
253 google_breakpad::CustomInfoEntry(L"num-extensions", L"N/A")); 253 google_breakpad::CustomInfoEntry(L"num-extensions", L"N/A"));
254 254
255 g_extension_ids_offset = g_custom_entries->size(); 255 g_extension_ids_offset = g_custom_entries->size();
256 for (int i = 0; i < kMaxReportedActiveExtensions; ++i) { 256 // one-based index for the name suffix.
257 for (int i = 1; i <= kMaxReportedActiveExtensions; ++i) {
257 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( 258 g_custom_entries->push_back(google_breakpad::CustomInfoEntry(
258 base::StringPrintf(L"extension-%i", i + 1).c_str(), L"")); 259 base::StringPrintf(L"extension-%i", i).c_str(), L""));
259 } 260 }
260 261
261 // Add empty values for the gpu_info. We'll put the actual values when we 262 // Add empty values for the gpu_info. We'll put the actual values when we
262 // collect them at this location. 263 // collect them at this location.
263 g_gpu_info_offset = g_custom_entries->size(); 264 g_gpu_info_offset = g_custom_entries->size();
264 static const wchar_t* const kGpuEntries[] = { 265 static const wchar_t* const kGpuEntries[] = {
265 L"gpu-venid", 266 L"gpu-venid",
266 L"gpu-devid", 267 L"gpu-devid",
267 L"gpu-driver", 268 L"gpu-driver",
268 L"gpu-psver", 269 L"gpu-psver",
269 L"gpu-vsver", 270 L"gpu-vsver",
270 }; 271 };
271 for (size_t i = 0; i < arraysize(kGpuEntries); ++i) { 272 for (size_t i = 0; i < arraysize(kGpuEntries); ++i) {
272 g_custom_entries->push_back( 273 g_custom_entries->push_back(
273 google_breakpad::CustomInfoEntry(kGpuEntries[i], L"")); 274 google_breakpad::CustomInfoEntry(kGpuEntries[i], L""));
274 } 275 }
275 276
276 // Add empty values for the prn_info-*. We'll put the actual values when we 277 // Add empty values for the prn_info-*. We'll put the actual values when we
277 // collect them at this location. 278 // collect them at this location.
278 g_printer_info_offset = g_custom_entries->size(); 279 g_printer_info_offset = g_custom_entries->size();
279 for (size_t i = 0; i < kMaxReportedPrinterRecords; ++i) { 280 // one-based index for the name suffix.
281 for (size_t i = 1; i <= kMaxReportedPrinterRecords; ++i) {
280 g_custom_entries->push_back( 282 g_custom_entries->push_back(
281 google_breakpad::CustomInfoEntry( 283 google_breakpad::CustomInfoEntry(
282 base::StringPrintf(L"prn-info-%d", i + 1).c_str(), L"")); 284 base::StringPrintf(L"prn-info-%d", i).c_str(), L""));
283 } 285 }
284 286
285 // Read the id from registry. If reporting has never been enabled 287 // Read the id from registry. If reporting has never been enabled
286 // the result will be empty string. Its OK since when user enables reporting 288 // the result will be empty string. Its OK since when user enables reporting
287 // we will insert the new value at this location. 289 // we will insert the new value at this location.
288 std::wstring guid; 290 std::wstring guid;
289 GoogleUpdateSettings::GetMetricsId(&guid); 291 GoogleUpdateSettings::GetMetricsId(&guid);
290 g_client_id_offset = g_custom_entries->size(); 292 g_client_id_offset = g_custom_entries->size();
291 g_custom_entries->push_back( 293 g_custom_entries->push_back(
292 google_breakpad::CustomInfoEntry(L"guid", guid.c_str())); 294 google_breakpad::CustomInfoEntry(L"guid", guid.c_str()));
293 295
294 // Add empty values for the command line switches. We will fill them with 296 // Add empty values for the command line switches. We will fill them with
295 // actual values as part of SetCommandLine(). 297 // actual values as part of SetCommandLine().
296 g_num_switches_offset = g_custom_entries->size(); 298 g_num_switches_offset = g_custom_entries->size();
297 g_custom_entries->push_back( 299 g_custom_entries->push_back(
298 google_breakpad::CustomInfoEntry(L"num-switches", L"")); 300 google_breakpad::CustomInfoEntry(L"num-switches", L""));
299 301
300 g_switches_offset = g_custom_entries->size(); 302 g_switches_offset = g_custom_entries->size();
301 for (int i = 0; i < kMaxSwitches; ++i) { 303 // one-based index for the name suffix.
304 for (int i = 1; i <= kMaxSwitches; ++i) {
302 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( 305 g_custom_entries->push_back(google_breakpad::CustomInfoEntry(
303 base::StringPrintf(L"switch-%i", i + 1).c_str(), L"")); 306 base::StringPrintf(L"switch-%i", i).c_str(), L""));
304 } 307 }
305 308
306 // Fill in the command line arguments using CommandLine::ForCurrentProcess(). 309 // Fill in the command line arguments using CommandLine::ForCurrentProcess().
307 // The browser process may call SetCommandLine() again later on with a command 310 // The browser process may call SetCommandLine() again later on with a command
308 // line that has been augmented with the about:flags experiments. 311 // line that has been augmented with the about:flags experiments.
309 SetCommandLine(CommandLine::ForCurrentProcess()); 312 SetCommandLine(CommandLine::ForCurrentProcess());
310 313
311 if (type == L"renderer" || type == L"plugin" || type == L"gpu-process") { 314 if (type == L"renderer" || type == L"plugin" || type == L"gpu-process") {
312 g_num_of_views_offset = g_custom_entries->size(); 315 g_num_of_views_offset = g_custom_entries->size();
313 g_custom_entries->push_back( 316 g_custom_entries->push_back(
314 google_breakpad::CustomInfoEntry(L"num-views", L"")); 317 google_breakpad::CustomInfoEntry(L"num-views", L""));
315 // Create entries for the URL. Currently we only allow each chunk to be 64 318 // Create entries for the URL. Currently we only allow each chunk to be 64
316 // characters, which isn't enough for a URL. As a hack we create 8 entries 319 // characters, which isn't enough for a URL. As a hack we create 8 entries
317 // and split the URL across the g_custom_entries. 320 // and split the URL across the g_custom_entries.
318 g_url_chunks_offset = g_custom_entries->size(); 321 g_url_chunks_offset = g_custom_entries->size();
319 for (int i = 0; i < kMaxUrlChunks; ++i) { 322 // one-based index for the name suffix.
323 for (int i = 1; i <= kMaxUrlChunks; ++i) {
320 g_custom_entries->push_back(google_breakpad::CustomInfoEntry( 324 g_custom_entries->push_back(google_breakpad::CustomInfoEntry(
321 base::StringPrintf(L"url-chunk-%i", i + 1).c_str(), L"")); 325 base::StringPrintf(L"url-chunk-%i", i).c_str(), L""));
322 } 326 }
323 327
324 if (type == L"plugin") { 328 if (type == L"plugin") {
325 std::wstring plugin_path = 329 std::wstring plugin_path =
326 CommandLine::ForCurrentProcess()->GetSwitchValueNative("plugin-path"); 330 CommandLine::ForCurrentProcess()->GetSwitchValueNative("plugin-path");
327 if (!plugin_path.empty()) 331 if (!plugin_path.empty())
328 SetPluginPath(plugin_path); 332 SetPluginPath(plugin_path);
329 } 333 }
330 } else { 334 } else {
331 g_custom_entries->push_back( 335 g_custom_entries->push_back(
332 google_breakpad::CustomInfoEntry(L"num-views", L"N/A")); 336 google_breakpad::CustomInfoEntry(L"num-views", L"N/A"));
333 } 337 }
334 338
339 breakpad_win::g_num_of_experiments_offset = g_custom_entries->size();
robertshield 2012/03/23 15:42:10 please add a "using" statement above for g_num_of_
MAD 2012/03/23 18:24:23 Done.
340 g_custom_entries->push_back(
341 google_breakpad::CustomInfoEntry(L"num-experiments", L"N/A"));
342
343 breakpad_win::g_experiment_chunks_offset = g_custom_entries->size();
344 // We depend on this in UpdateExperiments...
345 DCHECK_NE(0UL, breakpad_win::g_experiment_chunks_offset);
346 // And the test code depends on this.
347 DCHECK_EQ(breakpad_win::g_num_of_experiments_offset + 1,
348 breakpad_win::g_experiment_chunks_offset);
349 // one-based index for the name suffix.
350 for (int i = 1; i <= kMaxReportedExperimentChunks; ++i) {
351 g_custom_entries->push_back(google_breakpad::CustomInfoEntry(
352 base::StringPrintf(L"experiment-chunk-%i", i).c_str(), L""));
353 }
354
335 static google_breakpad::CustomClientInfo custom_client_info; 355 static google_breakpad::CustomClientInfo custom_client_info;
336 custom_client_info.entries = &g_custom_entries->front(); 356 custom_client_info.entries = &g_custom_entries->front();
337 custom_client_info.count = g_custom_entries->size(); 357 custom_client_info.count = g_custom_entries->size();
338 358
339 return &custom_client_info; 359 return &custom_client_info;
340 } 360 }
341 361
342 // This callback is used when we want to get a dump without crashing the 362 // This callback is used when we want to get a dump without crashing the
343 // process. 363 // process.
344 bool DumpDoneCallbackWhenNoCrash(const wchar_t*, const wchar_t*, void*, 364 bool DumpDoneCallbackWhenNoCrash(const wchar_t*, const wchar_t*, void*,
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 } 548 }
529 } 549 }
530 550
531 extern "C" void __declspec(dllexport) __cdecl SetNumberOfViews( 551 extern "C" void __declspec(dllexport) __cdecl SetNumberOfViews(
532 int number_of_views) { 552 int number_of_views) {
533 SetIntegerValue(g_num_of_views_offset, number_of_views); 553 SetIntegerValue(g_num_of_views_offset, number_of_views);
534 } 554 }
535 555
536 } // namespace 556 } // namespace
537 557
558 namespace breakpad_win {
559
560 std::vector<google_breakpad::CustomInfoEntry>* g_custom_entries = NULL;
561 size_t g_num_of_experiments_offset = 0;
562 size_t g_experiment_chunks_offset = 0;
563
564 } // namespace breakpad_win
robertshield 2012/03/23 15:42:10 please move the above breakpad_win namespace block
MAD 2012/03/23 18:24:23 Done.
565
566 namespace testing {
567
568 // Access to namespace protected functions for testing purposes.
569 void InitCustomInfoEntries() {
570 GetCustomInfo(L"", L"", L"");
571 }
572
573 } // namespace testing
574
538 bool WrapMessageBoxWithSEH(const wchar_t* text, const wchar_t* caption, 575 bool WrapMessageBoxWithSEH(const wchar_t* text, const wchar_t* caption,
539 UINT flags, bool* exit_now) { 576 UINT flags, bool* exit_now) {
540 // We wrap the call to MessageBoxW with a SEH handler because it some 577 // We wrap the call to MessageBoxW with a SEH handler because it some
541 // machines with CursorXP, PeaDict or with FontExplorer installed it crashes 578 // machines with CursorXP, PeaDict or with FontExplorer installed it crashes
542 // uncontrollably here. Being this a best effort deal we better go away. 579 // uncontrollably here. Being this a best effort deal we better go away.
543 __try { 580 __try {
544 *exit_now = (IDOK != ::MessageBoxW(NULL, text, caption, flags)); 581 *exit_now = (IDOK != ::MessageBoxW(NULL, text, caption, flags));
545 } __except(EXCEPTION_EXECUTE_HANDLER) { 582 } __except(EXCEPTION_EXECUTE_HANDLER) {
546 // Its not safe to continue executing, exit silently here. 583 // Its not safe to continue executing, exit silently here.
547 ::ExitProcess(chrome::RESULT_CODE_RESPAWN_FAILED); 584 ::ExitProcess(chrome::RESULT_CODE_RESPAWN_FAILED);
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 // Tells breakpad to handle breakpoint and single step exceptions. 814 // Tells breakpad to handle breakpoint and single step exceptions.
778 // This might break JIT debuggers, but at least it will always 815 // This might break JIT debuggers, but at least it will always
779 // generate a crashdump for these exceptions. 816 // generate a crashdump for these exceptions.
780 g_breakpad->set_handle_debug_exceptions(true); 817 g_breakpad->set_handle_debug_exceptions(true);
781 } 818 }
782 } 819 }
783 820
784 void InitDefaultCrashCallback(LPTOP_LEVEL_EXCEPTION_FILTER filter) { 821 void InitDefaultCrashCallback(LPTOP_LEVEL_EXCEPTION_FILTER filter) {
785 previous_filter = SetUnhandledExceptionFilter(filter); 822 previous_filter = SetUnhandledExceptionFilter(filter);
786 } 823 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698