diff --git a/lldb/include/lldb/Breakpoint/BreakpointSite.h b/lldb/include/lldb/Breakpoint/BreakpointSite.h --- a/lldb/include/lldb/Breakpoint/BreakpointSite.h +++ b/lldb/include/lldb/Breakpoint/BreakpointSite.h @@ -61,6 +61,8 @@ /// Sets the trap opcode bool SetTrapOpcode(const uint8_t *trap_opcode, uint32_t trap_opcode_size); + void SetHardwareIndex(uint32_t index) override; + /// Gets the original instruction bytes that were overwritten by the trap uint8_t *GetSavedOpcodeBytes(); diff --git a/lldb/include/lldb/Breakpoint/StoppointLocation.h b/lldb/include/lldb/Breakpoint/StoppointLocation.h --- a/lldb/include/lldb/Breakpoint/StoppointLocation.h +++ b/lldb/include/lldb/Breakpoint/StoppointLocation.h @@ -48,7 +48,7 @@ virtual void Dump(Stream *stream) const {} - void SetHardwareIndex(uint32_t index) { m_hardware_index = index; } + virtual void SetHardwareIndex(uint32_t index) { m_hardware_index = index; } lldb::break_id_t GetID() const { return m_loc_id; } diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py --- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py @@ -21,7 +21,7 @@ def test_hw_break_set_delete_multi_thread_linux(self): self.build() self.setTearDownCleanup() - self.break_multi_thread('delete', 'breakpoint') + self.break_multi_thread('delete') # LLDB on linux supports hardware breakpoints for arm and aarch64 # architectures. @@ -30,7 +30,7 @@ def test_hw_break_set_disable_multi_thread_linux(self): self.build() self.setTearDownCleanup() - self.break_multi_thread('disable', 'breakpoint') + self.break_multi_thread('disable') # LLDB on darwin supports hardware breakpoints for arm, aarch64, x86_64 and # i386 architectures. @@ -39,7 +39,7 @@ def test_hw_break_set_delete_multi_thread_macos(self): self.build() self.setTearDownCleanup() - self.break_multi_thread('delete', 'EXC_BREAKPOINT') + self.break_multi_thread('delete') # LLDB on darwin supports hardware breakpoints for arm, aarch64, x86_64 and # i386 architectures. @@ -48,7 +48,7 @@ def test_hw_break_set_disable_multi_thread_macos(self): self.build() self.setTearDownCleanup() - self.break_multi_thread('disable', 'EXC_BREAKPOINT') + self.break_multi_thread('disable') def setUp(self): @@ -60,7 +60,7 @@ self.first_stop = line_number( self.source, 'Starting thread creation with hardware breakpoint set') - def break_multi_thread(self, removal_type, stop_reason): + def break_multi_thread(self, removal_type): """Test that lldb hardware breakpoints work for multiple threads.""" self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) @@ -95,7 +95,7 @@ # The stop reason of the thread should be breakpoint. self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=[ - 'stop reason = {}'.format(stop_reason), + 'stop reason = breakpoint', 'hw_break_function']) # Continue the loop and test that we are stopped 4 times. diff --git a/lldb/source/Breakpoint/BreakpointSite.cpp b/lldb/source/Breakpoint/BreakpointSite.cpp --- a/lldb/source/Breakpoint/BreakpointSite.cpp +++ b/lldb/source/Breakpoint/BreakpointSite.cpp @@ -156,6 +156,13 @@ } } +void BreakpointSite::SetHardwareIndex(uint32_t index) { + std::lock_guard guard(m_owners_mutex); + for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) { + loc_sp->SetHardwareIndex(index); + } +} + bool BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp --- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -8,6 +8,7 @@ #include "StopInfoMachException.h" +#include "lldb/lldb-forward.h" #if defined(__APPLE__) // Needed for the EXC_RESOURCE interpretation macros @@ -293,6 +294,44 @@ return m_description.c_str(); } +static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target, + uint32_t exc_data_count, + uint64_t exc_sub_code, + uint64_t exc_sub_sub_code) { + // Try hardware watchpoint. + if (target) { + // The exc_sub_code indicates the data break address. + lldb::WatchpointSP wp_sp = + target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code); + if (wp_sp && wp_sp->IsEnabled()) { + // Debugserver may piggyback the hardware index of the fired watchpoint + // in the exception data. Set the hardware index if that's the case. + if (exc_data_count >= 3) + wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); + return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); + } + } + + // Try hardware breakpoint. + ProcessSP process_sp(thread.GetProcess()); + if (process_sp) { + // The exc_sub_code indicates the data break address. + lldb::BreakpointSiteSP bp_sp = + process_sp->GetBreakpointSiteList().FindByAddress( + (lldb::addr_t)exc_sub_code); + if (bp_sp && bp_sp->IsEnabled()) { + // Debugserver may piggyback the hardware index of the fired breakpoint + // in the exception data. Set the hardware index if that's the case. + if (exc_data_count >= 3) + bp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); + return StopInfo::CreateStopReasonWithBreakpointSiteID(thread, + bp_sp->GetID()); + } + } + + return nullptr; +} + StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( Thread &thread, uint32_t exc_type, uint32_t exc_data_count, uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code, @@ -350,22 +389,10 @@ is_actual_breakpoint = true; is_trace_if_actual_breakpoint_missing = true; } else { - - // It's a watchpoint, then. - // The exc_sub_code indicates the data break address. - lldb::WatchpointSP wp_sp; - if (target) - wp_sp = target->GetWatchpointList().FindByAddress( - (lldb::addr_t)exc_sub_code); - if (wp_sp && wp_sp->IsEnabled()) { - // Debugserver may piggyback the hardware index of the fired - // watchpoint in the exception data. Set the hardware index if - // that's the case. - if (exc_data_count >= 3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); - return StopInfo::CreateStopReasonWithWatchpointID(thread, - wp_sp->GetID()); - } + if (StopInfoSP stop_info = + GetStopInfoForHardwareBP(thread, target, exc_data_count, + exc_sub_code, exc_sub_sub_code)) + return stop_info; } } else if (exc_code == 2 || // EXC_I386_BPT exc_code == 3) // EXC_I386_BPTFLT