OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/breakpad/app/breakpad_win.h" | 5 #include "components/breakpad/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 #include <userenv.h> | 10 #include <userenv.h> |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 } | 389 } |
390 | 390 |
391 // Exception filter for the service process used when breakpad is not enabled. | 391 // Exception filter for the service process used when breakpad is not enabled. |
392 // We just display the "Do you want to restart" message and then die | 392 // We just display the "Do you want to restart" message and then die |
393 // (without calling the previous filter). | 393 // (without calling the previous filter). |
394 long WINAPI ServiceExceptionFilter(EXCEPTION_POINTERS* info) { | 394 long WINAPI ServiceExceptionFilter(EXCEPTION_POINTERS* info) { |
395 DumpDoneCallback(NULL, NULL, NULL, info, NULL, false); | 395 DumpDoneCallback(NULL, NULL, NULL, info, NULL, false); |
396 return EXCEPTION_EXECUTE_HANDLER; | 396 return EXCEPTION_EXECUTE_HANDLER; |
397 } | 397 } |
398 | 398 |
| 399 // Sets |key| to |value|, g_dynamic_entries_lock must be held. |
| 400 static void SetCrashKeyValueLocked(const std::wstring& safe_key, |
| 401 const std::wstring& safe_value) { |
| 402 DCHECK(g_dynamic_entries && g_dynamic_entries_lock); |
| 403 DCHECK(safe_key.length() < google_breakpad::CustomInfoEntry::kNameMaxLength); |
| 404 DCHECK(safe_value.length() < |
| 405 google_breakpad::CustomInfoEntry::kValueMaxLength); |
| 406 g_dynamic_entries_lock->AssertAcquired(); |
| 407 |
| 408 DynamicEntriesMap::iterator it = g_dynamic_entries->find(safe_key); |
| 409 google_breakpad::CustomInfoEntry* entry = NULL; |
| 410 if (it == g_dynamic_entries->end()) { |
| 411 if (g_dynamic_entries->size() >= kMaxDynamicEntries) |
| 412 return; |
| 413 entry = &(*g_custom_entries)[g_dynamic_keys_offset++]; |
| 414 g_dynamic_entries->insert(std::make_pair(safe_key, entry)); |
| 415 } else { |
| 416 entry = it->second; |
| 417 } |
| 418 |
| 419 entry->set(safe_key.data(), safe_value.data()); |
| 420 } |
| 421 |
399 // NOTE: This function is used by SyzyASAN to annotate crash reports. If you | 422 // NOTE: This function is used by SyzyASAN to annotate crash reports. If you |
400 // change the name or signature of this function you will break SyzyASAN | 423 // change the name or signature of this function you will break SyzyASAN |
401 // instrumented releases of Chrome. Please contact syzygy-team@chromium.org | 424 // instrumented releases of Chrome. Please contact syzygy-team@chromium.org |
402 // before doing so! | 425 // before doing so! |
403 extern "C" void __declspec(dllexport) __cdecl SetCrashKeyValueImpl( | 426 extern "C" void __declspec(dllexport) __cdecl SetCrashKeyValueImpl( |
404 const wchar_t* key, const wchar_t* value) { | 427 const wchar_t* key, const wchar_t* value) { |
405 if (!g_dynamic_entries) | 428 if (!g_dynamic_entries) |
406 return; | 429 return; |
407 | 430 |
408 // CustomInfoEntry limits the length of key and value. If they exceed | 431 // CustomInfoEntry limits the length of key and value. If they exceed |
409 // their maximum length the underlying string handling functions raise | 432 // their maximum length the underlying string handling functions raise |
410 // an exception and prematurely trigger a crash. Truncate here. | 433 // an exception and prematurely trigger a crash. Truncate here. |
411 std::wstring safe_key(std::wstring(key).substr( | 434 std::wstring safe_key(std::wstring(key).substr( |
412 0, google_breakpad::CustomInfoEntry::kNameMaxLength - 1)); | 435 0, google_breakpad::CustomInfoEntry::kNameMaxLength - 1)); |
413 std::wstring safe_value(std::wstring(value).substr( | 436 std::wstring safe_value(std::wstring(value).substr( |
414 0, google_breakpad::CustomInfoEntry::kValueMaxLength - 1)); | 437 0, google_breakpad::CustomInfoEntry::kValueMaxLength - 1)); |
415 | 438 |
416 // If we already have a value for this key, update it; otherwise, insert | 439 // If we already have a value for this key, update it; otherwise, insert |
417 // the new value if we have not exhausted the pre-allocated slots for dynamic | 440 // the new value if we have not exhausted the pre-allocated slots for dynamic |
418 // entries. | 441 // entries. |
419 DCHECK(g_dynamic_entries_lock); | 442 DCHECK(g_dynamic_entries_lock); |
420 base::AutoLock lock(*g_dynamic_entries_lock); | 443 base::AutoLock lock(*g_dynamic_entries_lock); |
421 | 444 |
422 DynamicEntriesMap::iterator it = g_dynamic_entries->find(safe_key); | 445 SetCrashKeyValueLocked(safe_key, safe_value); |
423 google_breakpad::CustomInfoEntry* entry = NULL; | 446 |
424 if (it == g_dynamic_entries->end()) { | 447 // TODO(siggi): remove this code, see http://crbug.com/371817. |
425 if (g_dynamic_entries->size() >= kMaxDynamicEntries) | 448 static size_t guid_set_count = 0; |
426 return; | 449 if (safe_key == L"guid") { |
427 entry = &(*g_custom_entries)[g_dynamic_keys_offset++]; | 450 // Bracket the value to get something recorded if it's set to the empty |
428 g_dynamic_entries->insert(std::make_pair(safe_key, entry)); | 451 // string. Truncate to 61 char max, to allow for brackets and terminating |
429 } else { | 452 // zero in the allotted 64 chars. |
430 entry = it->second; | 453 std::wstring bracketed_guid = base::StringPrintf(L"{%.61ls}", value); |
| 454 if (guid_set_count == 0) { |
| 455 // Keep track of the first GUID set. |
| 456 SetCrashKeyValueLocked(L"first-guid", bracketed_guid); |
| 457 } else { |
| 458 // Keep track of the last GUID set. |
| 459 SetCrashKeyValueLocked(L"last-guid", bracketed_guid); |
| 460 } |
| 461 |
| 462 // Bump the set count and record the latest. |
| 463 ++guid_set_count; |
| 464 SetCrashKeyValueLocked(L"guid-set-count", |
| 465 base::StringPrintf(L"%d", guid_set_count)); |
431 } | 466 } |
432 | |
433 entry->set(safe_key.data(), safe_value.data()); | |
434 } | 467 } |
435 | 468 |
436 extern "C" void __declspec(dllexport) __cdecl ClearCrashKeyValueImpl( | 469 extern "C" void __declspec(dllexport) __cdecl ClearCrashKeyValueImpl( |
437 const wchar_t* key) { | 470 const wchar_t* key) { |
438 if (!g_dynamic_entries) | 471 if (!g_dynamic_entries) |
439 return; | 472 return; |
440 | 473 |
441 DCHECK(g_dynamic_entries_lock); | 474 DCHECK(g_dynamic_entries_lock); |
442 base::AutoLock lock(*g_dynamic_entries_lock); | 475 base::AutoLock lock(*g_dynamic_entries_lock); |
443 | 476 |
444 std::wstring key_string(key); | 477 std::wstring key_string(key); |
445 DynamicEntriesMap::iterator it = g_dynamic_entries->find(key_string); | 478 DynamicEntriesMap::iterator it = g_dynamic_entries->find(key_string); |
446 if (it == g_dynamic_entries->end()) | 479 if (it == g_dynamic_entries->end()) |
447 return; | 480 return; |
448 | 481 |
449 it->second->set_value(NULL); | 482 it->second->set_value(NULL); |
| 483 |
| 484 // TODO(siggi): remove this code, see http://crbug.com/371817. |
| 485 static size_t guid_clear_count = 0; |
| 486 if (key_string == L"guid") { |
| 487 // Bump the clear count and record the latest. |
| 488 ++guid_clear_count; |
| 489 SetCrashKeyValueLocked(L"guid-clear-count", |
| 490 base::StringPrintf(L"%d", guid_clear_count)); |
| 491 } |
450 } | 492 } |
451 | 493 |
452 } // namespace | 494 } // namespace |
453 | 495 |
454 static bool WrapMessageBoxWithSEH(const wchar_t* text, const wchar_t* caption, | 496 static bool WrapMessageBoxWithSEH(const wchar_t* text, const wchar_t* caption, |
455 UINT flags, bool* exit_now) { | 497 UINT flags, bool* exit_now) { |
456 // We wrap the call to MessageBoxW with a SEH handler because it some | 498 // We wrap the call to MessageBoxW with a SEH handler because it some |
457 // machines with CursorXP, PeaDict or with FontExplorer installed it crashes | 499 // machines with CursorXP, PeaDict or with FontExplorer installed it crashes |
458 // uncontrollably here. Being this a best effort deal we better go away. | 500 // uncontrollably here. Being this a best effort deal we better go away. |
459 __try { | 501 __try { |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 if (process_type != L"browser" && | 788 if (process_type != L"browser" && |
747 !GetBreakpadClient()->IsRunningUnattended()) { | 789 !GetBreakpadClient()->IsRunningUnattended()) { |
748 // Initialize the hook TerminateProcess to catch unexpected exits. | 790 // Initialize the hook TerminateProcess to catch unexpected exits. |
749 InitTerminateProcessHooks(); | 791 InitTerminateProcessHooks(); |
750 } | 792 } |
751 #endif | 793 #endif |
752 } | 794 } |
753 } | 795 } |
754 | 796 |
755 } // namespace breakpad | 797 } // namespace breakpad |
OLD | NEW |