[Lldb-commits] [lldb] f5ca275 - [lldb] [Process/Linux] Reuse NativeRegisterContextWatchpoint_x86
Michał Górny via lldb-commits
lldb-commits at lists.llvm.org
Mon Oct 26 03:56:21 PDT 2020
Author: Michał Górny
Date: 2020-10-26T11:55:22+01:00
New Revision: f5ca27569eacc398f0e4fc63a9b55cafac398c04
URL: https://github.com/llvm/llvm-project/commit/f5ca27569eacc398f0e4fc63a9b55cafac398c04
DIFF: https://github.com/llvm/llvm-project/commit/f5ca27569eacc398f0e4fc63a9b55cafac398c04.diff
LOG: [lldb] [Process/Linux] Reuse NativeRegisterContextWatchpoint_x86
Differential Revision: https://reviews.llvm.org/D90119
Added:
Modified:
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
Removed:
################################################################################
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
index 1b9e067639cc..90a6d8dcba04 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
@@ -19,11 +19,6 @@
using namespace lldb_private;
using namespace lldb_private::process_linux;
-NativeRegisterContextLinux::NativeRegisterContextLinux(
- NativeThreadProtocol &native_thread,
- RegisterInfoInterface *reg_info_interface_p)
- : NativeRegisterContextRegisterInfo(native_thread, reg_info_interface_p) {}
-
lldb::ByteOrder NativeRegisterContextLinux::GetByteOrder() const {
return m_thread.GetProcess().GetByteOrder();
}
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
index 7f321c0b5926..fa067b78d176 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
@@ -15,11 +15,9 @@
namespace lldb_private {
namespace process_linux {
-class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo {
+class NativeRegisterContextLinux
+ : public virtual NativeRegisterContextRegisterInfo {
public:
- NativeRegisterContextLinux(NativeThreadProtocol &native_thread,
- RegisterInfoInterface *reg_info_interface_p);
-
// This function is implemented in the NativeRegisterContextLinux_* subclasses
// to create a new instance of the host specific NativeRegisterContextLinux.
// The implementations can't collide as only one NativeRegisterContextLinux_*
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index 04714ec3c374..e15e0f8a5651 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -56,8 +56,8 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextLinux(native_thread,
- new RegisterInfoPOSIX_arm(target_arch)) {
+ : NativeRegisterContextRegisterInfo(
+ native_thread, new RegisterInfoPOSIX_arm(target_arch)) {
assert(target_arch.GetMachine() == llvm::Triple::arm);
::memset(&m_fpr, 0, sizeof(m_fpr));
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 0aef36c7e231..810bc8479742 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -56,8 +56,8 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextLinux(native_thread,
- new RegisterInfoPOSIX_arm64(target_arch)) {
+ : NativeRegisterContextRegisterInfo(
+ native_thread, new RegisterInfoPOSIX_arm64(target_arch)) {
::memset(&m_fpr, 0, sizeof(m_fpr));
::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64));
::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
index b0a4ad94ce0b..5abbab11d11d 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
@@ -104,8 +104,8 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) {
NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextLinux(native_thread,
- CreateRegisterInfoInterface(target_arch)) {
+ : NativeRegisterContextRegisterInfo(
+ native_thread, CreateRegisterInfoInterface(target_arch)) {
switch (target_arch.GetMachine()) {
case llvm::Triple::mips:
case llvm::Triple::mipsel:
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
index 6d1a15a0b70b..22acbda8ebb9 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
@@ -127,8 +127,8 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
NativeRegisterContextLinux_ppc64le::NativeRegisterContextLinux_ppc64le(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextLinux(native_thread,
- new RegisterInfoPOSIX_ppc64le(target_arch)) {
+ : NativeRegisterContextRegisterInfo(
+ native_thread, new RegisterInfoPOSIX_ppc64le(target_arch)) {
if (target_arch.GetMachine() != llvm::Triple::ppc64le) {
llvm_unreachable("Unhandled target architecture.");
}
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
index c72b89a519f4..098aa348c62d 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
@@ -109,8 +109,8 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) {
NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextLinux(native_thread,
- CreateRegisterInfoInterface(target_arch)) {
+ : NativeRegisterContextRegisterInfo(
+ native_thread, CreateRegisterInfoInterface(target_arch)) {
// Set up data about ranges of valid registers.
switch (target_arch.GetMachine()) {
case llvm::Triple::systemz:
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
index fad5f74426f5..0eb83b44274d 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
@@ -293,8 +293,8 @@ static std::size_t GetXSTATESize() {
NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextLinux(native_thread,
- CreateRegisterInfoInterface(target_arch)),
+ : NativeRegisterContextRegisterInfo(
+ native_thread, CreateRegisterInfoInterface(target_arch)),
m_xstate_type(XStateType::Invalid), m_ymm_set(), m_mpx_set(),
m_reg_info(), m_gpr_x86_64() {
// Set up data about ranges of valid registers.
@@ -321,6 +321,7 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
m_reg_info.first_mpxc = lldb_bndcfgu_i386;
m_reg_info.last_mpxc = lldb_bndstatus_i386;
m_reg_info.first_dr = lldb_dr0_i386;
+ m_reg_info.last_dr = lldb_dr7_i386;
m_reg_info.gpr_flags = lldb_eflags_i386;
break;
case llvm::Triple::x86_64:
@@ -345,6 +346,7 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
m_reg_info.first_mpxc = lldb_bndcfgu_x86_64;
m_reg_info.last_mpxc = lldb_bndstatus_x86_64;
m_reg_info.first_dr = lldb_dr0_x86_64;
+ m_reg_info.last_dr = lldb_dr7_x86_64;
m_reg_info.gpr_flags = lldb_rflags_x86_64;
break;
default:
@@ -578,7 +580,7 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister(
UpdateXSTATEforWrite(reg_index);
- if (IsGPR(reg_index))
+ if (IsGPR(reg_index) || IsDR(reg_index))
return WriteRegisterRaw(reg_index, reg_value);
if (IsFPR(reg_index) || IsAVX(reg_index) || IsMPX(reg_index)) {
@@ -877,6 +879,11 @@ bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const {
reg_index <= m_reg_info.last_fpr);
}
+bool NativeRegisterContextLinux_x86_64::IsDR(uint32_t reg_index) const {
+ return (m_reg_info.first_dr <= reg_index &&
+ reg_index <= m_reg_info.last_dr);
+}
+
Status NativeRegisterContextLinux_x86_64::WriteFPR() {
switch (m_xstate_type) {
case XStateType::FXSAVE:
@@ -1009,210 +1016,6 @@ bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) {
return true;
}
-Status NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index,
- bool &is_hit) {
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return Status("Watchpoint index out of range");
-
- RegisterValue reg_value;
- Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
- if (error.Fail()) {
- is_hit = false;
- return error;
- }
-
- uint64_t status_bits = reg_value.GetAsUInt64();
-
- is_hit = status_bits & (1 << wp_index);
-
- return error;
-}
-
-Status NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(
- uint32_t &wp_index, lldb::addr_t trap_addr) {
- uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
- for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
- bool is_hit;
- Status error = IsWatchpointHit(wp_index, is_hit);
- if (error.Fail()) {
- wp_index = LLDB_INVALID_INDEX32;
- return error;
- } else if (is_hit) {
- return error;
- }
- }
- wp_index = LLDB_INVALID_INDEX32;
- return Status();
-}
-
-Status NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index,
- bool &is_vacant) {
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return Status("Watchpoint index out of range");
-
- RegisterValue reg_value;
- Status error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
- if (error.Fail()) {
- is_vacant = false;
- return error;
- }
-
- uint64_t control_bits = reg_value.GetAsUInt64();
-
- is_vacant = !(control_bits & (1 << (2 * wp_index)));
-
- return error;
-}
-
-Status NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex(
- lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
-
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return Status("Watchpoint index out of range");
-
- // Read only watchpoints aren't supported on x86_64. Fall back to read/write
- // waitchpoints instead.
- // TODO: Add logic to detect when a write happens and ignore that watchpoint
- // hit.
- if (watch_flags == 0x2)
- watch_flags = 0x3;
-
- if (watch_flags != 0x1 && watch_flags != 0x3)
- return Status("Invalid read/write bits for watchpoint");
-
- if (size != 1 && size != 2 && size != 4 && size != 8)
- return Status("Invalid size for watchpoint");
-
- bool is_vacant;
- Status error = IsWatchpointVacant(wp_index, is_vacant);
- if (error.Fail())
- return error;
- if (!is_vacant)
- return Status("Watchpoint index not vacant");
-
- RegisterValue reg_value;
- error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
- if (error.Fail())
- 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);
-
- // set bits 16-17, 20-21, 24-25, or 28-29
- // with 0b01 for write, and 0b11 for read/write
- uint64_t rw_bits = watch_flags << (16 + 4 * wp_index);
-
- // set bits 18-19, 22-23, 26-27, or 30-31
- // with 0b00, 0b01, 0b10, or 0b11
- // for 1, 2, 8 (if supported), or 4 bytes, respectively
- uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
-
- uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
-
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
-
- control_bits |= enable_bit | rw_bits | size_bits;
-
- error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr));
- if (error.Fail())
- return error;
-
- error =
- WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
- if (error.Fail())
- return error;
-
- error.Clear();
- return error;
-}
-
-bool NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint(
- uint32_t wp_index) {
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return false;
-
- RegisterValue reg_value;
-
- // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of
- // the debug status register (DR6)
- Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
- if (error.Fail())
- return false;
- uint64_t bit_mask = 1 << wp_index;
- uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
- error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
- if (error.Fail())
- return false;
-
- // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19},
- // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register
- // (DR7)
- error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
- if (error.Fail())
- return false;
- bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits))
- .Success();
-}
-
-Status NativeRegisterContextLinux_x86_64::ClearAllHardwareWatchpoints() {
- RegisterValue reg_value;
-
- // clear bits {0-4} of the debug status register (DR6)
- Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
- if (error.Fail())
- return error;
- uint64_t bit_mask = 0xF;
- uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
- error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
- if (error.Fail())
- return error;
-
- // clear bits {0-7,16-31} of the debug control register (DR7)
- error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
- if (error.Fail())
- return error;
- bit_mask = 0xFF | (0xFFFF << 16);
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
-}
-
-uint32_t NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint(
- lldb::addr_t addr, size_t size, uint32_t watch_flags) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) {
- bool is_vacant;
- Status error = IsWatchpointVacant(wp_index, is_vacant);
- if (is_vacant) {
- error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
- if (error.Success())
- return wp_index;
- }
- if (error.Fail() && log) {
- LLDB_LOGF(log, "NativeRegisterContextLinux_x86_64::%s Error: %s",
- __FUNCTION__, error.AsCString());
- }
- }
- return LLDB_INVALID_INDEX32;
-}
-
-lldb::addr_t
-NativeRegisterContextLinux_x86_64::GetWatchpointAddress(uint32_t wp_index) {
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return LLDB_INVALID_ADDRESS;
- RegisterValue reg_value;
- if (ReadRegisterRaw(m_reg_info.first_dr + wp_index, reg_value).Fail())
- return LLDB_INVALID_ADDRESS;
- return reg_value.GetAsUInt64();
-}
-
-uint32_t NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints() {
- // Available debug address registers: dr0, dr1, dr2, dr3
- return 4;
-}
-
uint32_t
NativeRegisterContextLinux_x86_64::GetPtraceOffset(uint32_t reg_index) {
// If register is MPX, remove extra factor from gdb offset
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
index 5651602aae2e..82270dd560cd 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
@@ -12,6 +12,7 @@
#define lldb_NativeRegisterContextLinux_x86_64_h
#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
+#include "Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h"
#include "Plugins/Process/Utility/RegisterContext_x86.h"
#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
#include <sys/uio.h>
@@ -21,7 +22,9 @@ namespace process_linux {
class NativeProcessLinux;
-class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux {
+class NativeRegisterContextLinux_x86_64
+ : public NativeRegisterContextLinux,
+ public NativeRegisterContextWatchpoint_x86 {
public:
NativeRegisterContextLinux_x86_64(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
@@ -42,28 +45,6 @@ class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux {
Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
-
- Status GetWatchpointHitIndex(uint32_t &wp_index,
- lldb::addr_t trap_addr) override;
-
- Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
-
- bool ClearHardwareWatchpoint(uint32_t wp_index) override;
-
- Status ClearAllHardwareWatchpoints() override;
-
- Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
- uint32_t watch_flags,
- uint32_t wp_index);
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
- uint32_t watch_flags) override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
llvm::Optional<SyscallData> GetSyscallData() override;
llvm::Optional<MmapData> GetMmapData() override;
@@ -109,6 +90,7 @@ class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux {
uint32_t first_mpxc;
uint32_t last_mpxc;
uint32_t first_dr;
+ uint32_t last_dr;
uint32_t gpr_flags;
};
@@ -132,6 +114,8 @@ class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux {
bool IsFPR(uint32_t reg_index) const;
+ bool IsDR(uint32_t reg_index) const;
+
bool CopyXSTATEtoYMM(uint32_t reg_index, lldb::ByteOrder byte_order);
bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
More information about the lldb-commits
mailing list