https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/146602
>From 656beb2df5f39604454af0e3f4a9f4b1b7e9c5f8 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Tue, 1 Jul 2025 16:02:21 -0700 Subject: [PATCH 1/4] [lldb] Add SB API to make a breakpoint a hardware breakpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds SBBreakpoint::SetIsHardware, allowing clients to mark an existing breakpoint as a hardware breakpoint purely through the API. This is safe to do after creation, as the hardware/software distinction doesn't affect how breakpoint locations are selected. In some cases (e.g. when writing a trap instruction would alter program behavior), it's important to use hardware breakpoints. Ideally, we’d extend the various Create methods to support this, but given their number, this patch limits the scope to the post-creation API. As a workaround, users can also rely on target.require-hardware-breakpoint or use the breakpoint set command. rdar://153528045 --- lldb/include/lldb/API/SBBreakpoint.h | 2 + lldb/include/lldb/Breakpoint/Breakpoint.h | 1 + lldb/source/API/SBBreakpoint.cpp | 11 +++++ lldb/source/Breakpoint/Breakpoint.cpp | 21 ++++++++++ .../simple_hw_breakpoints/Makefile | 7 ++++ .../TestSimpleHWBreakpoints.py | 40 +++++++++++++++++++ .../simple_hw_breakpoints/main.c | 7 ++++ 7 files changed, 89 insertions(+) create mode 100644 lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/Makefile create mode 100644 lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py create mode 100644 lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/main.c diff --git a/lldb/include/lldb/API/SBBreakpoint.h b/lldb/include/lldb/API/SBBreakpoint.h index e08df3b6d5ab0..307c9e13d7e39 100644 --- a/lldb/include/lldb/API/SBBreakpoint.h +++ b/lldb/include/lldb/API/SBBreakpoint.h @@ -148,6 +148,8 @@ class LLDB_API SBBreakpoint { bool IsHardware() const; + void SetIsHardware(bool is_hardware); + // Can only be called from a ScriptedBreakpointResolver... SBError AddLocation(SBAddress &address); diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h index f623a2e0c295b..8b1ab219832cc 100644 --- a/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -518,6 +518,7 @@ class Breakpoint : public std::enable_shared_from_this<Breakpoint>, lldb::break_id_t bp_loc_id); bool IsHardware() const { return m_hardware; } + void SetIsHardware(bool is_hardware); lldb::BreakpointResolverSP GetResolver() { return m_resolver_sp; } diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp index 87fadbcec4f26..d790b3f4ca271 100644 --- a/lldb/source/API/SBBreakpoint.cpp +++ b/lldb/source/API/SBBreakpoint.cpp @@ -781,6 +781,17 @@ bool SBBreakpoint::IsHardware() const { return false; } +void SBBreakpoint::SetIsHardware(bool is_hardware) { + LLDB_INSTRUMENT_VA(this, is_hardware); + + BreakpointSP bkpt_sp = GetSP(); + if (bkpt_sp) { + std::lock_guard<std::recursive_mutex> guard( + bkpt_sp->GetTarget().GetAPIMutex()); + bkpt_sp->SetIsHardware(is_hardware); + } +} + BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); } // This is simple collection of breakpoint id's and their target. diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp index 2ed0c9314e3e1..d5845ebeeb08a 100644 --- a/lldb/source/Breakpoint/Breakpoint.cpp +++ b/lldb/source/Breakpoint/Breakpoint.cpp @@ -251,6 +251,27 @@ const lldb::TargetSP Breakpoint::GetTargetSP() { bool Breakpoint::IsInternal() const { return LLDB_BREAK_ID_IS_INTERNAL(m_bid); } +void Breakpoint::SetIsHardware(bool is_hardware) { + if (is_hardware == m_hardware) + return; + + // Remember all the breakpoint locations we've disabled. + std::vector<BreakpointLocationSP> locations; + for (BreakpointLocationSP location : m_locations.BreakpointLocations()) { + if (location->IsEnabled()) { + locations.push_back(location); + location->SetEnabled(false); + } + } + + // Toggle the hardware mode. + m_hardware = is_hardware; + + // Re-enable the breakpoint locations. + for (BreakpointLocationSP location : locations) + location->SetEnabled(true); +} + BreakpointLocationSP Breakpoint::AddLocation(const Address &addr, bool *new_location) { return m_locations.AddLocation(addr, m_resolve_indirect_symbols, diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/Makefile b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/Makefile new file mode 100644 index 0000000000000..304633c2dca1f --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/Makefile @@ -0,0 +1,7 @@ +C_SOURCES := main.c + +ifeq ($(CC_TYPE), icc) + CFLAGS_EXTRAS := -debug inline-debug-info +endif + +include Makefile.rules diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py new file mode 100644 index 0000000000000..abb5eef8f193f --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py @@ -0,0 +1,40 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +from functionalities.breakpoint.hardware_breakpoints.base import * + + +class SimpleHWBreakpointTest(HardwareBreakpointTestBase): + def does_not_support_hw_breakpoints(self): + # FIXME: Use HardwareBreakpointTestBase.supports_hw_breakpoints + if super().supports_hw_breakpoints() is None: + return "Hardware breakpoints are unsupported" + return None + + @skipTestIfFn(does_not_support_hw_breakpoints) + def test(self): + """Test SBBreakpoint::SetIsHardware""" + self.build() + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + + breakpoint = target.BreakpointCreateByLocation("main.c", 1) + self.assertFalse(breakpoint.IsHardware()) + breakpoint.SetIsHardware(True) + self.assertTrue(breakpoint.IsHardware()) + + self.runCmd("run", RUN_SUCCEEDED) + + self.expect( + "thread list", + STOPPED_DUE_TO_BREAKPOINT, + substrs=["stopped", "stop reason = breakpoint"], + ) + + # Check the breakpoint list. + self.expect( + "breakpoint list -v", + substrs=["file = 'main.c'", "hardware = true"], + ) diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/main.c b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/main.c new file mode 100644 index 0000000000000..4f1c9df56200a --- /dev/null +++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/main.c @@ -0,0 +1,7 @@ +int break_on_me() { + int i = 10; + i++; + return i; +} + +int main() { return break_on_me(); } >From 00987591bd49a717bba36bbf1a4a1654d818d8b3 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Tue, 1 Jul 2025 20:42:26 -0700 Subject: [PATCH 2/4] Address Jim's feedback --- lldb/include/lldb/API/SBBreakpoint.h | 2 +- lldb/include/lldb/Breakpoint/Breakpoint.h | 3 +- .../lldb/Breakpoint/BreakpointLocation.h | 2 +- lldb/source/API/SBBreakpoint.cpp | 5 +-- lldb/source/Breakpoint/Breakpoint.cpp | 31 ++++++++++++------- lldb/source/Breakpoint/BreakpointLocation.cpp | 10 +++--- .../TestSimpleHWBreakpoints.py | 2 +- 7 files changed, 32 insertions(+), 23 deletions(-) diff --git a/lldb/include/lldb/API/SBBreakpoint.h b/lldb/include/lldb/API/SBBreakpoint.h index 307c9e13d7e39..11f84034bd7b9 100644 --- a/lldb/include/lldb/API/SBBreakpoint.h +++ b/lldb/include/lldb/API/SBBreakpoint.h @@ -148,7 +148,7 @@ class LLDB_API SBBreakpoint { bool IsHardware() const; - void SetIsHardware(bool is_hardware); + bool SetIsHardware(bool is_hardware); // Can only be called from a ScriptedBreakpointResolver... SBError diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h index 8b1ab219832cc..3f5c3a8b89a02 100644 --- a/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -518,7 +518,8 @@ class Breakpoint : public std::enable_shared_from_this<Breakpoint>, lldb::break_id_t bp_loc_id); bool IsHardware() const { return m_hardware; } - void SetIsHardware(bool is_hardware); + + bool SetIsHardware(bool is_hardware); lldb::BreakpointResolverSP GetResolver() { return m_resolver_sp; } diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/lldb/include/lldb/Breakpoint/BreakpointLocation.h index 3592291bb2d06..f4fe2e9a9abfc 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointLocation.h +++ b/lldb/include/lldb/Breakpoint/BreakpointLocation.h @@ -69,7 +69,7 @@ class BreakpointLocation // The next section deals with various breakpoint options. /// If \a enabled is \b true, enable the breakpoint, if \b false disable it. - void SetEnabled(bool enabled); + bool SetEnabled(bool enabled); /// Check the Enable/Disable state. /// diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp index d790b3f4ca271..100f63f92ef4f 100644 --- a/lldb/source/API/SBBreakpoint.cpp +++ b/lldb/source/API/SBBreakpoint.cpp @@ -781,15 +781,16 @@ bool SBBreakpoint::IsHardware() const { return false; } -void SBBreakpoint::SetIsHardware(bool is_hardware) { +bool SBBreakpoint::SetIsHardware(bool is_hardware) { LLDB_INSTRUMENT_VA(this, is_hardware); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard<std::recursive_mutex> guard( bkpt_sp->GetTarget().GetAPIMutex()); - bkpt_sp->SetIsHardware(is_hardware); + return bkpt_sp->SetIsHardware(is_hardware); } + return false; } BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); } diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp index d5845ebeeb08a..5d166e6888420 100644 --- a/lldb/source/Breakpoint/Breakpoint.cpp +++ b/lldb/source/Breakpoint/Breakpoint.cpp @@ -251,25 +251,34 @@ const lldb::TargetSP Breakpoint::GetTargetSP() { bool Breakpoint::IsInternal() const { return LLDB_BREAK_ID_IS_INTERNAL(m_bid); } -void Breakpoint::SetIsHardware(bool is_hardware) { +bool Breakpoint::SetIsHardware(bool is_hardware) { if (is_hardware == m_hardware) - return; + return true; - // Remember all the breakpoint locations we've disabled. + // Disable all non-hardware breakpoint locations. std::vector<BreakpointLocationSP> locations; - for (BreakpointLocationSP location : m_locations.BreakpointLocations()) { - if (location->IsEnabled()) { - locations.push_back(location); - location->SetEnabled(false); - } + for (BreakpointLocationSP location_sp : m_locations.BreakpointLocations()) { + if (!location_sp || !location_sp->IsEnabled()) + continue; + + lldb::BreakpointSiteSP breakpoint_site_sp = + location_sp->GetBreakpointSite(); + if (!breakpoint_site_sp || + breakpoint_site_sp->GetType() == BreakpointSite::eHardware) + continue; + + locations.push_back(location_sp); + location_sp->SetEnabled(false); } // Toggle the hardware mode. m_hardware = is_hardware; - // Re-enable the breakpoint locations. - for (BreakpointLocationSP location : locations) - location->SetEnabled(true); + // Re-enable all breakpoint locations. + bool success = true; + for (BreakpointLocationSP location_sp : locations) + success &= location_sp->SetEnabled(true); + return success; } BreakpointLocationSP Breakpoint::AddLocation(const Address &addr, diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp index c7ea50407ae1c..574f1f3fec19b 100644 --- a/lldb/source/Breakpoint/BreakpointLocation.cpp +++ b/lldb/source/Breakpoint/BreakpointLocation.cpp @@ -74,15 +74,13 @@ bool BreakpointLocation::IsEnabled() const { return true; } -void BreakpointLocation::SetEnabled(bool enabled) { +bool BreakpointLocation::SetEnabled(bool enabled) { GetLocationOptions().SetEnabled(enabled); - if (enabled) { - ResolveBreakpointSite(); - } else { - ClearBreakpointSite(); - } + const bool success = + enabled ? ResolveBreakpointSite() : ClearBreakpointSite(); SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled : eBreakpointEventTypeDisabled); + return success; } bool BreakpointLocation::IsAutoContinue() const { diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py index abb5eef8f193f..80ba8a6447d98 100644 --- a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py +++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py @@ -22,7 +22,7 @@ def test(self): breakpoint = target.BreakpointCreateByLocation("main.c", 1) self.assertFalse(breakpoint.IsHardware()) - breakpoint.SetIsHardware(True) + self.assertTrue(breakpoint.SetIsHardware(True)) self.assertTrue(breakpoint.IsHardware()) self.runCmd("run", RUN_SUCCEEDED) >From 9a9e8a3161697b24ba61c162bb742e43212b133d Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Wed, 2 Jul 2025 09:47:57 -0700 Subject: [PATCH 3/4] More logging to debug test failure --- lldb/include/lldb/API/SBBreakpoint.h | 2 ++ lldb/source/Breakpoint/BreakpointLocation.cpp | 8 ++++---- .../simple_hw_breakpoints/TestSimpleHWBreakpoints.py | 4 ++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lldb/include/lldb/API/SBBreakpoint.h b/lldb/include/lldb/API/SBBreakpoint.h index 11f84034bd7b9..945bdb8369253 100644 --- a/lldb/include/lldb/API/SBBreakpoint.h +++ b/lldb/include/lldb/API/SBBreakpoint.h @@ -148,6 +148,8 @@ class LLDB_API SBBreakpoint { bool IsHardware() const; + /// Turn this breakpoint into a hardware breakpoint. Returns true if all + /// existing breakpoint locations were replaced with hardware breakpoints. bool SetIsHardware(bool is_hardware); // Can only be called from a ScriptedBreakpointResolver... diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp index 574f1f3fec19b..ae1d933cac4ca 100644 --- a/lldb/source/Breakpoint/BreakpointLocation.cpp +++ b/lldb/source/Breakpoint/BreakpointLocation.cpp @@ -443,10 +443,10 @@ bool BreakpointLocation::ResolveBreakpointSite() { process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware()); if (new_id == LLDB_INVALID_BREAK_ID) { - Log *log = GetLog(LLDBLog::Breakpoints); - if (log) - log->Warning("Failed to add breakpoint site at 0x%" PRIx64, - m_address.GetOpcodeLoadAddress(&m_owner.GetTarget())); + LLDB_LOGF(GetLog(LLDBLog::Breakpoints), + "Failed to add breakpoint site at 0x%" PRIx64 "(resolved=%s)", + m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()), + IsResolved() ? "yes" : "no"); } return IsResolved(); diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py index 80ba8a6447d98..c43ccd1f164c7 100644 --- a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py +++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py @@ -20,6 +20,10 @@ def test(self): exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) + if self.TraceOn(): + self.runCmd("log enable lldb break") + self.addTearDownHook(lambda: self.runCmd("log disable lldb break")) + breakpoint = target.BreakpointCreateByLocation("main.c", 1) self.assertFalse(breakpoint.IsHardware()) self.assertTrue(breakpoint.SetIsHardware(True)) >From 76974a39c2d8e7dd55031ebfe6a013e8e30a6003 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Wed, 2 Jul 2025 09:58:59 -0700 Subject: [PATCH 4/4] Return an SBError --- lldb/include/lldb/API/SBBreakpoint.h | 7 +- lldb/include/lldb/Breakpoint/Breakpoint.h | 2 +- lldb/source/API/SBBreakpoint.cpp | 6 +- lldb/source/Breakpoint/Breakpoint.cpp | 74 ++++++++++++------- .../TestSimpleHWBreakpoints.py | 3 +- 5 files changed, 57 insertions(+), 35 deletions(-) diff --git a/lldb/include/lldb/API/SBBreakpoint.h b/lldb/include/lldb/API/SBBreakpoint.h index 945bdb8369253..18ed3e7226d3b 100644 --- a/lldb/include/lldb/API/SBBreakpoint.h +++ b/lldb/include/lldb/API/SBBreakpoint.h @@ -148,9 +148,10 @@ class LLDB_API SBBreakpoint { bool IsHardware() const; - /// Turn this breakpoint into a hardware breakpoint. Returns true if all - /// existing breakpoint locations were replaced with hardware breakpoints. - bool SetIsHardware(bool is_hardware); + /// Make this breakpoint a hardware breakpoint. This will replace all existing + /// breakpoint locations with hardware breakpoints. Returns an error if this + /// fails, e.g. when there aren't enough hardware resources available. + lldb::SBError SetIsHardware(bool is_hardware); // Can only be called from a ScriptedBreakpointResolver... SBError diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h index 3f5c3a8b89a02..b200a1e4893df 100644 --- a/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -519,7 +519,7 @@ class Breakpoint : public std::enable_shared_from_this<Breakpoint>, bool IsHardware() const { return m_hardware; } - bool SetIsHardware(bool is_hardware); + llvm::Error SetIsHardware(bool is_hardware); lldb::BreakpointResolverSP GetResolver() { return m_resolver_sp; } diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp index 100f63f92ef4f..397afc1f10f94 100644 --- a/lldb/source/API/SBBreakpoint.cpp +++ b/lldb/source/API/SBBreakpoint.cpp @@ -781,16 +781,16 @@ bool SBBreakpoint::IsHardware() const { return false; } -bool SBBreakpoint::SetIsHardware(bool is_hardware) { +lldb::SBError SBBreakpoint::SetIsHardware(bool is_hardware) { LLDB_INSTRUMENT_VA(this, is_hardware); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard<std::recursive_mutex> guard( bkpt_sp->GetTarget().GetAPIMutex()); - return bkpt_sp->SetIsHardware(is_hardware); + return SBError(Status::FromError(bkpt_sp->SetIsHardware(is_hardware))); } - return false; + return SBError(); } BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); } diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp index 5d166e6888420..202d2db9f1092 100644 --- a/lldb/source/Breakpoint/Breakpoint.cpp +++ b/lldb/source/Breakpoint/Breakpoint.cpp @@ -61,7 +61,7 @@ Breakpoint::Breakpoint(Target &new_target, const Breakpoint &source_bp) Breakpoint::~Breakpoint() = default; BreakpointSP Breakpoint::CopyFromBreakpoint(TargetSP new_target, - const Breakpoint& bp_to_copy_from) { + const Breakpoint &bp_to_copy_from) { if (!new_target) return BreakpointSP(); @@ -163,7 +163,7 @@ lldb::BreakpointSP Breakpoint::CreateFromStructuredData( std::make_shared<SearchFilterForUnconstrainedSearches>(target_sp); else { filter_sp = SearchFilter::CreateFromStructuredData(target_sp, *filter_dict, - create_error); + create_error); if (create_error.Fail()) { error = Status::FromErrorStringWithFormat( "Error creating breakpoint filter from data: %s.", @@ -174,7 +174,7 @@ lldb::BreakpointSP Breakpoint::CreateFromStructuredData( std::unique_ptr<BreakpointOptions> options_up; StructuredData::Dictionary *options_dict; - Target& target = *target_sp; + Target &target = *target_sp; success = breakpoint_dict->GetValueForKeyAsDictionary( BreakpointOptions::GetSerializationKey(), options_dict); if (success) { @@ -192,8 +192,8 @@ lldb::BreakpointSP Breakpoint::CreateFromStructuredData( success = breakpoint_dict->GetValueForKeyAsBoolean( Breakpoint::GetKey(OptionNames::Hardware), hardware); - result_sp = target.CreateBreakpoint(filter_sp, resolver_sp, false, - hardware, true); + result_sp = + target.CreateBreakpoint(filter_sp, resolver_sp, false, hardware, true); if (result_sp && options_up) { result_sp->m_options = *options_up; @@ -251,9 +251,9 @@ const lldb::TargetSP Breakpoint::GetTargetSP() { bool Breakpoint::IsInternal() const { return LLDB_BREAK_ID_IS_INTERNAL(m_bid); } -bool Breakpoint::SetIsHardware(bool is_hardware) { +llvm::Error Breakpoint::SetIsHardware(bool is_hardware) { if (is_hardware == m_hardware) - return true; + return llvm::Error::success(); // Disable all non-hardware breakpoint locations. std::vector<BreakpointLocationSP> locations; @@ -275,10 +275,18 @@ bool Breakpoint::SetIsHardware(bool is_hardware) { m_hardware = is_hardware; // Re-enable all breakpoint locations. - bool success = true; - for (BreakpointLocationSP location_sp : locations) - success &= location_sp->SetEnabled(true); - return success; + size_t num_failures = 0; + for (BreakpointLocationSP location_sp : locations) { + if (!location_sp->SetEnabled(true)) + num_failures++; + } + + if (num_failures != 0) + return llvm::createStringError( + "failed to convert %ull out of %ull breakpoint locations to hardware", + num_failures, locations.size()); + + return llvm::Error::success(); } BreakpointLocationSP Breakpoint::AddLocation(const Address &addr, @@ -986,8 +994,7 @@ void Breakpoint::GetResolverDescription(Stream *s) { m_resolver_sp->GetDescription(s); } -bool Breakpoint::GetMatchingFileLine(ConstString filename, - uint32_t line_number, +bool Breakpoint::GetMatchingFileLine(ConstString filename, uint32_t line_number, BreakpointLocationCollection &loc_coll) { // TODO: To be correct, this method needs to fill the breakpoint location // collection @@ -1044,19 +1051,32 @@ void Breakpoint::SendBreakpointChangedEvent( const char *Breakpoint::BreakpointEventTypeAsCString(BreakpointEventType type) { switch (type) { - case eBreakpointEventTypeInvalidType: return "invalid"; - case eBreakpointEventTypeAdded: return "breakpoint added"; - case eBreakpointEventTypeRemoved: return "breakpoint removed"; - case eBreakpointEventTypeLocationsAdded: return "locations added"; - case eBreakpointEventTypeLocationsRemoved: return "locations removed"; - case eBreakpointEventTypeLocationsResolved: return "locations resolved"; - case eBreakpointEventTypeEnabled: return "breakpoint enabled"; - case eBreakpointEventTypeDisabled: return "breakpoint disabled"; - case eBreakpointEventTypeCommandChanged: return "command changed"; - case eBreakpointEventTypeConditionChanged: return "condition changed"; - case eBreakpointEventTypeIgnoreChanged: return "ignore count changed"; - case eBreakpointEventTypeThreadChanged: return "thread changed"; - case eBreakpointEventTypeAutoContinueChanged: return "autocontinue changed"; + case eBreakpointEventTypeInvalidType: + return "invalid"; + case eBreakpointEventTypeAdded: + return "breakpoint added"; + case eBreakpointEventTypeRemoved: + return "breakpoint removed"; + case eBreakpointEventTypeLocationsAdded: + return "locations added"; + case eBreakpointEventTypeLocationsRemoved: + return "locations removed"; + case eBreakpointEventTypeLocationsResolved: + return "locations resolved"; + case eBreakpointEventTypeEnabled: + return "breakpoint enabled"; + case eBreakpointEventTypeDisabled: + return "breakpoint disabled"; + case eBreakpointEventTypeCommandChanged: + return "command changed"; + case eBreakpointEventTypeConditionChanged: + return "condition changed"; + case eBreakpointEventTypeIgnoreChanged: + return "ignore count changed"; + case eBreakpointEventTypeThreadChanged: + return "thread changed"; + case eBreakpointEventTypeAutoContinueChanged: + return "autocontinue changed"; }; llvm_unreachable("Fully covered switch above!"); } @@ -1094,7 +1114,7 @@ void Breakpoint::BreakpointEventData::Dump(Stream *s) const { BreakpointEventType event_type = GetBreakpointEventType(); break_id_t bkpt_id = GetBreakpoint()->GetID(); s->Format("bkpt: {0} type: {1}", bkpt_id, - BreakpointEventTypeAsCString(event_type)); + BreakpointEventTypeAsCString(event_type)); } const Breakpoint::BreakpointEventData * diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py index c43ccd1f164c7..9c2186f525877 100644 --- a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py +++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/simple_hw_breakpoints/TestSimpleHWBreakpoints.py @@ -26,7 +26,8 @@ def test(self): breakpoint = target.BreakpointCreateByLocation("main.c", 1) self.assertFalse(breakpoint.IsHardware()) - self.assertTrue(breakpoint.SetIsHardware(True)) + error = breakpoint.SetIsHardware(True) + self.assertSuccess(error) self.assertTrue(breakpoint.IsHardware()) self.runCmd("run", RUN_SUCCEEDED) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits