blob: 7d3a7488a7f75331076162ee965148d12fa99eee [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/debug/third_party/libunwindstack/fuchsia/RegsFuchsia.h"
#include <zircon/syscalls.h>
#include <zircon/syscalls/debug.h>
#include "unwindstack/Elf.h"
#include "unwindstack/MachineArm64.h"
#include "unwindstack/MachineX86_64.h"
#include "unwindstack/Memory.h"
namespace unwindstack {
namespace {
constexpr uint16_t kUnwindStackRegCount = ARM64_REG_LAST;
} // namespace
RegsFuchsia::RegsFuchsia()
: RegsImpl<uint64_t>(kUnwindStackRegCount,
Location(LOCATION_SP_OFFSET, -8)) {}
RegsFuchsia::~RegsFuchsia() = default;
ArchEnum RegsFuchsia::Arch() { return ARCH_ARM64; }
void RegsFuchsia::Set(const zx_thread_state_general_regs& input) {
regs_.resize(kUnwindStackRegCount);
regs_[ARM64_REG_R0] = input.r[0];
regs_[ARM64_REG_R1] = input.r[1];
regs_[ARM64_REG_R2] = input.r[2];
regs_[ARM64_REG_R3] = input.r[3];
regs_[ARM64_REG_R4] = input.r[4];
regs_[ARM64_REG_R5] = input.r[5];
regs_[ARM64_REG_R6] = input.r[6];
regs_[ARM64_REG_R7] = input.r[7];
regs_[ARM64_REG_R8] = input.r[8];
regs_[ARM64_REG_R9] = input.r[9];
regs_[ARM64_REG_R10] = input.r[10];
regs_[ARM64_REG_R11] = input.r[11];
regs_[ARM64_REG_R12] = input.r[12];
regs_[ARM64_REG_R13] = input.r[13];
regs_[ARM64_REG_R14] = input.r[14];
regs_[ARM64_REG_R15] = input.r[15];
regs_[ARM64_REG_R16] = input.r[16];
regs_[ARM64_REG_R17] = input.r[17];
regs_[ARM64_REG_R18] = input.r[18];
regs_[ARM64_REG_R19] = input.r[19];
regs_[ARM64_REG_R20] = input.r[20];
regs_[ARM64_REG_R21] = input.r[21];
regs_[ARM64_REG_R22] = input.r[22];
regs_[ARM64_REG_R23] = input.r[23];
regs_[ARM64_REG_R24] = input.r[24];
regs_[ARM64_REG_R25] = input.r[25];
regs_[ARM64_REG_R26] = input.r[26];
regs_[ARM64_REG_R27] = input.r[27];
regs_[ARM64_REG_R28] = input.r[28];
regs_[ARM64_REG_R29] = input.r[29];
regs_[ARM64_REG_LR] = input.lr;
regs_[ARM64_REG_SP] = input.sp;
regs_[ARM64_REG_PC] = input.pc;
}
zx_status_t RegsFuchsia::Read(zx_handle_t thread) {
zx_thread_state_general_regs thread_regs;
zx_status_t status = zx_thread_read_state(
thread, ZX_THREAD_STATE_GENERAL_REGS, &thread_regs, sizeof(thread_regs));
if (status != ZX_OK)
return status;
Set(thread_regs);
return ZX_OK;
}
uint64_t RegsFuchsia::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
if (rel_pc < 4) {
return 0;
}
return 4;
}
bool RegsFuchsia::SetPcFromReturnAddress(Memory* process_memory) {
uint64_t lr = regs_[ARM64_REG_LR];
if (regs_[ARM64_REG_PC] == lr) {
return false;
}
regs_[ARM64_REG_PC] = lr;
return true;
}
bool RegsFuchsia::StepIfSignalHandler(uint64_t rel_pc, Elf* elf,
Memory* process_memory) {
// TODO(brettw) Figure out if we need to implement this.
return false;
}
void RegsFuchsia::IterateRegisters(
std::function<void(const char*, uint64_t)> fn) {
if (IsDefined(ARM64_REG_R0))
fn("x0", regs_[ARM64_REG_R0]);
if (IsDefined(ARM64_REG_R1))
fn("x1", regs_[ARM64_REG_R1]);
if (IsDefined(ARM64_REG_R2))
fn("x2", regs_[ARM64_REG_R2]);
if (IsDefined(ARM64_REG_R3))
fn("x3", regs_[ARM64_REG_R3]);
if (IsDefined(ARM64_REG_R4))
fn("x4", regs_[ARM64_REG_R4]);
if (IsDefined(ARM64_REG_R5))
fn("x5", regs_[ARM64_REG_R5]);
if (IsDefined(ARM64_REG_R6))
fn("x6", regs_[ARM64_REG_R6]);
if (IsDefined(ARM64_REG_R7))
fn("x7", regs_[ARM64_REG_R7]);
if (IsDefined(ARM64_REG_R8))
fn("x8", regs_[ARM64_REG_R8]);
if (IsDefined(ARM64_REG_R9))
fn("x9", regs_[ARM64_REG_R9]);
if (IsDefined(ARM64_REG_R10))
fn("x10", regs_[ARM64_REG_R10]);
if (IsDefined(ARM64_REG_R11))
fn("x11", regs_[ARM64_REG_R11]);
if (IsDefined(ARM64_REG_R12))
fn("x12", regs_[ARM64_REG_R12]);
if (IsDefined(ARM64_REG_R13))
fn("x13", regs_[ARM64_REG_R13]);
if (IsDefined(ARM64_REG_R14))
fn("x14", regs_[ARM64_REG_R14]);
if (IsDefined(ARM64_REG_R15))
fn("x15", regs_[ARM64_REG_R15]);
if (IsDefined(ARM64_REG_R16))
fn("x16", regs_[ARM64_REG_R16]);
if (IsDefined(ARM64_REG_R17))
fn("x17", regs_[ARM64_REG_R17]);
if (IsDefined(ARM64_REG_R18))
fn("x18", regs_[ARM64_REG_R18]);
if (IsDefined(ARM64_REG_R19))
fn("x19", regs_[ARM64_REG_R19]);
if (IsDefined(ARM64_REG_R20))
fn("x20", regs_[ARM64_REG_R20]);
if (IsDefined(ARM64_REG_R21))
fn("x21", regs_[ARM64_REG_R21]);
if (IsDefined(ARM64_REG_R22))
fn("x22", regs_[ARM64_REG_R22]);
if (IsDefined(ARM64_REG_R23))
fn("x23", regs_[ARM64_REG_R23]);
if (IsDefined(ARM64_REG_R24))
fn("x24", regs_[ARM64_REG_R24]);
if (IsDefined(ARM64_REG_R25))
fn("x25", regs_[ARM64_REG_R25]);
if (IsDefined(ARM64_REG_R26))
fn("x26", regs_[ARM64_REG_R26]);
if (IsDefined(ARM64_REG_R27))
fn("x27", regs_[ARM64_REG_R27]);
if (IsDefined(ARM64_REG_R28))
fn("x28", regs_[ARM64_REG_R28]);
if (IsDefined(ARM64_REG_R29))
fn("x29", regs_[ARM64_REG_R29]);
if (IsDefined(ARM64_REG_SP))
fn("sp", regs_[ARM64_REG_SP]);
if (IsDefined(ARM64_REG_LR))
fn("lr", regs_[ARM64_REG_LR]);
if (IsDefined(ARM64_REG_PC))
fn("pc", regs_[ARM64_REG_PC]);
}
uint64_t RegsFuchsia::pc() { return regs_[ARM64_REG_PC]; }
uint64_t RegsFuchsia::sp() { return regs_[ARM64_REG_SP]; }
void RegsFuchsia::set_pc(uint64_t pc) { regs_[ARM64_REG_PC] = pc; }
void RegsFuchsia::set_sp(uint64_t sp) { regs_[ARM64_REG_SP] = sp; }
Regs* RegsFuchsia::Clone() { return new RegsFuchsia(*this); }
} // namespace unwindstack