Skip to content
Permalink
Browse files

[lldb] [Process/NetBSD] Support reading YMM registers via PT_*XSTATE

Provide a (conditional) support for the new PT_GETXSTATE
and PT_SETXSTATE ptrace() requests, and use them to implement getting
and setting YMM registers.  The functions used for splitting
and recombining YMM register data are based on matching functions
in FreeBSD plugin, with some simplification and updates to match NetBSD
structures.

Differential Revision: https://reviews.llvm.org/D63545

llvm-svn: 364779
  • Loading branch information...
mgorny committed Jul 1, 2019
1 parent 2ba1601 commit 2b2ad9342e65042baefc379e4a70774d8e538e84
@@ -22,7 +22,10 @@
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/sysctl.h>
#include <sys/uio.h>
#include <x86/cpu.h>
#include <x86/cpu_extended_state.h>
#include <x86/specialreg.h>
#include <elf.h>
#include <err.h>
#include <stdint.h>
@@ -148,7 +151,7 @@ int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum(
else if (reg_num <= k_last_fpr_x86_64)
return FPRegSet;
else if (reg_num <= k_last_avx_x86_64)
return -1; // AVX
return XStateRegSet; // AVX
else if (reg_num <= k_last_mpxr_x86_64)
return -1; // MPXR
else if (reg_num <= k_last_mpxc_x86_64)
@@ -167,6 +170,15 @@ Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) {
return DoRegisterSet(PT_GETFPREGS, &m_fpr_x86_64);
case DBRegSet:
return DoRegisterSet(PT_GETDBREGS, &m_dbr_x86_64);
case XStateRegSet:
#ifdef HAVE_XSTATE
{
struct iovec iov = {&m_xstate_x86_64, sizeof(m_xstate_x86_64)};
return DoRegisterSet(PT_GETXSTATE, &iov);
}
#else
return Status("XState is not supported by the kernel");
#endif
}
llvm_unreachable("NativeRegisterContextNetBSD_x86_64::ReadRegisterSet");
}
@@ -179,6 +191,15 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) {
return DoRegisterSet(PT_SETFPREGS, &m_fpr_x86_64);
case DBRegSet:
return DoRegisterSet(PT_SETDBREGS, &m_dbr_x86_64);
case XStateRegSet:
#ifdef HAVE_XSTATE
{
struct iovec iov = {&m_xstate_x86_64, sizeof(m_xstate_x86_64)};
return DoRegisterSet(PT_SETXSTATE, &iov);
}
#else
return Status("XState is not supported by the kernel");
#endif
}
llvm_unreachable("NativeRegisterContextNetBSD_x86_64::WriteRegisterSet");
}
@@ -360,6 +381,39 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info,
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 {
uint32_t reg_index = reg - lldb_ymm0_x86_64;
YMMReg ymm = XStateToYMM(
m_xstate_x86_64.xs_fxsave.fx_xmm[reg_index].xmm_bytes,
m_xstate_x86_64.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes);
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:
@@ -552,6 +606,39 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister(
::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 {
uint32_t reg_index = reg - lldb_ymm0_x86_64;
YMMReg ymm;
::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize());
YMMToXState(ymm,
m_xstate_x86_64.xs_fxsave.fx_xmm[reg_index].xmm_bytes,
m_xstate_x86_64.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes);
}
#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:
@@ -14,13 +14,18 @@
// clang-format off
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <machine/reg.h>
// clang-format on

#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
#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 {

@@ -68,12 +73,15 @@ class NativeRegisterContextNetBSD_x86_64 : public NativeRegisterContextNetBSD {

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;

0 comments on commit 2b2ad93

Please sign in to comment.
You can’t perform that action at this time.