Reland "[Berberis][CrashReporting] Extend ThreadInfo to ..."

Revert submission 3081452-revert-3062926-CJGHTRPCBP

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

(Original CL commit message)
This CL is to get guest registers information.

Bug: b/321799516
Test: m
Testing for TLS Slot:
Manual testing by: 1. crash the jni tests to produce tombstones file 2.
get the signature field of guest state header 3. verified it is the same
value as NATIVE_BRIDGE_GUEST_STATE_SIGNATURE

Manual test the arm64 by: 1. flash build to pixel phone and verify
retrieving TLS_SLOT_THREAD_ID's tid field is the same as current thread
id.

Testing for register values:
Test and print out registers values for riscv64, looks make sense that
has null zero value slots.

Change-Id: Ieebf845bff517380ee07fac77f24b48efeb53521
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 203b485..6706650 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -25,6 +25,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <cstdint>
 #include <limits>
 #include <map>
 #include <memory>
@@ -42,6 +43,7 @@
 #include <android-base/unique_fd.h>
 #include <bionic/macros.h>
 #include <bionic/reserved_signals.h>
+#include <bionic/tls_defines.h>
 #include <cutils/sockets.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
@@ -52,7 +54,18 @@
 
 #include <unwindstack/AndroidUnwinder.h>
 #include <unwindstack/Error.h>
+#include <unwindstack/MachineArm.h>
+#include <unwindstack/MachineArm64.h>
+#include <unwindstack/MachineRiscv64.h>
 #include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
+#include <unwindstack/RegsArm64.h>
+#include <unwindstack/RegsRiscv64.h>
+#include <unwindstack/UserArm.h>
+#include <unwindstack/UserArm64.h>
+#include <unwindstack/UserRiscv64.h>
+
+#include <native_bridge_support/guest_state_accessor/accessor.h>
 
 #include "libdebuggerd/backtrace.h"
 #include "libdebuggerd/tombstone.h"
@@ -403,6 +416,103 @@
   sigaction(SIGPIPE, &action, nullptr);
 }
 
+static bool PtracePeek(int request, pid_t tid, uintptr_t addr, void* data, std::string_view err_msg,
+                       uintptr_t* result) {
+  errno = 0;
+  *result = ptrace(request, tid, addr, data);
+  if (errno != 0) {
+    PLOG(ERROR) << err_msg;
+    return false;
+  }
+  return true;
+}
+
+static bool GetGuestRegistersFromCrashedProcess([[maybe_unused]] pid_t tid,
+                                                NativeBridgeGuestRegs* guest_regs) {
+  auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(tid);
+
+  uintptr_t header_ptr = 0;
+  uintptr_t base = 0;
+#if defined(__x86_64__)
+  if (!PtracePeek(PTRACE_PEEKUSER, tid, offsetof(user_regs_struct, fs_base), nullptr,
+                  "failed to read thread register for thread " + std::to_string(tid), &base)) {
+    return false;
+  }
+#elif defined(__aarch64__)
+  // base is implicitly casted to uint64_t.
+  struct iovec pt_iov {
+    .iov_base = &base, .iov_len = sizeof(base),
+  };
+
+  if (ptrace(PTRACE_GETREGSET, tid, NT_ARM_TLS, &pt_iov) != 0) {
+    PLOG(ERROR) << "failed to read thread register for thread " << tid;
+  }
+#else
+  // TODO(b/339287219): Add case for Riscv host.
+  return false;
+#endif
+  auto ptr_to_guest_slot = base + TLS_SLOT_NATIVE_BRIDGE_GUEST_STATE * sizeof(uintptr_t);
+  if (!process_memory->ReadFully(ptr_to_guest_slot, &header_ptr, sizeof(uintptr_t))) {
+    PLOG(ERROR) << "failed to get guest state TLS slot content for thread " << tid;
+    return false;
+  }
+
+  NativeBridgeGuestStateHeader header;
+  if (!process_memory->ReadFully(header_ptr, &header, sizeof(NativeBridgeGuestStateHeader))) {
+    PLOG(ERROR) << "failed to get the guest state header for thread " << tid;
+    return false;
+  }
+  if (header.signature != NATIVE_BRIDGE_GUEST_STATE_SIGNATURE) {
+    // Return when ptr points to unmapped memory or no valid guest state.
+    return false;
+  }
+  auto guest_state_data_copy = std::make_unique<unsigned char[]>(header.guest_state_data_size);
+  if (!process_memory->ReadFully(reinterpret_cast<uintptr_t>(header.guest_state_data),
+                                 guest_state_data_copy.get(), header.guest_state_data_size)) {
+    PLOG(ERROR) << "failed to read the guest state data for thread " << tid;
+    return false;
+  }
+
+  LoadGuestStateRegisters(guest_state_data_copy.get(), header.guest_state_data_size, guest_regs);
+  return true;
+}
+
+static void ReadGuestRegisters([[maybe_unused]] std::unique_ptr<unwindstack::Regs>* regs,
+                               pid_t tid) {
+  // TODO: remove [[maybe_unused]], when the ARM32 case is removed from the native bridge support.
+  NativeBridgeGuestRegs guest_regs;
+  if (!GetGuestRegistersFromCrashedProcess(tid, &guest_regs)) {
+    return;
+  }
+
+  switch (guest_regs.guest_arch) {
+#if defined(__LP64__)
+    case NATIVE_BRIDGE_ARCH_ARM64: {
+      unwindstack::arm64_user_regs arm64_user_regs = {};
+      for (size_t i = 0; i < unwindstack::ARM64_REG_R31; i++) {
+        arm64_user_regs.regs[i] = guest_regs.regs_arm64.x[i];
+      }
+      arm64_user_regs.sp = guest_regs.regs_arm64.sp;
+      arm64_user_regs.pc = guest_regs.regs_arm64.ip;
+      regs->reset(unwindstack::RegsArm64::Read(&arm64_user_regs));
+      break;
+    }
+    case NATIVE_BRIDGE_ARCH_RISCV64: {
+      unwindstack::riscv64_user_regs riscv64_user_regs = {};
+      // RISCV64_REG_PC is at the first position.
+      riscv64_user_regs.regs[0] = guest_regs.regs_riscv64.ip;
+      for (size_t i = 1; i < unwindstack::RISCV64_REG_REAL_COUNT; i++) {
+        riscv64_user_regs.regs[i] = guest_regs.regs_riscv64.x[i];
+      }
+      regs->reset(unwindstack::RegsRiscv64::Read(&riscv64_user_regs, tid));
+      break;
+    }
+#endif
+    default:
+      break;
+  }
+}
+
 int main(int argc, char** argv) {
   DefuseSignalHandlers();
   InstallSigPipeHandler();
@@ -551,6 +661,7 @@
           continue;
         }
       }
+      ReadGuestRegisters(&info.guest_registers, thread);
 
       thread_info[thread] = std::move(info);
     }