blob: 382fd92682ade98f9a3db6d8ac3c2da79368db1f [file] [log] [blame]
// Copyright 2016 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 <cstring>
#include <src/lib/fxl/arraysize.h>
#include <src/lib/fxl/logging.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/debug.h>
#include "garnet/lib/debugger_utils/util.h"
#include "registers.h"
namespace inferior_control {
namespace {
class RegistersArm64 final : public Registers {
public:
static constexpr int kNumGeneralRegisters = 34;
RegistersArm64(Thread* thread) : Registers(thread) {}
bool GetRegister(int regno, void* buffer, size_t buf_size) override {
if (regno < 0 || regno >= kNumGeneralRegisters) {
FXL_LOG(ERROR) << "Bad register_number: " << regno;
return false;
}
// On arm64 all general register values are 64-bit.
// Note that this includes CPSR, whereas in the GDB RSP CPSR is 32 bits.
if (buf_size != sizeof(uint64_t)) {
FXL_LOG(ERROR) << "Bad buffer size: " << buf_size;
return false;
}
auto greg_bytes = reinterpret_cast<const uint8_t*>(&general_regs_);
greg_bytes += regno * sizeof(uint64_t);
std::memcpy(buffer, greg_bytes, buf_size);
FXL_VLOG(2) << "Get register " << regno << " = "
<< debugger_utils::EncodeByteArrayString(greg_bytes, buf_size);
return true;
}
bool SetRegister(int regno, const void* value, size_t value_size) override {
if (regno < 0 || regno >= kNumGeneralRegisters) {
FXL_LOG(ERROR) << "Invalid arm64 register number: " << regno;
return false;
}
// On arm64 all general register values are 64-bit.
// Note that this includes CPSR, whereas in the GDB RSP CPSR is 32 bits.
if (value_size != sizeof(uint64_t)) {
FXL_LOG(ERROR) << "Invalid arm64 register value size: " << value_size;
return false;
}
auto greg_bytes = reinterpret_cast<uint8_t*>(&general_regs_);
greg_bytes += regno * sizeof(uint64_t);
std::memcpy(greg_bytes, value, value_size);
FXL_VLOG(2) << "Set register " << regno << " = "
<< debugger_utils::EncodeByteArrayString(greg_bytes,
value_size);
return true;
}
zx_vaddr_t GetPC() override {
return general_regs_.pc;
}
zx_vaddr_t GetSP() override {
return general_regs_.sp;
}
zx_vaddr_t GetFP() override {
return general_regs_.r[29];
}
void SetPC(zx_vaddr_t pc) override {
general_regs_.pc = pc;
}
bool SetSingleStep(bool enable) override {
FXL_NOTIMPLEMENTED();
return false;
}
std::string GetFormattedRegset(int regset) override {
return "unimplemented\n";
}
};
} // namespace
// static
std::unique_ptr<Registers> Registers::Create(Thread* thread) {
return std::unique_ptr<Registers>(new RegistersArm64(thread));
}
} // namespace inferior_control