jwolfe added you to the CC list for the revision "FreeBSD watchpoint support".
Hi emaste,
Implement x86_64 debug register read/write in support of hardware watchpoints.
Hoist LinuxThread::TraceNotify code back into POSIXThread::TraceNotify()
llvm.org/pr16706
http://llvm-reviews.chandlerc.com/D2572
Files:
source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
source/Plugins/Process/FreeBSD/ProcessMonitor.h
source/Plugins/Process/Linux/LinuxThread.cpp
source/Plugins/Process/Linux/LinuxThread.h
source/Plugins/Process/POSIX/POSIXThread.cpp
source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
Index: source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
===================================================================
--- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -111,6 +111,16 @@
log->Printf("PT_GETREGS: bp=0x%lx", r->r_rbp);
log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax);
}
+ if (req == PT_GETDBREGS) {
+ struct dbreg *r = (struct dbreg *) addr;
+
+ log->Printf("PT_GETDBREGS: dr[0]=0x%lx", r->dr[0]);
+ log->Printf("PT_GETDBREGS: dr[1]=0x%lx", r->dr[1]);
+ log->Printf("PT_GETDBREGS: dr[2]=0x%lx", r->dr[2]);
+ log->Printf("PT_GETDBREGS: dr[3]=0x%lx", r->dr[3]);
+ log->Printf("PT_GETDBREGS: dr[6]=0x%lx", r->dr[6]);
+ log->Printf("PT_GETDBREGS: dr[7]=0x%lx", r->dr[7]);
+ }
}
#endif
@@ -348,6 +358,82 @@
}
//------------------------------------------------------------------------------
+/// @class ReadDebugRegOperation
+/// @brief Implements ProcessMonitor::ReadDebugRegisterValue.
+class ReadDebugRegOperation : public Operation
+{
+public:
+ ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
+ RegisterValue &value, bool &result)
+ : m_tid(tid), m_offset(offset), m_size(size),
+ m_value(value), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ unsigned m_offset;
+ unsigned m_size;
+ RegisterValue &m_value;
+ bool &m_result;
+};
+
+void
+ReadDebugRegOperation::Execute(ProcessMonitor *monitor)
+{
+ struct dbreg regs;
+ int rc;
+
+ if ((rc = PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0)) < 0) {
+ m_result = false;
+ } else {
+ if (m_size == sizeof(uintptr_t))
+ m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset);
+ else
+ memcpy(&m_value, (((caddr_t)®s) + m_offset), m_size);
+ m_result = true;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// @class WriteDebugRegOperation
+/// @brief Implements ProcessMonitor::WriteDebugRegisterValue.
+class WriteDebugRegOperation : public Operation
+{
+public:
+ WriteDebugRegOperation(lldb::tid_t tid, unsigned offset,
+ const RegisterValue &value, bool &result)
+ : m_tid(tid), m_offset(offset),
+ m_value(value), m_result(result)
+ { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ unsigned m_offset;
+ const RegisterValue &m_value;
+ bool &m_result;
+};
+
+void
+WriteDebugRegOperation::Execute(ProcessMonitor *monitor)
+{
+ struct dbreg regs;
+
+ if (PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0) < 0) {
+ m_result = false;
+ return;
+ }
+ *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64();
+ if (PTRACE(PT_SETDBREGS, m_tid, (caddr_t)®s, 0) < 0)
+ m_result = false;
+ else
+ m_result = true;
+}
+
+//------------------------------------------------------------------------------
/// @class ReadGPROperation
/// @brief Implements ProcessMonitor::ReadGPR.
class ReadGPROperation : public Operation
@@ -1459,6 +1545,28 @@
}
bool
+ProcessMonitor::ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset,
+ const char *reg_name, unsigned size,
+ lldb_private::RegisterValue &value)
+{
+ bool result;
+ ReadDebugRegOperation op(tid, offset, size, value, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
+ProcessMonitor::WriteDebugRegisterValue(lldb::tid_t tid, unsigned offset,
+ const char *reg_name,
+ const lldb_private::RegisterValue &value)
+{
+ bool result;
+ WriteDebugRegOperation op(tid, offset, value, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size)
{
bool result;
Index: source/Plugins/Process/FreeBSD/ProcessMonitor.h
===================================================================
--- source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -120,6 +120,27 @@
WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
const lldb_private::RegisterValue &value);
+ /// Reads the contents from the debug register identified by the given
+ /// (architecture dependent) offset.
+ ///
+ /// This method is provided for use by RegisterContextFreeBSD derivatives.
+ /// FIXME: ???? The FreeBSD implementation of this function should use tid in order
+ /// to enable support for debugging threaded programs.
+ bool
+ ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset,
+ const char *reg_name, unsigned size,
+ lldb_private::RegisterValue &value);
+
+ /// Writes the given value to the debug register identified by the given
+ /// (architecture dependent) offset.
+ ///
+ /// This method is provided for use by RegisterContextFreeBSD derivatives.
+ /// FIXME: ???? The FreeBSD implementation of this function should use tid in order
+ /// to enable support for debugging threaded programs.
+ bool
+ WriteDebugRegisterValue(lldb::tid_t tid, unsigned offset,
+ const char *reg_name,
+ const lldb_private::RegisterValue &value);
/// Reads all general purpose registers into the specified buffer.
/// FIXME: The FreeBSD implementation of this function should use tid in order
/// to enable support for debugging threaded programs.
Index: source/Plugins/Process/Linux/LinuxThread.cpp
===================================================================
--- source/Plugins/Process/Linux/LinuxThread.cpp
+++ source/Plugins/Process/Linux/LinuxThread.cpp
@@ -40,24 +40,3 @@
POSIXThread::RefreshStateAfterStop();
}
-
-void
-LinuxThread::TraceNotify(const ProcessMessage &message)
-{
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- {
- uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
- {
- if (reg_ctx->IsWatchpointHit(wp_idx))
- {
- WatchNotify(message);
- return;
- }
- }
- }
-
- POSIXThread::TraceNotify (message);
-}
Index: source/Plugins/Process/Linux/LinuxThread.h
===================================================================
--- source/Plugins/Process/Linux/LinuxThread.h
+++ source/Plugins/Process/Linux/LinuxThread.h
@@ -34,10 +34,6 @@
// POSIXThread override
virtual void
RefreshStateAfterStop();
-
-protected:
- virtual void
- TraceNotify(const ProcessMessage &message);
};
#endif // #ifndef liblldb_LinuxThread_H_
Index: source/Plugins/Process/POSIX/POSIXThread.cpp
===================================================================
--- source/Plugins/Process/POSIX/POSIXThread.cpp
+++ source/Plugins/Process/POSIX/POSIXThread.cpp
@@ -511,6 +511,21 @@
void
POSIXThread::TraceNotify(const ProcessMessage &message)
{
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ if (reg_ctx)
+ {
+ uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
+ uint32_t wp_idx;
+ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+ {
+ if (reg_ctx->IsWatchpointHit(wp_idx))
+ {
+ WatchNotify(message);
+ return;
+ }
+ }
+ }
+
SetStopInfo (StopInfo::CreateStopReasonToTrace(*this));
}
Index: source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
===================================================================
--- source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
+++ source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
@@ -11,6 +11,7 @@
#include "RegisterContextPOSIX_x86.h"
#include "RegisterContextFreeBSD_i386.h"
#include "RegisterContextFreeBSD_x86_64.h"
+#include <machine/reg.h>
using namespace lldb_private;
using namespace lldb;
@@ -46,8 +47,10 @@
uint64_t ss;
} GPR;
-#define DR_SIZE 0
-#define DR_OFFSET(reg_index) 0
+#define DR_SIZE sizeof(uint64_t)
+#define DR_OFFSET(reg_index) \
+ (LLVM_EXTENSION offsetof(dbreg, dr[reg_index]))
+
//---------------------------------------------------------------------------
// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure.
Index: source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
===================================================================
--- source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -109,6 +109,15 @@
RegisterValue &value)
{
ProcessMonitor &monitor = GetMonitor();
+
+#if defined(__FreeBSD__)
+ if (reg >= m_reg_info.first_dr)
+ return monitor.ReadDebugRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg),
+ GetRegisterName(reg),
+ GetRegisterSize(reg),
+ value);
+#endif
return monitor.ReadRegisterValue(m_thread.GetID(),
GetRegisterOffset(reg),
GetRegisterName(reg),
@@ -164,6 +173,13 @@
}
ProcessMonitor &monitor = GetMonitor();
+#if defined(__FreeBSD__)
+ if (reg >= m_reg_info.first_dr)
+ return monitor.WriteDebugRegisterValue(m_thread.GetID(),
+ GetRegisterOffset(reg_to_write),
+ GetRegisterName(reg_to_write),
+ value_to_write);
+#endif
return monitor.WriteRegisterValue(m_thread.GetID(),
GetRegisterOffset(reg_to_write),
GetRegisterName(reg_to_write),
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits