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

Commit 1add237c authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Add full support for initing registers."

parents 896297b2 2a25c4aa
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -64,6 +64,15 @@ cc_defaults {
        "Symbols.cpp",
    ],

    arch: {
        x86: {
            srcs: ["AsmGetRegsX86.S"],
        },
        x86_64: {
            srcs: ["AsmGetRegsX86_64.S"],
        },
    },

    shared_libs: [
        "libbase",
        "liblog",
@@ -112,6 +121,7 @@ cc_defaults {
        "tests/MemoryTest.cpp",
        "tests/RegsTest.cpp",
        "tests/SymbolsTest.cpp",
        "tests/UnwindTest.cpp",
    ],

    cflags: [
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

  .text
  .global AsmGetRegs
  .balign 16
  .type AsmGetRegs, @function
AsmGetRegs:
  .cfi_startproc
  mov 4(%esp), %eax
  movl $0, (%eax)
  movl %ecx, 4(%eax)
  movl %edx, 8(%eax)
  movl %ebx, 12(%eax)

  /* ESP */
  leal 4(%esp), %ecx
  movl %ecx, 16(%eax)

  movl %ebp, 20(%eax)
  movl %esi, 24(%eax)
  movl %edi, 28(%eax)

  /* EIP */
  movl (%esp), %ecx
  movl %ecx, 32(%eax)

  movl %cs, 36(%eax)
  movl %ss, 40(%eax)
  movl %ds, 44(%eax)
  movl %es, 48(%eax)
  movl %fs, 52(%eax)
  movl %gs, 56(%eax)
  ret

  .cfi_endproc
  .size AsmGetRegs, .-AsmGetRegs
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

  .text
  .global AsmGetRegs
  .balign 16
  .type AsmGetRegs, @function
AsmGetRegs:
  .cfi_startproc
  movq %rax, (%rdi)
  movq %rdx, 8(%rdi)
  movq %rcx, 16(%rdi)
  movq %rbx, 24(%rdi)
  movq %rsi, 32(%rdi)
  movq %rdi, 40(%rdi)
  movq %rbp, 48(%rdi)

  /* RSP */
  lea 8(%rsp), %rax
  movq %rax, 56(%rdi)

  movq %r8, 64(%rdi)
  movq %r9, 72(%rdi)
  movq %r10, 80(%rdi)
  movq %r11, 88(%rdi)
  movq %r12, 96(%rdi)
  movq %r13, 104(%rdi)
  movq %r14, 112(%rdi)
  movq %r15, 120(%rdi)

  /* RIP */
  movq (%rsp), %rax
  movq %rax, 128(%rdi)
  ret

  .cfi_endproc
  .size AsmGetRegs, .-AsmGetRegs
+35 −31
Original line number Diff line number Diff line
@@ -83,47 +83,51 @@ enum Arm64Reg : uint16_t {
  ARM64_REG_LR = ARM64_REG_R30,
};

// Matches the numbers for the registers as generated by compilers.
// If this is changed, then unwinding will fail.
enum X86Reg : uint16_t {
  X86_REG_EAX = 0,
  X86_REG_ECX,
  X86_REG_EDX,
  X86_REG_EBX,
  X86_REG_ESP,
  X86_REG_EBP,
  X86_REG_ESI,
  X86_REG_EDI,
  X86_REG_EIP,
  X86_REG_EFL,
  X86_REG_CS,
  X86_REG_SS,
  X86_REG_DS,
  X86_REG_ES,
  X86_REG_FS,
  X86_REG_GS,
  X86_REG_ECX = 1,
  X86_REG_EDX = 2,
  X86_REG_EBX = 3,
  X86_REG_ESP = 4,
  X86_REG_EBP = 5,
  X86_REG_ESI = 6,
  X86_REG_EDI = 7,
  X86_REG_EIP = 8,
  X86_REG_EFL = 9,
  X86_REG_CS = 10,
  X86_REG_SS = 11,
  X86_REG_DS = 12,
  X86_REG_ES = 13,
  X86_REG_FS = 14,
  X86_REG_GS = 15,
  X86_REG_LAST,

  X86_REG_SP = X86_REG_ESP,
  X86_REG_PC = X86_REG_EIP,
};

// Matches the numbers for the registers as generated by compilers.
// If this is changed, then unwinding will fail.
enum X86_64Reg : uint16_t {
  X86_64_REG_RAX = 0,
  X86_64_REG_RDX,
  X86_64_REG_RCX,
  X86_64_REG_RBX,
  X86_64_REG_RSI,
  X86_64_REG_RDI,
  X86_64_REG_RBP,
  X86_64_REG_RSP,
  X86_64_REG_R8,
  X86_64_REG_R9,
  X86_64_REG_R10,
  X86_64_REG_R11,
  X86_64_REG_R12,
  X86_64_REG_R13,
  X86_64_REG_R14,
  X86_64_REG_R15,
  X86_64_REG_RIP,
  X86_64_REG_RDX = 1,
  X86_64_REG_RCX = 2,
  X86_64_REG_RBX = 3,
  X86_64_REG_RSI = 4,
  X86_64_REG_RDI = 5,
  X86_64_REG_RBP = 6,
  X86_64_REG_RSP = 7,
  X86_64_REG_R8 = 8,
  X86_64_REG_R9 = 9,
  X86_64_REG_R10 = 10,
  X86_64_REG_R11 = 11,
  X86_64_REG_R12 = 12,
  X86_64_REG_R13 = 13,
  X86_64_REG_R14 = 14,
  X86_64_REG_R15 = 15,
  X86_64_REG_RIP = 16,
  X86_64_REG_LAST,

  X86_64_REG_SP = X86_64_REG_RSP,
+136 −13
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "Machine.h"
#include "MapInfo.h"
#include "Regs.h"
#include "Ucontext.h"
#include "User.h"

template <typename AddressType>
@@ -88,6 +89,11 @@ uint64_t RegsArm::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
  return rel_pc - 4;
}

void RegsArm::SetFromRaw() {
  set_pc(regs_[ARM_REG_PC]);
  set_sp(regs_[ARM_REG_SP]);
}

RegsArm64::RegsArm64()
    : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}

@@ -102,6 +108,11 @@ uint64_t RegsArm64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
  return rel_pc - 4;
}

