Switch to libcorkscrew for native stack traces.

This is both for the current thread (which backtrace(3) could do) and other
threads, which is functionality we didn't have on x86 before.
We jump through the appropriate hoops to get static symbols as well as dynamic
ones.

Also unify the existing native stack dumpers so they can share the best code.

Example x86 check failure:

  *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
  Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR) fault addr 0xdeadd00d
  Registers:
      eax: 0x00000000    ebx: 0x55a966f0    ecx: 0x55d523c0    edx: 0x09225a50
      edi: 0x559d9b84    esi: 0xfffd8bcc    ebp: 0x55a9aba0    esp: 0xfffd8b90
      eip: 0x558e2e98                    eflags: 0x00010246 [ PF ZF IF ]
       cs: 0x00000023     ds: 0x0000002b     es: 0x0000002b     fs: 0x00000007
       gs: 0x00000063     ss: 0x0000002b
  Backtrace:
  	#00 unwind_backtrace_thread+536 [0x55d76bb8] (libcorkscrew.so)
  	#01 art::DumpNativeStack(std::ostream&, int, char const*, bool)+79 [0x55924fcf] (libartd.so)
  	#02 art::HandleUnexpectedSignal(int, siginfo*, void*)+1431814659 [0x5597cc23] (libartd.so)
  	#03 __kernel_rt_sigreturn [0x55573410] ([vdso])
  	#04 art::Runtime::Abort()+600 [0x558e2e98] (libartd.so)
  	#05 art::LogMessage::~LogMessage()+1052 [0x5580c16c] (libartd.so)
  	#06 art::EnsureResolved(art::Class*)+336 [0x5570dad0] (libartd.so)
  	#07 art::ClassLinker::FindClass(char const*, art::ClassLoader const*)+144 [0x5571bc90] (libartd.so)
  	#08 art::ClassLinker::FindSystemClass(char const*)+43 [0x5572287b] (libartd.so)
  	#09 art::ClassLinker::FinishInit()+82 [0x557228d2] (libartd.so)
  	#10 art::ClassLinker::InitFromImage()+1469 [0x5572451d] (libartd.so)
  	#11 art::ClassLinker::CreateFromImage(art::InternTable*)+60 [0x5572583c] (libartd.so)
  	#12 art::Runtime::Init(std::vector<std::pair<std::string, void const*>, std::allocator<std::pair<std::string, void const*> > > const&, bool)+943 [0x558e882f] (libartd.so)
  	#13 art::Runtime::Create(std::vector<std::pair<std::string, void const*>, std::allocator<std::pair<std::string, void const*> > > const&, bool)+119 [0x558e9057] (libartd.so)
  	#14 art::Dex2Oat::CreateRuntime(std::vector<std::pair<std::string, void const*>, std::allocator<std::pair<std::string, void const*> > >&, art::InstructionSet)+42 [0x80ac68a] (dex2oatd)
  	#15 art::Dex2Oat::Create(std::vector<std::pair<std::string, void const*>, std::allocator<std::pair<std::string, void const*> > >&, art::InstructionSet, unsigned int, bool)+60 [0x80ac87c] (dex2oatd)
  	#16 art::dex2oat(int, char**)+3167 [0x80894cf] (dex2oatd)
  	#17 main+17 [0x8086a01] (dex2oatd)
  	#18 __libc_start_main+230 [0x55c12bd6] (libc-2.11.1.so)

