Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(465)

Side by Side Diff: components/crash/content/app/crashpad.cc

Issue 2256723002: Fix SyzyASAN build (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« chrome/BUILD.gn ('K') | « components/crash/content/app/crashpad.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 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/crash/content/app/crashpad.h" 5 #include "components/crash/content/app/crashpad.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <string.h> 8 #include <string.h>
9 9
10 #if BUILDFLAG(ENABLE_KASKO)
11 #include <psapi.h>
12 #endif // BUILDFLAG(ENABLE_KASKO)
13
14 #include <algorithm> 10 #include <algorithm>
15 #include <map> 11 #include <map>
16 #include <vector> 12 #include <vector>
17 13
18 #include "base/auto_reset.h" 14 #include "base/auto_reset.h"
19 #include "base/base_paths.h" 15 #include "base/base_paths.h"
20 #include "base/command_line.h" 16 #include "base/command_line.h"
21 #include "base/debug/crash_logging.h" 17 #include "base/debug/crash_logging.h"
22 #include "base/debug/dump_without_crashing.h" 18 #include "base/debug/dump_without_crashing.h"
23 #include "base/logging.h" 19 #include "base/logging.h"
24 #include "base/macros.h" 20 #include "base/macros.h"
25 #include "base/strings/string_number_conversions.h" 21 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_piece.h" 22 #include "base/strings/string_piece.h"
27 #include "base/strings/stringprintf.h" 23 #include "base/strings/stringprintf.h"
28 #include "base/strings/sys_string_conversions.h" 24 #include "base/strings/sys_string_conversions.h"
29 #include "base/strings/utf_string_conversions.h" 25 #include "base/strings/utf_string_conversions.h"
30 #include "build/build_config.h" 26 #include "build/build_config.h"
31 #include "components/crash/content/app/crash_reporter_client.h" 27 #include "components/crash/content/app/crash_reporter_client.h"
32 #include "third_party/crashpad/crashpad/client/crash_report_database.h" 28 #include "third_party/crashpad/crashpad/client/crash_report_database.h"
33 #include "third_party/crashpad/crashpad/client/crashpad_client.h" 29 #include "third_party/crashpad/crashpad/client/crashpad_client.h"
34 #include "third_party/crashpad/crashpad/client/crashpad_info.h" 30 #include "third_party/crashpad/crashpad/client/crashpad_info.h"
35 #include "third_party/crashpad/crashpad/client/settings.h" 31 #include "third_party/crashpad/crashpad/client/settings.h"
36 #include "third_party/crashpad/crashpad/client/simple_string_dictionary.h" 32 #include "third_party/crashpad/crashpad/client/simple_string_dictionary.h"
37 #include "third_party/crashpad/crashpad/client/simulate_crash.h" 33 #include "third_party/crashpad/crashpad/client/simulate_crash.h"
38 34
39 #if defined(OS_POSIX) 35 #if defined(OS_POSIX)
40 #include <unistd.h> 36 #include <unistd.h>
41 #endif // OS_POSIX 37 #endif // OS_POSIX
42 38
43 #if BUILDFLAG(ENABLE_KASKO)
44 #include "base/win/scoped_handle.h"
45 #include "third_party/crashpad/crashpad/snapshot/api/module_annotations_win.h"
46 #endif
47
48 namespace crash_reporter { 39 namespace crash_reporter {
49 40
50 namespace { 41 namespace {
51 42
52 crashpad::SimpleStringDictionary* g_simple_string_dictionary; 43 crashpad::SimpleStringDictionary* g_simple_string_dictionary;
53 crashpad::CrashReportDatabase* g_database; 44 crashpad::CrashReportDatabase* g_database;
54 45
55 void SetCrashKeyValue(const base::StringPiece& key, 46 void SetCrashKeyValue(const base::StringPiece& key,
56 const base::StringPiece& value) { 47 const base::StringPiece& value) {
57 g_simple_string_dictionary->SetKeyValue(key.data(), value.data()); 48 g_simple_string_dictionary->SetKeyValue(key.data(), value.data());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 87
97 // Rather than including the code to force the crash here, allow the caller to 88 // Rather than including the code to force the crash here, allow the caller to
98 // do it. 89 // do it.
99 return false; 90 return false;
100 } 91 }
101 92
102 void DumpWithoutCrashing() { 93 void DumpWithoutCrashing() {
103 CRASHPAD_SIMULATE_CRASH(); 94 CRASHPAD_SIMULATE_CRASH();
104 } 95 }
105 96
106 #if BUILDFLAG(ENABLE_KASKO)
107 // TODO(ananta)
108 // We cannot depend on functionality in base which pulls in dependencies on
109 // user32 directly or indirectly. The GetLoadedModulesSnapshot is a copy of the
110 // function in base/win/win_util.cc. Depending on the base function pulls in
111 // dependencies on user32 due to other functionality in win_util.cc. This
112 // function should be removed when KASKO is removed.
113 bool GetLoadedModulesSnapshot(HANDLE process, std::vector<HMODULE>* snapshot) {
114 DCHECK(snapshot);
115 DCHECK_EQ(0u, snapshot->size());
116 snapshot->resize(128);
117
118 // We will retry at least once after first determining |bytes_required|. If
119 // the list of modules changes after we receive |bytes_required| we may retry
120 // more than once.
121 int retries_remaining = 5;
122 do {
123 DWORD bytes_required = 0;
124 // EnumProcessModules returns 'success' even if the buffer size is too
125 // small.
126 DCHECK_GE(std::numeric_limits<DWORD>::max(),
127 snapshot->size() * sizeof(HMODULE));
128 if (!::EnumProcessModules(
129 process, &(*snapshot)[0],
130 static_cast<DWORD>(snapshot->size() * sizeof(HMODULE)),
131 &bytes_required)) {
132 DPLOG(ERROR) << "::EnumProcessModules failed.";
133 return false;
134 }
135 DCHECK_EQ(0u, bytes_required % sizeof(HMODULE));
136 size_t num_modules = bytes_required / sizeof(HMODULE);
137 if (num_modules <= snapshot->size()) {
138 // Buffer size was too big, presumably because a module was unloaded.
139 snapshot->erase(snapshot->begin() + num_modules, snapshot->end());
140 return true;
141 } else if (num_modules == 0) {
142 DLOG(ERROR) << "Can't determine the module list size.";
143 return false;
144 } else {
145 // Buffer size was too small. Try again with a larger buffer. A little
146 // more room is given to avoid multiple expensive calls to
147 // ::EnumProcessModules() just because one module has been added.
148 snapshot->resize(num_modules + 8, NULL);
149 }
150 } while (--retries_remaining);
151
152 DLOG(ERROR) << "Failed to enumerate modules.";
153 return false;
154 }
155
156 HMODULE GetModuleInProcess(base::ProcessHandle process,
157 const wchar_t* module_name) {
158 std::vector<HMODULE> modules_snapshot;
159 if (!GetLoadedModulesSnapshot(process, &modules_snapshot))
160 return nullptr;
161
162 for (HMODULE module : modules_snapshot) {
163 wchar_t current_module_name[MAX_PATH];
164 if (!::GetModuleBaseName(process, module, current_module_name, MAX_PATH))
165 continue;
166
167 if (std::wcscmp(module_name, current_module_name) == 0)
168 return module;
169 }
170 return nullptr;
171 }
172 #endif // BUILDFLAG(ENABLE_KASKO)
173
174 void InitializeCrashpadImpl(bool initial_client, 97 void InitializeCrashpadImpl(bool initial_client,
175 const std::string& process_type, 98 const std::string& process_type,
176 bool embedded_handler) { 99 bool embedded_handler) {
177 static bool initialized = false; 100 static bool initialized = false;
178 DCHECK(!initialized); 101 DCHECK(!initialized);
179 initialized = true; 102 initialized = true;
180 103
181 const bool browser_process = process_type.empty(); 104 const bool browser_process = process_type.empty();
182 CrashReporterClient* crash_reporter_client = GetCrashReporterClient(); 105 CrashReporterClient* crash_reporter_client = GetCrashReporterClient();
183 106
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 report.state = ReportUploadState::Pending; 279 report.state = ReportUploadState::Pending;
357 reports->push_back(report); 280 reports->push_back(report);
358 } 281 }
359 282
360 std::sort(reports->begin(), reports->end(), 283 std::sort(reports->begin(), reports->end(),
361 [](const Report& a, const Report& b) { 284 [](const Report& a, const Report& b) {
362 return a.capture_time > b.capture_time; 285 return a.capture_time > b.capture_time;
363 }); 286 });
364 } 287 }
365 288
366 #if BUILDFLAG(ENABLE_KASKO)
367
368 void GetCrashKeysForKasko(std::vector<kasko::api::CrashKey>* crash_keys) {
369 // Get the platform annotations.
370 std::map<std::string, std::string> annotations;
371 internal::GetPlatformCrashpadAnnotations(&annotations);
372
373 // Reserve room for the GUID and the platform annotations.
374 crash_keys->clear();
375 crash_keys->reserve(
376 g_simple_string_dictionary->GetCount() + 1 + annotations.size());
377
378 // Set the Crashpad client ID in the crash keys.
379 bool got_guid = false;
380 if (g_database) {
381 crashpad::Settings* settings = g_database->GetSettings();
382 crashpad::UUID uuid;
383 if (settings->GetClientID(&uuid)) {
384 kasko::api::CrashKey kv;
385 wcsncpy_s(kv.name, L"guid", _TRUNCATE);
386 wcsncpy_s(kv.value, base::UTF8ToWide(uuid.ToString()).c_str(), _TRUNCATE);
387 crash_keys->push_back(kv);
388 got_guid = true;
389 }
390 }
391
392 crashpad::SimpleStringDictionary::Iterator iter(*g_simple_string_dictionary);
393 for (;;) {
394 const auto* entry = iter.Next();
395 if (!entry)
396 break;
397
398 // Skip the 'guid' key if it was already set.
399 static const char kGuid[] = "guid";
400 if (got_guid && ::strncmp(entry->key, kGuid, arraysize(kGuid)) == 0)
401 continue;
402
403 // Skip any platform annotations as they'll be set below.
404 if (annotations.count(entry->key))
405 continue;
406
407 kasko::api::CrashKey kv;
408 wcsncpy_s(kv.name, base::UTF8ToWide(entry->key).c_str(), _TRUNCATE);
409 wcsncpy_s(kv.value, base::UTF8ToWide(entry->value).c_str(), _TRUNCATE);
410 crash_keys->push_back(kv);
411 }
412
413 // Merge in the platform annotations.
414 for (const auto& entry : annotations) {
415 kasko::api::CrashKey kv;
416 wcsncpy_s(kv.name, base::UTF8ToWide(entry.first).c_str(), _TRUNCATE);
417 wcsncpy_s(kv.value, base::UTF8ToWide(entry.second).c_str(), _TRUNCATE);
418 crash_keys->push_back(kv);
419 }
420 }
421
422 void ReadMainModuleAnnotationsForKasko(
423 const base::Process& process,
424 std::vector<kasko::api::CrashKey>* crash_keys) {
425 // Reopen process with necessary access.
426 base::win::ScopedHandle process_handle(::OpenProcess(
427 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process.Pid()));
428 if (!process_handle.IsValid())
429 return;
430
431 // The executable name is the same for the browser process and the crash
432 // reporter.
433 wchar_t exe_file[MAX_PATH] = {};
434 CHECK(::GetModuleFileName(nullptr, exe_file, arraysize(exe_file)));
435
436 base::FilePath exe_path(exe_file);
437
438 HMODULE module = GetModuleInProcess(process_handle.Get(),
439 exe_path.BaseName().value().c_str());
440 if (!module)
441 return;
442
443 std::map<std::string, std::string> annotations;
444 crashpad::ReadModuleAnnotations(process_handle.Get(), module, &annotations);
445
446 // Append the annotations to the crash keys.
447 for (const auto& entry : annotations) {
448 kasko::api::CrashKey kv;
449 wcsncpy_s(kv.name, base::UTF8ToWide(entry.first).c_str(), _TRUNCATE);
450 wcsncpy_s(kv.value, base::UTF8ToWide(entry.second).c_str(), _TRUNCATE);
451 crash_keys->push_back(kv);
452 }
453 }
454
455 #endif // BUILDFLAG(ENABLE_KASKO)
456
457 } // namespace crash_reporter 289 } // namespace crash_reporter
458 290
459 #if defined(OS_WIN) 291 #if defined(OS_WIN)
460 292
461 extern "C" { 293 extern "C" {
462 294
463 // NOTE: This function is used by SyzyASAN to annotate crash reports. If you 295 // NOTE: This function is used by SyzyASAN to annotate crash reports. If you
464 // change the name or signature of this function you will break SyzyASAN 296 // change the name or signature of this function you will break SyzyASAN
465 // instrumented releases of Chrome. Please contact syzygy-team@chromium.org 297 // instrumented releases of Chrome. Please contact syzygy-team@chromium.org
466 // before doing so! See also http://crbug.com/567781. 298 // before doing so! See also http://crbug.com/567781.
467 void __declspec(dllexport) __cdecl SetCrashKeyValueImpl(const wchar_t* key, 299 void __declspec(dllexport) __cdecl SetCrashKeyValueImpl(const wchar_t* key,
468 const wchar_t* value) { 300 const wchar_t* value) {
469 crash_reporter::SetCrashKeyValue(base::UTF16ToUTF8(key), 301 crash_reporter::SetCrashKeyValue(base::UTF16ToUTF8(key),
470 base::UTF16ToUTF8(value)); 302 base::UTF16ToUTF8(value));
471 } 303 }
472 304
473 void __declspec(dllexport) __cdecl ClearCrashKeyValueImpl(const wchar_t* key) { 305 void __declspec(dllexport) __cdecl ClearCrashKeyValueImpl(const wchar_t* key) {
474 crash_reporter::ClearCrashKey(base::UTF16ToUTF8(key)); 306 crash_reporter::ClearCrashKey(base::UTF16ToUTF8(key));
475 } 307 }
476 308
477 } // extern "C" 309 } // extern "C"
478 310
479 #endif // OS_WIN 311 #endif // OS_WIN
OLDNEW
« chrome/BUILD.gn ('K') | « components/crash/content/app/crashpad.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698