diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:51:52 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:51:52 +0000 |
| commit | 5f29bb8a675e8f96452b632e7129113f7dec850e (patch) | |
| tree | 3d3f2a0d3ad10872a4dcaba8ec8d1d20c87ab147 /source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp | |
| parent | 88c643b6fec27eec436c8d138fee6346e92337d6 (diff) | |
Notes
Diffstat (limited to 'source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp')
| -rw-r--r-- | source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp | 233 |
1 files changed, 115 insertions, 118 deletions
diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp index 78da3527122f..a7cd637bf826 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -1,9 +1,8 @@ //===-- NativeRegisterContextNetBSD_x86_64.cpp ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -21,8 +20,12 @@ // clang-format off #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> @@ -32,9 +35,7 @@ using namespace lldb_private; using namespace lldb_private::process_netbsd; -// ---------------------------------------------------------------------------- // Private namespace. -// ---------------------------------------------------------------------------- namespace { // x86 64-bit general purpose registers. @@ -93,58 +94,6 @@ static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { }; #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize()) - -const int fpu_present = []() -> int { - int mib[2]; - int error; - size_t len; - int val; - - len = sizeof(val); - mib[0] = CTL_MACHDEP; - mib[1] = CPU_FPU_PRESENT; - - error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0); - if (error) - errx(EXIT_FAILURE, "sysctl"); - - return val; -}(); - -const int osfxsr = []() -> int { - int mib[2]; - int error; - size_t len; - int val; - - len = sizeof(val); - mib[0] = CTL_MACHDEP; - mib[1] = CPU_OSFXSR; - - error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0); - if (error) - errx(EXIT_FAILURE, "sysctl"); - - return val; -}(); - -const int fpu_save = []() -> int { - int mib[2]; - int error; - size_t len; - int val; - - len = sizeof(val); - mib[0] = CTL_MACHDEP; - mib[1] = CPU_FPU_SAVE; - - error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0); - if (error) - errx(EXIT_FAILURE, "sysctl"); - - return val; -}(); - } // namespace NativeRegisterContextNetBSD * @@ -153,9 +102,7 @@ NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread); } -// ---------------------------------------------------------------------------- // NativeRegisterContextNetBSD_x86_64 members. -// ---------------------------------------------------------------------------- static RegisterInfoInterface * CreateRegisterInfoInterface(const ArchSpec &target_arch) { @@ -202,9 +149,9 @@ int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( if (reg_num <= k_last_gpr_x86_64) return GPRegSet; else if (reg_num <= k_last_fpr_x86_64) - return (fpu_present == 1 && osfxsr == 1 && fpu_save >= 1) ? FPRegSet : -1; + 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) @@ -215,37 +162,46 @@ int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( return -1; } -int NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) { +Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) { switch (set) { case GPRegSet: - ReadGPR(); - return 0; + return DoRegisterSet(PT_GETREGS, &m_gpr_x86_64); case FPRegSet: - ReadFPR(); - return 0; + return DoRegisterSet(PT_GETFPREGS, &m_fpr_x86_64); case DBRegSet: - ReadDBR(); - return 0; - default: - break; + 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 } - return -1; + llvm_unreachable("NativeRegisterContextNetBSD_x86_64::ReadRegisterSet"); } -int NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) { + +Status NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) { switch (set) { case GPRegSet: - WriteGPR(); - return 0; + return DoRegisterSet(PT_SETREGS, &m_gpr_x86_64); case FPRegSet: - WriteFPR(); - return 0; + return DoRegisterSet(PT_SETFPREGS, &m_fpr_x86_64); case DBRegSet: - WriteDBR(); - return 0; - default: - break; + 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 } - return -1; + llvm_unreachable("NativeRegisterContextNetBSD_x86_64::WriteRegisterSet"); } Status @@ -277,13 +233,9 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, return error; } - if (ReadRegisterSet(set) != 0) { - // This is likely an internal register for lldb use only and should not be - // directly queried. - error.SetErrorStringWithFormat( - "reading register set for register \"%s\" failed", reg_info->name); + error = ReadRegisterSet(set); + if (error.Fail()) return error; - } switch (reg) { case lldb_rax_x86_64: @@ -407,7 +359,7 @@ NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, case lldb_mm5_x86_64: case lldb_mm6_x86_64: case lldb_mm7_x86_64: - reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64], + reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_mm0_x86_64], reg_info->byte_size, endian::InlHostByteOrder()); break; case lldb_xmm0_x86_64: @@ -429,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: @@ -473,13 +458,9 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( return error; } - if (ReadRegisterSet(set) != 0) { - // This is likely an internal register for lldb use only and should not be - // directly queried. - error.SetErrorStringWithFormat( - "reading register set for register \"%s\" failed", reg_info->name); + error = ReadRegisterSet(set); + if (error.Fail()) return error; - } switch (reg) { case lldb_rax_x86_64: @@ -603,7 +584,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( case lldb_mm5_x86_64: case lldb_mm6_x86_64: case lldb_mm7_x86_64: - ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64], + ::memcpy(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_mm0_x86_64], reg_value.GetBytes(), reg_value.GetByteSize()); break; case lldb_xmm0_x86_64: @@ -625,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: @@ -637,10 +651,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteRegister( break; } - if (WriteRegisterSet(set) != 0) - error.SetErrorStringWithFormat("failed to write register set"); - - return error; + return WriteRegisterSet(set); } Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues( @@ -648,25 +659,11 @@ Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues( Status error; data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) { - error.SetErrorStringWithFormat( - "failed to allocate DataBufferHeap instance of size %" PRIu64, - REG_CONTEXT_SIZE); - return error; - } - - error = ReadGPR(); + error = ReadRegisterSet(GPRegSet); if (error.Fail()) return error; uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 - " returned a null pointer", - REG_CONTEXT_SIZE); - return error; - } - ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); dst += GetRegisterInfoInterface().GetGPRSize(); @@ -707,7 +704,7 @@ Status NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues( } ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize()); - error = WriteGPR(); + error = WriteRegisterSet(GPRegSet); if (error.Fail()) return error; src += GetRegisterInfoInterface().GetGPRSize(); @@ -767,7 +764,7 @@ Status NativeRegisterContextNetBSD_x86_64::IsWatchpointVacant(uint32_t wp_index, uint64_t control_bits = reg_value.GetAsUInt64(); - is_vacant = !(control_bits & (1 << (2 * wp_index))); + is_vacant = !(control_bits & (1 << (2 * wp_index + 1))); return error; } @@ -806,7 +803,7 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex( return error; // for watchpoints 0, 1, 2, or 3, respectively, set bits 1, 3, 5, or 7 - uint64_t enable_bit = 1 << (2 * wp_index); + uint64_t enable_bit = 1 << (2 * wp_index + 1); // set bits 16-17, 20-21, 24-25, or 28-29 // with 0b01 for write, and 0b11 for read/write |