Example x86 SIGQUIT dump (note the three stacks, and note the absence of all
the crap that makes dalvik's attempt so unreadable):

  "Thread-10" prio=5 tid=11 VmWait
    | group="main" sCount=1 dsCount=0 obj=0x612d6620 self=0x884f8f0
    | sysTid=30512 nice=0 sched=0/0 cgrp=default handle=1458686832
    | schedstat=( 1249502 8995 26 ) utm=0 stm=0 core=14 HZ=100
    | stackSize=1044KB stack=0x57905000-0x57906000
    kernel: futex_wait_queue_me+0xcd/0x110
    kernel: futex_wait+0x1e5/0x310
    kernel: do_futex+0x101/0xb00
    kernel: compat_sys_futex+0x75/0x160
    kernel: sysenter_dispatch+0x7/0x2e
    native: __kernel_vsyscall+14 [0x5557342e] ([vdso])
    native: pthread_mutex_lock+54 [0x55cd8bf6] (libc-2.11.1.so)
    native: art::Mutex::Lock()+86 [0x55823a86] (libartd.so)
    at java.lang.AbstractStringBuilder.<init>(AbstractStringBuilder.java:75)
    at java.lang.StringBuilder.<init>(StringBuilder.java:54)
    at java.lang.Thread.create(Thread.java:427)
    at java.lang.Thread.<init>(Thread.java:223)
    at ThreadStress$1.run(ThreadStress.java:134)

(cherry picked from commit 00e446e5d912100b831fdcdbc276e7c31447f0c4)

Conflicts:

	src/thread.cc

Change-Id: I4712f8235992eafe6d8d6f915aa96f684bceaff2
diff --git a/src/runtime_linux.cc b/src/runtime_linux.cc
index 3e39fa2..80a8643 100644
--- a/src/runtime_linux.cc
+++ b/src/runtime_linux.cc
@@ -16,97 +16,18 @@
 
 #include "runtime.h"
 
-#include <cxxabi.h>
-#include <execinfo.h>
 #include <signal.h>
 #include <string.h>
 
 #include "logging.h"
 #include "stringprintf.h"
+#include "utils.h"
 
 namespace art {
 
-static std::string Demangle(const std::string& mangled_name) {
-  if (mangled_name.empty()) {
-    return "??";
-  }
-
-  // http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html
-  int status;
-  char* name(abi::__cxa_demangle(mangled_name.c_str(), NULL, NULL, &status));
-  if (name != NULL) {
-    std::string result(name);
-    free(name);
-    return result;
-  }
-
-  return mangled_name;
-}
-
 struct Backtrace {
   void Dump(std::ostream& os) {
-    // Get the raw stack frames.
-    size_t MAX_STACK_FRAMES = 128;
-    void* frames[MAX_STACK_FRAMES];
-    size_t frame_count = backtrace(frames, MAX_STACK_FRAMES);
-    if (frame_count == 0) {
-      os << "--- backtrace(3) returned no frames";
-      return;
-    }
-
-    // Turn them into something human-readable with symbols.
-    char** symbols = backtrace_symbols(frames, frame_count);
-    if (symbols == NULL) {
-      os << "--- backtrace_symbols(3) failed";
-      return;
-    }
-
-
-    // Parse the backtrace strings and demangle, so we can produce output like this:
-    // ]    #00 art::Runtime::Abort(char const*, int)+0x15b [0xf770dd51] (libartd.so)
-    for (size_t i = 0; i < frame_count; ++i) {
-      std::string text(symbols[i]);
-      std::string filename("???");
-      std::string function_name;
-
-#if defined(__APPLE__)
-      // backtrace_symbols(3) gives us lines like this on Mac OS:
-      // "0   libartd.dylib                       0x001cd29a _ZN3art9Backtrace4DumpERSo + 40>"
-      // "3   ???                                 0xffffffff 0x0 + 4294967295>"
-      text.erase(0, 4);
-      size_t index = text.find(' ');
-      filename = text.substr(0, index);
-      text.erase(0, 40 - 4);
-      index = text.find(' ');
-      std::string address(text.substr(0, index));
-      text.erase(0, index + 1);
-      index = text.find(' ');
-      function_name = Demangle(text.substr(0, index));
-      text.erase(0, index);
-      text += " [" + address + "]";
-#else
-      // backtrace_symbols(3) gives us lines like this on Linux:
-      // "/usr/local/google/home/enh/a1/out/host/linux-x86/bin/../lib/libartd.so(_ZN3art7Runtime5AbortEPKci+0x15b) [0xf76c5af3]"
-      // "[0xf7b62057]"
-      size_t index = text.find('(');
-      if (index != std::string::npos) {
-        filename = text.substr(0, index);
-        text.erase(0, index + 1);
-
-        index = text.find_first_of("+)");
-        function_name = Demangle(text.substr(0, index));
-        text.erase(0, index);
-        index = text.find(')');
-        text.erase(index, 1);
-      }
-#endif
-
-      const char* last_slash = strrchr(filename.c_str(), '/');
-      const char* so_name = (last_slash == NULL) ? filename.c_str() : last_slash + 1;
-      os << StringPrintf("\t#%02zd ", i) << function_name << text << " (" << so_name << ")\n";
-    }
-
-    free(symbols);
+    DumpNativeStack(os, GetTid(), "\t", true);
   }
 };
 
@@ -213,7 +134,9 @@
     os << '\n';
 
     DumpRegister32(os, "eip", context->__ss.__eip);
+    os << "                   ";
     DumpRegister32(os, "eflags", context->__ss.__eflags);
+    DumpX86Flags(os, context->__ss.__eflags);
     os << '\n';
 
     DumpRegister32(os, "cs",  context->__ss.__cs);
@@ -237,7 +160,9 @@
     os << '\n';
 
     DumpRegister32(os, "eip", context.gregs[REG_EIP]);
+    os << "                   ";
     DumpRegister32(os, "eflags", context.gregs[REG_EFL]);
+    DumpX86Flags(os, context.gregs[REG_EFL]);
     os << '\n';
 
     DumpRegister32(os, "cs",  context.gregs[REG_CS]);
@@ -254,6 +179,38 @@
     os << StringPrintf(" %6s: 0x%08x", name, value);
   }
 
+  void DumpX86Flags(std::ostream& os, uint32_t flags) {
+    os << " [";
+    if ((flags & (1 << 0)) != 0) {
+      os << " CF";
+    }
+    if ((flags & (1 << 2)) != 0) {
+      os << " PF";
+    }
+    if ((flags & (1 << 4)) != 0) {
+      os << " AF";
+    }
+    if ((flags & (1 << 6)) != 0) {
+      os << " ZF";
+    }
+    if ((flags & (1 << 7)) != 0) {
+      os << " SF";
+    }
+    if ((flags & (1 << 8)) != 0) {
+      os << " TF";
+    }
+    if ((flags & (1 << 9)) != 0) {
+      os << " IF";
+    }
+    if ((flags & (1 << 10)) != 0) {
+      os << " DF";
+    }
+    if ((flags & (1 << 11)) != 0) {
+      os << " OF";
+    }
+    os << " ]";
+  }
+
   mcontext_t& context;
 };