Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h =================================================================== --- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h +++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h @@ -41,6 +41,9 @@ virtual Status ReadDBR(); virtual Status WriteDBR(); + virtual Status ReadXState(); + virtual Status WriteXState(); + virtual void *GetGPRBuffer() { return nullptr; } virtual size_t GetGPRSize() { return GetRegisterInfoInterface().GetGPRSize(); @@ -52,6 +55,9 @@ virtual void *GetDBRBuffer() { return nullptr; } virtual size_t GetDBRSize() { return 0; } + virtual void *GetXStateBuffer() { return nullptr; } + virtual size_t GetXStateSize() { return 0; } + virtual Status DoReadGPR(void *buf); virtual Status DoWriteGPR(void *buf); @@ -61,6 +67,9 @@ virtual Status DoReadDBR(void *buf); virtual Status DoWriteDBR(void *buf); + virtual Status DoReadXState(void *buf, size_t buflen); + virtual Status DoWriteXState(void *buf, size_t buflen); + virtual NativeProcessNetBSD &GetProcess(); virtual ::pid_t GetProcessPid(); }; Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp =================================================================== --- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp +++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp @@ -16,6 +16,7 @@ // clang-format off #include #include +#include // clang-format on NativeRegisterContextNetBSD::NativeRegisterContextNetBSD( @@ -72,6 +73,28 @@ return DoWriteDBR(buf); } +Status NativeRegisterContextNetBSD::ReadXState() { + void *buf = GetXStateBuffer(); + size_t buflen = GetXStateSize(); + if (!buf) + return Status("XState buffer is NULL"); + if (buflen == 0) + return Status("XState length is zero"); + + return DoReadXState(buf, buflen); +} + +Status NativeRegisterContextNetBSD::WriteXState() { + void *buf = GetXStateBuffer(); + size_t buflen = GetXStateSize(); + if (!buf) + return Status("XState buffer is NULL"); + if (buflen == 0) + return Status("XState length is zero"); + + return DoWriteXState(buf, buflen); +} + Status NativeRegisterContextNetBSD::DoReadGPR(void *buf) { return NativeProcessNetBSD::PtraceWrapper(PT_GETREGS, GetProcessPid(), buf, m_thread.GetID()); @@ -102,6 +125,32 @@ m_thread.GetID()); } +Status NativeRegisterContextNetBSD::DoReadXState(void *buf, size_t buflen) { +#ifdef PT_GETXSTATE + struct iovec iov = { + .iov_base = buf, + .iov_len = buflen + }; + return NativeProcessNetBSD::PtraceWrapper(PT_GETXSTATE, GetProcessPid(), &iov, + m_thread.GetID()); +#else + return Status("PT_GETXSTATE not supported by the kernel"); +#endif +} + +Status NativeRegisterContextNetBSD::DoWriteXState(void *buf, size_t buflen) { +#ifdef PT_SETXSTATE + struct iovec iov = { + .iov_base = buf, + .iov_len = buflen + }; + return NativeProcessNetBSD::PtraceWrapper(PT_SETXSTATE, GetProcessPid(), &iov, + m_thread.GetID()); +#else + return Status("PT_SETXSTATE not supported by the kernel"); +#endif +} + NativeProcessNetBSD &NativeRegisterContextNetBSD::GetProcess() { return static_cast(m_thread.GetProcess()); } Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h =================================================================== --- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h +++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -14,6 +14,7 @@ // clang-format off #include #include +#include #include // clang-format on @@ -21,6 +22,10 @@ #include "Plugins/Process/Utility/RegisterContext_x86.h" #include "Plugins/Process/Utility/lldb-x86-register-enums.h" +#if defined(PT_GETXSTATE) && defined(PT_SETXSTATE) +#define HAVE_XSTATE +#endif + namespace lldb_private { namespace process_netbsd { @@ -70,20 +75,31 @@ void *GetGPRBuffer() override { return &m_gpr_x86_64; } void *GetFPRBuffer() override { return &m_fpr_x86_64; } void *GetDBRBuffer() override { return &m_dbr_x86_64; } +#ifdef HAVE_XSTATE + void *GetXStateBuffer() override { return &m_xstate_x86_64; } + size_t GetXStateSize() override { return sizeof(m_xstate_x86_64); } +#endif private: // Private member types. - enum { GPRegSet, FPRegSet, DBRegSet }; + enum { GPRegSet, FPRegSet, DBRegSet, XStateRegSet }; // Private member variables. struct reg m_gpr_x86_64; struct fpreg m_fpr_x86_64; struct dbreg m_dbr_x86_64; +#ifdef HAVE_XSTATE + struct xstate m_xstate_x86_64; +#endif int GetSetForNativeRegNum(int reg_num) const; Status ReadRegisterSet(uint32_t set); Status WriteRegisterSet(uint32_t set); + + YMMReg CopyXSTATEtoYMM(uint32_t reg_index, lldb::ByteOrder byte_order); + void CopyYMMtoXSTATE(uint32_t reg_index, lldb::ByteOrder byte_order, + YMMReg reg); }; } // namespace process_netbsd Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp =================================================================== --- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -199,7 +201,7 @@ else if (reg_num <= k_last_fpr_x86_64) return (fpu_present == 1 && osfxsr == 1 && fpu_save >= 1) ? FPRegSet : -1; else if (reg_num <= k_last_avx_x86_64) - return -1; // AVX + return (fpu_present == 1 && fpu_save >= 2) ? XStateRegSet : -1; // AVX else if (reg_num <= k_last_mpxr_x86_64) return -1; // MPXR else if (reg_num <= k_last_mpxc_x86_64) @@ -218,6 +220,10 @@ return ReadFPR(); case DBRegSet: return ReadDBR(); + case XStateRegSet: + return ReadXState(); + default: + break; } llvm_unreachable("NativeRegisterContextNetBSD_x86_64::ReadRegisterSet"); } @@ -230,10 +236,74 @@ return WriteFPR(); case DBRegSet: return WriteDBR(); + case XStateRegSet: + return WriteXState(); + default: + break; } llvm_unreachable("NativeRegisterContextNetBSD_x86_64::WriteRegisterSet"); } +YMMReg NativeRegisterContextNetBSD_x86_64::CopyXSTATEtoYMM( + uint32_t reg_index, lldb::ByteOrder byte_order) { +#ifdef HAVE_XSTATE + YMMReg ret; + + if (byte_order == lldb::eByteOrderLittle) { + ::memcpy(ret.bytes, + m_xstate_x86_64.xs_fxsave.fx_xmm[reg_index].xmm_bytes, + sizeof(XMMReg)); + ::memcpy(ret.bytes + sizeof(XMMReg), + m_xstate_x86_64.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes, + sizeof(YMMHReg)); + return ret; + } + + if (byte_order == lldb::eByteOrderBig) { + ::memcpy(ret.bytes + sizeof(XMMReg), + m_xstate_x86_64.xs_fxsave.fx_xmm[reg_index].xmm_bytes, + sizeof(XMMReg)); + ::memcpy(ret.bytes, + m_xstate_x86_64.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes, + sizeof(YMMHReg)); + return ret; + } + + llvm_unreachable("invalid byte order"); +#else + llvm_unreachable("CopyXSTATEtoYMM() called without XState support"); +#endif +} + +void NativeRegisterContextNetBSD_x86_64::CopyYMMtoXSTATE( + uint32_t reg_index, lldb::ByteOrder byte_order, YMMReg reg) { +#ifdef HAVE_XSTATE + if (byte_order == lldb::eByteOrderLittle) { + ::memcpy(m_xstate_x86_64.xs_fxsave.fx_xmm[reg_index].xmm_bytes, + reg.bytes, + sizeof(XMMReg)); + ::memcpy(m_xstate_x86_64.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes, + reg.bytes + sizeof(XMMReg), + sizeof(YMMHReg)); + return; + } + + if (byte_order == lldb::eByteOrderBig) { + ::memcpy(m_xstate_x86_64.xs_fxsave.fx_xmm[reg_index].xmm_bytes, + reg.bytes + sizeof(XMMReg), + sizeof(XMMReg)); + ::memcpy(m_xstate_x86_64.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes, + reg.bytes, + sizeof(YMMHReg)); + return; + } + + llvm_unreachable("invalid byte order"); +#else + llvm_unreachable("CopyYMMtoXSTATE() called without XState support"); +#endif +} + Status NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) { @@ -411,6 +481,37 @@ reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], reg_info->byte_size, endian::InlHostByteOrder()); break; + case lldb_ymm0_x86_64: + case lldb_ymm1_x86_64: + case lldb_ymm2_x86_64: + case lldb_ymm3_x86_64: + case lldb_ymm4_x86_64: + case lldb_ymm5_x86_64: + case lldb_ymm6_x86_64: + case lldb_ymm7_x86_64: + case lldb_ymm8_x86_64: + case lldb_ymm9_x86_64: + case lldb_ymm10_x86_64: + case lldb_ymm11_x86_64: + case lldb_ymm12_x86_64: + case lldb_ymm13_x86_64: + case lldb_ymm14_x86_64: + case lldb_ymm15_x86_64: +#ifdef HAVE_XSTATE + if (!(m_xstate_x86_64.xs_rfbm & XCR0_SSE) || + !(m_xstate_x86_64.xs_rfbm & XCR0_YMM_Hi128)) { + error.SetErrorStringWithFormat("register \"%s\" not supported by CPU/kernel", + reg_info->name); + } else { + YMMReg ymm = CopyXSTATEtoYMM(reg - lldb_ymm0_x86_64, + endian::InlHostByteOrder()); + reg_value.SetBytes(ymm.bytes, reg_info->byte_size, + endian::InlHostByteOrder()); + } +#else + error.SetErrorString("XState queries not supported by the kernel"); +#endif + break; case lldb_dr0_x86_64: case lldb_dr1_x86_64: case lldb_dr2_x86_64: @@ -603,6 +704,36 @@ ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], reg_value.GetBytes(), reg_value.GetByteSize()); break; + case lldb_ymm0_x86_64: + case lldb_ymm1_x86_64: + case lldb_ymm2_x86_64: + case lldb_ymm3_x86_64: + case lldb_ymm4_x86_64: + case lldb_ymm5_x86_64: + case lldb_ymm6_x86_64: + case lldb_ymm7_x86_64: + case lldb_ymm8_x86_64: + case lldb_ymm9_x86_64: + case lldb_ymm10_x86_64: + case lldb_ymm11_x86_64: + case lldb_ymm12_x86_64: + case lldb_ymm13_x86_64: + case lldb_ymm14_x86_64: + case lldb_ymm15_x86_64: +#ifdef HAVE_XSTATE + if (!(m_xstate_x86_64.xs_rfbm & XCR0_SSE) || + !(m_xstate_x86_64.xs_rfbm & XCR0_YMM_Hi128)) { + error.SetErrorStringWithFormat("register \"%s\" not supported by CPU/kernel", + reg_info->name); + } else { + YMMReg ymm; + ::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize()); + CopyYMMtoXSTATE(reg - lldb_ymm0_x86_64, endian::InlHostByteOrder(), ymm); + } +#else + error.SetErrorString("XState not supported by the kernel"); +#endif + break; case lldb_dr0_x86_64: case lldb_dr1_x86_64: case lldb_dr2_x86_64: