9#if defined(__riscv) && __riscv_xlen == 64
26#include <sys/ptrace.h>
29#ifndef PTRACE_GETREGSET
30#define PTRACE_GETREGSET 0x4204
37std::unique_ptr<NativeRegisterContextLinux>
40 switch (target_arch.GetMachine()) {
41 case llvm::Triple::riscv64: {
46 ioVec.iov_base = &fpr;
47 ioVec.iov_len =
sizeof(fpr);
48 unsigned int regset = NT_FPREGSET;
51 native_thread.
GetID(), ®set,
57 auto register_info_up =
58 std::make_unique<RegisterInfoPOSIX_riscv64>(target_arch, opt_regsets);
59 return std::make_unique<NativeRegisterContextLinux_riscv64>(
60 target_arch, native_thread, std::move(register_info_up));
63 llvm_unreachable(
"have no register context for architecture");
67llvm::Expected<ArchSpec>
69 return HostInfo::GetArchitecture();
72NativeRegisterContextLinux_riscv64::NativeRegisterContextLinux_riscv64(
74 std::unique_ptr<RegisterInfoPOSIX_riscv64> register_info_up)
76 register_info_up.release()),
78 ::memset(&m_fpr, 0,
sizeof(m_fpr));
79 ::memset(&m_gpr, 0,
sizeof(m_gpr));
81 m_gpr_is_valid =
false;
82 m_fpu_is_valid =
false;
86NativeRegisterContextLinux_riscv64::GetRegisterInfo()
const {
91uint32_t NativeRegisterContextLinux_riscv64::GetRegisterSetCount()
const {
96NativeRegisterContextLinux_riscv64::GetRegisterSet(uint32_t set_index)
const {
97 return GetRegisterInfo().GetRegisterSet(set_index);
100uint32_t NativeRegisterContextLinux_riscv64::GetUserRegisterCount()
const {
102 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
108NativeRegisterContextLinux_riscv64::ReadRegister(
const RegisterInfo *reg_info,
121 "no lldb regnum for %s",
122 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
129 uint8_t *src =
nullptr;
138 assert(offset < GetGPRSize());
139 src = (uint8_t *)GetGPRBuffer() + offset;
141 }
else if (IsFPR(reg)) {
146 offset = CalculateFprOffset(reg_info);
147 assert(offset < GetFPRSize());
148 src = (uint8_t *)GetFPRBuffer() + offset;
151 "failed - register wasn't recognized to be a GPR or an FPR, "
152 "write strategy unknown");
160Status NativeRegisterContextLinux_riscv64::WriteRegister(
171 "no lldb regnum for %s",
172 reg_info->
name !=
nullptr ? reg_info->
name :
"<unknown register>");
179 uint8_t *dst =
nullptr;
188 dst = (uint8_t *)GetGPRBuffer() + reg_info->
byte_offset;
192 }
else if (IsFPR(reg)) {
197 offset = CalculateFprOffset(reg_info);
198 assert(offset < GetFPRSize());
199 dst = (uint8_t *)GetFPRBuffer() + offset;
208Status NativeRegisterContextLinux_riscv64::ReadAllRegisterValues(
218 if (GetRegisterInfo().IsFPPresent()) {
224 uint8_t *dst =
const_cast<uint8_t *
>(data_sp->GetBytes());
225 ::memcpy(dst, GetGPRBuffer(), GetGPRSize());
227 if (GetRegisterInfo().IsFPPresent())
228 ::memcpy(dst, GetFPRBuffer(), GetFPRSize());
233Status NativeRegisterContextLinux_riscv64::WriteAllRegisterValues(
239 "NativeRegisterContextLinux_riscv64::%s invalid data_sp provided",
244 if (data_sp->GetByteSize() != GetRegContextSize()) {
246 "NativeRegisterContextLinux_riscv64::%s data_sp contained mismatched "
247 "data size, expected %" PRIu64
", actual %" PRIu64,
248 __FUNCTION__, GetRegContextSize(), data_sp->GetByteSize());
252 uint8_t *src =
const_cast<uint8_t *
>(data_sp->GetBytes());
253 if (src ==
nullptr) {
255 "NativeRegisterContextLinux_riscv64::%s "
256 "DataBuffer::GetBytes() returned a null "
261 ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize());
267 src += GetRegisterInfoInterface().GetGPRSize();
269 if (GetRegisterInfo().IsFPPresent()) {
270 ::memcpy(GetFPRBuffer(), src, GetFPRSize());
280size_t NativeRegisterContextLinux_riscv64::GetRegContextSize() {
281 size_t size = GetGPRSize();
282 if (GetRegisterInfo().IsFPPresent())
283 size += GetFPRSize();
287bool NativeRegisterContextLinux_riscv64::IsGPR(
unsigned reg)
const {
288 return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
292bool NativeRegisterContextLinux_riscv64::IsFPR(
unsigned reg)
const {
293 return GetRegisterInfo().IsFPReg(reg);
296Status NativeRegisterContextLinux_riscv64::ReadGPR() {
303 ioVec.iov_base = GetGPRBuffer();
304 ioVec.iov_len = GetGPRSize();
306 error = ReadRegisterSet(&ioVec, GetGPRSize(), NT_PRSTATUS);
309 m_gpr_is_valid =
true;
314Status NativeRegisterContextLinux_riscv64::WriteGPR() {
320 ioVec.iov_base = GetGPRBuffer();
321 ioVec.iov_len = GetGPRSize();
323 m_gpr_is_valid =
false;
325 return WriteRegisterSet(&ioVec, GetGPRSize(), NT_PRSTATUS);
328Status NativeRegisterContextLinux_riscv64::ReadFPR() {
335 ioVec.iov_base = GetFPRBuffer();
336 ioVec.iov_len = GetFPRSize();
338 error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
341 m_fpu_is_valid =
true;
346Status NativeRegisterContextLinux_riscv64::WriteFPR() {
352 ioVec.iov_base = GetFPRBuffer();
353 ioVec.iov_len = GetFPRSize();
355 m_fpu_is_valid =
false;
357 return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
360void NativeRegisterContextLinux_riscv64::InvalidateAllRegisters() {
361 m_gpr_is_valid =
false;
362 m_fpu_is_valid =
false;
365uint32_t NativeRegisterContextLinux_riscv64::CalculateFprOffset(
370std::vector<uint32_t> NativeRegisterContextLinux_riscv64::GetExpeditedRegisters(
372 std::vector<uint32_t> expedited_reg_nums =
375 return expedited_reg_nums;
static llvm::raw_ostream & error(Stream &strm)
size_t GetRegisterSetCount() const override
A subclass of DataBuffer that stores a data buffer on the heap.
const RegisterInfoInterface & GetRegisterInfoInterface() const
virtual std::vector< uint32_t > GetExpeditedRegisters(ExpeditedRegs expType) const
lldb::tid_t GetID() const
uint32_t SetFromMemoryData(const RegisterInfo ®_info, const void *src, uint32_t src_len, lldb::ByteOrder src_byte_order, Status &error)
bool SetUInt(uint64_t uint, uint32_t byte_size)
const void * GetBytes() const
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr=nullptr, void *data=nullptr, size_t data_size=0, long *result=nullptr)
}
static std::unique_ptr< NativeRegisterContextLinux > CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch, NativeThreadLinux &native_thread)
static llvm::Expected< ArchSpec > DetermineArchitecture(lldb::tid_t tid)
#define LLDB_INVALID_INDEX32
#define LLDB_INVALID_REGNUM
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...
uint32_t byte_offset
The byte offset in the register context data where this register's value is found.
uint32_t byte_size
Size in bytes of the register.
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
const char * name
Name of this register, can't be NULL.
Registers are grouped into register sets.
size_t num_registers
The number of registers in REGISTERS array below.