void RegsArm64::SetFromRaw() {
  set_pc(regs_[ARM64_REG_PC]);
  set_sp(regs_[ARM64_REG_SP]);
}

RegsX86::RegsX86()
    : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {}

@@ -116,6 +127,11 @@ uint64_t RegsX86::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
  return rel_pc - 1;
}

void RegsX86::SetFromRaw() {
  set_pc(regs_[X86_REG_PC]);
  set_sp(regs_[X86_REG_SP]);
}

RegsX86_64::RegsX86_64()
    : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {}

@@ -131,15 +147,17 @@ uint64_t RegsX86_64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
  return rel_pc - 1;
}

void RegsX86_64::SetFromRaw() {
  set_pc(regs_[X86_64_REG_PC]);
  set_sp(regs_[X86_64_REG_SP]);
}

static Regs* ReadArm(void* remote_data) {
  arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data);

  RegsArm* regs = new RegsArm();
  memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));

  regs->set_pc(user->regs[ARM_REG_PC]);
  regs->set_sp(user->regs[ARM_REG_SP]);

  regs->SetFromRaw();
  return regs;
}

@@ -148,9 +166,10 @@ static Regs* ReadArm64(void* remote_data) {

  RegsArm64* regs = new RegsArm64();
  memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R31 + 1) * sizeof(uint64_t));
  regs->set_pc(user->pc);
  regs->set_sp(user->sp);

  uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
  reg_data[ARM64_REG_PC] = user->pc;
  reg_data[ARM64_REG_SP] = user->sp;
  regs->SetFromRaw();
  return regs;
}

@@ -168,9 +187,7 @@ static Regs* ReadX86(void* remote_data) {
  (*regs)[X86_REG_ESP] = user->esp;
  (*regs)[X86_REG_EIP] = user->eip;

  regs->set_pc(user->eip);
  regs->set_sp(user->esp);

  regs->SetFromRaw();
  return regs;
}

@@ -196,9 +213,7 @@ static Regs* ReadX86_64(void* remote_data) {
  (*regs)[X86_64_REG_RSP] = user->rsp;
  (*regs)[X86_64_REG_RIP] = user->rip;

  regs->set_pc(user->rip);
  regs->set_sp(user->rsp);

  regs->SetFromRaw();
  return regs;
}

@@ -231,3 +246,111 @@ Regs* Regs::RemoteGet(pid_t pid, uint32_t* machine_type) {
  }
  return nullptr;
}

static Regs* CreateFromArmUcontext(void* ucontext) {
  arm_ucontext_t* arm_ucontext = reinterpret_cast<arm_ucontext_t*>(ucontext);

  RegsArm* regs = new RegsArm();
  memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t));
  regs->SetFromRaw();
  return regs;
}

