Index: source/Plugins/Process/FreeBSD/ProcessMonitor.h =================================================================== --- source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -116,6 +116,23 @@ 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. + 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. + 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. bool ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size); Index: source/Plugins/Process/FreeBSD/ProcessMonitor.cpp =================================================================== --- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -101,8 +101,8 @@ log->Printf("ptrace() failed; errno=%d (%s)", errno, str); } -#ifdef __amd64__ if (log) { +#ifdef __amd64__ if (req == PT_GETREGS) { struct reg *r = (struct reg *) addr; @@ -111,8 +111,15 @@ log->Printf("PT_GETREGS: bp=0x%lx", r->r_rbp); log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax); } - } #endif + if (req == PT_GETDBREGS || req == PT_SETDBREGS) { + struct dbreg *r = (struct dbreg *) addr; + char setget = (req == PT_GETDBREGS) ? 'G' : 'S'; + + for (int i = 0; i <= 7; i++) + log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); + } + } return result; } @@ -348,6 +355,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 @@ -1175,7 +1258,7 @@ case 0: case TRAP_TRACE: if (log) - log->Printf ("ProcessMonitor::%s() received trace event, tid = %" PRIu64, __FUNCTION__, tid); + log->Printf ("ProcessMonitor::%s() received trace event, tid = %" PRIu64 " : si_code = %d", __FUNCTION__, tid, info->si_code); message = ProcessMessage::Trace(tid); break; @@ -1464,6 +1547,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/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/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/POSIX/POSIXThread.cpp =================================================================== --- source/Plugins/Process/POSIX/POSIXThread.cpp +++ source/Plugins/Process/POSIX/POSIXThread.cpp @@ -65,7 +65,16 @@ lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx); if (wp.get() && wp->IsEnabled()) { - assert(EnableHardwareWatchpoint(wp.get())); + // This watchpoint as been enabled; obviously this "new" thread + // has been created since that watchpoint was enabled. Since + // the POSIXBreakpointProtocol has yet to be initialized, its + // m_watchpoints_initialized member will be FALSE. Attempting to + // read the debug status register to determine if a watchpoint + // has been hit would result in the zeroing of that register. + // Since the active debug registers would have been cloned when + // this thread was created, simply force the m_watchpoints_initized + // member to TRUE and avoid resetting dr6 and dr7. + GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized(); } } } @@ -511,6 +520,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_i386.cpp =================================================================== --- source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp +++ source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp @@ -37,8 +37,18 @@ uint32_t gs; }; -#define DR_SIZE 0 -#define DR_OFFSET(reg_index) 0 +struct dbreg { + uint32_t dr[8]; /* debug registers */ + /* Index 0-3: debug address registers */ + /* Index 4-5: reserved */ + /* Index 6: debug status */ + /* Index 7: debug control */ +}; + + +#define DR_SIZE sizeof(uint32_t) +#define DR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(dbreg, dr[reg_index])) //--------------------------------------------------------------------------- // Include RegisterInfos_i386 to declare our g_register_infos_i386 structure. 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 @@ -46,8 +46,19 @@ uint64_t ss; } GPR; -#define DR_SIZE 0 -#define DR_OFFSET(reg_index) 0 +struct dbreg { + uint64_t dr[16]; /* debug registers */ + /* Index 0-3: debug address registers */ + /* Index 4-5: reserved */ + /* Index 6: debug status */ + /* Index 7: debug control */ + /* Index 8-15: reserved */ +}; + +#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/RegisterContextPOSIX.h =================================================================== --- source/Plugins/Process/POSIX/RegisterContextPOSIX.h +++ source/Plugins/Process/POSIX/RegisterContextPOSIX.h @@ -66,6 +66,10 @@ virtual uint32_t NumSupportedHardwareWatchpoints () = 0; + // Force m_watchpoints_initialized to TRUE + void + ForceWatchpointsInitialized () {m_watchpoints_initialized = true;} + protected: bool m_watchpoints_initialized; }; 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),