1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/kasko/api/client.h"
16 :
17 : #include <dbghelp.h>
18 : #include <stdint.h>
19 :
20 : #include <vector>
21 :
22 : #include "base/logging.h"
23 : #include "syzygy/kasko/client.h"
24 : #include "syzygy/kasko/dll_lifetime.h"
25 : #include "syzygy/kasko/minidump_request.h"
26 : #include "syzygy/kasko/api/internal/crash_key_registration.h"
27 :
28 : namespace kasko {
29 : namespace api {
30 :
31 : namespace {
32 :
33 : static_assert(sizeof(CrashKey) == 256u,
34 : "CrashKey struct size must match that of the "
35 : "google_breakpad::CustomInfoEntry struct.");
36 :
37 : static_assert(kProtobufStreamType > LastReservedStream,
38 : "kProtobufStreamType <= LastReservedStream.");
39 :
40 : const DllLifetime* g_dll_lifetime;
41 : const Client* g_client = nullptr;
42 :
43 : // Returns true if |buffer| is a null-terminated string whose length is greater
44 : // than 0 and less than |buffer_length|.
45 E : bool IsValidNonEmptyString(const base::char16* buffer, size_t buffer_length) {
46 E : size_t string_length = ::wcsnlen(buffer, buffer_length);
47 E : return string_length > 0 && string_length < buffer_length;
48 E : }
49 :
50 : } // namespace
51 :
52 E : void InitializeClient(const base::char16* endpoint_name) {
53 E : DCHECK(!g_dll_lifetime);
54 E : g_dll_lifetime = new DllLifetime;
55 :
56 E : DCHECK(!g_client);
57 E : DCHECK(endpoint_name);
58 E : g_client = new Client(endpoint_name);
59 E : }
60 :
61 E : void RegisterCrashKeys(const CrashKey* crash_keys, size_t count) {
62 E : internal::RegisterCrashKeys(crash_keys, count);
63 E : }
64 :
65 : void SendReport(const EXCEPTION_POINTERS* exception_pointers,
66 : MinidumpType minidump_type,
67 : const char* protobuf,
68 : size_t protobuf_length,
69 : const CrashKey* crash_keys,
70 : size_t crash_key_count,
71 : const MemoryRange* user_selected_memory_ranges,
72 E : size_t user_selected_memory_range_count) {
73 E : if (!g_client) {
74 i : LOG(ERROR) << "SendReport failed: uninitialized.";
75 i : return;
76 : }
77 :
78 E : MinidumpRequest request;
79 E : request.client_exception_pointers = true;
80 : request.exception_info_address =
81 E : reinterpret_cast<uint32_t>(exception_pointers);
82 E : if (protobuf_length) {
83 : MinidumpRequest::CustomStream custom_stream = {kProtobufStreamType,
84 i : protobuf, protobuf_length};
85 i : request.custom_streams.push_back(custom_stream);
86 : }
87 :
88 E : for (size_t i = 0; i < crash_key_count; ++i) {
89 : if (!IsValidNonEmptyString(crash_keys[i].name,
90 : arraysize(crash_keys[i].name)) ||
91 : !IsValidNonEmptyString(crash_keys[i].value,
92 E : arraysize(crash_keys[i].value))) {
93 E : continue;
94 : }
95 : request.crash_keys.push_back(
96 E : MinidumpRequest::CrashKey(crash_keys[i].name, crash_keys[i].value));
97 E : }
98 :
99 E : for (size_t i = 0; i < user_selected_memory_range_count; ++i) {
100 : MinidumpRequest::MemoryRange memory_range = {
101 : reinterpret_cast<uint32_t>(user_selected_memory_ranges[i].base_address),
102 E : user_selected_memory_ranges[i].length};
103 E : request.user_selected_memory_ranges.push_back(memory_range);
104 E : }
105 :
106 E : switch (minidump_type) {
107 : case SMALL_DUMP_TYPE:
108 E : request.type = MinidumpRequest::SMALL_DUMP_TYPE;
109 E : break;
110 : case LARGER_DUMP_TYPE:
111 i : request.type = MinidumpRequest::LARGER_DUMP_TYPE;
112 i : break;
113 : case FULL_DUMP_TYPE:
114 i : request.type = MinidumpRequest::FULL_DUMP_TYPE;
115 i : break;
116 : default:
117 i : NOTREACHED();
118 : break;
119 : }
120 :
121 E : g_client->SendReport(request);
122 E : }
123 :
124 E : void ShutdownClient() {
125 E : DCHECK(g_client);
126 E : delete g_client;
127 E : g_client = nullptr;
128 :
129 E : DCHECK(g_dll_lifetime);
130 E : delete g_dll_lifetime;
131 E : g_dll_lifetime = nullptr;
132 E : }
133 :
134 : } // namespace api
135 : } // namespace kasko
|