Reland "[Berberis][CrashReporting] Dump guest thread inf..."

Guest thread information will print out follow host thread.

Revert submission 3081452-revert-3062926-CJGHTRPCBP

Reason for revert: Will make the change base on the original CLs for a reland.

Bug: b/321799516
Test: riscv64, checked tombstone file has wanted block.
https://paste.googleplex.com/6282302317658112
Added arm64 support and tested arm64 unwinding in internal repo.
https://paste.googleplex.com/6545612887818240

Change-Id: Ie54ad6f359d60283442adfcd9ee95f5a116e4b72
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
index be999e0..dfdfabd 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
@@ -28,6 +28,7 @@
 #include <android-base/unique_fd.h>
 
 #include "open_files_list.h"
+#include "tombstone.pb.h"
 #include "types.h"
 
 // Forward declarations
@@ -54,14 +55,17 @@
                        unwindstack::AndroidUnwinder* unwinder,
                        const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
                        const ProcessInfo& process_info, OpenFilesList* open_files,
-                       std::string* amfd_data);
+                       std::string* amfd_data, const Architecture* guest_arch = nullptr,
+                       unwindstack::AndroidUnwinder* guest_unwinder = nullptr);
 
 void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address,
                                 siginfo_t* siginfo, ucontext_t* ucontext);
 
 void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
                              const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
-                             const ProcessInfo& process_info, const OpenFilesList* open_files);
+                             const ProcessInfo& process_info, const OpenFilesList* open_files,
+                             const Architecture* guest_arch,
+                             unwindstack::AndroidUnwinder* guest_unwinder);
 
 bool tombstone_proto_to_text(
     const Tombstone& tombstone,
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 5a416d6..0ce5573 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -125,10 +125,12 @@
                        unwindstack::AndroidUnwinder* unwinder,
                        const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
                        const ProcessInfo& process_info, OpenFilesList* open_files,
-                       std::string* amfd_data) {
+                       std::string* amfd_data, const Architecture* guest_arch,
+                       unwindstack::AndroidUnwinder* guest_unwinder) {
   // Don't copy log messages to tombstone unless this is a development device.
   Tombstone tombstone;
-  engrave_tombstone_proto(&tombstone, unwinder, threads, target_thread, process_info, open_files);
+  engrave_tombstone_proto(&tombstone, unwinder, threads, target_thread, process_info, open_files,
+                          guest_arch, guest_unwinder);
 
   if (proto_fd != -1) {
     if (!tombstone.SerializeToFileDescriptor(proto_fd.get())) {
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 5546b7b..3e8ab6e 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -482,7 +482,8 @@
 }
 
 static void dump_thread(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
-                        const ThreadInfo& thread_info, bool memory_dump = false) {
+                        const ThreadInfo& thread_info, bool memory_dump = false,
+                        unwindstack::AndroidUnwinder* guest_unwinder = nullptr) {
   Thread thread;
 
   thread.set_id(thread_info.tid);
@@ -509,6 +510,27 @@
 
   auto& threads = *tombstone->mutable_threads();
   threads[thread_info.tid] = thread;
+
+  if (guest_unwinder) {
+    if (!thread_info.guest_registers) {
+      async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
+                            "No guest state registers information for tid %d", thread_info.tid);
+      return;
+    }
+    Thread guest_thread;
+    unwindstack::AndroidUnwinderData guest_data;
+    guest_data.saved_initial_regs = std::make_optional<std::unique_ptr<unwindstack::Regs>>();
+    if (guest_unwinder->Unwind(thread_info.guest_registers.get(), guest_data)) {
+      dump_thread_backtrace(guest_data.frames, guest_thread);
+    } else {
+      async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                            "Unwind guest state registers failed for tid %d: Error %s",
+                            thread_info.tid, guest_data.GetErrorString().c_str());
+    }
+    dump_registers(guest_unwinder, *guest_data.saved_initial_regs, guest_thread, memory_dump);
+    auto& guest_threads = *tombstone->mutable_guest_threads();
+    guest_threads[thread_info.tid] = guest_thread;
+  }
 }
 
 static void dump_mappings(Tombstone* tombstone, unwindstack::Maps* maps,
@@ -686,10 +708,17 @@
 
 void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
                              const std::map<pid_t, ThreadInfo>& threads, pid_t target_tid,
-                             const ProcessInfo& process_info, const OpenFilesList* open_files) {
+                             const ProcessInfo& process_info, const OpenFilesList* open_files,
+                             const Architecture* guest_arch,
+                             unwindstack::AndroidUnwinder* guest_unwinder) {
   Tombstone result;
 
   result.set_arch(get_arch());
+  if (guest_arch != nullptr) {
+    result.set_guest_arch(*guest_arch);
+  } else {
+    result.set_guest_arch(Architecture::NONE);
+  }
   result.set_build_fingerprint(android::base::GetProperty("ro.build.fingerprint", "unknown"));
   result.set_revision(android::base::GetProperty("ro.revision", "unknown"));
   result.set_timestamp(get_timestamp());
@@ -750,11 +779,11 @@
   dump_abort_message(&result, unwinder->GetProcessMemory(), process_info);
   dump_crash_details(&result, unwinder->GetProcessMemory(), process_info);
   // Dump the target thread, but save the memory around the registers.
-  dump_thread(&result, unwinder, target_thread, /* memory_dump */ true);
+  dump_thread(&result, unwinder, target_thread, /* memory_dump */ true, guest_unwinder);
 
   for (const auto& [tid, thread_info] : threads) {
     if (tid != target_tid) {
-      dump_thread(&result, unwinder, thread_info);
+      dump_thread(&result, unwinder, thread_info, /* memory_dump */ false, guest_unwinder);
     }
   }
 
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index 08c1cc0..1900719 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -79,8 +79,8 @@
   return describe_end(value, desc);
 }
 
