| 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 |