diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-09-29 16:16:15 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-11-09 10:04:06 +0000 |
commit | a95a7417ad456115a1ef2da4bb8320531c0821f1 (patch) | |
tree | edcd59279e486d2fd4a8f88a7ed025bcf925c6e6 /chromium/components/crash | |
parent | 33fc33aa94d4add0878ec30dc818e34e1dd3cc2a (diff) | |
download | qtwebengine-chromium-a95a7417ad456115a1ef2da4bb8320531c0821f1.tar.gz |
BASELINE: Update Chromium to 106.0.5249.126
Change-Id: Ib0bb21c437a7d1686e21c33f2d329f2ac425b7ab
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/438936
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/crash')
29 files changed, 348 insertions, 97 deletions
diff --git a/chromium/components/crash/android/BUILD.gn b/chromium/components/crash/android/BUILD.gn index 63a0d916db9..4a4c539d61e 100644 --- a/chromium/components/crash/android/BUILD.gn +++ b/chromium/components/crash/android/BUILD.gn @@ -39,25 +39,10 @@ android_library("java") { sources += _jni_sources } -android_library("javatests") { - testonly = true - sources = [ "javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java" ] - deps = [ - ":java", - "//base:base_java_test_support", - "//components/minidump_uploader:minidump_uploader_java_test_support", - "//content/public/test/android:content_java_test_support", - "//third_party/androidx:androidx_test_runner_java", - "//third_party/junit", - ] -} - -java_library("junit") { - # Skip platform checks since Robolectric depends on requires_android targets. - bypass_platform_checks = true - testonly = true +robolectric_library("junit") { sources = [ "junit/src/org/chromium/components/crash/LogcatCrashExtractorTest.java", + "junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java", "junit/src/org/chromium/components/crash/anr/AnrCollectorTest.java", ] deps = [ @@ -66,7 +51,9 @@ java_library("junit") { ":java", "//base:base_java_test_support", "//base:base_junit_test_support", - "//third_party/android_deps:robolectric_all_java", + "//components/minidump_uploader:minidump_uploader_java_test_support", + "//content/public/test/android:content_java_test_support", + "//third_party/androidx:androidx_test_runner_java", "//third_party/junit", ] } diff --git a/chromium/components/crash/android/crash_keys_android.cc b/chromium/components/crash/android/crash_keys_android.cc index ad3c01dab93..5ce5f929f0d 100644 --- a/chromium/components/crash/android/crash_keys_android.cc +++ b/chromium/components/crash/android/crash_keys_android.cc @@ -23,6 +23,7 @@ JavaCrashKey& GetCrashKey(int index) { {"emulated_modules", JavaCrashKey::Tag::kArray}, {"dynamic_module_dex_name", JavaCrashKey::Tag::kArray}, {"partner_customization_config", JavaCrashKey::Tag::kArray}, + {"first_run", JavaCrashKey::Tag::kArray}, }; static_assert( std::size(crash_keys) == static_cast<size_t>(CrashKeyIndex::NUM_ENTRIES), diff --git a/chromium/components/crash/android/crash_keys_android.h b/chromium/components/crash/android/crash_keys_android.h index 5936ba09809..25ae526065b 100644 --- a/chromium/components/crash/android/crash_keys_android.h +++ b/chromium/components/crash/android/crash_keys_android.h @@ -18,6 +18,7 @@ enum class CrashKeyIndex { EMULATED_MODULES, DYNAMIC_MODULE_DEX_NAME, PARTNER_CUSTOMIZATION_CONFIG, + FIRST_RUN, NUM_ENTRIES }; diff --git a/chromium/components/crash/android/javatests/src/org/chromium/components/crash/DEPS b/chromium/components/crash/android/junit/src/org/chromium/components/crash/DEPS index 877e2a4da34..aa935913119 100644 --- a/chromium/components/crash/android/javatests/src/org/chromium/components/crash/DEPS +++ b/chromium/components/crash/android/junit/src/org/chromium/components/crash/DEPS @@ -1,3 +1,3 @@ include_rules = [ "+content/public/test/android", -]
\ No newline at end of file +] diff --git a/chromium/components/crash/android/javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java b/chromium/components/crash/android/junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java index 5bff2770b06..30c5349ab9d 100644 --- a/chromium/components/crash/android/javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java +++ b/chromium/components/crash/android/junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java @@ -11,7 +11,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.Batch; import org.chromium.components.minidump_uploader.CrashTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -23,7 +24,8 @@ import java.io.IOException; /** * Unittests for {@link PureJavaExceptionReporter}. */ -@RunWith(BaseJUnit4ClassRunner.class) +@RunWith(BaseRobolectricTestRunner.class) +@Batch(Batch.UNIT_TESTS) public class PureJavaExceptionReporterTest { @Rule public CrashTestRule mTestRule = new CrashTestRule(); @@ -33,7 +35,7 @@ public class PureJavaExceptionReporterTest { private File mMinidump; public TestPureJavaExceptionReporter() { - super(mTestRule.getCacheDir()); + super(mTestRule.getCacheDir(), /*attachLogcat=*/true); } @Override diff --git a/chromium/components/crash/content/browser/crash_metrics_reporter_android.cc b/chromium/components/crash/content/browser/crash_metrics_reporter_android.cc index e4363f6e8f7..6c1a57b80c8 100644 --- a/chromium/components/crash/content/browser/crash_metrics_reporter_android.cc +++ b/chromium/components/crash/content/browser/crash_metrics_reporter_android.cc @@ -201,16 +201,29 @@ void CrashMetricsReporter::ChildProcessExited( &reported_counts); } break; - case base::android::ChildBindingState::MODERATE: + case base::android::ChildBindingState::VISIBLE: if (intentional_kill || info.normal_termination) { ReportCrashCount( ProcessedCrashCounts:: - kRendererForegroundInvisibleWithModerateBindingKilled, + kRendererForegroundInvisibleWithVisibleBindingKilled, &reported_counts); } else { ReportCrashCount( ProcessedCrashCounts:: - kRendererForegroundInvisibleWithModerateBindingOom, + kRendererForegroundInvisibleWithVisibleBindingOom, + &reported_counts); + } + break; + case base::android::ChildBindingState::NOT_PERCEPTIBLE: + if (intentional_kill || info.normal_termination) { + ReportCrashCount( + ProcessedCrashCounts:: + kRendererForegroundInvisibleWithNotPerceptibleBindingKilled, + &reported_counts); + } else { + ReportCrashCount( + ProcessedCrashCounts:: + kRendererForegroundInvisibleWithNotPerceptibleBindingOom, &reported_counts); } break; diff --git a/chromium/components/crash/content/browser/crash_metrics_reporter_android.h b/chromium/components/crash/content/browser/crash_metrics_reporter_android.h index 271ac34adae..7b0f686d7ce 100644 --- a/chromium/components/crash/content/browser/crash_metrics_reporter_android.h +++ b/chromium/components/crash/content/browser/crash_metrics_reporter_android.h @@ -51,7 +51,11 @@ class CrashMetricsReporter { kUtilityForegroundOom = 17, kUtilityCrashAll = 18, kRendererProcessHostShutdown = 19, - kMaxValue = kRendererProcessHostShutdown + kRendererForegroundInvisibleWithVisibleBindingKilled = 20, + kRendererForegroundInvisibleWithVisibleBindingOom = 21, + kRendererForegroundInvisibleWithNotPerceptibleBindingKilled = 22, + kRendererForegroundInvisibleWithNotPerceptibleBindingOom = 23, + kMaxValue = kRendererForegroundInvisibleWithNotPerceptibleBindingOom }; using ReportedCrashTypeSet = base::flat_set<ProcessedCrashCounts>; diff --git a/chromium/components/crash/core/app/BUILD.gn b/chromium/components/crash/core/app/BUILD.gn index 7a5e5244cfd..82e765a019f 100644 --- a/chromium/components/crash/core/app/BUILD.gn +++ b/chromium/components/crash/core/app/BUILD.gn @@ -56,6 +56,7 @@ static_library("app") { sources += [ "breakpad_linux.cc", "breakpad_linux.h", + "breakpad_linux_impl.cc", "breakpad_linux_impl.h", "crashpad_linux.cc", ] @@ -68,13 +69,17 @@ static_library("app") { "//base", "//build:branding_buildflags", "//build:chromeos_buildflags", + "//components/crash/core/common:crash_key_lib", "//content/public/common:content_descriptors", "//third_party/crashpad/crashpad/client", "//third_party/crashpad/crashpad/util", ] if (is_ios) { - deps -= [ "//content/public/common:content_descriptors" ] + deps -= [ + "//components/crash/core/common:crash_key_lib", + "//content/public/common:content_descriptors", + ] } if (is_android) { @@ -287,6 +292,7 @@ source_set("unit_tests") { ] deps += [ ":run_as_crashpad_handler", + "//components/crash/win:unit_tests", "//third_party/breakpad:client", "//third_party/crashpad/crashpad/client:client", "//third_party/crashpad/crashpad/snapshot:snapshot", diff --git a/chromium/components/crash/core/app/DEPS b/chromium/components/crash/core/app/DEPS index 2a92793b04c..9717215396c 100644 --- a/chromium/components/crash/core/app/DEPS +++ b/chromium/components/crash/core/app/DEPS @@ -7,6 +7,7 @@ include_rules = [ "+components/gwp_asan/buildflags/buildflags.h", "+components/gwp_asan/crash_handler/crash_handler.h", "+content/public/common/content_descriptors.h", + "+third_party/abseil-cpp/absl/base/internal/raw_logging.h", "+third_party/crashpad", "+third_party/lss/linux_syscall_support.h", ] diff --git a/chromium/components/crash/core/app/breakpad_linux.cc b/chromium/components/crash/core/app/breakpad_linux.cc index 3c28019ae3d..6aa864db880 100644 --- a/chromium/components/crash/core/app/breakpad_linux.cc +++ b/chromium/components/crash/core/app/breakpad_linux.cc @@ -706,7 +706,7 @@ bool CrashDone(const MinidumpDescriptor& minidump, DCHECK(!(upload && minidump.IsFD())); - BreakpadInfo info = {0}; + BreakpadInfo info; info.filename = minidump.path(); info.fd = minidump.fd(); #if defined(ADDRESS_SANITIZER) diff --git a/chromium/components/crash/core/app/breakpad_linux_impl.cc b/chromium/components/crash/core/app/breakpad_linux_impl.cc new file mode 100644 index 00000000000..2f138d5e10e --- /dev/null +++ b/chromium/components/crash/core/app/breakpad_linux_impl.cc @@ -0,0 +1,11 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/crash/core/app/breakpad_linux_impl.h" + +namespace breakpad { + +BreakpadInfo::BreakpadInfo() {} + +} // namespace breakpad diff --git a/chromium/components/crash/core/app/breakpad_linux_impl.h b/chromium/components/crash/core/app/breakpad_linux_impl.h index ee75a02082f..83a9e2b4975 100644 --- a/chromium/components/crash/core/app/breakpad_linux_impl.h +++ b/chromium/components/crash/core/app/breakpad_linux_impl.h @@ -12,6 +12,7 @@ #include <stdint.h> #include <sys/types.h> +#include "base/memory/raw_ptr.h" #include "components/crash/core/app/breakpad_linux.h" #include "components/crash/core/common/crash_key_internal.h" @@ -38,7 +39,9 @@ const size_t kCrashIovSize = 7; // The minidump information can either be contained in a file descriptor (fd) or // in a file (whose path is in filename). struct BreakpadInfo { - int fd; // File descriptor to the Breakpad dump data. + BreakpadInfo(); + + int fd = 0; // File descriptor to the Breakpad dump data. const char* filename; // Path to the Breakpad dump data. #if defined(ADDRESS_SANITIZER) const char* log_filename; // Path to the ASan log file. @@ -53,7 +56,7 @@ struct BreakpadInfo { uint64_t process_start_time; // Uptime of the crashing process. size_t oom_size; // Amount of memory requested if OOM. uint64_t pid; // PID where applicable. - crash_reporter::internal::TransitionalCrashKeyStorage* crash_keys; + raw_ptr<crash_reporter::internal::TransitionalCrashKeyStorage> crash_keys; }; extern void HandleCrashDump(const BreakpadInfo& info); diff --git a/chromium/components/crash/core/app/crash_reporter_client.cc b/chromium/components/crash/core/app/crash_reporter_client.cc index 82b7f241e26..463f92a6e54 100644 --- a/chromium/components/crash/core/app/crash_reporter_client.cc +++ b/chromium/components/crash/core/app/crash_reporter_client.cc @@ -81,7 +81,11 @@ bool CrashReporterClient::GetIsPerUserInstall() { int CrashReporterClient::GetResultCodeRespawnFailed() { return 0; } -#endif + +std::wstring CrashReporterClient::GetWerRuntimeExceptionModule() { + return std::wstring(); +} +#endif // BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)) bool CrashReporterClient::GetShouldDumpLargerDumps() { diff --git a/chromium/components/crash/core/app/crash_reporter_client.h b/chromium/components/crash/core/app/crash_reporter_client.h index 24e53fa62c2..2532e99f00b 100644 --- a/chromium/components/crash/core/app/crash_reporter_client.h +++ b/chromium/components/crash/core/app/crash_reporter_client.h @@ -82,6 +82,11 @@ class CrashReporterClient { // Returns the result code to return when breakpad failed to respawn a // crashed process. virtual int GetResultCodeRespawnFailed(); + + // Returns the fully-qualified path for a registered out of process exception + // helper module. The module is optional. Return an empty string to indicate + // that no module should be registered. + virtual std::wstring GetWerRuntimeExceptionModule(); #endif #if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)) diff --git a/chromium/components/crash/core/app/crashpad.cc b/chromium/components/crash/core/app/crashpad.cc index 9058d56e8bd..8c0ae200194 100644 --- a/chromium/components/crash/core/app/crashpad.cc +++ b/chromium/components/crash/core/app/crashpad.cc @@ -28,6 +28,7 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "components/crash/core/app/crash_reporter_client.h" +#include "third_party/abseil-cpp/absl/base/internal/raw_logging.h" #include "third_party/crashpad/crashpad/client/annotation.h" #include "third_party/crashpad/crashpad/client/annotation_list.h" #include "third_party/crashpad/crashpad/client/crash_report_database.h" @@ -44,53 +45,29 @@ #include "components/crash/core/app/crash_export_thunks.h" #endif +#if !BUILDFLAG(IS_IOS) +#include "components/crash/core/common/crash_key.h" // nogncheck +#endif + namespace crash_reporter { namespace { +void AbslAbortHook(const char* file, + int line, + const char* buf_start, + const char* prefix_end, + const char* buf_end) { + // This simulates that a CHECK(false) was done at file:line instead of here. + // This is used instead of IMMEDIATE_CRASH() to give better error messages + // locally (printed stack for one). + logging::CheckError::Check(file, line, "false").stream() << prefix_end; +} + base::FilePath* g_database_path; crashpad::CrashReportDatabase* g_database; -bool LogMessageHandler(int severity, - const char* file, - int line, - size_t message_start, - const std::string& string) { - // Only handle FATAL. - if (severity != logging::LOG_FATAL) { - return false; - } - - // In case of an out-of-memory condition, this code could be reentered when - // constructing and storing the key. Using a static is not thread-safe, but if - // multiple threads are in the process of a fatal crash at the same time, this - // should work. - static bool guarded = false; - if (guarded) { - return false; - } - base::AutoReset<bool> guard(&guarded, true); - - // Only log last path component. This matches logging.cc. - if (file) { - const char* slash = strrchr(file, '/'); - if (slash) { - file = slash + 1; - } - } - - CHECK_LE(message_start, string.size()); - std::string message = base::StringPrintf("%s:%d: %s", file, line, - string.c_str() + message_start); - static crashpad::StringAnnotation<512> crash_key("LOG_FATAL"); - crash_key.Set(message); - - // Rather than including the code to force the crash here, allow the caller to - // do it. - return false; -} - void InitializeDatabasePath(const base::FilePath& database_path) { DCHECK(!g_database_path); @@ -160,7 +137,16 @@ bool InitializeCrashpadImpl(bool initial_client, } #endif // BUILDFLAG(IS_APPLE) +// TODO(pbos): Remove this exception for iOS once it's 100% on Crashpad and +// depending on //components/crash/core/common:crash_key_lib does not cause a +// forbidden dependency through crash_key_breakpad_ios.mm depending on +// //components/previous_session_info. As of writing this //base crash keys are +// set up in //ios/chrome/browser/crash_report/crash_helper.mm. +#if BUILDFLAG(IS_IOS) crashpad::AnnotationList::Register(); +#else + InitializeCrashKeys(); +#endif // BUILDFLAG(IS_IOS) #if !BUILDFLAG(IS_IOS) static crashpad::StringAnnotation<24> ptype_key("ptype"); @@ -182,8 +168,6 @@ bool InitializeCrashpadImpl(bool initial_client, platform.Set(base::SysInfo::HardwareModelName()); #endif // !BUILDFLAG(IS_IOS) - logging::SetLogMessageHandler(LogMessageHandler); - // If clients called CRASHPAD_SIMULATE_CRASH() instead of // base::debug::DumpWithoutCrashing(), these dumps would appear as crashes in // the correct function, at the correct file and line. This would be @@ -191,6 +175,12 @@ bool InitializeCrashpadImpl(bool initial_client, // the same file and line. base::debug::SetDumpWithoutCrashingFunction(DumpWithoutCrashing); + // TODO(pbos): Update this to not rely on a _internal namespace once there's + // a public API in absl::. + // Note: If this fails to compile because of an absl roll, this is fair to + // remove if you file a crbug.com/new and assign it to pbos@. + absl::raw_log_internal::RegisterAbortHook(&AbslAbortHook); + #if BUILDFLAG(IS_APPLE) // On Mac, we only want the browser to initialize the database, but not the // relauncher. diff --git a/chromium/components/crash/core/app/crashpad_linux.cc b/chromium/components/crash/core/app/crashpad_linux.cc index 39fb479eba5..a80a792f1cb 100644 --- a/chromium/components/crash/core/app/crashpad_linux.cc +++ b/chromium/components/crash/core/app/crashpad_linux.cc @@ -191,11 +191,8 @@ bool PlatformCrashpadInitialization( } #endif - bool result = - client.StartHandler(handler_path, *database_path, metrics_path, url, - annotations, arguments, false, false); - DCHECK(result); - + CHECK(client.StartHandler(handler_path, *database_path, metrics_path, url, + annotations, arguments, false, false)); } else { int fd = base::GlobalDescriptors::GetInstance()->Get(kCrashDumpSignal); @@ -216,12 +213,16 @@ bool PlatformCrashpadInitialization( *database_path = base::FilePath(); } - if (crash_reporter_client->GetShouldDumpLargerDumps()) { - const uint32_t kIndirectMemoryLimit = 4 * 1024 * 1024; - crashpad::CrashpadInfo::GetCrashpadInfo() - ->set_gather_indirectly_referenced_memory(crashpad::TriState::kEnabled, - kIndirectMemoryLimit); - } + // In the not-large-dumps case record enough extra memory to be able to save + // dereferenced memory from all registers on the crashing thread. crashpad may + // save 512-bytes per register, and the largest register set (not including + // stack pointers) is ARM64 with 32 registers. Hence, 16 KiB. + const uint32_t kIndirectMemoryLimit = + crash_reporter_client->GetShouldDumpLargerDumps() ? 4 * 1024 * 1024 + : 16 * 1024; + crashpad::CrashpadInfo::GetCrashpadInfo() + ->set_gather_indirectly_referenced_memory(crashpad::TriState::kEnabled, + kIndirectMemoryLimit); return true; } diff --git a/chromium/components/crash/core/app/crashpad_win.cc b/chromium/components/crash/core/app/crashpad_win.cc index 80f33dc5e2f..ae8801a7fc8 100644 --- a/chromium/components/crash/core/app/crashpad_win.cc +++ b/chromium/components/crash/core/app/crashpad_win.cc @@ -15,6 +15,7 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/win/windows_version.h" #include "build/branding_buildflags.h" #include "build/build_config.h" #include "components/crash/core/app/crash_export_thunks.h" @@ -164,13 +165,25 @@ bool PlatformCrashpadInitialization( if (!initialized) return false; - if (crash_reporter_client->GetShouldDumpLargerDumps()) { - const uint32_t kIndirectMemoryLimit = 4 * 1024 * 1024; - crashpad::CrashpadInfo::GetCrashpadInfo() - ->set_gather_indirectly_referenced_memory(crashpad::TriState::kEnabled, - kIndirectMemoryLimit); + // Regester WER helper only if it will produce useful information - prior to + // 20H1 the crashes it can help with did not make their way to the helper. + if (base::win::GetVersion() >= base::win::Version::WIN10_20H1) { + auto path = crash_reporter_client->GetWerRuntimeExceptionModule(); + if (!path.empty()) + GetCrashpadClient().RegisterWerModule(path); } + // In the not-large-dumps case record enough extra memory to be able to save + // dereferenced memory from all registers on the crashing thread. crashpad may + // save 512-bytes per register, and the largest register set (not including + // stack pointers) is ARM64 with 32 registers. Hence, 16 KiB. + const uint32_t kIndirectMemoryLimit = + crash_reporter_client->GetShouldDumpLargerDumps() ? 4 * 1024 * 1024 + : 16 * 1024; + crashpad::CrashpadInfo::GetCrashpadInfo() + ->set_gather_indirectly_referenced_memory(crashpad::TriState::kEnabled, + kIndirectMemoryLimit); + return true; } diff --git a/chromium/components/crash/core/browser/resources/crashes.js b/chromium/components/crash/core/browser/resources/crashes.js index 2ee88479245..fe07f128f1b 100644 --- a/chromium/components/crash/core/browser/resources/crashes.js +++ b/chromium/components/crash/core/browser/resources/crashes.js @@ -40,7 +40,7 @@ function updateCrashList({ crashes, version, os, - isGoogleAccount + isGoogleAccount, }) { $('crashesCount').textContent = loadTimeData.getStringF( 'crashCountFormat', crashes.length.toLocaleString()); @@ -154,8 +154,8 @@ function updateCrashList({ function fileBug(crashId, os, version) { const commentLines = [ 'IMPORTANT: Your crash has already been automatically reported ' + - 'to our crash system. Please file this bug only if you can provide ' + - 'more information about it.', + 'to our crash system. Please file this bug only if you can provide ' + + 'more information about it.', '', '', 'Chrome Version: ' + version, @@ -166,11 +166,13 @@ function fileBug(crashId, os, version) { 'Can you reproduce this crash?', '', 'What steps will reproduce this crash? (If it\'s not ' + - 'reproducible, what were you doing just before the crash?)', - '1.', '2.', '3.', + 'reproducible, what were you doing just before the crash?)', + '1.', + '2.', + '3.', '', '****DO NOT CHANGE BELOW THIS LINE****', - 'Crash ID: crash/' + crashId + 'Crash ID: crash/' + crashId, ]; const params = { template: 'Crash Report', diff --git a/chromium/components/crash/core/common/BUILD.gn b/chromium/components/crash/core/common/BUILD.gn index 81460a6cd79..d7ff8a1d414 100644 --- a/chromium/components/crash/core/common/BUILD.gn +++ b/chromium/components/crash/core/common/BUILD.gn @@ -33,8 +33,8 @@ use_crashpad_annotation = # implementations will be instantiated and set, doubling the storage # used for keys. This is intended to be used temporarily to test Crashpad # integrations without disabling Breakpad. -use_combined_annotations = - (is_ios && !is_cronet_build) || is_linux || is_chromeos +use_combined_annotations = ((is_ios && !is_cronet_build) || is_linux || + is_chromeos) && !use_crash_key_stubs buildflag_header("crash_buildflags") { header = "crash_buildflags.h" diff --git a/chromium/components/crash/core/common/crash_key.h b/chromium/components/crash/core/common/crash_key.h index c0771b00922..bf88c1180ee 100644 --- a/chromium/components/crash/core/common/crash_key.h +++ b/chromium/components/crash/core/common/crash_key.h @@ -288,7 +288,9 @@ void SetCrashKeyStringToStackTrace(CrashKeyString<Size>* key, key->Set(trace_string); } -// Initializes the crash key subsystem if it is required. +// Initializes the crash key subsystem if it is required. Calling this multiple +// times is safe (though not thread-safe) and will not result in data loss from +// crash keys set prior to the last initialization. CRASH_KEY_EXPORT void InitializeCrashKeys(); #if defined(UNIT_TEST) || defined(CRASH_CORE_COMMON_IMPLEMENTATION) diff --git a/chromium/components/crash/core/common/crash_key_base_support.cc b/chromium/components/crash/core/common/crash_key_base_support.cc index cd563b9fdda..2c744456a3a 100644 --- a/chromium/components/crash/core/common/crash_key_base_support.cc +++ b/chromium/components/crash/core/common/crash_key_base_support.cc @@ -42,6 +42,9 @@ struct BaseCrashKeyString : public base::debug::CrashKeyString { case base::debug::CrashKeySize::Size256: \ operation_prefix BaseCrashKeyString<256> operation_suffix; \ break; \ + case base::debug::CrashKeySize::Size1024: \ + operation_prefix BaseCrashKeyString<1024> operation_suffix; \ + break; \ } class CrashKeyBaseSupport : public base::debug::CrashKeyImplementation { diff --git a/chromium/components/crash/win/BUILD.gn b/chromium/components/crash/win/BUILD.gn new file mode 100644 index 00000000000..37f387ac09c --- /dev/null +++ b/chromium/components/crash/win/BUILD.gn @@ -0,0 +1,43 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/compiler/compiler.gni") +import("//build/config/win/manifest.gni") +import("//chrome/process_version_rc_template.gni") +import("//testing/test.gni") + +assert(is_win) + +process_version_rc_template("chrome_wer_resources") { + sources = [ "chrome_wer.ver" ] + output = "$target_gen_dir/chrome_wer_version.rc" +} + +shared_library("chrome_wer") { + sources = [ + "chrome_wer.def", + "chrome_wer_main.cc", + ] + no_default_deps = true + deps = [ + ":chrome_wer_resources", + "//third_party/crashpad/crashpad/handler/win/wer:crashpad_wer_handler", + ] + + # Keep this a tiny dll as it does very little. + assert_no_deps = [ + "//third_party/abseil-cpp:absl", + "//third_party/perfetto:libperfetto", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ "chrome_wer_module_unittest.cc" ] + deps = [ + "//base:base", + "//testing/gtest", + ] + data_deps = [ ":chrome_wer" ] +} diff --git a/chromium/components/crash/win/DEPS b/chromium/components/crash/win/DEPS new file mode 100644 index 00000000000..f9cc0498c73 --- /dev/null +++ b/chromium/components/crash/win/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+third_party/crashpad/crashpad/handler/win/wer/crashpad_wer.h", +] diff --git a/chromium/components/crash/win/OWNERS b/chromium/components/crash/win/OWNERS new file mode 100644 index 00000000000..abc9de6eb1d --- /dev/null +++ b/chromium/components/crash/win/OWNERS @@ -0,0 +1,2 @@ +ajgo@chromium.org +jperaza@chromium.org diff --git a/chromium/components/crash/win/README.md b/chromium/components/crash/win/README.md new file mode 100644 index 00000000000..77abe578e9c --- /dev/null +++ b/chromium/components/crash/win/README.md @@ -0,0 +1,23 @@ +# chrome_wer - Runtime Exception Helper Module for Windows Error Reporting + +This builds a DLL which can be registered as a runtime exception helper using +[WerRegisterExceptionHelperModule](https://docs.microsoft.com/en-us/windows/win32/api/werapi/nf-werapi-werregisterruntimeexceptionmodule). + +It integrates tightly with crashpad's client (in chrome_elf) and the crashpad +handler process. It should be distributed alongside Chrome and is not intended +to work with a different Chrome version. + +Interesting exceptions find their way to the helper starting with Windows 20H1 +(19042). Prior versions did not attempt to load the helper. + +The full path to the DLL must be registered under: + +``` +{ HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE } + \Software + \Microsoft + \Windows + \Windows Error Reporting + \RuntimeExceptionHelperModules + Value:{full path to dll} DWORD:{ 0 - any value } + ``` diff --git a/chromium/components/crash/win/chrome_wer.def b/chromium/components/crash/win/chrome_wer.def new file mode 100644 index 00000000000..1983834e2bb --- /dev/null +++ b/chromium/components/crash/win/chrome_wer.def @@ -0,0 +1,10 @@ +; Copyright 2022 The Chromium Authors. All rights reserved. +; Use of this source code is governed by a BSD-style license that can be +; found in the LICENSE file. +LIBRARY "chrome_wer.dll" + +EXPORTS + ; These are required for the WER api. + OutOfProcessExceptionEventCallback + OutOfProcessExceptionEventSignatureCallback + OutOfProcessExceptionEventDebuggerLaunchCallback diff --git a/chromium/components/crash/win/chrome_wer.ver b/chromium/components/crash/win/chrome_wer.ver new file mode 100644 index 00000000000..58ad9b44cf7 --- /dev/null +++ b/chromium/components/crash/win/chrome_wer.ver @@ -0,0 +1,2 @@ +INTERNAL_NAME=chrome_wer_dll +ORIGINAL_FILENAME=chrome_wer.dll diff --git a/chromium/components/crash/win/chrome_wer_main.cc b/chromium/components/crash/win/chrome_wer_main.cc new file mode 100644 index 00000000000..135beb45bbc --- /dev/null +++ b/chromium/components/crash/win/chrome_wer_main.cc @@ -0,0 +1,63 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <Windows.h> + +// werapi.h must be after Windows.h +#include <werapi.h> + +#include "third_party/crashpad/crashpad/handler/win/wer/crashpad_wer.h" + +extern "C" { +BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { + return true; +} + +HRESULT OutOfProcessExceptionEventCallback( + PVOID pContext, + const PWER_RUNTIME_EXCEPTION_INFORMATION pExceptionInformation, + BOOL* pbOwnershipClaimed, + PWSTR pwszEventName, + PDWORD pchSize, + PDWORD pdwSignatureCount) { + // Exceptions that are not collected by crashpad's in-process handlers. + std::vector<DWORD> wanted_exceptions = { + 0xC0000409, // STATUS_STACK_BUFFER_OVERRUN + }; + bool result = crashpad::wer::ExceptionEvent(wanted_exceptions, pContext, + pExceptionInformation); + + if (result) { + *pbOwnershipClaimed = TRUE; + // Technically we failed as we terminated the process. + return E_FAIL; + } + // Could not dump for whatever reason, so let other helpers/wer have a chance. + *pbOwnershipClaimed = FALSE; + return S_OK; +} + +HRESULT OutOfProcessExceptionEventSignatureCallback( + PVOID pContext, + const PWER_RUNTIME_EXCEPTION_INFORMATION pExceptionInformation, + DWORD dwIndex, + PWSTR pwszName, + PDWORD pchName, + PWSTR pwszValue, + PDWORD pchValue) { + // This function should never be called. + return E_FAIL; +} + +HRESULT OutOfProcessExceptionEventDebuggerLaunchCallback( + PVOID pContext, + const PWER_RUNTIME_EXCEPTION_INFORMATION pExceptionInformation, + PBOOL pbIsCustomDebugger, + PWSTR pwszDebuggerLaunch, + PDWORD pchDebuggerLaunch, + PBOOL pbIsDebuggerAutolaunch) { + // This function should never be called. + return E_FAIL; +} +} // extern "C" diff --git a/chromium/components/crash/win/chrome_wer_module_unittest.cc b/chromium/components/crash/win/chrome_wer_module_unittest.cc new file mode 100644 index 00000000000..f22648f5dfd --- /dev/null +++ b/chromium/components/crash/win/chrome_wer_module_unittest.cc @@ -0,0 +1,56 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <Windows.h> +#include <werapi.h> + +#include "base/files/file_path.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace crash { +namespace test { +namespace { +base::FilePath ModulePath() { + return base::FilePath(FILE_PATH_LITERAL("chrome_wer.dll")); +} + +// Check that chrome_wer.dll has expected exports and loads. +// The module is usually loaded by WerFault.exe after a crash. +TEST(ChromeWerModule, ValidModule) { + // Module loads. + HMODULE hMod = LoadLibraryW(ModulePath().value().c_str()); + ASSERT_TRUE(hMod); + + // Required functions exist. + auto wref = reinterpret_cast<PFN_WER_RUNTIME_EXCEPTION_EVENT>( + GetProcAddress(hMod, WER_RUNTIME_EXCEPTION_EVENT_FUNCTION)); + ASSERT_TRUE(wref); + auto wrees = reinterpret_cast<PFN_WER_RUNTIME_EXCEPTION_EVENT_SIGNATURE>( + GetProcAddress(hMod, WER_RUNTIME_EXCEPTION_EVENT_SIGNATURE_FUNCTION)); + ASSERT_TRUE(wrees); + auto wredl = reinterpret_cast<PFN_WER_RUNTIME_EXCEPTION_DEBUGGER_LAUNCH>( + GetProcAddress(hMod, WER_RUNTIME_EXCEPTION_DEBUGGER_LAUNCH)); + ASSERT_TRUE(wredl); + + // Call each function to verify the calling convention. + // Not-implemented functions return E_FAIL as expected. + HRESULT res = wrees(nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr); + ASSERT_EQ(res, E_FAIL); + res = wredl(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); + ASSERT_EQ(res, E_FAIL); + + WER_RUNTIME_EXCEPTION_INFORMATION wer_ex; + BOOL claimed = TRUE; + + // No registration context => skip. + res = wref(nullptr, &wer_ex, &claimed, nullptr, nullptr, nullptr); + ASSERT_EQ(res, S_OK); + ASSERT_EQ(claimed, FALSE); + + FreeLibrary(hMod); +} + +} // namespace +} // namespace test +} // namespace crash |