| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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. | |
| 4 | |
| 5 | |
| 6 #include "chrome/app/kasko_client.h" | |
| 7 | |
| 8 #if BUILDFLAG(ENABLE_KASKO) | |
| 9 | |
| 10 #include <windows.h> | |
| 11 #include <stddef.h> | |
| 12 | |
| 13 #include <string> | |
| 14 #include <vector> | |
| 15 | |
| 16 #include "base/lazy_instance.h" | |
| 17 #include "base/logging.h" | |
| 18 #include "base/process/process_handle.h" | |
| 19 #include "chrome/app/chrome_watcher_client_win.h" | |
| 20 #include "chrome/chrome_watcher/chrome_watcher_main_api.h" | |
| 21 #include "chrome/common/chrome_constants.h" | |
| 22 #include "components/crash/content/app/crashpad.h" | |
| 23 #include "syzygy/kasko/api/client.h" | |
| 24 | |
| 25 namespace { | |
| 26 | |
| 27 ChromeWatcherClient* g_chrome_watcher_client = nullptr; | |
| 28 kasko::api::MinidumpType g_minidump_type = kasko::api::SMALL_DUMP_TYPE; | |
| 29 | |
| 30 base::LazyInstance<std::vector<kasko::api::CrashKey>>::Leaky | |
| 31 g_kasko_crash_keys = LAZY_INSTANCE_INITIALIZER; | |
| 32 | |
| 33 void GetKaskoCrashKeys(const kasko::api::CrashKey** crash_keys, | |
| 34 size_t* crash_key_count) { | |
| 35 crash_reporter::GetCrashKeysForKasko(g_kasko_crash_keys.Pointer()); | |
| 36 *crash_key_count = g_kasko_crash_keys.Pointer()->size(); | |
| 37 *crash_keys = g_kasko_crash_keys.Pointer()->data(); | |
| 38 } | |
| 39 | |
| 40 } // namespace | |
| 41 | |
| 42 KaskoClient::KaskoClient(ChromeWatcherClient* chrome_watcher_client, | |
| 43 kasko::api::MinidumpType minidump_type) { | |
| 44 DCHECK(!g_chrome_watcher_client); | |
| 45 g_minidump_type = minidump_type; | |
| 46 g_chrome_watcher_client = chrome_watcher_client; | |
| 47 | |
| 48 kasko::api::InitializeClient( | |
| 49 GetKaskoEndpoint(base::GetCurrentProcId()).c_str()); | |
| 50 | |
| 51 // Register the crash keys so that they will be available whether a crash | |
| 52 // report is triggered directly by the browser process or requested by the | |
| 53 // Chrome Watcher process. | |
| 54 size_t crash_key_count = 0; | |
| 55 const kasko::api::CrashKey* crash_keys = nullptr; | |
| 56 GetKaskoCrashKeys(&crash_keys, &crash_key_count); | |
| 57 kasko::api::RegisterCrashKeys(crash_keys, crash_key_count); | |
| 58 } | |
| 59 | |
| 60 KaskoClient::~KaskoClient() { | |
| 61 DCHECK(g_chrome_watcher_client); | |
| 62 g_chrome_watcher_client = nullptr; | |
| 63 kasko::api::ShutdownClient(); | |
| 64 } | |
| 65 | |
| 66 // Sends a diagnostic report for the current process, then terminates it. | |
| 67 // |info| is an optional exception record describing an exception on the current | |
| 68 // thread. | |
| 69 // |protobuf| is an optional buffer of length |protobuf_length|. | |
| 70 // |base_addresses| and |lengths| are optional null-terminated arrays of the | |
| 71 // same length. For each entry in |base_addresses|, a memory range starting at | |
| 72 // the specified address and having the length specified in the corresponding | |
| 73 // entry in |lengths| will be explicitly included in the report. | |
| 74 extern "C" void __declspec(dllexport) | |
| 75 ReportCrashWithProtobufAndMemoryRanges(EXCEPTION_POINTERS* info, | |
| 76 const char* protobuf, | |
| 77 size_t protobuf_length, | |
| 78 const void* const* base_addresses, | |
| 79 const size_t* lengths) { | |
| 80 if (g_chrome_watcher_client && g_chrome_watcher_client->EnsureInitialized()) { | |
| 81 size_t crash_key_count = 0; | |
| 82 const kasko::api::CrashKey* crash_keys = nullptr; | |
| 83 GetKaskoCrashKeys(&crash_keys, &crash_key_count); | |
| 84 std::vector<kasko::api::MemoryRange> memory_ranges; | |
| 85 if (base_addresses && lengths) { | |
| 86 for (int i = 0; base_addresses[i] != nullptr && lengths[i] != 0; ++i) { | |
| 87 kasko::api::MemoryRange memory_range = {base_addresses[i], lengths[i]}; | |
| 88 memory_ranges.push_back(memory_range); | |
| 89 } | |
| 90 } | |
| 91 kasko::api::SendReport(info, g_minidump_type, protobuf, protobuf_length, | |
| 92 crash_keys, crash_key_count, | |
| 93 memory_ranges.size() ? &memory_ranges[0] : nullptr, | |
| 94 memory_ranges.size()); | |
| 95 } | |
| 96 | |
| 97 // The Breakpad integration hooks TerminateProcess. Sidestep it to avoid a | |
| 98 // secondary report. Crashpad, on the other hand, does not hook | |
| 99 // TerminateProcess so it can be safely invoked. | |
| 100 // TODO(chrisha): When Breakpad is completely ripped out make this Crashpad | |
| 101 // specific. | |
| 102 using TerminateProcessWithoutDumpProc = void(__cdecl*)(); | |
| 103 TerminateProcessWithoutDumpProc terminate_process_without_dump = | |
| 104 reinterpret_cast<TerminateProcessWithoutDumpProc>(::GetProcAddress( | |
| 105 ::GetModuleHandle(chrome::kBrowserProcessExecutableName), | |
| 106 "TerminateProcessWithoutDump")); | |
| 107 if (terminate_process_without_dump) | |
| 108 terminate_process_without_dump(); | |
| 109 else | |
| 110 ::TerminateProcess(::GetCurrentProcess(), 0); | |
| 111 } | |
| 112 | |
| 113 extern "C" void __declspec(dllexport) ReportCrashWithProtobuf( | |
| 114 EXCEPTION_POINTERS* info, const char* protobuf, size_t protobuf_length) { | |
| 115 ReportCrashWithProtobufAndMemoryRanges(info, protobuf, protobuf_length, | |
| 116 nullptr, nullptr); | |
| 117 } | |
| 118 | |
| 119 #endif // BUILDFLAG(ENABLE_KASKO) | |
| OLD | NEW |