| // 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. |
| |
| #ifndef CRASH_REPORTER_CHROME_COLLECTOR_H_ |
| #define CRASH_REPORTER_CHROME_COLLECTOR_H_ |
| |
| #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 { |
| public: |
| 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& dump_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); |
| |
| static CollectorInfo GetHandlerInfo(CrashSendingMode mode, |
| const std::string& dump_file_path, |
| int memfd, |
| pid_t pid, |
| uid_t uid, |
| const std::string& executable_name, |
| const std::string& non_exe_error_key, |
| const std::string& chrome_dump_dir); |
| |
| void set_max_upload_bytes_for_test(int max_upload_bytes) { |
| max_upload_bytes_ = max_upload_bytes; |
| } |
| |
| private: |
| 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.) |
| kExecutableCrash, |
| |
| // A JavaScript error is being reported. |
| kJavaScriptError |
| }; |
| |
| // 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_; |
| }; |
| |
| #endif // CRASH_REPORTER_CHROME_COLLECTOR_H_ |