9#if defined(__loongarch__) && __loongarch_grlen == 64
30#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
36std::unique_ptr<NativeRegisterContextLinux>
37NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
40 case llvm::Triple::loongarch64: {
42 auto register_info_up = std::make_unique<RegisterInfoPOSIX_loongarch64>(
43 target_arch, opt_regsets);
44 return std::make_unique<NativeRegisterContextLinux_loongarch64>(
45 target_arch, native_thread, std::move(register_info_up));
48 llvm_unreachable(
"have no register context for architecture");
52llvm::Expected<ArchSpec>
53NativeRegisterContextLinux::DetermineArchitecture(
lldb::tid_t tid) {
54 return HostInfo::GetArchitecture();
57NativeRegisterContextLinux_loongarch64::NativeRegisterContextLinux_loongarch64(
59 std::unique_ptr<RegisterInfoPOSIX_loongarch64> register_info_up)
61 register_info_up.release()),
63 ::memset(&m_fpr, 0,
sizeof(m_fpr));
64 ::memset(&m_gpr, 0,
sizeof(m_gpr));
66 ::memset(&m_hwp_regs, 0,
sizeof(m_hwp_regs));
67 ::memset(&m_hbp_regs, 0,
sizeof(m_hbp_regs));
72 m_max_hwp_supported = 14;
73 m_max_hbp_supported = 14;
74 m_refresh_hwdebug_info =
true;
76 m_gpr_is_valid =
false;
77 m_fpu_is_valid =
false;
81NativeRegisterContextLinux_loongarch64::GetRegisterInfo()
const {
83 NativeRegisterContextRegisterInfo::GetRegisterInfoInterface());
86uint32_t NativeRegisterContextLinux_loongarch64::GetRegisterSetCount()
const {
90const RegisterSet *NativeRegisterContextLinux_loongarch64::GetRegisterSet(
91 uint32_t set_index)
const {
92 return GetRegisterInfo().GetRegisterSet(set_index);
95uint32_t NativeRegisterContextLinux_loongarch64::GetUserRegisterCount()
const {
97 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
102Status NativeRegisterContextLinux_loongarch64::ReadRegister(
107 error = Status::FromErrorString(
"reg_info NULL");
114 return Status::FromErrorStringWithFormat(
115 "no lldb regnum for %s",
116 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
118 uint8_t *src =
nullptr;
127 assert(offset < GetGPRSize());
128 src = (uint8_t *)GetGPRBuffer() + offset;
130 }
else if (IsFPR(reg)) {
135 offset = CalculateFprOffset(reg_info);
136 assert(offset < GetFPRSize());
137 src = (uint8_t *)GetFPRBuffer() + offset;
139 return Status::FromErrorString(
140 "failed - register wasn't recognized to be a GPR or an FPR, "
141 "write strategy unknown");
144 eByteOrderLittle,
error);
149Status NativeRegisterContextLinux_loongarch64::WriteRegister(
154 return Status::FromErrorString(
"reg_info NULL");
159 return Status::FromErrorStringWithFormat(
160 "no lldb regnum for %s",
161 reg_info->
name !=
nullptr ? reg_info->
name :
"<unknown register>");
163 uint8_t *dst =
nullptr;
172 dst = (uint8_t *)GetGPRBuffer() + reg_info->
byte_offset;
176 }
else if (IsFPR(reg)) {
181 offset = CalculateFprOffset(reg_info);
182 assert(offset < GetFPRSize());
183 dst = (uint8_t *)GetFPRBuffer() + offset;
189 return Status::FromErrorString(
"Failed to write register value");
192Status NativeRegisterContextLinux_loongarch64::ReadAllRegisterValues(
206 uint8_t *dst = data_sp->GetBytes();
207 ::memcpy(dst, GetGPRBuffer(), GetGPRSize());
209 ::memcpy(dst, GetFPRBuffer(), GetFPRSize());
214Status NativeRegisterContextLinux_loongarch64::WriteAllRegisterValues(
219 error = Status::FromErrorStringWithFormat(
220 "NativeRegisterContextLinux_loongarch64::%s invalid data_sp provided",
226 error = Status::FromErrorStringWithFormat(
227 "NativeRegisterContextLinux_loongarch64::%s data_sp contained "
228 "mismatched data size, expected %" PRIu64
", actual %" PRIu64,
233 const uint8_t *src = data_sp->GetBytes();
234 if (src ==
nullptr) {
235 error = Status::FromErrorStringWithFormat(
236 "NativeRegisterContextLinux_loongarch64::%s "
237 "DataBuffer::GetBytes() returned a null "
242 ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize());
248 src += GetRegisterInfoInterface().GetGPRSize();
249 ::memcpy(GetFPRBuffer(), src, GetFPRSize());
258bool NativeRegisterContextLinux_loongarch64::IsGPR(
unsigned reg)
const {
259 return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
263bool NativeRegisterContextLinux_loongarch64::IsFPR(
unsigned reg)
const {
264 return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
268Status NativeRegisterContextLinux_loongarch64::ReadGPR() {
275 ioVec.iov_base = GetGPRBuffer();
276 ioVec.iov_len = GetGPRSize();
278 error = ReadRegisterSet(&ioVec, GetGPRSize(), NT_PRSTATUS);
281 m_gpr_is_valid =
true;
286Status NativeRegisterContextLinux_loongarch64::WriteGPR() {
292 ioVec.iov_base = GetGPRBuffer();
293 ioVec.iov_len = GetGPRSize();
295 m_gpr_is_valid =
false;
297 return WriteRegisterSet(&ioVec, GetGPRSize(), NT_PRSTATUS);
300Status NativeRegisterContextLinux_loongarch64::ReadFPR() {
307 ioVec.iov_base = GetFPRBuffer();
308 ioVec.iov_len = GetFPRSize();
310 error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
313 m_fpu_is_valid =
true;
318Status NativeRegisterContextLinux_loongarch64::WriteFPR() {
324 ioVec.iov_base = GetFPRBuffer();
325 ioVec.iov_len = GetFPRSize();
327 m_fpu_is_valid =
false;
329 return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
332void NativeRegisterContextLinux_loongarch64::InvalidateAllRegisters() {
333 m_gpr_is_valid =
false;
334 m_fpu_is_valid =
false;
337uint32_t NativeRegisterContextLinux_loongarch64::CalculateFprOffset(
343NativeRegisterContextLinux_loongarch64::GetExpeditedRegisters(
345 std::vector<uint32_t> expedited_reg_nums =
346 NativeRegisterContext::GetExpeditedRegisters(expType);
348 return expedited_reg_nums;
351llvm::Error NativeRegisterContextLinux_loongarch64::ReadHardwareDebugInfo() {
352 if (!m_refresh_hwdebug_info)
353 return llvm::Error::success();
355 ::pid_t tid = m_thread.GetID();
357 int regset = NT_LOONGARCH_HW_WATCH;
359 struct user_watch_state dreg_state;
362 ioVec.iov_base = &dreg_state;
363 ioVec.iov_len =
sizeof(dreg_state);
365 &ioVec, ioVec.iov_len);
367 return error.ToError();
369 m_max_hwp_supported = dreg_state.dbg_info & 0x3f;
371 regset = NT_LOONGARCH_HW_BREAK;
373 &ioVec, ioVec.iov_len);
375 return error.ToError();
377 m_max_hbp_supported = dreg_state.dbg_info & 0x3f;
379 m_refresh_hwdebug_info =
false;
381 return llvm::Error::success();
384llvm::Error NativeRegisterContextLinux_loongarch64::WriteHardwareDebugRegs(
387 struct user_watch_state dreg_state;
390 memset(&dreg_state, 0,
sizeof(dreg_state));
391 ioVec.iov_base = &dreg_state;
395 regset = NT_LOONGARCH_HW_WATCH;
396 ioVec.iov_len =
sizeof(dreg_state.dbg_info) +
397 (
sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
399 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
400 dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
401 dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
405 regset = NT_LOONGARCH_HW_BREAK;
406 ioVec.iov_len =
sizeof(dreg_state.dbg_info) +
407 (
sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
409 for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
410 dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address;
411 dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control;
416 return NativeProcessLinux::PtraceWrapper(
PTRACE_SETREGSET, m_thread.GetID(),
417 ®set, &ioVec, ioVec.iov_len)
static llvm::raw_ostream & error(Stream &strm)
size_t GetRegisterSetCount() const override
An architecture specification class.
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
A subclass of DataBuffer that stores a data buffer on the heap.
uint32_t SetFromMemoryData(const RegisterInfo ®_info, const void *src, uint32_t src_len, lldb::ByteOrder src_byte_order, Status &error)
const void * GetBytes() const
#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.