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; }