Extend VLOG(signals) to be more useful.

-verbose:signals was pretty useless because it didn't tell you much
about what the signal being examined actually was. Extend HandleFault
logging to include details about the signal being handled.

Test: ./test/run-test --runtime-option -verbose:signals --host --dev 983
Change-Id: I78baca685623c6b37f8148d6eeb2614c38fdfa69
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index 9d6e5de..3015b10 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -17,6 +17,7 @@
 #include "fault_handler.h"
 
 #include <setjmp.h>
+#include <string.h>
 #include <sys/mman.h>
 #include <sys/ucontext.h>
 
@@ -183,8 +184,31 @@
   return false;
 }
 
+static const char* SignalCodeName(int sig, int code) {
+  if (sig != SIGSEGV) {
+    return "UNKNOWN";
+  } else {
+    switch (code) {
+      case SEGV_MAPERR: return "SEGV_MAPERR";
+      case SEGV_ACCERR: return "SEGV_ACCERR";
+      default:          return "UNKNOWN";
+    }
+  }
+}
+static std::ostream& PrintSignalInfo(std::ostream& os, siginfo_t* info) {
+  os << "  si_signo: " << info->si_signo << " (" << strsignal(info->si_signo) << ")\n"
+     << "  si_code: " << info->si_code
+     << " (" << SignalCodeName(info->si_signo, info->si_code) << ")";
+  if (info->si_signo == SIGSEGV) {
+    os << "\n" << "  si_addr: " << info->si_addr;
+  }
+  return os;
+}
+
 bool FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
-  VLOG(signals) << "Handling fault";
+  if (VLOG_IS_ON(signals)) {
+    PrintSignalInfo(VLOG_STREAM(signals) << "Handling fault:" << "\n", info);
+  }
 
 #ifdef TEST_NESTED_SIGNAL
   // Simulate a crash in a handler.