diff options
Diffstat (limited to 'lldb/tools/debugserver/source/MacOSX')
7 files changed, 135 insertions, 13 deletions
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp index aca47f9120f..f9e3dd569f6 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp @@ -700,6 +700,18 @@ MachThread::HardwareWatchpointStateChanged () } bool +MachThread::RollbackTransForHWP() +{ + return m_arch_ap->RollbackTransForHWP(); +} + +bool +MachThread::FinishTransForHWP() +{ + return m_arch_ap->FinishTransForHWP(); +} + +bool MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp) { if (bp != NULL && bp->IsHardware()) diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h index 724043ab039..90bd05f2dc7 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h @@ -66,6 +66,8 @@ public: bool DisableHardwareBreakpoint (const DNBBreakpoint *breakpoint); bool DisableHardwareWatchpoint (const DNBBreakpoint *watchpoint); uint32_t NumSupportedHardwareWatchpoints () const; + bool RollbackTransForHWP(); + bool FinishTransForHWP(); nub_state_t GetState(); void SetState(nub_state_t state); diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp index e2aa0f2eedd..b8044fe6c7f 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp @@ -478,8 +478,17 @@ MachThreadList::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const for (uint32_t idx = 0; idx < num_threads; ++idx) { if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(wp)) == INVALID_NUB_HW_INDEX) + { + // We know that idx failed for some reason. Let's rollback the transaction for [0, idx). + for (uint32_t i = 0; i < idx; ++i) + m_threads[i]->RollbackTransForHWP(); return INVALID_NUB_HW_INDEX; + } } + // Notify each thread to commit the pending transaction. + for (uint32_t idx = 0; idx < num_threads; ++idx) + m_threads[idx]->FinishTransForHWP(); + // Use an arbitrary thread to signal the completion of our transaction. if (num_threads) m_threads[0]->HardwareWatchpointStateChanged(); @@ -498,8 +507,17 @@ MachThreadList::DisableHardwareWatchpoint (const DNBBreakpoint* wp) const for (uint32_t idx = 0; idx < num_threads; ++idx) { if (!m_threads[idx]->DisableHardwareWatchpoint(wp)) + { + // We know that idx failed for some reason. Let's rollback the transaction for [0, idx). + for (uint32_t i = 0; i < idx; ++i) + m_threads[i]->RollbackTransForHWP(); return false; + } } + // Notify each thread to commit the pending transaction. + for (uint32_t idx = 0; idx < num_threads; ++idx) + m_threads[idx]->FinishTransForHWP(); + // Use an arbitrary thread to signal the completion of our transaction. if (num_threads) m_threads[0]->HardwareWatchpointStateChanged(); diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp index 3962b9b6c5d..9a1abfbf286 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp @@ -818,6 +818,42 @@ DNBArchImplI386::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) } } +bool +DNBArchImplI386::StartTransForHWP() +{ + if (m_2pc_trans_state != Trans_Done || m_2pc_trans_state != Trans_Rolled_Back) + DNBLogError ("%s inconsistent state detected, expected %d or %d, got: %d", __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state); + m_2pc_dbg_checkpoint = m_state.context.dbg; + m_2pc_trans_state = Trans_Pending; + return true; +} +bool +DNBArchImplI386::RollbackTransForHWP() +{ + m_state.context.dbg = m_2pc_dbg_checkpoint; + if (m_2pc_trans_state != Trans_Pending) + DNBLogError ("%s inconsistent state detected, expected %d, got: %d", __FUNCTION__, Trans_Pending, m_2pc_trans_state); + m_2pc_trans_state = Trans_Rolled_Back; + kern_return_t kret = SetDBGState(); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret); + + if (kret == KERN_SUCCESS) + return true; + else + return false; +} +bool +DNBArchImplI386::FinishTransForHWP() +{ + m_2pc_trans_state = Trans_Done; + return true; +} +DNBArchImplI386::DBG +DNBArchImplI386::GetDBGCheckpoint() +{ + return m_2pc_dbg_checkpoint; +} + uint32_t DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write) { @@ -842,7 +878,6 @@ DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, boo uint32_t i = 0; DBG &debug_state = m_state.context.dbg; - DBG dsCheckPoint = m_state.context.dbg; for (i = 0; i < num_hw_watchpoints; ++i) { if (IsWatchpointVacant(debug_state, i)) @@ -852,6 +887,8 @@ DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, boo // See if we found an available hw breakpoint slot above if (i < num_hw_watchpoints) { + StartTransForHWP(); + // Modify our local copy of the debug state, first. SetWatchpoint(debug_state, i, addr, size, read, write); // Now set the watch point in the inferior. @@ -860,8 +897,8 @@ DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, boo if (kret == KERN_SUCCESS) return i; - else // Recovery block. - m_state.context.dbg = dsCheckPoint; + else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed. + m_state.context.dbg = GetDBGCheckpoint(); } else { @@ -880,9 +917,10 @@ DNBArchImplI386::DisableHardwareWatchpoint (uint32_t hw_index) if (kret == KERN_SUCCESS) { DBG &debug_state = m_state.context.dbg; - DBG dsCheckPoint = m_state.context.dbg; if (hw_index < num_hw_points && !IsWatchpointVacant(debug_state, hw_index)) { + StartTransForHWP(); + // Modify our local copy of the debug state, first. ClearWatchpoint(debug_state, hw_index); // Now disable the watch point in the inferior. @@ -892,8 +930,8 @@ DNBArchImplI386::DisableHardwareWatchpoint (uint32_t hw_index) if (kret == KERN_SUCCESS) return true; - else // Recovery block. - m_state.context.dbg = dsCheckPoint; + else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed. + m_state.context.dbg = GetDBGCheckpoint(); } } return false; diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h index 316aed2ba50..7a282bd8577 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h @@ -231,8 +231,15 @@ protected: static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); + virtual bool StartTransForHWP(); + virtual bool RollbackTransForHWP(); + virtual bool FinishTransForHWP(); + DBG GetDBGCheckpoint(); + MachThread *m_thread; State m_state; + DBG m_2pc_dbg_checkpoint; + uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)? }; #endif // #if defined (__i386__) || defined (__x86_64__) diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index 94aa9a18664..2a8cf69c26a 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -795,6 +795,42 @@ DNBArchImplX86_64::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) } } +bool +DNBArchImplX86_64::StartTransForHWP() +{ + if (m_2pc_trans_state != Trans_Done || m_2pc_trans_state != Trans_Rolled_Back) + DNBLogError ("%s inconsistent state detected, expected %d or %d, got: %d", __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state); + m_2pc_dbg_checkpoint = m_state.context.dbg; + m_2pc_trans_state = Trans_Pending; + return true; +} +bool +DNBArchImplX86_64::RollbackTransForHWP() +{ + m_state.context.dbg = m_2pc_dbg_checkpoint; + if (m_2pc_trans_state != Trans_Pending) + DNBLogError ("%s inconsistent state detected, expected %d, got: %d", __FUNCTION__, Trans_Pending, m_2pc_trans_state); + m_2pc_trans_state = Trans_Rolled_Back; + kern_return_t kret = SetDBGState(); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret); + + if (kret == KERN_SUCCESS) + return true; + else + return false; +} +bool +DNBArchImplX86_64::FinishTransForHWP() +{ + m_2pc_trans_state = Trans_Done; + return true; +} +DNBArchImplX86_64::DBG +DNBArchImplX86_64::GetDBGCheckpoint() +{ + return m_2pc_dbg_checkpoint; +} + uint32_t DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write) { @@ -819,7 +855,6 @@ DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, b uint32_t i = 0; DBG &debug_state = m_state.context.dbg; - DBG dsCheckPoint = m_state.context.dbg; for (i = 0; i < num_hw_watchpoints; ++i) { if (IsWatchpointVacant(debug_state, i)) @@ -829,6 +864,8 @@ DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, b // See if we found an available hw breakpoint slot above if (i < num_hw_watchpoints) { + StartTransForHWP(); + // Modify our local copy of the debug state, first. SetWatchpoint(debug_state, i, addr, size, read, write); // Now set the watch point in the inferior. @@ -837,8 +874,8 @@ DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, b if (kret == KERN_SUCCESS) return i; - else // Recovery block. - m_state.context.dbg = dsCheckPoint; + else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed. + m_state.context.dbg = GetDBGCheckpoint(); } else { @@ -857,9 +894,10 @@ DNBArchImplX86_64::DisableHardwareWatchpoint (uint32_t hw_index) if (kret == KERN_SUCCESS) { DBG &debug_state = m_state.context.dbg; - DBG dsCheckPoint = m_state.context.dbg; if (hw_index < num_hw_points && !IsWatchpointVacant(debug_state, hw_index)) { + StartTransForHWP(); + // Modify our local copy of the debug state, first. ClearWatchpoint(debug_state, hw_index); // Now disable the watch point in the inferior. @@ -869,8 +907,8 @@ DNBArchImplX86_64::DisableHardwareWatchpoint (uint32_t hw_index) if (kret == KERN_SUCCESS) return true; - else // Recovery block. - m_state.context.dbg = dsCheckPoint; + else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed. + m_state.context.dbg = GetDBGCheckpoint(); } } return false; diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h index 04c07bc0dd1..148780ee414 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h @@ -238,8 +238,15 @@ protected: static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); + virtual bool StartTransForHWP(); + virtual bool RollbackTransForHWP(); + virtual bool FinishTransForHWP(); + DBG GetDBGCheckpoint(); + MachThread *m_thread; - State m_state; + State m_state; + DBG m_2pc_dbg_checkpoint; + uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)? }; #endif // #if defined (__i386__) || defined (__x86_64__) |

