blob: 38d62315d1f9a815026e6c3255d53b6a78703e00 [file] [log] [blame]
// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// The chrome collector collects crashes from the chrome binary.
// It's a bit special - instead of the kernel running it through
// /proc/sys/kernel/core_pattern, chrome invokes it directly and passes in a
// crash dump generated by Crashpad or the JavaScript error reporting system.
#include <map>
#include <memory>
#include <string>
#include <base/files/file_path.h>
#include <base/macros.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include "crash-reporter/crash_collector.h"
// Chrome crash collector.
class ChromeCollector : public CrashCollector {
explicit ChromeCollector(CrashSendingMode crash_sending_mode);
ChromeCollector(const ChromeCollector&) = delete;
ChromeCollector& operator=(const ChromeCollector&) = delete;
~ChromeCollector() override;
// Magic string to let Chrome know the crash report succeeded.
static const char kSuccessMagic[];
// Handle a specific chrome crash. Returns true on success.
bool HandleCrash(const base::FilePath& file_path,
pid_t pid,
uid_t uid,
const std::string& exe_name);
// Handle a specific chrome crash through a memfd instead of a file.
// Returns true on success.
bool HandleCrashThroughMemfd(int memfd,
pid_t pid,
uid_t uid,
const std::string& executable_name,
const std::string& non_exe_error_key,
const std::string& dump_dir);
void set_max_upload_bytes_for_test(int max_upload_bytes) {
max_upload_bytes_ = max_upload_bytes;
friend class ChromeCollectorTest;
FRIEND_TEST(ChromeCollectorTest, GoodValues);
FRIEND_TEST(ChromeCollectorTest, GoodLacros);
FRIEND_TEST(ChromeCollectorTest, ParseCrashLogNoDump);
FRIEND_TEST(ChromeCollectorTest, ParseCrashLogJSStack);
FRIEND_TEST(ChromeCollectorTest, BadValues);
FRIEND_TEST(ChromeCollectorTest, Newlines);
FRIEND_TEST(ChromeCollectorTest, File);
FRIEND_TEST(ChromeCollectorTest, HandleCrash);
FRIEND_TEST(ChromeCollectorTest, HandleCrashWithEmbeddedNuls);
FRIEND_TEST(ChromeCollectorTest, HandleCrashWithWeirdFilename);
enum CrashType {
// An executable received a signal like SIGSEGV or SIGILL; the sort of thing
// that would lead to a core file on Linux. (Also covers Chrome's
// DumpWithoutCrashing function.)
// A JavaScript error is being reported.
// Handle a specific chrome crash with dump data.
// Returns true on success.
bool HandleCrashWithDumpData(const std::string& data,
pid_t pid,
uid_t uid,
const std::string& executable_name,
const std::string& non_exe_error_key,
const std::string& dump_dir);
// Crashes are expected to be in a TLV-style format of:
// <name>:<length>:<value>
// Length is encoded as a decimal number. It can be zero, but must consist of
// at least one character
// For file values, name actually contains both a description and a filename,
// in a fixed format of: <description>"; filename="<filename>".
// The path to the payload (minidump or JS Exception) will be written to
// |payload|.
bool ParseCrashLog(const std::string& data,
const base::FilePath& dir,
const std::string& basename,
CrashType crash_type,
base::FilePath* payload,
bool* is_lacros_crash);
// Some classes of JavaScript errors do not have stacks. Since crash_sender
// cannot send error reports without a payload, create a simple payload that
// just states there was no stack.
bool CreateNoStackJSPayload(const base::FilePath& dir,
const std::string& dump_basename,
base::FilePath* payload_path);
// Gets the GPU's error state from debugd and writes it to |error_state_path|.
// Returns true on success.
bool GetDriErrorState(const base::FilePath& error_state_path);
// Writes additional logs for the crash to files based on |basename| within
// |dir|. |key_for_logs| is the key into crash_reporter_logs.conf file. Crash
// report metadata key names and the corresponding file paths are returned.
std::map<std::string, base::FilePath> GetAdditionalLogs(
const base::FilePath& dir,
const std::string& basename,
const std::string& key_for_logs,
CrashType crash_type);
// Add the (|log_map_key|, |complete_file_name|) pair to |logs| if we are not
// over kDefaultMaxUploadBytes. If we are over kDefaultMaxUploadBytes,
// delete the file |complete_file_name| instead and don't change |logs|.
// |complete_file_name| must be a file created by
// CrashCollector::WriteNewFile() or CrashCollector::WriteNewCompressedFile()
// so that CrashCollector::RemoveNewFile() works on it.
void AddLogIfNotTooBig(const char* log_map_key,
const base::FilePath& complete_file_name,
std::map<std::string, base::FilePath>* logs);
// The file where we write our special "done" marker (to indicate to Chrome
// that we are finished dumping). Always stdout in production.
FILE* output_file_ptr_;
// We skip uploading the supplemental files (logs, i915_error_state) if it
// would make the report larger than max_upload_bytes_. In production, this
// is always kDefaultMaxUploadBytes.
int max_upload_bytes_;