1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
|
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_CRASH_CORE_APP_CRASHPAD_H_
#define COMPONENTS_CRASH_CORE_APP_CRASHPAD_H_
#include <time.h>
#include <map>
#include <optional>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#if BUILDFLAG(IS_APPLE)
#include "base/apple/scoped_mach_port.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/windows_types.h"
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include <signal.h>
#endif
#if BUILDFLAG(IS_IOS)
#include "base/containers/span.h"
#include "third_party/crashpad/crashpad/client/simple_address_range_bag.h"
#include "third_party/crashpad/crashpad/handler/user_stream_data_source.h" // nogncheck
#endif
namespace base {
class Time;
}
namespace crashpad {
class CrashpadClient;
class CrashReportDatabase;
} // namespace crashpad
namespace crash_reporter {
// Initializes Crashpad in a way that is appropriate for initial_client and
// process_type.
//
// If initial_client is true, this starts crashpad_handler and sets it as the
// exception handler. Child processes will inherit this exception handler, and
// should specify false for this parameter. Although they inherit the exception
// handler, child processes still need to call this function to perform
// additional initialization.
//
// If process_type is empty, initialization will be done for the browser
// process. The browser process performs additional initialization of the crash
// report database. The browser process is also the only process type that is
// eligible to have its crashes forwarded to the system crash report handler (in
// release mode only). Note that when process_type is empty, initial_client must
// be true.
//
// On Mac, process_type may be non-empty with initial_client set to true. This
// indicates that an exception handler has been inherited but should be
// discarded in favor of a new Crashpad handler. This configuration should be
// used infrequently. It is provided to allow an install-from-.dmg relauncher
// process to disassociate from an old Crashpad handler so that after performing
// an installation from a disk image, the relauncher process may unmount the
// disk image that contains its inherited crashpad_handler. This is only
// supported when initial_client is true and process_type is "relauncher".
//
// On Windows, use InitializeCrashpadWithEmbeddedHandler() when crashpad_handler
// is embedded into a binary that can be launched with --type=crashpad-handler.
// Otherwise, this function should be used and will launch an external
// crashpad_handler.exe which is generally used for test situations.
//
// On iOS, this will return false if Crashpad initialization fails.
bool InitializeCrashpad(bool initial_client, const std::string& process_type);
#if BUILDFLAG(IS_WIN)
// This is the same as InitializeCrashpad(), but rather than launching a
// crashpad_handler executable, relaunches the executable at |exe_path| or the
// current executable if |exe_path| is empty with a command line argument of
// --type=crashpad-handler. If |user_data_dir| is non-empty, it is added to the
// handler's command line for use by Chrome Crashpad extensions.
bool InitializeCrashpadWithEmbeddedHandler(bool initial_client,
const std::string& process_type,
const std::string& user_data_dir,
const base::FilePath& exe_path);
// This version of InitializeCrashpadWithEmbeddedHandler is used to call an
// embedded crash handler that comes from an entry point in a DLL. The command
// line for these kind of embedded handlers is usually:
// C:\Windows\System32\rundll.exe <path to dll>,<entrypoint> ...
// In this situation the exe_path is not sufficient to allow spawning a crash
// handler through the DLL so |initial_arguments| needs to be passed to
// specify the DLL entry point.
bool InitializeCrashpadWithDllEmbeddedHandler(
bool initial_client,
const std::string& process_type,
const std::string& user_data_dir,
const base::FilePath& exe_path,
const std::vector<std::string>& initial_arguments);
#endif // BUILDFLAG(IS_WIN)
// Returns the CrashpadClient for this process. This will lazily create it if
// it does not already exist. This is called as part of InitializeCrashpad.
// This code is not MT-safe
crashpad::CrashpadClient& GetCrashpadClient();
// In case GetCrashpadClient() was called and so constructed a new
// CrashpadClient instance then calling this method destroys that object,
// otherwise it does nothing.
// This method is useful when the CrashpadClient need to be explicitly removed,
// like when the crashpad is being used from a dynamically loaded DLL.
// This code is not MT-safe
void DestroyCrashpadClient();
// ChromeOS has its own, OS-level consent system; Chrome does not maintain a
// separate Upload Consent on ChromeOS.
#if !BUILDFLAG(IS_CHROMEOS)
// Enables or disables crash report upload, taking the given consent to upload
// into account. Consent may be ignored, uploads may not be enabled even with
// consent, but will only be enabled without consent when policy enforces crash
// reporting. Whether reports upload is a property of the Crashpad database. In
// a newly-created database, uploads will be disabled. This function only has an
// effect when called in the browser process. Its effect is immediate and
// applies to all other process types, including processes that are already
// running.
void SetUploadConsent(bool consent);
#endif // !BUILDFLAG(IS_CHROMEOS)
enum class ReportUploadState {
NotUploaded,
Pending,
Pending_UserRequested,
Uploaded
};
struct Report {
char local_id[64];
time_t capture_time;
char remote_id[64];
time_t upload_time;
ReportUploadState state;
};
// Obtains a list of reports uploaded to the collection server. This function
// only operates when called in the browser process. All reports in the Crashpad
// database that have been successfully uploaded will be included in this list.
// The list will be sorted in descending order by report creation time (newest
// reports first).
void GetReports(std::vector<Report>* reports);
// Requests a user triggered upload for a crash report with a given id.
void RequestSingleCrashUpload(const std::string& local_id);
void DumpWithoutCrashing();
#if BUILDFLAG(IS_IOS)
void DumpWithoutCrashAndDeferProcessing();
void DumpWithoutCrashAndDeferProcessingAtPath(const base::FilePath& path);
// Processes an externally generated dump.
// An empty minidump is generated and an attachment is created with |dump_data|.
// |source_name| is used as attachment name and is appended to the product name.
// |override_annotations| overrides the standard simple annotations sent with
// the report.
// Returns whether the external dump was processed successfully.
bool ProcessExternalDump(
const std::string& source_name,
base::span<const uint8_t> dump_data,
const std::map<std::string, std::string>& override_annotations = {});
// "platform", used to determine device_model, can be overridden.
void OverridePlatformValue(const std::string& platform_value);
// The simple extra memory ranges SimpleAddressRangeBag object.
crashpad::SimpleAddressRangeBag* ExtraMemoryRanges();
// Sets the bag of extra memory ranges to be included in the snapshot.
void SetExtraMemoryRanges(crashpad::SimpleAddressRangeBag* address_range_bag);
// The extra memory ranges SimpleAddressRangeBag object stored in the snapshot
// but not the minidump.
crashpad::SimpleAddressRangeBag* IntermediateDumpExtraMemoryRanges();
// Sets the bag of extra memory ranges to be included in the snapshot but not
// the minidump.
void SetIntermediateDumpExtraMemoryRanges(
crashpad::SimpleAddressRangeBag* address_range_bag);
#endif // BUILDFLAG(IS_IOS)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
// Logs message and immediately crashes the current process without triggering a
// crash dump.
[[noreturn]] void CrashWithoutDumping(const std::string& message);
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
// BUILDFLAG(IS_ANDROID)
// Returns the Crashpad database path, only valid in the browser. This will
// return std::nullopt if crashpad has not yet been initialized. On Windows,
// this will also return std::nullopt if running as part of browser_tests, as
// there is no crash reporting in that configuration.
std::optional<base::FilePath> GetCrashpadDatabasePath();
// Deletes any reports that were recorded or uploaded within the time range.
void ClearReportsBetween(const base::Time& begin, const base::Time& end);
// The implementation function for GetReports.
void GetReportsImpl(std::vector<Report>* reports);
// The implementation function for RequestSingleCrashUpload.
void RequestSingleCrashUploadImpl(const std::string& local_id);
// The implementation function for GetCrashpadDatabasePath.
base::FilePath::StringType::const_pointer GetCrashpadDatabasePathImpl();
// The implementation function for ClearReportsBetween.
void ClearReportsBetweenImpl(time_t begin, time_t end);
#if BUILDFLAG(IS_CHROMEOS_DEVICE)
// Called late in shutdown to remove the file that tells ChromeOS's
// crash_reporter "This browser process has crashpad initialized; you don't
// need to handle the crash reports coming from the kernel".
//
// Since crash_reporter will do a lot of unnecessary work if there is a
// crash after this file is removed, this function should be called as late
// as possible in the shutdown process, ideally after any code that might crash
// has executed.
//
// Only needed in the browser process; calls in other processes will be
// ignored. Multiple calls will be ignored as well.
void DeleteCrashpadIsReadyFile();
#endif
#if BUILDFLAG(IS_MAC)
// Captures a minidump for the process named by its |task_port| and stores it
// in the current crash report database.
void DumpProcessWithoutCrashing(task_t task_port);
#endif
#if BUILDFLAG(IS_IOS)
// Convert intermediate dumps into minidumps and trigger an upload if
// StartProcessingPendingReports() has been called. Optional |annotations| will
// merge with any process annotations. These are useful for adding annotations
// detected on the next run after a crash but before upload.
void ProcessIntermediateDumps(
const std::map<std::string, std::string>& annotations = {},
const crashpad::UserStreamDataSources* user_stream_sources = nullptr);
// Convert a single intermediate dump at |file| into a minidump and
// trigger an upload if StartProcessingPendingReports() has been called.
// Optional |annotations| will merge with any process annotations. These are
// useful for adding annotations detected on the next run after a crash but
// before upload.
void ProcessIntermediateDump(
const base::FilePath& file,
const std::map<std::string, std::string>& annotations = {});
// Requests that the handler begin in-process uploading of any pending reports.
void StartProcessingPendingReports();
#endif
#if BUILDFLAG(IS_ANDROID)
// If a CrashReporterClient has enabled sanitization, this function specifies
// regions of memory which are allowed to be collected by Crashpad.
void AllowMemoryRange(void* begin, size_t size);
#endif // BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// Install a handler that gets a chance to handle faults before Crashpad. This
// is used by V8 for trap-based bounds checks.
void SetFirstChanceExceptionHandler(bool (*handler)(int, siginfo_t*, void*));
// Gets the socket and process ID of the Crashpad handler connected to this
// process, valid if this function returns `true`.
bool GetHandlerSocket(int* sock, pid_t* pid);
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
namespace internal {
#if BUILDFLAG(IS_WIN)
// Returns platform specific annotations. This is broken out on Windows only so
// that it may be reused by GetCrashKeysForKasko.
void GetPlatformCrashpadAnnotations(
std::map<std::string, std::string>* annotations);
// The thread functions that implement the InjectDumpForHungInput in the
// target process.
DWORD WINAPI DumpProcessForHungInputThread(void* param);
#endif // BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_ANDROID)
// Starts the handler process with an initial client connected on fd,
// the handler will write minidump to database if write_minidump_to_database is
// true.
// Returns `true` on success.
bool StartHandlerForClient(int fd, bool write_minidump_to_database);
#endif // BUILDFLAG(IS_ANDROID)
// The platform-specific portion of InitializeCrashpad(). On Windows, if
// |user_data_dir| is non-empty, the user data directory will be passed to the
// handler process for use by Chrome Crashpad extensions; if |exe_path| is
// non-empty, it specifies the path to the executable holding the embedded
// handler. Sets the database path in |database_path|, if initializing in the
// browser process. Returns false if initialization fails.
bool PlatformCrashpadInitialization(
bool initial_client,
bool browser_process,
bool embedded_handler,
const std::string& user_data_dir,
const base::FilePath& exe_path,
const std::vector<std::string>& initial_arguments,
base::FilePath* database_path);
// Returns the current crash report database object, or null if it has not
// been initialized yet.
crashpad::CrashReportDatabase* GetCrashReportDatabase();
// Sets the global database and database path for testing. Must be called when
// crashpad is not running.
void SetCrashReportDatabaseForTesting(crashpad::CrashReportDatabase* database,
base::FilePath* database_path);
} // namespace internal
} // namespace crash_reporter
#endif // COMPONENTS_CRASH_CORE_APP_CRASHPAD_H_
|