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. | 399 // NOTE: This function is used by SyzyASAN to annotate crash reports. If you |
400 static void SetCrashKeyValueLocked(const std::wstring& safe_key, | 400 // change the name or signature of this function you will break SyzyASAN |
401 const std::wstring& safe_value) { | 401 // instrumented releases of Chrome. Please contact syzygy-team@chromium.org |
402 DCHECK(g_dynamic_entries && g_dynamic_entries_lock); | 402 // before doing so! |
403 DCHECK(safe_key.length() < google_breakpad::CustomInfoEntry::kNameMaxLength); | 403 extern "C" void __declspec(dllexport) __cdecl SetCrashKeyValueImpl( |
404 DCHECK(safe_value.length() < | 404 const wchar_t* key, const wchar_t* value) { |
405 google_breakpad::CustomInfoEntry::kValueMaxLength); | 405 if (!g_dynamic_entries) |
406 g_dynamic_entries_lock->AssertAcquired(); | 406 return; |
| 407 |
| 408 // CustomInfoEntry limits the length of key and value. If they exceed |
| 409 // their maximum length the underlying string handling functions raise |
| 410 // an exception and prematurely trigger a crash. Truncate here. |
| 411 std::wstring safe_key(std::wstring(key).substr( |
| 412 0, google_breakpad::CustomInfoEntry::kNameMaxLength - 1)); |
| 413 std::wstring safe_value(std::wstring(value).substr( |
| 414 0, google_breakpad::CustomInfoEntry::kValueMaxLength - 1)); |
| 415 |
| 416 // 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 |
| 418 // entries. |
| 419 DCHECK(g_dynamic_entries_lock); |
| 420 base::AutoLock lock(*g_dynamic_entries_lock); |
407 | 421 |
408 DynamicEntriesMap::iterator it = g_dynamic_entries->find(safe_key); | 422 DynamicEntriesMap::iterator it = g_dynamic_entries->find(safe_key); |
409 google_breakpad::CustomInfoEntry* entry = NULL; | 423 google_breakpad::CustomInfoEntry* entry = NULL; |
410 if (it == g_dynamic_entries->end()) { | 424 if (it == g_dynamic_entries->end()) { |
411 if (g_dynamic_entries->size() >= kMaxDynamicEntries) | 425 if (g_dynamic_entries->size() >= kMaxDynamicEntries) |
412 return; | 426 return; |
413 entry = &(*g_custom_entries)[g_dynamic_keys_offset++]; | 427 entry = &(*g_custom_entries)[g_dynamic_keys_offset++]; |
414 g_dynamic_entries->insert(std::make_pair(safe_key, entry)); | 428 g_dynamic_entries->insert(std::make_pair(safe_key, entry)); |
415 } else { | 429 } else { |
416 entry = it->second; | 430 entry = it->second; |
417 } | 431 } |
418 | 432 |
419 entry->set(safe_key.data(), safe_value.data()); | 433 entry->set(safe_key.data(), safe_value.data()); |
420 } | 434 } |
421 | 435 |
422 // NOTE: This function is used by SyzyASAN to annotate crash reports. If you | |
423 // change the name or signature of this function you will break SyzyASAN | |
424 // instrumented releases of Chrome. Please contact syzygy-team@chromium.org | |
425 // before doing so! | |
426 extern "C" void __declspec(dllexport) __cdecl SetCrashKeyValueImpl( | |
427 const wchar_t* key, const wchar_t* value) { | |
428 if (!g_dynamic_entries) | |
429 return; | |
430 | |
431 // CustomInfoEntry limits the length of key and value. If they exceed | |
432 // their maximum length the underlying string handling functions raise | |
433 // an exception and prematurely trigger a crash. Truncate here. | |
434 std::wstring safe_key(std::wstring(key).substr( | |
435 0, google_breakpad::CustomInfoEntry::kNameMaxLength - 1)); | |
436 std::wstring safe_value(std::wstring(value).substr( | |
437 0, google_breakpad::CustomInfoEntry::kValueMaxLength - 1)); | |
438 | |
439 // If we already have a value for this key, update it; otherwise, insert | |
440 // the new value if we have not exhausted the pre-allocated slots for dynamic | |
441 // entries. | |
442 DCHECK(g_dynamic_entries_lock); | |
443 base::AutoLock lock(*g_dynamic_entries_lock); | |
444 | |
445 SetCrashKeyValueLocked(safe_key, safe_value); | |
446 | |
447 // TODO(siggi): remove this code, see http://crbug.com/371817. | |
448 static size_t guid_set_count = 0; | |
449 if (safe_key == L"guid") { | |
450 // Bracket the value to get something recorded if it's set to the empty | |
451 // string. Truncate to 61 char max, to allow for brackets and terminating | |
452 // zero in the allotted 64 chars. | |
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)); | |
466 } | |
467 } | |
468 | |
469 extern "C" void __declspec(dllexport) __cdecl ClearCrashKeyValueImpl( | 436 extern "C" void __declspec(dllexport) __cdecl ClearCrashKeyValueImpl( |
470 const wchar_t* key) { | 437 const wchar_t* key) { |
471 if (!g_dynamic_entries) | 438 if (!g_dynamic_entries) |
472 return; | 439 return; |
473 | 440 |
474 DCHECK(g_dynamic_entries_lock); | 441 DCHECK(g_dynamic_entries_lock); |
475 base::AutoLock lock(*g_dynamic_entries_lock); | 442 base::AutoLock lock(*g_dynamic_entries_lock); |
476 | 443 |
477 std::wstring key_string(key); | 444 std::wstring key_string(key); |
478 DynamicEntriesMap::iterator it = g_dynamic_entries->find(key_string); | 445 DynamicEntriesMap::iterator it = g_dynamic_entries->find(key_string); |
479 if (it == g_dynamic_entries->end()) | 446 if (it == g_dynamic_entries->end()) |
480 return; | 447 return; |
481 | 448 |
482 it->second->set_value(NULL); | 449 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 } | |
492 } | 450 } |
493 | 451 |
494 } // namespace | 452 } // namespace |
495 | 453 |
496 static bool WrapMessageBoxWithSEH(const wchar_t* text, const wchar_t* caption, | 454 static bool WrapMessageBoxWithSEH(const wchar_t* text, const wchar_t* caption, |
497 UINT flags, bool* exit_now) { | 455 UINT flags, bool* exit_now) { |
498 // We wrap the call to MessageBoxW with a SEH handler because it some | 456 // We wrap the call to MessageBoxW with a SEH handler because it some |
499 // machines with CursorXP, PeaDict or with FontExplorer installed it crashes | 457 // machines with CursorXP, PeaDict or with FontExplorer installed it crashes |
500 // uncontrollably here. Being this a best effort deal we better go away. | 458 // uncontrollably here. Being this a best effort deal we better go away. |
501 __try { | 459 __try { |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 if (process_type != L"browser" && | 746 if (process_type != L"browser" && |
789 !GetBreakpadClient()->IsRunningUnattended()) { | 747 !GetBreakpadClient()->IsRunningUnattended()) { |
790 // Initialize the hook TerminateProcess to catch unexpected exits. | 748 // Initialize the hook TerminateProcess to catch unexpected exits. |
791 InitTerminateProcessHooks(); | 749 InitTerminateProcessHooks(); |
792 } | 750 } |
793 #endif | 751 #endif |
794 } | 752 } |
795 } | 753 } |
796 | 754 |
797 } // namespace breakpad | 755 } // namespace breakpad |
OLD | NEW |