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 |