diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h --- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h +++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h @@ -35,6 +35,10 @@ protected: virtual NativeProcessFreeBSD &GetProcess(); virtual ::pid_t GetProcessPid(); + + virtual size_t GetGPRSize() const { + return GetRegisterInfoInterface().GetGPRSize(); + } }; } // namespace process_freebsd diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h --- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h +++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h @@ -63,14 +63,29 @@ // LLDB's GPR/FPU structs. However, all fields have matching offsets // and sizes, so we do not have to worry about these (and we have // a unittest to assert that). - std::array m_reg_data; + std::array m_reg_data; + std::array m_fpreg_data; #ifdef LLDB_HAS_FREEBSD_WATCHPOINT dbreg m_dbreg; bool m_read_dbreg; #endif - Status ReadRegisterSet(uint32_t set); - Status WriteRegisterSet(uint32_t set); + void *GetGPRBuffer() { return &m_reg_data; } + size_t GetGPRBufferSize() { return sizeof(m_reg_data); } + + void *GetFPRBuffer() { return &m_fpreg_data; } + size_t GetFPRSize() { return sizeof(m_fpreg_data); } + + bool IsGPR(unsigned reg) const; + bool IsFPR(unsigned reg) const; + + Status ReadGPR(); + Status WriteGPR(); + + Status ReadFPR(); + Status WriteFPR(); + + uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const; llvm::Error ReadHardwareDebugInfo() override; llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override; diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp --- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp @@ -24,6 +24,8 @@ #include // clang-format on +#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) + using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_freebsd; @@ -68,30 +70,43 @@ return count; } -Status NativeRegisterContextFreeBSD_arm64::ReadRegisterSet(uint32_t set) { - switch (set) { - case RegisterInfoPOSIX_arm64::GPRegSet: - return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(), - m_reg_data.data()); - case RegisterInfoPOSIX_arm64::FPRegSet: - return NativeProcessFreeBSD::PtraceWrapper( - PT_GETFPREGS, m_thread.GetID(), - m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm64::GPR)); - } - llvm_unreachable("NativeRegisterContextFreeBSD_arm64::ReadRegisterSet"); +bool NativeRegisterContextFreeBSD_arm64::IsGPR(unsigned reg) const { + if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_arm64::GPRegSet) + return true; + return false; } -Status NativeRegisterContextFreeBSD_arm64::WriteRegisterSet(uint32_t set) { - switch (set) { - case RegisterInfoPOSIX_arm64::GPRegSet: - return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(), - m_reg_data.data()); - case RegisterInfoPOSIX_arm64::FPRegSet: - return NativeProcessFreeBSD::PtraceWrapper( - PT_SETFPREGS, m_thread.GetID(), - m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm64::GPR)); - } - llvm_unreachable("NativeRegisterContextFreeBSD_arm64::WriteRegisterSet"); +bool NativeRegisterContextFreeBSD_arm64::IsFPR(unsigned reg) const { + if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_arm64::FPRegSet) + return true; + return false; +} + +Status NativeRegisterContextFreeBSD_arm64::ReadGPR() { + return NativeProcessFreeBSD::PtraceWrapper( + PT_GETREGS, m_thread.GetID(), m_reg_data.data()); +} + +Status NativeRegisterContextFreeBSD_arm64::WriteGPR() { + return NativeProcessFreeBSD::PtraceWrapper( + PT_SETREGS, m_thread.GetID(), m_reg_data.data()); +} + +Status NativeRegisterContextFreeBSD_arm64::ReadFPR() { + return NativeProcessFreeBSD::PtraceWrapper( + PT_GETFPREGS, m_thread.GetID(), m_fpreg_data.data()); +} + +Status NativeRegisterContextFreeBSD_arm64::WriteFPR() { + return NativeProcessFreeBSD::PtraceWrapper( + PT_SETFPREGS, m_thread.GetID(), m_fpreg_data.data()); +} + +uint32_t NativeRegisterContextFreeBSD_arm64::CalculateFprOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - GetGPRSize(); } Status @@ -111,14 +126,30 @@ ? reg_info->name : ""); - uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg); - error = ReadRegisterSet(set); - if (error.Fail()) - return error; - - assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size()); - reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset, - reg_info->byte_size, endian::InlHostByteOrder()); + uint8_t *src; + uint32_t offset = LLDB_INVALID_INDEX32; + + if (IsGPR(reg)) { + error = ReadGPR(); + if (error.Fail()) + return error; + + offset = reg_info->byte_offset; + assert(offset < GetGPRSize()); + src = (uint8_t *)GetGPRBuffer() + offset; + } else if (IsFPR(reg)) { + error = ReadFPR(); + if (error.Fail()) + return error; + + offset = CalculateFprOffset(reg_info); + assert(offset < GetFPRSize()); + src = (uint8_t *)GetFPRBuffer() + offset; + } else + return Status("Failed to read register value"); + + reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, + endian::InlHostByteOrder(), error); return error; } @@ -136,33 +167,53 @@ ? reg_info->name : ""); - uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg); - error = ReadRegisterSet(set); - if (error.Fail()) - return error; + uint8_t *dst; + uint32_t offset = LLDB_INVALID_INDEX32; + + if (IsGPR(reg)) { + error = ReadGPR(); + if (error.Fail()) + return error; + + assert(reg_info->byte_offset < GetGPRSize()); + dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset; + ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); + + return WriteGPR(); + } else if (IsFPR(reg)) { + error = ReadFPR(); + if (error.Fail()) + return error; + + offset = CalculateFprOffset(reg_info); + assert(offset < GetFPRSize()); + dst = (uint8_t *)GetFPRBuffer() + offset; + ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); - assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size()); - ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(), - reg_info->byte_size); + return WriteFPR(); + } - return WriteRegisterSet(set); + return Status("Failed to write register value"); } Status NativeRegisterContextFreeBSD_arm64::ReadAllRegisterValues( lldb::DataBufferSP &data_sp) { Status error; - error = ReadRegisterSet(RegisterInfoPOSIX_arm64::GPRegSet); + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + + error = ReadGPR(); if (error.Fail()) return error; - error = ReadRegisterSet(RegisterInfoPOSIX_arm64::FPRegSet); + error = ReadFPR(); if (error.Fail()) return error; - data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0)); uint8_t *dst = data_sp->GetBytes(); - ::memcpy(dst, m_reg_data.data(), m_reg_data.size()); + ::memcpy(dst, GetGPRBuffer(), GetGPRSize()); + dst += GetGPRSize(); + ::memcpy(dst, GetFPRBuffer(), GetFPRSize()); return error; } @@ -178,7 +229,7 @@ return error; } - if (data_sp->GetByteSize() != m_reg_data.size()) { + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { error.SetErrorStringWithFormat( "NativeRegisterContextFreeBSD_arm64::%s data_sp contained mismatched " "data size, expected %" PRIu64 ", actual %" PRIu64, @@ -194,13 +245,20 @@ __FUNCTION__); return error; } - ::memcpy(m_reg_data.data(), src, m_reg_data.size()); + ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize()); - error = WriteRegisterSet(RegisterInfoPOSIX_arm64::GPRegSet); + error = WriteGPR(); if (error.Fail()) return error; - return WriteRegisterSet(RegisterInfoPOSIX_arm64::FPRegSet); + src += GetRegisterInfoInterface().GetGPRSize(); + ::memcpy(GetFPRBuffer(), src, GetFPRSize()); + + error = WriteFPR(); + if (error.Fail()) + return error; + + return error; } llvm::Error NativeRegisterContextFreeBSD_arm64::CopyHardwareWatchpointsFrom(