static Regs* CreateFromArm64Ucontext(void* ucontext) {
  arm64_ucontext_t* arm64_ucontext = reinterpret_cast<arm64_ucontext_t*>(ucontext);

  RegsArm64* regs = new RegsArm64();
  memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t));
  regs->SetFromRaw();
  return regs;
}

static Regs* CreateFromX86Ucontext(void* ucontext) {
  x86_ucontext_t* x86_ucontext = reinterpret_cast<x86_ucontext_t*>(ucontext);

  RegsX86* regs = new RegsX86();
  // Put the registers in the expected order.
  (*regs)[X86_REG_GS] = x86_ucontext->uc_mcontext.gs;
  (*regs)[X86_REG_FS] = x86_ucontext->uc_mcontext.fs;
  (*regs)[X86_REG_ES] = x86_ucontext->uc_mcontext.es;
  (*regs)[X86_REG_DS] = x86_ucontext->uc_mcontext.ds;
  (*regs)[X86_REG_EDI] = x86_ucontext->uc_mcontext.edi;
  (*regs)[X86_REG_ESI] = x86_ucontext->uc_mcontext.esi;
  (*regs)[X86_REG_EBP] = x86_ucontext->uc_mcontext.ebp;
  (*regs)[X86_REG_ESP] = x86_ucontext->uc_mcontext.esp;
  (*regs)[X86_REG_EBX] = x86_ucontext->uc_mcontext.ebx;
  (*regs)[X86_REG_EDX] = x86_ucontext->uc_mcontext.edx;
  (*regs)[X86_REG_ECX] = x86_ucontext->uc_mcontext.ecx;
  (*regs)[X86_REG_EAX] = x86_ucontext->uc_mcontext.eax;
  (*regs)[X86_REG_EIP] = x86_ucontext->uc_mcontext.eip;
  regs->SetFromRaw();
  return regs;
}

static Regs* CreateFromX86_64Ucontext(void* ucontext) {
  x86_64_ucontext_t* x86_64_ucontext = reinterpret_cast<x86_64_ucontext_t*>(ucontext);

  RegsX86_64* regs = new RegsX86_64();
  // Put the registers in the expected order.

  // R8-R15
  memcpy(&(*regs)[X86_64_REG_R8], &x86_64_ucontext->uc_mcontext.r8, 8 * sizeof(uint64_t));

  // Rest of the registers.
  (*regs)[X86_64_REG_RDI] = x86_64_ucontext->uc_mcontext.rdi;
  (*regs)[X86_64_REG_RSI] = x86_64_ucontext->uc_mcontext.rsi;
  (*regs)[X86_64_REG_RBP] = x86_64_ucontext->uc_mcontext.rbp;
  (*regs)[X86_64_REG_RBX] = x86_64_ucontext->uc_mcontext.rbx;
  (*regs)[X86_64_REG_RDX] = x86_64_ucontext->uc_mcontext.rdx;
  (*regs)[X86_64_REG_RAX] = x86_64_ucontext->uc_mcontext.rax;
  (*regs)[X86_64_REG_RCX] = x86_64_ucontext->uc_mcontext.rcx;
  (*regs)[X86_64_REG_RSP] = x86_64_ucontext->uc_mcontext.rsp;
  (*regs)[X86_64_REG_RIP] = x86_64_ucontext->uc_mcontext.rip;

  regs->SetFromRaw();
  return regs;
}

Regs* Regs::CreateFromUcontext(uint32_t machine_type, void* ucontext) {
  switch (machine_type) {
    case EM_386:
      return CreateFromX86Ucontext(ucontext);
    case EM_X86_64:
      return CreateFromX86_64Ucontext(ucontext);
    case EM_ARM:
      return CreateFromArmUcontext(ucontext);
    case EM_AARCH64:
      return CreateFromArm64Ucontext(ucontext);
  }
  return nullptr;
}

uint32_t Regs::GetMachineType() {
#if defined(__arm__)
  return EM_ARM;
#elif defined(__aarch64__)
  return EM_AARCH64;
#elif defined(__i386__)
  return EM_386;
#elif defined(__x86_64__)
  return EM_X86_64;
#else
  abort();
#endif
}

Regs* Regs::CreateFromLocal() {
  Regs* regs;
#if defined(__arm__)
  regs = new RegsArm();
#elif defined(__aarch64__)
  regs = new RegsArm64();
#elif defined(__i386__)
  regs = new RegsX86();
#elif defined(__x86_64__)
  regs = new RegsX86_64();
#else
  abort();
#endif
  return regs;
}
Loading