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)&regs, 0)) < 0) {
+        m_result = false;
+    } else {
+        if (m_size == sizeof(uintptr_t))
+            m_value = *(uintptr_t *)(((caddr_t)&regs) + m_offset);
+        else 
+            memcpy(&m_value, (((caddr_t)&regs) + 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)&regs, 0) < 0) {
+        m_result = false;
+        return;
+    }
+    *(uintptr_t *)(((caddr_t)&regs) + m_offset) = (uintptr_t)m_value.GetAsUInt64();
+    if (PTRACE(PT_SETDBREGS, m_tid, (caddr_t)&regs, 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

Reply via email to