aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/Process
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Process')
-rw-r--r--source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp117
-rw-r--r--source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp26
-rw-r--r--source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h9
-rw-r--r--source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp460
-rw-r--r--source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h25
-rw-r--r--source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp71
-rw-r--r--source/Plugins/Process/NetBSD/NativeThreadNetBSD.h7
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp7
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_x86_64.h2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp14
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h4
11 files changed, 697 insertions, 45 deletions
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 298faa48e1c3..347c12943bd5 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -224,36 +224,83 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
// Get details on the signal raised.
- if (siginfo_err.Success()) {
- switch (info.psi_siginfo.si_code) {
- case TRAP_BRKPT:
+ if (siginfo_err.Fail()) {
+ return;
+ }
+
+ switch (info.psi_siginfo.si_code) {
+ case TRAP_BRKPT:
+ for (const auto &thread_sp : m_threads) {
+ static_pointer_cast<NativeThreadNetBSD>(thread_sp)
+ ->SetStoppedByBreakpoint();
+ FixupBreakpointPCAsNeeded(
+ *static_pointer_cast<NativeThreadNetBSD>(thread_sp));
+ }
+ SetState(StateType::eStateStopped, true);
+ break;
+ case TRAP_TRACE:
+ for (const auto &thread_sp : m_threads) {
+ static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace();
+ }
+ SetState(StateType::eStateStopped, true);
+ break;
+ case TRAP_EXEC: {
+ Error error = ReinitializeThreads();
+ if (error.Fail()) {
+ SetState(StateType::eStateInvalid);
+ return;
+ }
+
+ // Let our delegate know we have just exec'd.
+ NotifyDidExec();
+
+ for (const auto &thread_sp : m_threads) {
+ static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByExec();
+ }
+ SetState(StateType::eStateStopped, true);
+ } break;
+ case TRAP_DBREG: {
+ // If a watchpoint was hit, report it
+ uint32_t wp_index;
+ Error error =
+ static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid])
+ ->GetRegisterContext()
+ ->GetWatchpointHitIndex(wp_index,
+ (uintptr_t)info.psi_siginfo.si_addr);
+ if (error.Fail())
+ LLDB_LOG(log,
+ "received error while checking for watchpoint hits, pid = "
+ "{0}, LWP = {1}, error = {2}",
+ GetID(), info.psi_lwpid, error);
+ if (wp_index != LLDB_INVALID_INDEX32) {
for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)
- ->SetStoppedByBreakpoint();
- FixupBreakpointPCAsNeeded(
- *static_pointer_cast<NativeThreadNetBSD>(thread_sp));
+ ->SetStoppedByWatchpoint(wp_index);
}
SetState(StateType::eStateStopped, true);
break;
- case TRAP_TRACE:
+ }
+
+ // If a breakpoint was hit, report it
+ uint32_t bp_index;
+ error = static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid])
+ ->GetRegisterContext()
+ ->GetHardwareBreakHitIndex(bp_index,
+ (uintptr_t)info.psi_siginfo.si_addr);
+ if (error.Fail())
+ LLDB_LOG(log,
+ "received error while checking for hardware "
+ "breakpoint hits, pid = {0}, LWP = {1}, error = {2}",
+ GetID(), info.psi_lwpid, error);
+ if (bp_index != LLDB_INVALID_INDEX32) {
for (const auto &thread_sp : m_threads) {
- static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace();
+ static_pointer_cast<NativeThreadNetBSD>(thread_sp)
+ ->SetStoppedByBreakpoint();
}
SetState(StateType::eStateStopped, true);
break;
- case TRAP_EXEC: {
- Error error = ReinitializeThreads();
- if (error.Fail()) {
- SetState(StateType::eStateInvalid);
- return;
- }
-
- // Let our delegate know we have just exec'd.
- NotifyDidExec();
-
- SetState(StateType::eStateStopped, true);
- } break;
}
+ } break;
}
}
@@ -328,8 +375,8 @@ Error NativeProcessNetBSD::FixupBreakpointPCAsNeeded(
return error;
} else
LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
- // First try probing for a breakpoint at a software breakpoint location: PC -
- // breakpoint size.
+ // First try probing for a breakpoint at a software breakpoint location: PC
+ // - breakpoint size.
const lldb::addr_t initial_pc_addr =
context_sp->GetPCfromBreakpointLocation();
lldb::addr_t breakpoint_addr = initial_pc_addr;
@@ -439,7 +486,7 @@ Error NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
llvm_unreachable("Unexpected state");
default:
- return Error("NativeProcessLinux::%s (): unexpected state %s specified "
+ return Error("NativeProcessNetBSD::%s (): unexpected state %s specified "
"for pid %" PRIu64 ", tid %" PRIu64,
__FUNCTION__, StateAsCString(action->state), GetID(),
thread_sp->GetID());
@@ -540,8 +587,8 @@ Error NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
"descending memory map entries detected, unexpected");
prev_base_address = proc_entry_info.GetRange().GetRangeBase();
UNUSED_IF_ASSERT_DISABLED(prev_base_address);
- // If the target address comes before this entry, indicate distance to next
- // region.
+ // If the target address comes before this entry, indicate distance to
+ // next region.
if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
range_info.GetRange().SetRangeBase(load_addr);
range_info.GetRange().SetByteSize(
@@ -561,9 +608,8 @@ Error NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
}
// If we made it here, we didn't find an entry that contained the given
// address. Return the
- // load_addr as start and the amount of bytes betwwen load address and the end
- // of the memory as
- // size.
+ // load_addr as start and the amount of bytes betwwen load address and the
+ // end of the memory as size.
range_info.GetRange().SetRangeBase(load_addr);
range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
@@ -722,8 +768,8 @@ Error NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop,
LLDB_LOG(log, "waitpid for inferior failed with %s", error);
// Mark the inferior as invalid.
- // FIXME this could really use a new state - eStateLaunchFailure. For now,
- // using eStateInvalid.
+ // FIXME this could really use a new state - eStateLaunchFailure. For
+ // now, using eStateInvalid.
SetState(StateType::eStateInvalid);
return error;
@@ -766,6 +812,11 @@ Error NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop,
return error;
}
+ for (const auto &thread_sp : m_threads) {
+ static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
+ SIGSTOP);
+ }
+
/* Set process stopped */
SetState(StateType::eStateStopped);
@@ -894,6 +945,11 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
return -1;
}
+ for (const auto &thread_sp : m_threads) {
+ static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
+ SIGSTOP);
+ }
+
// Let our process instance know the thread has stopped.
SetState(StateType::eStateStopped);
@@ -1007,7 +1063,6 @@ Error NativeProcessNetBSD::ReinitializeThreads() {
// Reinitialize from scratch threads and register them in process
while (info.pl_lwpid != 0) {
NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid);
- thread_sp->SetStoppedByExec();
error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
if (error.Fail()) {
return error;
diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
index 1bb6324c97fe..cd47deac73ad 100644
--- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
+++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
@@ -57,6 +57,22 @@ Error NativeRegisterContextNetBSD::WriteFPR() {
return DoWriteFPR(buf);
}
+Error NativeRegisterContextNetBSD::ReadDBR() {
+ void *buf = GetDBRBuffer();
+ if (!buf)
+ return Error("DBR buffer is NULL");
+
+ return DoReadDBR(buf);
+}
+
+Error NativeRegisterContextNetBSD::WriteDBR() {
+ void *buf = GetDBRBuffer();
+ if (!buf)
+ return Error("DBR buffer is NULL");
+
+ return DoWriteDBR(buf);
+}
+
Error NativeRegisterContextNetBSD::DoReadGPR(void *buf) {
return NativeProcessNetBSD::PtraceWrapper(PT_GETREGS, GetProcessPid(), buf,
m_thread.GetID());
@@ -77,6 +93,16 @@ Error NativeRegisterContextNetBSD::DoWriteFPR(void *buf) {
m_thread.GetID());
}
+Error NativeRegisterContextNetBSD::DoReadDBR(void *buf) {
+ return NativeProcessNetBSD::PtraceWrapper(PT_GETDBREGS, GetProcessPid(), buf,
+ m_thread.GetID());
+}
+
+Error NativeRegisterContextNetBSD::DoWriteDBR(void *buf) {
+ return NativeProcessNetBSD::PtraceWrapper(PT_SETDBREGS, GetProcessPid(), buf,
+ m_thread.GetID());
+}
+
NativeProcessNetBSD &NativeRegisterContextNetBSD::GetProcess() {
auto process_sp =
std::static_pointer_cast<NativeProcessNetBSD>(m_thread.GetProcess());
diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
index 5ff59bc87c98..d820baac3afa 100644
--- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
+++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
@@ -41,6 +41,9 @@ protected:
virtual Error ReadFPR();
virtual Error WriteFPR();
+ virtual Error ReadDBR();
+ virtual Error WriteDBR();
+
virtual void *GetGPRBuffer() { return nullptr; }
virtual size_t GetGPRSize() {
return GetRegisterInfoInterface().GetGPRSize();
@@ -49,12 +52,18 @@ protected:
virtual void *GetFPRBuffer() { return nullptr; }
virtual size_t GetFPRSize() { return 0; }
+ virtual void *GetDBRBuffer() { return nullptr; }
+ virtual size_t GetDBRSize() { return 0; }
+
virtual Error DoReadGPR(void *buf);
virtual Error DoWriteGPR(void *buf);
virtual Error DoReadFPR(void *buf);
virtual Error DoWriteFPR(void *buf);
+ virtual Error DoReadDBR(void *buf);
+ virtual Error DoWriteDBR(void *buf);
+
virtual NativeProcessNetBSD &GetProcess();
virtual ::pid_t GetProcessPid();
};
diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
index 76e64ac48d66..dc37be7b934b 100644
--- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -19,7 +19,15 @@
#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
+// clang-format off
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <x86/cpu.h>
#include <elf.h>
+#include <err.h>
+#include <stdint.h>
+#include <stdlib.h>
+// clang-format on
using namespace lldb_private;
using namespace lldb_private::process_netbsd;
@@ -86,6 +94,57 @@ 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 *
@@ -114,7 +173,7 @@ NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64(
uint32_t concrete_frame_idx)
: NativeRegisterContextNetBSD(native_thread, concrete_frame_idx,
CreateRegisterInfoInterface(target_arch)),
- m_gpr_x86_64() {}
+ m_gpr_x86_64(), m_fpr_x86_64(), m_dbr_x86_64() {}
// CONSIDER after local and llgs debugging are merged, register set support can
// be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
@@ -143,8 +202,18 @@ NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const {
int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum(
int reg_num) const {
- if (reg_num < lldb_fctrl_x86_64)
+ 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;
+ else if (reg_num <= k_last_avx_x86_64)
+ return -1; // AVX
+ else if (reg_num <= k_last_mpxr_x86_64)
+ return -1; // MPXR
+ else if (reg_num <= k_last_mpxc_x86_64)
+ return -1; // MPXC
+ else if (reg_num <= lldb_dr7_x86_64)
+ return DBRegSet; // DBR
else
return -1;
}
@@ -157,6 +226,9 @@ int NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) {
case FPRegSet:
ReadFPR();
return 0;
+ case DBRegSet:
+ ReadDBR();
+ return 0;
default:
break;
}
@@ -170,6 +242,9 @@ int NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) {
case FPRegSet:
WriteFPR();
return 0;
+ case DBRegSet:
+ WriteDBR();
+ return 0;
default:
break;
}
@@ -285,6 +360,87 @@ Error NativeRegisterContextNetBSD_x86_64::ReadRegister(
case lldb_es_x86_64:
reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_ES];
break;
+ case lldb_fctrl_x86_64:
+ reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_cw;
+ break;
+ case lldb_fstat_x86_64:
+ reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_sw;
+ break;
+ case lldb_ftag_x86_64:
+ reg_value = (uint8_t)m_fpr_x86_64.fxstate.fx_tw;
+ break;
+ case lldb_fop_x86_64:
+ reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_opcode;
+ break;
+ case lldb_fiseg_x86_64:
+ reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_ip.fa_64;
+ break;
+ case lldb_fioff_x86_64:
+ reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off;
+ break;
+ case lldb_foseg_x86_64:
+ reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_dp.fa_64;
+ break;
+ case lldb_fooff_x86_64:
+ reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off;
+ break;
+ case lldb_mxcsr_x86_64:
+ reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr;
+ break;
+ case lldb_mxcsrmask_x86_64:
+ reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr_mask;
+ break;
+ case lldb_st0_x86_64:
+ case lldb_st1_x86_64:
+ case lldb_st2_x86_64:
+ case lldb_st3_x86_64:
+ case lldb_st4_x86_64:
+ case lldb_st5_x86_64:
+ case lldb_st6_x86_64:
+ case lldb_st7_x86_64:
+ reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64],
+ reg_info->byte_size, endian::InlHostByteOrder());
+ break;
+ case lldb_mm0_x86_64:
+ case lldb_mm1_x86_64:
+ case lldb_mm2_x86_64:
+ case lldb_mm3_x86_64:
+ case lldb_mm4_x86_64:
+ 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_info->byte_size, endian::InlHostByteOrder());
+ break;
+ case lldb_xmm0_x86_64:
+ case lldb_xmm1_x86_64:
+ case lldb_xmm2_x86_64:
+ case lldb_xmm3_x86_64:
+ case lldb_xmm4_x86_64:
+ case lldb_xmm5_x86_64:
+ case lldb_xmm6_x86_64:
+ case lldb_xmm7_x86_64:
+ case lldb_xmm8_x86_64:
+ case lldb_xmm9_x86_64:
+ case lldb_xmm10_x86_64:
+ case lldb_xmm11_x86_64:
+ case lldb_xmm12_x86_64:
+ case lldb_xmm13_x86_64:
+ case lldb_xmm14_x86_64:
+ case lldb_xmm15_x86_64:
+ reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64],
+ reg_info->byte_size, endian::InlHostByteOrder());
+ break;
+ case lldb_dr0_x86_64:
+ case lldb_dr1_x86_64:
+ case lldb_dr2_x86_64:
+ case lldb_dr3_x86_64:
+ case lldb_dr4_x86_64:
+ case lldb_dr5_x86_64:
+ case lldb_dr6_x86_64:
+ case lldb_dr7_x86_64:
+ reg_value = (uint64_t)m_dbr_x86_64.dr[reg - lldb_dr0_x86_64];
+ break;
}
return error;
@@ -400,6 +556,87 @@ Error NativeRegisterContextNetBSD_x86_64::WriteRegister(
case lldb_es_x86_64:
m_gpr_x86_64.regs[_REG_ES] = reg_value.GetAsUInt64();
break;
+ case lldb_fctrl_x86_64:
+ m_fpr_x86_64.fxstate.fx_cw = reg_value.GetAsUInt16();
+ break;
+ case lldb_fstat_x86_64:
+ m_fpr_x86_64.fxstate.fx_sw = reg_value.GetAsUInt16();
+ break;
+ case lldb_ftag_x86_64:
+ m_fpr_x86_64.fxstate.fx_tw = reg_value.GetAsUInt8();
+ break;
+ case lldb_fop_x86_64:
+ m_fpr_x86_64.fxstate.fx_opcode = reg_value.GetAsUInt16();
+ break;
+ case lldb_fiseg_x86_64:
+ m_fpr_x86_64.fxstate.fx_ip.fa_64 = reg_value.GetAsUInt64();
+ break;
+ case lldb_fioff_x86_64:
+ m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off = reg_value.GetAsUInt32();
+ break;
+ case lldb_foseg_x86_64:
+ m_fpr_x86_64.fxstate.fx_dp.fa_64 = reg_value.GetAsUInt64();
+ break;
+ case lldb_fooff_x86_64:
+ m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off = reg_value.GetAsUInt32();
+ break;
+ case lldb_mxcsr_x86_64:
+ m_fpr_x86_64.fxstate.fx_mxcsr = reg_value.GetAsUInt32();
+ break;
+ case lldb_mxcsrmask_x86_64:
+ m_fpr_x86_64.fxstate.fx_mxcsr_mask = reg_value.GetAsUInt32();
+ break;
+ case lldb_st0_x86_64:
+ case lldb_st1_x86_64:
+ case lldb_st2_x86_64:
+ case lldb_st3_x86_64:
+ case lldb_st4_x86_64:
+ case lldb_st5_x86_64:
+ case lldb_st6_x86_64:
+ case lldb_st7_x86_64:
+ ::memcpy(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64],
+ reg_value.GetBytes(), reg_value.GetByteSize());
+ break;
+ case lldb_mm0_x86_64:
+ case lldb_mm1_x86_64:
+ case lldb_mm2_x86_64:
+ case lldb_mm3_x86_64:
+ case lldb_mm4_x86_64:
+ 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],
+ reg_value.GetBytes(), reg_value.GetByteSize());
+ break;
+ case lldb_xmm0_x86_64:
+ case lldb_xmm1_x86_64:
+ case lldb_xmm2_x86_64:
+ case lldb_xmm3_x86_64:
+ case lldb_xmm4_x86_64:
+ case lldb_xmm5_x86_64:
+ case lldb_xmm6_x86_64:
+ case lldb_xmm7_x86_64:
+ case lldb_xmm8_x86_64:
+ case lldb_xmm9_x86_64:
+ case lldb_xmm10_x86_64:
+ case lldb_xmm11_x86_64:
+ case lldb_xmm12_x86_64:
+ case lldb_xmm13_x86_64:
+ case lldb_xmm14_x86_64:
+ case lldb_xmm15_x86_64:
+ ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64],
+ reg_value.GetBytes(), reg_value.GetByteSize());
+ break;
+ case lldb_dr0_x86_64:
+ case lldb_dr1_x86_64:
+ case lldb_dr2_x86_64:
+ case lldb_dr3_x86_64:
+ case lldb_dr4_x86_64:
+ case lldb_dr5_x86_64:
+ case lldb_dr6_x86_64:
+ case lldb_dr7_x86_64:
+ m_dbr_x86_64.dr[reg - lldb_dr0_x86_64] = reg_value.GetAsUInt64();
+ break;
}
if (WriteRegisterSet(set) != 0)
@@ -480,4 +717,223 @@ Error NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues(
return error;
}
+Error NativeRegisterContextNetBSD_x86_64::IsWatchpointHit(uint32_t wp_index,
+ bool &is_hit) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Error("Watchpoint index out of range");
+
+ RegisterValue reg_value;
+ const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr6_x86_64);
+ Error error = ReadRegister(reg_info, 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;
+}
+
+Error NativeRegisterContextNetBSD_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;
+ Error 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 Error();
+}
+
+Error NativeRegisterContextNetBSD_x86_64::IsWatchpointVacant(uint32_t wp_index,
+ bool &is_vacant) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Error("Watchpoint index out of range");
+
+ RegisterValue reg_value;
+ const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr7_x86_64);
+ Error error = ReadRegister(reg_info, 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;
+}
+
+Error NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
+
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Error("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 Error("Invalid read/write bits for watchpoint");
+
+ if (size != 1 && size != 2 && size != 4 && size != 8)
+ return Error("Invalid size for watchpoint");
+
+ bool is_vacant;
+ Error error = IsWatchpointVacant(wp_index, is_vacant);
+ if (error.Fail())
+ return error;
+ if (!is_vacant)
+ return Error("Watchpoint index not vacant");
+
+ RegisterValue reg_value;
+ const RegisterInfo *const reg_info_dr7 =
+ GetRegisterInfoAtIndex(lldb_dr7_x86_64);
+ error = ReadRegister(reg_info_dr7, 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;
+
+ const RegisterInfo *const reg_info_drN =
+ GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
+ error = WriteRegister(reg_info_drN, RegisterValue(addr));
+ if (error.Fail())
+ return error;
+
+ error = WriteRegister(reg_info_dr7, RegisterValue(control_bits));
+ if (error.Fail())
+ return error;
+
+ error.Clear();
+ return error;
+}
+
+bool NativeRegisterContextNetBSD_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)
+ const RegisterInfo *const reg_info_dr6 =
+ GetRegisterInfoAtIndex(lldb_dr6_x86_64);
+ Error error = ReadRegister(reg_info_dr6, reg_value);
+ if (error.Fail())
+ return false;
+ uint64_t bit_mask = 1 << wp_index;
+ uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ error = WriteRegister(reg_info_dr6, 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)
+ const RegisterInfo *const reg_info_dr7 =
+ GetRegisterInfoAtIndex(lldb_dr7_x86_64);
+ error = ReadRegister(reg_info_dr7, 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 WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
+}
+
+Error NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() {
+ RegisterValue reg_value;
+
+ // clear bits {0-4} of the debug status register (DR6)
+ const RegisterInfo *const reg_info_dr6 =
+ GetRegisterInfoAtIndex(lldb_dr6_x86_64);
+ Error error = ReadRegister(reg_info_dr6, reg_value);
+ if (error.Fail())
+ return error;
+ uint64_t bit_mask = 0xF;
+ uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ error = WriteRegister(reg_info_dr6, RegisterValue(status_bits));
+ if (error.Fail())
+ return error;
+
+ // clear bits {0-7,16-31} of the debug control register (DR7)
+ const RegisterInfo *const reg_info_dr7 =
+ GetRegisterInfoAtIndex(lldb_dr7_x86_64);
+ error = ReadRegister(reg_info_dr7, reg_value);
+ if (error.Fail())
+ return error;
+ bit_mask = 0xFF | (0xFFFF << 16);
+ uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ return WriteRegister(reg_info_dr7, RegisterValue(control_bits));
+}
+
+uint32_t NativeRegisterContextNetBSD_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;
+ Error 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) {
+ log->Printf("NativeRegisterContextNetBSD_x86_64::%s Error: %s",
+ __FUNCTION__, error.AsCString());
+ }
+ }
+ return LLDB_INVALID_INDEX32;
+}
+
+lldb::addr_t
+NativeRegisterContextNetBSD_x86_64::GetWatchpointAddress(uint32_t wp_index) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return LLDB_INVALID_ADDRESS;
+ RegisterValue reg_value;
+ const RegisterInfo *const reg_info_drN =
+ GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
+ if (ReadRegister(reg_info_drN, reg_value).Fail())
+ return LLDB_INVALID_ADDRESS;
+ return reg_value.GetAsUInt64();
+}
+
+uint32_t NativeRegisterContextNetBSD_x86_64::NumSupportedHardwareWatchpoints() {
+ // Available debug address registers: dr0, dr1, dr2, dr3
+ return 4;
+}
+
#endif // defined(__x86_64__)
diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
index f6f7d7f0976a..35b7cf1c2f19 100644
--- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
+++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
@@ -46,17 +46,40 @@ public:
Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+ Error IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
+
+ Error GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) override;
+
+ Error IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
+
+ bool ClearHardwareWatchpoint(uint32_t wp_index) override;
+
+ Error ClearAllHardwareWatchpoints() override;
+
+ Error 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;
+
protected:
void *GetGPRBuffer() override { return &m_gpr_x86_64; }
void *GetFPRBuffer() override { return &m_fpr_x86_64; }
+ void *GetDBRBuffer() override { return &m_dbr_x86_64; }
private:
// Private member types.
- enum { GPRegSet, FPRegSet };
+ enum { GPRegSet, FPRegSet, DBRegSet };
// Private member variables.
struct reg m_gpr_x86_64;
struct fpreg m_fpr_x86_64;
+ struct dbreg m_dbr_x86_64;
int GetSetForNativeRegNum(int reg_num) const;
diff --git a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
index f23621e45aad..9beb65288c2f 100644
--- a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -16,6 +16,9 @@
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/State.h"
+#include "lldb/Utility/LLDBAssert.h"
+
+#include <sstream>
using namespace lldb;
using namespace lldb_private;
@@ -68,6 +71,23 @@ void NativeThreadNetBSD::SetStoppedByExec() {
m_stop_info.details.signal.signo = SIGTRAP;
}
+void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
+ SetStopped();
+
+ lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");
+
+ std::ostringstream ostr;
+ ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
+ ostr << wp_index;
+
+ ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index);
+
+ m_stop_description = ostr.str();
+
+ m_stop_info.reason = StopReason::eStopReasonWatchpoint;
+ m_stop_info.details.signal.signo = SIGTRAP;
+}
+
void NativeThreadNetBSD::SetStopped() {
const StateType new_state = StateType::eStateStopped;
m_state = new_state;
@@ -142,18 +162,61 @@ NativeRegisterContextSP NativeThreadNetBSD::GetRegisterContext() {
Error NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,
uint32_t watch_flags, bool hardware) {
- return Error("Unimplemented");
+ if (!hardware)
+ return Error("not implemented");
+ if (m_state == eStateLaunching)
+ return Error();
+ Error error = RemoveWatchpoint(addr);
+ if (error.Fail())
+ return error;
+ NativeRegisterContextSP reg_ctx = GetRegisterContext();
+ uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags);
+ if (wp_index == LLDB_INVALID_INDEX32)
+ return Error("Setting hardware watchpoint failed.");
+ m_watchpoint_index_map.insert({addr, wp_index});
+ return Error();
}
Error NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) {
- return Error("Unimplemented");
+ auto wp = m_watchpoint_index_map.find(addr);
+ if (wp == m_watchpoint_index_map.end())
+ return Error();
+ uint32_t wp_index = wp->second;
+ m_watchpoint_index_map.erase(wp);
+ if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
+ return Error();
+ return Error("Clearing hardware watchpoint failed.");
}
Error NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr,
size_t size) {
- return Error("Unimplemented");
+ if (m_state == eStateLaunching)
+ return Error();
+
+ Error error = RemoveHardwareBreakpoint(addr);
+ if (error.Fail())
+ return error;
+
+ NativeRegisterContextSP reg_ctx = GetRegisterContext();
+ uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size);
+
+ if (bp_index == LLDB_INVALID_INDEX32)
+ return Error("Setting hardware breakpoint failed.");
+
+ m_hw_break_index_map.insert({addr, bp_index});
+ return Error();
}
Error NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {
- return Error("Unimplemented");
+ auto bp = m_hw_break_index_map.find(addr);
+ if (bp == m_hw_break_index_map.end())
+ return Error();
+
+ uint32_t bp_index = bp->second;
+ if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) {
+ m_hw_break_index_map.erase(bp);
+ return Error();
+ }
+
+ return Error("Clearing hardware breakpoint failed.");
}
diff --git a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
index 85fff5d5653f..96d7fd0ce03b 100644
--- a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
+++ b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
@@ -12,6 +12,9 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
+#include <map>
+#include <string>
+
namespace lldb_private {
namespace process_netbsd {
@@ -53,6 +56,7 @@ private:
void SetStoppedByBreakpoint();
void SetStoppedByTrace();
void SetStoppedByExec();
+ void SetStoppedByWatchpoint(uint32_t wp_index);
void SetStopped();
void SetRunning();
void SetStepping();
@@ -64,6 +68,9 @@ private:
ThreadStopInfo m_stop_info;
NativeRegisterContextSP m_reg_context_sp;
std::string m_stop_description;
+ using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>;
+ WatchpointIndexMap m_watchpoint_index_map;
+ WatchpointIndexMap m_hw_break_index_map;
};
typedef std::shared_ptr<NativeThreadNetBSD> NativeThreadNetBSDSP;
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
index 207c69313282..6a55947ba5c2 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
@@ -55,9 +55,10 @@ RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64(
m_registers_count[i] = reg_set_ptr->num_registers;
}
- assert(m_num_registers == m_registers_count[gpr_registers_count] +
- m_registers_count[fpr_registers_count] +
- m_registers_count[msa_registers_count]);
+ assert(m_num_registers ==
+ static_cast<uint32_t>(m_registers_count[gpr_registers_count] +
+ m_registers_count[fpr_registers_count] +
+ m_registers_count[msa_registers_count]));
// elf-core yet to support ReadFPR()
ProcessSP base = CalculateProcess();
diff --git a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
index 2ba8059911a0..8861ecd66806 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
@@ -148,7 +148,7 @@
DR_OFFSET(i), eEncodingUint, eFormatHex, \
{LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
- LLDB_INVALID_REGNUM }, \
+ lldb_##reg##i##_x86_64 }, \
nullptr, nullptr, nullptr, 0 \
}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 7ef253decad6..d527b4daaab9 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -1310,12 +1310,20 @@ void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); }
GDBRemoteCommunication::ScopedTimeout::ScopedTimeout(
GDBRemoteCommunication &gdb_comm, std::chrono::seconds timeout)
- : m_gdb_comm(gdb_comm) {
- m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout);
+ : m_gdb_comm(gdb_comm), m_timeout_modified(false) {
+ auto curr_timeout = gdb_comm.GetPacketTimeout();
+ // Only update the timeout if the timeout is greater than the current
+ // timeout. If the current timeout is larger, then just use that.
+ if (curr_timeout < timeout) {
+ m_timeout_modified = true;
+ m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout);
+ }
}
GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout() {
- m_gdb_comm.SetPacketTimeout(m_saved_timeout);
+ // Only restore the timeout if we set it in the constructor.
+ if (m_timeout_modified)
+ m_gdb_comm.SetPacketTimeout(m_saved_timeout);
}
// This function is called via the Communications class read thread when bytes
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 1f3fa17cfc26..b49e05e22d95 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -89,6 +89,10 @@ public:
private:
GDBRemoteCommunication &m_gdb_comm;
std::chrono::seconds m_saved_timeout;
+ // Don't ever reduce the timeout for a packet, only increase it. If the
+ // requested timeout if less than the current timeout, we don't set it
+ // and won't need to restore it.
+ bool m_timeout_modified;
};
GDBRemoteCommunication(const char *comm_name, const char *listener_name);