Linux: Write out si_code for SIGBUS exceptions.

Store the information in the exception record's exception_information
field.

Change-Id: Ie215cae2f070fdab63c3d05cc1bc4fb4b7b095fa
Reviewed-on: https://chromium-review.googlesource.com/990799
Reviewed-by: Mark Mentovai <mark@chromium.org>
diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc
index 180873f..fa3c171 100644
--- a/src/client/linux/microdump_writer/microdump_writer.cc
+++ b/src/client/linux/microdump_writer/microdump_writer.cc
@@ -648,9 +648,7 @@
     if (blob_size != sizeof(ExceptionHandler::CrashContext))
       return false;
     context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
-    dumper.set_crash_address(
-        reinterpret_cast<uintptr_t>(context->siginfo.si_addr));
-    dumper.set_crash_signal(context->siginfo.si_signo);
+    dumper.SetCrashInfoFromSigInfo(context->siginfo);
     dumper.set_crash_thread(context->tid);
   }
   MicrodumpWriter writer(context, mappings,
diff --git a/src/client/linux/minidump_writer/linux_core_dumper.cc b/src/client/linux/minidump_writer/linux_core_dumper.cc
index 622f050..9bf2d2e 100644
--- a/src/client/linux/minidump_writer/linux_core_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_core_dumper.cc
@@ -212,6 +212,7 @@
         if (first_thread) {
           crash_thread_ = pid;
           crash_signal_ = status->pr_info.si_signo;
+          crash_signal_code_ = status->pr_info.si_code;
         }
         first_thread = false;
         threads_.push_back(pid);
diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc
index 515af3f..dbedecd 100644
--- a/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper.cc
@@ -283,6 +283,7 @@
       root_prefix_(root_prefix),
       crash_address_(0),
       crash_signal_(0),
+      crash_signal_code_(0),
       crash_thread_(pid),
       threads_(&allocator_, 8),
       mappings_(&allocator_),
@@ -354,6 +355,12 @@
   return success;
 }
 
+void LinuxDumper::SetCrashInfoFromSigInfo(const siginfo_t& siginfo) {
+  set_crash_address(reinterpret_cast<uintptr_t>(siginfo.si_addr));
+  set_crash_signal(siginfo.si_signo);
+  set_crash_signal_code(siginfo.si_code);
+}
+
 const char* LinuxDumper::GetCrashSignalString() const {
   switch (static_cast<unsigned int>(crash_signal_)) {
     case MD_EXCEPTION_CODE_LIN_SIGHUP:
diff --git a/src/client/linux/minidump_writer/linux_dumper.h b/src/client/linux/minidump_writer/linux_dumper.h
index 4a4e0b0..76448fa 100644
--- a/src/client/linux/minidump_writer/linux_dumper.h
+++ b/src/client/linux/minidump_writer/linux_dumper.h
@@ -170,6 +170,8 @@
                                    unsigned int mapping_id,
                                    wasteful_vector<uint8_t>& identifier);
 
+  void SetCrashInfoFromSigInfo(const siginfo_t& siginfo);
+
   uintptr_t crash_address() const { return crash_address_; }
   void set_crash_address(uintptr_t crash_address) {
     crash_address_ = crash_address;
@@ -179,6 +181,9 @@
   void set_crash_signal(int crash_signal) { crash_signal_ = crash_signal; }
   const char* GetCrashSignalString() const;
 
+  void set_crash_signal_code(int code) { crash_signal_code_ = code; }
+  int crash_signal_code() const { return crash_signal_code_; }
+
   pid_t crash_thread() const { return crash_thread_; }
   void set_crash_thread(pid_t crash_thread) { crash_thread_ = crash_thread; }
 
@@ -228,6 +233,9 @@
   // Signal that terminated the crashed process.
   int crash_signal_;
 
+  // The code associated with |crash_signal_|.
+  int crash_signal_code_;
+
   // ID of the crashed thread.
   pid_t crash_thread_;
 
diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc
index c716143..cdf4bf6 100644
--- a/src/client/linux/minidump_writer/minidump_writer.cc
+++ b/src/client/linux/minidump_writer/minidump_writer.cc
@@ -702,15 +702,18 @@
     TypedMDRVA<MDRawExceptionStream> exc(&minidump_writer_);
     if (!exc.Allocate())
       return false;
-    my_memset(exc.get(), 0, sizeof(MDRawExceptionStream));
+
+    MDRawExceptionStream* stream = exc.get();
+    my_memset(stream, 0, sizeof(MDRawExceptionStream));
 
     dirent->stream_type = MD_EXCEPTION_STREAM;
     dirent->location = exc.location();
 
-    exc.get()->thread_id = GetCrashThread();
-    exc.get()->exception_record.exception_code = dumper_->crash_signal();
-    exc.get()->exception_record.exception_address = dumper_->crash_address();
-    exc.get()->thread_context = crashing_thread_context_;
+    stream->thread_id = GetCrashThread();
+    stream->exception_record.exception_code = dumper_->crash_signal();
+    stream->exception_record.exception_flags = dumper_->crash_signal_code();
+    stream->exception_record.exception_address = dumper_->crash_address();
+    stream->thread_context = crashing_thread_context_;
 
     return true;
   }
@@ -1366,9 +1369,7 @@
     if (blob_size != sizeof(ExceptionHandler::CrashContext))
       return false;
     context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
-    dumper.set_crash_address(
-        reinterpret_cast<uintptr_t>(context->siginfo.si_addr));
-    dumper.set_crash_signal(context->siginfo.si_signo);
+    dumper.SetCrashInfoFromSigInfo(context->siginfo);
     dumper.set_crash_thread(context->tid);
   }
   MinidumpWriter writer(minidump_path, minidump_fd, context, mappings,