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

Commit 2a25c4aa authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Add full support for initing registers.

- Fixes a few bugs in untested functionality.
- Add tests for the way the register handling code is used.
- Fix a few tests that were not reaping child processes.

Bug: 23762183

Test: Ran unit tests on host (32 bit and 64 bit).
Test: Ran unit tests on angler (32 bit and 64 bit).
Change-Id: I573d6617b4f1561f6e8494d7213c52086d112d97
parent 896297b2
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