summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp109
1 files changed, 91 insertions, 18 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 1f31b45d0fa9..10006616b0c6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -31,19 +31,20 @@ using namespace lldb_private::process_gdb_remote;
// GDBRemoteRegisterContext constructor
GDBRemoteRegisterContext::GDBRemoteRegisterContext(
ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
- GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once,
+ GDBRemoteDynamicRegisterInfoSP reg_info_sp, bool read_all_at_once,
bool write_all_at_once)
- : RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info),
- m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once),
+ : RegisterContext(thread, concrete_frame_idx),
+ m_reg_info_sp(std::move(reg_info_sp)), m_reg_valid(), m_reg_data(),
+ m_read_all_at_once(read_all_at_once),
m_write_all_at_once(write_all_at_once) {
// Resize our vector of bools to contain one bool for every register. We will
// use these boolean values to know when a register value is valid in
// m_reg_data.
- m_reg_valid.resize(reg_info.GetNumRegisters());
+ m_reg_valid.resize(m_reg_info_sp->GetNumRegisters());
// Make a heap based buffer that is big enough to store all registers
DataBufferSP reg_data_sp(
- new DataBufferHeap(reg_info.GetRegisterDataByteSize(), 0));
+ new DataBufferHeap(m_reg_info_sp->GetRegisterDataByteSize(), 0));
m_reg_data.SetData(reg_data_sp);
m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder());
}
@@ -62,12 +63,12 @@ void GDBRemoteRegisterContext::SetAllRegisterValid(bool b) {
}
size_t GDBRemoteRegisterContext::GetRegisterCount() {
- return m_reg_info.GetNumRegisters();
+ return m_reg_info_sp->GetNumRegisters();
}
const RegisterInfo *
GDBRemoteRegisterContext::GetRegisterInfoAtIndex(size_t reg) {
- RegisterInfo *reg_info = m_reg_info.GetRegisterInfoAtIndex(reg);
+ RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfoAtIndex(reg);
if (reg_info && reg_info->dynamic_size_dwarf_expr_bytes) {
const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture();
@@ -78,11 +79,11 @@ GDBRemoteRegisterContext::GetRegisterInfoAtIndex(size_t reg) {
}
size_t GDBRemoteRegisterContext::GetRegisterSetCount() {
- return m_reg_info.GetNumRegisterSets();
+ return m_reg_info_sp->GetNumRegisterSets();
}
const RegisterSet *GDBRemoteRegisterContext::GetRegisterSet(size_t reg_set) {
- return m_reg_info.GetRegisterSet(reg_set);
+ return m_reg_info_sp->GetRegisterSet(reg_set);
}
bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info,
@@ -209,11 +210,12 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
SetAllRegisterValid(true);
return true;
} else if (buffer_sp->GetByteSize() > 0) {
- const int regcount = m_reg_info.GetNumRegisters();
+ const int regcount = m_reg_info_sp->GetNumRegisters();
for (int i = 0; i < regcount; i++) {
- struct RegisterInfo *reginfo = m_reg_info.GetRegisterInfoAtIndex(i);
- if (reginfo->byte_offset + reginfo->byte_size
- <= buffer_sp->GetByteSize()) {
+ struct RegisterInfo *reginfo =
+ m_reg_info_sp->GetRegisterInfoAtIndex(i);
+ if (reginfo->byte_offset + reginfo->byte_size <=
+ buffer_sp->GetByteSize()) {
m_reg_valid[i] = true;
} else {
m_reg_valid[i] = false;
@@ -342,6 +344,15 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
if (dst == nullptr)
return false;
+ // Code below is specific to AArch64 target in SVE state
+ // If vector granule (vg) register is being written then thread's
+ // register context reconfiguration is triggered on success.
+ bool do_reconfigure_arm64_sve = false;
+ const ArchSpec &arch = process->GetTarget().GetArchitecture();
+ if (arch.IsValid() && arch.GetTriple().isAArch64())
+ if (strcmp(reg_info->name, "vg") == 0)
+ do_reconfigure_arm64_sve = true;
+
if (data.CopyByteOrderedData(data_offset, // src offset
reg_info->byte_size, // src length
dst, // dst
@@ -361,6 +372,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
{
SetAllRegisterValid(false);
+
+ if (do_reconfigure_arm64_sve)
+ AArch64SVEReconfigure();
+
return true;
}
} else {
@@ -389,6 +404,9 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
} else {
// This is an actual register, write it
success = SetPrimordialRegister(reg_info, gdb_comm);
+
+ if (success && do_reconfigure_arm64_sve)
+ AArch64SVEReconfigure();
}
// Check if writing this register will invalidate any other register
@@ -506,7 +524,7 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues(
// m_reg_data buffer
}
data_sp = std::make_shared<DataBufferHeap>(
- m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize());
+ m_reg_data.GetDataStart(), m_reg_info_sp->GetRegisterDataByteSize());
return true;
} else {
@@ -654,9 +672,8 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
if (m_thread.GetProcess().get()) {
const ArchSpec &arch =
m_thread.GetProcess()->GetTarget().GetArchitecture();
- if (arch.IsValid() &&
- (arch.GetMachine() == llvm::Triple::aarch64 ||
- arch.GetMachine() == llvm::Triple::aarch64_32) &&
+ if (arch.IsValid() && (arch.GetMachine() == llvm::Triple::aarch64 ||
+ arch.GetMachine() == llvm::Triple::aarch64_32) &&
arch.GetTriple().getVendor() == llvm::Triple::Apple &&
arch.GetTriple().getOS() == llvm::Triple::IOS) {
arm64_debugserver = true;
@@ -708,7 +725,63 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
- return m_reg_info.ConvertRegisterKindToRegisterNumber(kind, num);
+ return m_reg_info_sp->ConvertRegisterKindToRegisterNumber(kind, num);
+}
+
+bool GDBRemoteRegisterContext::AArch64SVEReconfigure() {
+ if (!m_reg_info_sp)
+ return false;
+
+ const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("vg");
+ if (!reg_info)
+ return false;
+
+ uint64_t fail_value = LLDB_INVALID_ADDRESS;
+ uint32_t vg_reg_num = reg_info->kinds[eRegisterKindLLDB];
+ uint64_t vg_reg_value = ReadRegisterAsUnsigned(vg_reg_num, fail_value);
+
+ if (vg_reg_value != fail_value && vg_reg_value <= 32) {
+ const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("p0");
+ if (!reg_info || vg_reg_value == reg_info->byte_size)
+ return false;
+
+ if (m_reg_info_sp->UpdateARM64SVERegistersInfos(vg_reg_value)) {
+ // Make a heap based buffer that is big enough to store all registers
+ m_reg_data.SetData(std::make_shared<DataBufferHeap>(
+ m_reg_info_sp->GetRegisterDataByteSize(), 0));
+ m_reg_data.SetByteOrder(GetByteOrder());
+
+ InvalidateAllRegisters();
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool GDBRemoteDynamicRegisterInfo::UpdateARM64SVERegistersInfos(uint64_t vg) {
+ // SVE Z register size is vg x 8 bytes.
+ uint32_t z_reg_byte_size = vg * 8;
+
+ // SVE vector length has changed, accordingly set size of Z, P and FFR
+ // registers. Also invalidate register offsets it will be recalculated
+ // after SVE register size update.
+ for (auto &reg : m_regs) {
+ if (reg.value_regs == nullptr) {
+ if (reg.name[0] == 'z' && isdigit(reg.name[1]))
+ reg.byte_size = z_reg_byte_size;
+ else if (reg.name[0] == 'p' && isdigit(reg.name[1]))
+ reg.byte_size = vg;
+ else if (strcmp(reg.name, "ffr") == 0)
+ reg.byte_size = vg;
+ }
+ reg.byte_offset = LLDB_INVALID_INDEX32;
+ }
+
+ // Re-calculate register offsets
+ ConfigureOffsets();
+ return true;
}
void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {