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

Commit 4ce3fbd3 authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Add support for getting TLS on all arches." into main

parents 9807450a a7911182
Loading
Loading
Loading
Loading
+51 −17
Original line number Diff line number Diff line
@@ -22,9 +22,14 @@
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <unistd.h>

#if defined(__i386__)
#include <asm/ldt.h>
#endif

#include <cstdint>
#include <limits>
#include <map>
@@ -430,18 +435,12 @@ static bool PtracePeek(int request, pid_t tid, uintptr_t addr, void* data, std::
  return true;
}

static bool GetGuestRegistersFromCrashedProcess([[maybe_unused]] pid_t tid,
                                                NativeBridgeGuestRegs* guest_regs) {
static bool GetGuestRegistersFromCrashedProcess(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__)
#if defined(__aarch64__)
  // base is implicitly casted to uint64_t.
  struct iovec pt_iov {
    .iov_base = &base, .iov_len = sizeof(base),
@@ -451,6 +450,26 @@ static bool GetGuestRegistersFromCrashedProcess([[maybe_unused]] pid_t tid,
    PLOG(ERROR) << "failed to read thread register for thread " << tid;
    return false;
  }
#elif defined(__arm__)
  if (ptrace(PTRACE_GET_THREAD_AREA, tid, nullptr, &base) == 0) {
    PLOG(ERROR) << "failed to get thread area for thread " << tid;
    return false;
  }
#elif defined(__i386__)
  struct user_regs_struct regs;
  struct iovec pt_iov = {.iov_base = &regs, .iov_len = sizeof(regs)};
  if (ptrace(PTRACE_GETREGSET, tid, NT_PRSTATUS, &pt_iov) != 0) {
    PLOG(ERROR) << "failed to get registers for thread " << tid;
    return false;
  }

  struct user_desc desc;
  desc.entry_number = regs.xgs >> 3;
  if (ptrace(PTRACE_GET_THREAD_AREA, tid, desc.entry_number, &desc) != 0) {
    PLOG(ERROR) << "failed to get thread area for thread " << tid;
    return false;
  }
  base = desc.base_addr;
#elif defined(__riscv)
  struct user_regs_struct regs;
  struct iovec pt_iov = {.iov_base = &regs, .iov_len = sizeof(regs)};
@@ -459,6 +478,11 @@ static bool GetGuestRegistersFromCrashedProcess([[maybe_unused]] pid_t tid,
    return false;
  }
  base = reinterpret_cast<uintptr_t>(regs.tp);
#elif 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;
  }
#else
  // TODO(b/339287219): Add case for Riscv host.
  return false;
@@ -487,9 +511,7 @@ static bool GetGuestRegistersFromCrashedProcess([[maybe_unused]] pid_t tid,
  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.
static void ReadGuestRegisters(std::unique_ptr<unwindstack::Regs>* regs, pid_t tid) {
  NativeBridgeGuestRegs guest_regs;
  if (!GetGuestRegistersFromCrashedProcess(tid, &guest_regs)) {
    return;
@@ -521,6 +543,17 @@ static void ReadGuestRegisters([[maybe_unused]] std::unique_ptr<unwindstack::Reg
      g_guest_arch = Architecture::RISCV64;
      break;
    }
#else
    case NATIVE_BRIDGE_ARCH_ARM: {
      unwindstack::arm_user_regs arm_user_regs = {};
      regs->reset(unwindstack::RegsArm::Read(&arm_user_regs));
      for (size_t i = 0; i < unwindstack::ARM_REG_LAST; i++) {
        arm_user_regs.regs[i] = guest_regs.regs_arm.r[i];
      }

      g_guest_arch = Architecture::ARM32;
      break;
    }
#endif
    default:
      break;
@@ -796,16 +829,17 @@ int main(int argc, char** argv) {
      ATRACE_NAME("engrave_tombstone");
      unwindstack::ArchEnum regs_arch = unwindstack::ARCH_UNKNOWN;
      switch (g_guest_arch) {
        case Architecture::ARM64: {
        case Architecture::ARM32:
          regs_arch = unwindstack::ARCH_ARM;
          break;
        case Architecture::ARM64:
          regs_arch = unwindstack::ARCH_ARM64;
          break;
        }
        case Architecture::RISCV64: {
        case Architecture::RISCV64:
          regs_arch = unwindstack::ARCH_RISCV64;
          break;
        }
        default: {
        }
        default:
          break;
      }
      if (regs_arch == unwindstack::ARCH_UNKNOWN) {
        engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,