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.
7 #include "chrome/app/kasko_client.h"
14 #include "base/logging.h"
15 #include "base/process/process_handle.h"
16 #include "breakpad/src/client/windows/common/ipc_protocol.h"
17 #include "chrome/app/chrome_watcher_client_win.h"
18 #include "chrome/chrome_watcher/chrome_watcher_main_api.h"
19 #include "chrome/common/chrome_constants.h"
20 #include "components/crash/app/crash_keys_win.h"
21 #include "syzygy/kasko/api/client.h"
25 ChromeWatcherClient
* g_chrome_watcher_client
= nullptr;
26 kasko::api::MinidumpType g_minidump_type
= kasko::api::SMALL_DUMP_TYPE
;
28 void GetKaskoCrashKeys(const kasko::api::CrashKey
** crash_keys
,
29 size_t* crash_key_count
) {
31 sizeof(kasko::api::CrashKey
) == sizeof(google_breakpad::CustomInfoEntry
),
32 "CrashKey and CustomInfoEntry structs are not compatible.");
33 static_assert(offsetof(kasko::api::CrashKey
, name
) ==
34 offsetof(google_breakpad::CustomInfoEntry
, name
),
35 "CrashKey and CustomInfoEntry structs are not compatible.");
36 static_assert(offsetof(kasko::api::CrashKey
, value
) ==
37 offsetof(google_breakpad::CustomInfoEntry
, value
),
38 "CrashKey and CustomInfoEntry structs are not compatible.");
40 sizeof(reinterpret_cast<kasko::api::CrashKey
*>(0)->name
) ==
41 sizeof(reinterpret_cast<google_breakpad::CustomInfoEntry
*>(0)->name
),
42 "CrashKey and CustomInfoEntry structs are not compatible.");
44 sizeof(reinterpret_cast<kasko::api::CrashKey
*>(0)->value
) ==
45 sizeof(reinterpret_cast<google_breakpad::CustomInfoEntry
*>(0)->value
),
46 "CrashKey and CustomInfoEntry structs are not compatible.");
49 breakpad::CrashKeysWin::keeper()->custom_info_entries().size();
50 *crash_keys
= reinterpret_cast<const kasko::api::CrashKey
*>(
51 breakpad::CrashKeysWin::keeper()->custom_info_entries().data());
56 KaskoClient::KaskoClient(ChromeWatcherClient
* chrome_watcher_client
,
57 kasko::api::MinidumpType minidump_type
) {
58 DCHECK(!g_chrome_watcher_client
);
59 g_minidump_type
= minidump_type
;
60 g_chrome_watcher_client
= chrome_watcher_client
;
62 kasko::api::InitializeClient(
63 GetKaskoEndpoint(base::GetCurrentProcId()).c_str());
66 KaskoClient::~KaskoClient() {
67 DCHECK(g_chrome_watcher_client
);
68 g_chrome_watcher_client
= nullptr;
69 kasko::api::ShutdownClient();
72 // Sends a diagnostic report for the current process, then terminates it.
73 // |info| is an optional exception record describing an exception on the current
75 // |protobuf| is an optional buffer of length |protobuf_length|.
76 // |base_addresses| and |lengths| are optional null-terminated arrays of the
77 // same length. For each entry in |base_addresses|, a memory range starting at
78 // the specified address and having the length specified in the corresponding
79 // entry in |lengths| will be explicitly included in the report.
80 extern "C" void __declspec(dllexport
)
81 ReportCrashWithProtobufAndMemoryRanges(EXCEPTION_POINTERS
* info
,
83 size_t protobuf_length
,
84 const void* const* base_addresses
,
85 const size_t* lengths
) {
86 if (g_chrome_watcher_client
&& g_chrome_watcher_client
->EnsureInitialized()) {
87 size_t crash_key_count
= 0;
88 const kasko::api::CrashKey
* crash_keys
= nullptr;
89 GetKaskoCrashKeys(&crash_keys
, &crash_key_count
);
90 std::vector
<kasko::api::MemoryRange
> memory_ranges
;
91 if (base_addresses
&& lengths
) {
92 for (int i
= 0; base_addresses
[i
] != nullptr && lengths
[i
] != 0; ++i
) {
93 kasko::api::MemoryRange memory_range
= {base_addresses
[i
], lengths
[i
]};
94 memory_ranges
.push_back(memory_range
);
97 kasko::api::SendReport(info
, g_minidump_type
, protobuf
, protobuf_length
,
98 crash_keys
, crash_key_count
,
99 memory_ranges
.size() ? &memory_ranges
[0] : nullptr,
100 memory_ranges
.size());
103 // The Breakpad integration hooks TerminateProcess. Sidestep it to avoid a
106 using TerminateProcessWithoutDumpProc
= void(__cdecl
*)();
107 TerminateProcessWithoutDumpProc terminate_process_without_dump
=
108 reinterpret_cast<TerminateProcessWithoutDumpProc
>(::GetProcAddress(
109 ::GetModuleHandle(chrome::kBrowserProcessExecutableName
),
110 "TerminateProcessWithoutDump"));
111 CHECK(terminate_process_without_dump
);
112 terminate_process_without_dump();
115 extern "C" void __declspec(dllexport
) ReportCrashWithProtobuf(
116 EXCEPTION_POINTERS
* info
, const char* protobuf
, size_t protobuf_length
) {
117 ReportCrashWithProtobufAndMemoryRanges(info
, protobuf
, protobuf_length
,
121 #endif // defined(KASKO)