Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f88e4b7 authored by Sijie Chen's avatar Sijie Chen Committed by Gerrit Code Review
Browse files

Merge changes from topic "revert-3081452-revert-3062926-CJGHTRPCBP-GUVWVZQSHP" into main

* changes:
  Reland "[Berberis][CrashReporting] Dump guest thread inf..."
  Reland "[Berberis][CrashReporting] Extend ThreadInfo to ..."
parents c97381bf c8027933
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -452,6 +452,7 @@ cc_binary {

    header_libs: [
        "bionic_libc_platform_headers",
        "libnative_bridge_support_accessor_headers",
    ],

    static_libs: [
@@ -461,6 +462,8 @@ cc_binary {

        "libtombstone_proto",
        "libprotobuf-cpp-lite",

        "libnative_bridge_guest_state_accessor",
    ],

    shared_libs: [
@@ -476,6 +479,15 @@ cc_binary {

    // Required for tests.
    required: ["crash_dump.policy"],

    target: {
        android: {
            header_libs: [
                "libnative_bridge_support_accessor_headers", // For dlext_namespaces.h
            ],
            shared_libs: ["libdl_android"], // For android_get_exported_namespace implementation
        },
    },
}

cc_binary {
+145 −2
Original line number Diff line number Diff line
@@ -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"
@@ -68,6 +81,10 @@ using android::base::ErrnoRestorer;
using android::base::StringPrintf;
using android::base::unique_fd;

// This stores guest architecture. When the architecture is supported, tombstone file will output
// guest state information.
static Architecture g_guest_arch;

static bool pid_contains_tid(int pid_proc_fd, pid_t tid) {
  struct stat st;
  std::string task_path = StringPrintf("task/%d", tid);
@@ -403,6 +420,107 @@ static void InstallSigPipeHandler() {
  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));

      g_guest_arch = Architecture::ARM64;
      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));

      g_guest_arch = Architecture::RISCV64;
      break;
    }
#endif
    default:
      break;
  }
}

int main(int argc, char** argv) {
  DefuseSignalHandlers();
  InstallSigPipeHandler();
@@ -551,6 +669,7 @@ int main(int argc, char** argv) {
          continue;
        }
      }
      ReadGuestRegisters(&info.guest_registers, thread);

      thread_info[thread] = std::move(info);
    }
@@ -660,8 +779,32 @@ int main(int argc, char** argv) {

    {
      ATRACE_NAME("engrave_tombstone");
      unwindstack::ArchEnum regs_arch = unwindstack::ARCH_UNKNOWN;
      switch (g_guest_arch) {
        case Architecture::ARM32: {
          regs_arch = unwindstack::ARCH_ARM;
          break;
        }
        case Architecture::ARM64: {
          regs_arch = unwindstack::ARCH_ARM64;
          break;
        }
        case Architecture::RISCV64: {
          regs_arch = unwindstack::ARCH_RISCV64;
          break;
        }
        default: {
        }
      }
      if (regs_arch == unwindstack::ARCH_UNKNOWN) {
        engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,
                          g_target_thread, process_info, &open_files, &amfd_data);
      } else {
        unwindstack::AndroidRemoteUnwinder guest_unwinder(vm_pid, regs_arch);
        engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,
                          g_target_thread, process_info, &open_files, &amfd_data, &g_guest_arch,
                          &guest_unwinder);
      }
    }
  }

+6 −2
Original line number Diff line number Diff line
@@ -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 @@ void engrave_tombstone(android::base::unique_fd output_fd, android::base::unique
                       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,
+2 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ struct ThreadInfo {

  int signo = 0;
  siginfo_t* siginfo = nullptr;

  std::unique_ptr<unwindstack::Regs> guest_registers;
};

// This struct is written into a pipe from inside the crashing process.
+4 −2
Original line number Diff line number Diff line
@@ -125,10 +125,12 @@ void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd,
                       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())) {
Loading