From 38cbbfed71efcb28931b5e4a83e3c0d4661f1548 Mon Sep 17 00:00:00 2001 From: Tobias Sargeant Date: Fri, 11 Aug 2017 18:11:16 +0100 Subject: [PATCH] Add crash reason and address to microdumps. This will allow us to provide the right information for webview renderer crashes. At the moment the crash information for the browser process is captured (from the debuggerd output) instead. BUG=754715 Change-Id: I409546311b6e38fe1cf804097c18d7bb2a015d83 Reviewed-on: https://chromium-review.googlesource.com/612381 Reviewed-by: Robert Sesek --- .../microdump_writer/microdump_writer.cc | 11 +++ .../microdump_writer_unittest.cc | 27 +++++++ .../linux/minidump_writer/linux_dumper.cc | 72 +++++++++++++++++++ .../linux/minidump_writer/linux_dumper.h | 1 + 4 files changed, 111 insertions(+) diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc index 3764eec2..5c3c751d 100644 --- a/src/client/linux/microdump_writer/microdump_writer.cc +++ b/src/client/linux/microdump_writer/microdump_writer.cc @@ -181,6 +181,7 @@ class MicrodumpWriter { DumpProductInformation(); DumpOSInformation(); DumpProcessType(); + DumpCrashReason(); DumpGPUInformation(); #if !defined(__LP64__) DumpFreeSpace(); @@ -298,6 +299,16 @@ class MicrodumpWriter { LogCommitLine(); } + void DumpCrashReason() { + LogAppend("R "); + LogAppend(dumper_->crash_signal()); + LogAppend(" "); + LogAppend(dumper_->GetCrashSignalString()); + LogAppend(" "); + LogAppend(dumper_->crash_address()); + LogCommitLine(); + } + void DumpOSInformation() { const uint8_t n_cpus = static_cast(sysconf(_SC_NPROCESSORS_CONF)); diff --git a/src/client/linux/microdump_writer/microdump_writer_unittest.cc b/src/client/linux/microdump_writer/microdump_writer_unittest.cc index cbcd1399..c2fea022 100644 --- a/src/client/linux/microdump_writer/microdump_writer_unittest.cc +++ b/src/client/linux/microdump_writer/microdump_writer_unittest.cc @@ -65,6 +65,7 @@ MicrodumpExtraInfo MakeMicrodumpExtraInfo( info.build_fingerprint = build_fingerprint; info.product_info = product_info; info.gpu_fingerprint = gpu_fingerprint; + info.process_type = "Browser"; return info; } @@ -74,6 +75,7 @@ bool ContainsMicrodump(const std::string& buf) { } const char kIdentifiableString[] = "_IDENTIFIABLE_"; +const uintptr_t kCrashAddress = 0xdeaddeadu; void CrashAndGetMicrodump(const MappingList& mappings, const MicrodumpExtraInfo& microdump_extra_info, @@ -115,6 +117,8 @@ void CrashAndGetMicrodump(const MappingList& mappings, getcontext(&context.context); // Set a non-zero tid to avoid tripping asserts. context.tid = child; + context.siginfo.si_signo = MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED; + context.siginfo.si_addr = reinterpret_cast(kCrashAddress); // Redirect temporarily stderr to the stderr.log file. int save_err = dup(STDERR_FILENO); @@ -172,6 +176,8 @@ void CheckMicrodumpContents(const string& microdump_content, std::istringstream iss(microdump_content); bool did_find_os_info = false; bool did_find_product_info = false; + bool did_find_process_type = false; + bool did_find_crash_reason = false; bool did_find_gpu_info = false; for (string line; std::getline(iss, line);) { if (line.find("O ") == 0) { @@ -190,9 +196,28 @@ void CheckMicrodumpContents(const string& microdump_content, // Check that the build fingerprint is in the right place. os_info_tokens >> token; + ASSERT_FALSE(os_info_tokens.fail()); if (expected_info.build_fingerprint) ASSERT_EQ(expected_info.build_fingerprint, token); did_find_os_info = true; + } else if (line.find("P ") == 0) { + if (expected_info.process_type) + ASSERT_EQ(string("P ") + expected_info.process_type, line); + did_find_process_type = true; + } else if (line.find("R ") == 0) { + std::istringstream crash_reason_tokens(line); + string token; + unsigned crash_reason; + string crash_reason_str; + intptr_t crash_address; + crash_reason_tokens.ignore(2); // Ignore the "R " preamble. + crash_reason_tokens >> std::hex >> crash_reason >> crash_reason_str >> + crash_address; + ASSERT_FALSE(crash_reason_tokens.fail()); + ASSERT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED, crash_reason); + ASSERT_EQ("DUMP_REQUESTED", crash_reason_str); + ASSERT_EQ(0xDEADDEADu, kCrashAddress); + did_find_crash_reason = true; } else if (line.find("V ") == 0) { if (expected_info.product_info) ASSERT_EQ(string("V ") + expected_info.product_info, line); @@ -205,6 +230,8 @@ void CheckMicrodumpContents(const string& microdump_content, } ASSERT_TRUE(did_find_os_info); ASSERT_TRUE(did_find_product_info); + ASSERT_TRUE(did_find_process_type); + ASSERT_TRUE(did_find_crash_reason); ASSERT_TRUE(did_find_gpu_info); } diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc index 141aa07c..0013824b 100644 --- a/src/client/linux/minidump_writer/linux_dumper.cc +++ b/src/client/linux/minidump_writer/linux_dumper.cc @@ -50,6 +50,7 @@ #include "common/linux/linux_libc_support.h" #include "common/linux/memory_mapped_file.h" #include "common/linux/safe_readlink.h" +#include "google_breakpad/common/minidump_exception_linux.h" #include "third_party/lss/linux_syscall_support.h" #if defined(__ANDROID__) @@ -336,6 +337,77 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping, return success; } +const char* LinuxDumper::GetCrashSignalString() const { + switch (static_cast(crash_signal_)) { + case MD_EXCEPTION_CODE_LIN_SIGHUP: + return "SIGHUP"; + case MD_EXCEPTION_CODE_LIN_SIGINT: + return "SIGINT"; + case MD_EXCEPTION_CODE_LIN_SIGQUIT: + return "SIGQUIT"; + case MD_EXCEPTION_CODE_LIN_SIGILL: + return "SIGILL"; + case MD_EXCEPTION_CODE_LIN_SIGTRAP: + return "SIGTRAP"; + case MD_EXCEPTION_CODE_LIN_SIGABRT: + return "SIGABRT"; + case MD_EXCEPTION_CODE_LIN_SIGBUS: + return "SIGBUS"; + case MD_EXCEPTION_CODE_LIN_SIGFPE: + return "SIGFPE"; + case MD_EXCEPTION_CODE_LIN_SIGKILL: + return "SIGKILL"; + case MD_EXCEPTION_CODE_LIN_SIGUSR1: + return "SIGUSR1"; + case MD_EXCEPTION_CODE_LIN_SIGSEGV: + return "SIGSEGV"; + case MD_EXCEPTION_CODE_LIN_SIGUSR2: + return "SIGUSR2"; + case MD_EXCEPTION_CODE_LIN_SIGPIPE: + return "SIGPIPE"; + case MD_EXCEPTION_CODE_LIN_SIGALRM: + return "SIGALRM"; + case MD_EXCEPTION_CODE_LIN_SIGTERM: + return "SIGTERM"; + case MD_EXCEPTION_CODE_LIN_SIGSTKFLT: + return "SIGSTKFLT"; + case MD_EXCEPTION_CODE_LIN_SIGCHLD: + return "SIGCHLD"; + case MD_EXCEPTION_CODE_LIN_SIGCONT: + return "SIGCONT"; + case MD_EXCEPTION_CODE_LIN_SIGSTOP: + return "SIGSTOP"; + case MD_EXCEPTION_CODE_LIN_SIGTSTP: + return "SIGTSTP"; + case MD_EXCEPTION_CODE_LIN_SIGTTIN: + return "SIGTTIN"; + case MD_EXCEPTION_CODE_LIN_SIGTTOU: + return "SIGTTOU"; + case MD_EXCEPTION_CODE_LIN_SIGURG: + return "SIGURG"; + case MD_EXCEPTION_CODE_LIN_SIGXCPU: + return "SIGXCPU"; + case MD_EXCEPTION_CODE_LIN_SIGXFSZ: + return "SIGXFSZ"; + case MD_EXCEPTION_CODE_LIN_SIGVTALRM: + return "SIGVTALRM"; + case MD_EXCEPTION_CODE_LIN_SIGPROF: + return "SIGPROF"; + case MD_EXCEPTION_CODE_LIN_SIGWINCH: + return "SIGWINCH"; + case MD_EXCEPTION_CODE_LIN_SIGIO: + return "SIGIO"; + case MD_EXCEPTION_CODE_LIN_SIGPWR: + return "SIGPWR"; + case MD_EXCEPTION_CODE_LIN_SIGSYS: + return "SIGSYS"; + case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED: + return "DUMP_REQUESTED"; + default: + return "UNKNOWN"; + } +} + bool LinuxDumper::GetMappingAbsolutePath(const MappingInfo& mapping, char path[PATH_MAX]) const { return my_strlcpy(path, root_prefix_, PATH_MAX) < PATH_MAX && diff --git a/src/client/linux/minidump_writer/linux_dumper.h b/src/client/linux/minidump_writer/linux_dumper.h index 3a9a2e8b..389d8a21 100644 --- a/src/client/linux/minidump_writer/linux_dumper.h +++ b/src/client/linux/minidump_writer/linux_dumper.h @@ -177,6 +177,7 @@ class LinuxDumper { int crash_signal() const { return crash_signal_; } void set_crash_signal(int crash_signal) { crash_signal_ = crash_signal; } + const char* GetCrashSignalString() const; pid_t crash_thread() const { return crash_thread_; } void set_crash_thread(pid_t crash_thread) { crash_thread_ = crash_thread; }