Modify unwind to comply with stack parser tools.

Bug: 14081592

Change-Id: I6906b2575c74d64f1c3ba7602779b3a789de1c69
diff --git a/runtime/runtime_linux.cc b/runtime/runtime_linux.cc
index da1b2ca..960d332 100644
--- a/runtime/runtime_linux.cc
+++ b/runtime/runtime_linux.cc
@@ -33,7 +33,7 @@
 
 struct Backtrace {
   void Dump(std::ostream& os) {
-    DumpNativeStack(os, GetTid(), "\t", true);
+    DumpNativeStack(os, GetTid(), "\t");
   }
 };
 
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 8691dec..3408dd3 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -939,7 +939,7 @@
     if (dump_for_abort || ShouldShowNativeStack(this)) {
       DumpKernelStack(os, GetTid(), "  kernel: ", false);
       SirtRef<mirror::ArtMethod> method_ref(Thread::Current(), GetCurrentMethod(nullptr));
-      DumpNativeStack(os, GetTid(), "  native: ", false, method_ref.get());
+      DumpNativeStack(os, GetTid(), "  native: ", method_ref.get());
     }
     DumpJavaStack(os);
   } else {
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index 270deb0..6f93566 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -78,7 +78,7 @@
   MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
   for (const auto& thread : list_) {
     os << "DUMPING THREAD " << thread->GetTid() << "\n";
-    DumpNativeStack(os, thread->GetTid(), "\t", true);
+    DumpNativeStack(os, thread->GetTid(), "\t");
     os << "\n";
   }
 }
@@ -99,7 +99,7 @@
   // TODO: Reenable this when the native code in system_server can handle it.
   // Currently "adb shell kill -3 `pid system_server`" will cause it to exit.
   if (false) {
-    DumpNativeStack(os, tid, "  native: ", false);
+    DumpNativeStack(os, tid, "  native: ");
   }
   os << "\n";
 }
diff --git a/runtime/utils.cc b/runtime/utils.cc
index afbcbb7..c4d1a78 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -1041,20 +1041,7 @@
   return "";
 }
 
-static std::string CleanMapName(const backtrace_map_t* map) {
-  if (map == NULL || map->name.empty()) {
-    return "???";
-  }
-  // Turn "/usr/local/google/home/enh/clean-dalvik-dev/out/host/linux-x86/lib/libartd.so"
-  // into "libartd.so".
-  size_t last_slash = map->name.rfind('/');
-  if (last_slash == std::string::npos) {
-    return map->name;
-  }
-  return map->name.substr(last_slash + 1);
-}
-
-void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix, bool include_count,
+void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix,
     mirror::ArtMethod* current_method) {
   // We may be called from contexts where current_method is not null, so we must assert this.
   if (current_method != nullptr) {
@@ -1072,27 +1059,34 @@
   for (Backtrace::const_iterator it = backtrace->begin();
        it != backtrace->end(); ++it) {
     // We produce output like this:
-    // ]    #00 unwind_backtrace_thread+536 [0x55d75bb8] (libbacktrace.so)
-    os << prefix;
-    if (include_count) {
-      os << StringPrintf("#%02zu ", it->num);
-    }
-    if (!it->func_name.empty()) {
-      os << it->func_name;
+    // ]    #00 pc 000075bb8  /system/lib/libc.so (unwind_backtrace_thread+536)
+    // In order for parsing tools to continue to function, the stack dump
+    // format must at least adhere to this format:
+    //  #XX pc <RELATIVE_ADDR>  <FULL_PATH_TO_SHARED_LIBRARY> ...
+    // The parsers require a single space before and after pc, and two spaces
+    // after the <RELATIVE_ADDR>. There can be any prefix data before the
+    // #XX. <RELATIVE_ADDR> has to be a hex number but with no 0x prefix.
+    os << prefix << StringPrintf("#%02zu pc ", it->num);
+    if (!it->map) {
+      os << StringPrintf("%08" PRIxPTR "  ???", it->pc);
     } else {
-      if (current_method != nullptr && current_method->IsWithinQuickCode(it->pc)) {
+      os << StringPrintf("%08" PRIxPTR "  ", it->pc - it->map->start)
+         << it->map->name << " (";
+      if (!it->func_name.empty()) {
+        os << it->func_name;
+        if (it->func_offset != 0) {
+          os << "+" << it->func_offset;
+        }
+      } else if (current_method != nullptr && current_method->IsWithinQuickCode(it->pc)) {
         const void* start_of_code = current_method->GetEntryPointFromQuickCompiledCode();
         os << JniLongName(current_method) << "+"
            << (it->pc - reinterpret_cast<uintptr_t>(start_of_code));
       } else {
         os << "???";
       }
+      os << ")";
     }
-    if (it->func_offset != 0) {
-      os << "+" << it->func_offset;
-    }
-    os << StringPrintf(" [%p]", reinterpret_cast<void*>(it->pc));
-    os << " (" << CleanMapName(it->map) << ")\n";
+    os << "\n";
   }
 }
 
diff --git a/runtime/utils.h b/runtime/utils.h
index 5def66b..6ab1013 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -382,7 +382,7 @@
 
 // Dumps the native stack for thread 'tid' to 'os'.
 void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix = "",
-    bool include_count = true, mirror::ArtMethod* current_method = nullptr)
+    mirror::ArtMethod* current_method = nullptr)
     NO_THREAD_SAFETY_ANALYSIS;
 
 // Dumps the kernel stack for thread 'tid' to 'os'. Note that this is only available on linux-x86.