-static const char* abi_string(const Tombstone& tombstone) {
-  switch (tombstone.arch()) {
+static const char* abi_string(const Architecture& arch) {
+  switch (arch) {
     case Architecture::ARM32:
       return "arm";
     case Architecture::ARM64:
@@ -578,11 +578,28 @@
   }
 }
 
+static void print_guest_thread(CallbackType callback, const Tombstone& tombstone,
+                               const Thread& guest_thread, pid_t tid, bool should_log) {
+  CBS("--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---");
+  CBS("Guest thread information for tid: %d", tid);
+  print_thread_registers(callback, tombstone, guest_thread, should_log);
+
+  CBS("");
+  CB(true, "%d total frames", guest_thread.current_backtrace().size());
+  CB(true, "backtrace:");
+  print_backtrace(callback, tombstone, guest_thread.current_backtrace(), should_log);
+
+  print_thread_memory_dump(callback, tombstone, guest_thread);
+}
+
 bool tombstone_proto_to_text(const Tombstone& tombstone, CallbackType callback) {
   CBL("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***");
   CBL("Build fingerprint: '%s'", tombstone.build_fingerprint().c_str());
   CBL("Revision: '%s'", tombstone.revision().c_str());
-  CBL("ABI: '%s'", abi_string(tombstone));
+  CBL("ABI: '%s'", abi_string(tombstone.arch()));
+  if (tombstone.guest_arch() != Architecture::NONE) {
+    CBL("Guest architecture: '%s'", abi_string(tombstone.guest_arch()));
+  }
   CBL("Timestamp: %s", tombstone.timestamp().c_str());
   CBL("Process uptime: %ds", tombstone.process_uptime());
 
@@ -607,6 +624,12 @@
 
   print_logs(callback, tombstone, 50);
 
+  const auto& guest_threads = tombstone.guest_threads();
+  auto main_guest_thread_it = guest_threads.find(tombstone.tid());
+  if (main_guest_thread_it != threads.end()) {
+    print_guest_thread(callback, tombstone, main_guest_thread_it->second, tombstone.tid(), true);
+  }
+
   // protobuf's map is unordered, so sort the keys first.
   std::set<int> thread_ids;
   for (const auto& [tid, _] : threads) {
@@ -618,6 +641,10 @@
   for (const auto& tid : thread_ids) {
     CBS("--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---");
     print_thread(callback, tombstone, threads.find(tid)->second);
+    auto guest_thread_it = guest_threads.find(tid);
+    if (guest_thread_it != guest_threads.end()) {
+      print_guest_thread(callback, tombstone, guest_thread_it->second, tid, false);
+    }
   }
 
   if (tombstone.open_fds().size() > 0) {