[Lldb-commits] [lldb] 3a025e4 - [lldb] Copy valid breakpoint overrides from the dummy target (#235834)

via lldb-commits lldb-commits at lists.llvm.org
Thu Oct 29 18:06:41 PDT 2026


Author: Alexandre Perez
Date: 2026-10-29T18:06:35-07:00
New Revision: 3a025e4b02ea483a4a1b60b1248c3665b4dfda60

URL: https://github.com/llvm/llvm-project/commit/3a025e4b02ea483a4a1b60b1248c3665b4dfda60
DIFF: https://github.com/llvm/llvm-project/commit/3a025e4b02ea483a4a1b60b1248c3665b4dfda60.diff

LOG: [lldb] Copy valid breakpoint overrides from the dummy target (#235834)

`Target::PrimeFromDummyTarget` copied a breakpoint override into a new target only when `Validate` failed, because an `llvm::Error` converts to true on failure. Overrides registered on the dummy target therefore never reached later targets. Copy the overrides that validate, and log the error of those that don't.

Rename `Validate` to `HasErrors`, still returning an `llvm::Error`, so call sites read the right way round. It now also checks that the override's class exists, so adding an override with a missing class fails with a useful error instead of failing on every matching breakpoint.

Test both: an override on the dummy target applies to targets created later, and `test_bad_values` now covers a missing class.

Added: 
    

Modified: 
    lldb/include/lldb/Breakpoint/ScriptedBreakpointOverrideResolver.h
    lldb/include/lldb/Target/Target.h
    lldb/source/Breakpoint/ScriptedBreakpointOverrideResolver.cpp
    lldb/source/Target/Target.cpp
    lldb/test/API/functionalities/breakpoint/scripted_bkpt/overrides_resolver/TestOverridesResolver.py

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Breakpoint/ScriptedBreakpointOverrideResolver.h b/lldb/include/lldb/Breakpoint/ScriptedBreakpointOverrideResolver.h
index f787421b41303f..18149e188a6346 100644
--- a/lldb/include/lldb/Breakpoint/ScriptedBreakpointOverrideResolver.h
+++ b/lldb/include/lldb/Breakpoint/ScriptedBreakpointOverrideResolver.h
@@ -37,7 +37,7 @@ class ScriptedBreakpointResolverOverride
   CheckForOverride(Target &target,
                    lldb::BreakpointResolverSP initial_sp) override;
 
-  llvm::Error Validate() override;
+  llvm::Error HasErrors() override;
 
 private:
   StructuredDataImpl m_args_data;

diff  --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 97d2a58d68e629..781683caf2db63 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -1063,8 +1063,9 @@ class Target : public std::enable_shared_from_this<Target>,
     virtual ~BreakpointResolverOverride() {}
     virtual lldb::BreakpointResolverSP
     CheckForOverride(Target &target, lldb::BreakpointResolverSP initial_sp) = 0;
-    // Return whether constructing this resolver was successful.
-    virtual llvm::Error Validate() = 0;
+    // Returns an error describing why this override can't be used, for
+    // example because its script class doesn't exist.
+    virtual llvm::Error HasErrors() = 0;
     const std::string &GetDescription() { return m_desc; }
     uint64_t GetTypeMask() { return m_type_mask; }
     std::string DescribeTypeMask();

diff  --git a/lldb/source/Breakpoint/ScriptedBreakpointOverrideResolver.cpp b/lldb/source/Breakpoint/ScriptedBreakpointOverrideResolver.cpp
index 6adab023307708..f3782c84c68aef 100644
--- a/lldb/source/Breakpoint/ScriptedBreakpointOverrideResolver.cpp
+++ b/lldb/source/Breakpoint/ScriptedBreakpointOverrideResolver.cpp
@@ -9,6 +9,9 @@
 #include "lldb/Breakpoint/ScriptedBreakpointOverrideResolver.h"
 #include "lldb/Breakpoint/Breakpoint.h"
 #include "lldb/Breakpoint/BreakpointResolverScripted.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "llvm/Support/ErrorExtras.h"
 
 namespace lldb_private {
 lldb::BreakpointResolverSP ScriptedBreakpointResolverOverride::CheckForOverride(
@@ -20,9 +23,12 @@ lldb::BreakpointResolverSP ScriptedBreakpointResolverOverride::CheckForOverride(
   return {};
 }
 
-llvm::Error ScriptedBreakpointResolverOverride::Validate() {
-  // FIXME: we should make sure the module and class exist, though that will
-  // to happen in a scripting language specific function.
+llvm::Error ScriptedBreakpointResolverOverride::HasErrors() {
+  ScriptInterpreter *interpreter =
+      m_target.GetDebugger().GetScriptInterpreter();
+  if (!interpreter || !interpreter->CheckObjectExists(m_class_name.c_str()))
+    return llvm::createStringErrorV(
+        "class for breakpoint override: \"{0}\" does not exist", m_class_name);
   return llvm::Error::success();
 }
 } // namespace lldb_private

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index db53649a145c00..262b559623edb5 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -248,7 +248,11 @@ void Target::PrimeFromDummyTarget(Target &target) {
   for (auto const &elem : target.m_breakpoint_overrides) {
     BreakpointResolverOverrideUP new_override_up =
         elem.second->CopyIntoNewTarget(*this);
-    if (new_override_up->Validate())
+    if (llvm::Error error = new_override_up->HasErrors())
+      LLDB_LOG_ERROR(GetLog(LLDBLog::Breakpoints), std::move(error),
+                     "Can't copy breakpoint override from the dummy target: "
+                     "{0}");
+    else
       AddBreakpointResolverOverride(std::move(new_override_up));
   }
 
@@ -991,7 +995,7 @@ llvm::Expected<lldb::user_id_t> Target::AddBreakpointResolverOverride(
       new ScriptedBreakpointResolverOverride(*this, std::string(description),
                                              type_mask, std::string(class_name),
                                              impl));
-  llvm::Error error = new_override_up->Validate();
+  llvm::Error error = new_override_up->HasErrors();
   if (error)
     return error;
 

diff  --git a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/overrides_resolver/TestOverridesResolver.py b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/overrides_resolver/TestOverridesResolver.py
index 83c23d62a2bfee..906e80fdade26b 100644
--- a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/overrides_resolver/TestOverridesResolver.py
+++ b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/overrides_resolver/TestOverridesResolver.py
@@ -28,6 +28,34 @@ def test_bad_values(self):
         self.build()
         self.do_test_bad_values()
 
+    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
+    def test_overrides_copied_from_dummy_target(self):
+        """An override on the dummy target applies to targets created later."""
+        self.build()
+        self.import_resolver_script()
+        extra_args = lldb.SBStructuredData()
+        extra_args.SetFromJSON('{"symbol": "stop_here_instead"}')
+        error = lldb.SBError()
+        self.dbg.GetDummyTarget().AddBreakpointOverride(
+            "bkpt_resolver.OverrideExample",
+            "dummy target override",
+            lldb.eResolverFileAndLine,
+            extra_args,
+            error,
+        )
+        self.assertSuccess(error)
+
+        target = self.createTestTarget()
+        self.expect("breakpoint override list", substrs=["dummy target override"])
+        bkpt = target.BreakpointCreateByLocation(
+            "main.c", line_number("main.c", "I am in the stop symbol")
+        )
+        self.assertEqual(bkpt.GetNumLocations(), 1)
+        self.assertEqual(
+            bkpt.GetLocationAtIndex(0).GetAddress().GetFunction().GetName(),
+            "stop_here_instead",
+        )
+
     def make_target_and_import(self):
         self.target = lldbutil.run_to_breakpoint_make_target(self)
         self.import_resolver_script()
@@ -103,6 +131,8 @@ def add_override_cmd(
             override_id = int(result.GetOutput())
         else:
             self.assertFalse(result.Succeeded(), "We expected this to fail")
+            if error_string:
+                self.assertIn(error_string, result.GetError())
             return 0
 
         # Check the override listing, make sure our new entry is present:
@@ -280,18 +310,30 @@ def do_test_bad_values(self):
             expect_error=True,
             error_string="empty class name",
         )
-        # FIXME: We aren't currently returning a correct
-        # error when the class name doesn't exist.
         # And with a class name that doesn't exist:
-        # trivial_id = self.add_override_python(
-        #    trivial_help,
-        #    "NoModuleOfThisName.NoClassOfThisName",
-        #    lldb.eResolverName,
-        #    "test_key",
-        #    "test_value",
-        #    expect_error=True,
-        #    error_string=""
-        # )
+        missing_class = "NoModuleOfThisName.NoClassOfThisName"
+        missing_class_error = (
+            f'class for breakpoint override: "{missing_class}" does not exist'
+        )
+        trivial_id = self.add_override_python(
+            trivial_help,
+            missing_class,
+            lldb.eResolverName,
+            "test_key",
+            "test_value",
+            expect_error=True,
+            error_string=missing_class_error,
+        )
+        trivial_id = self.add_override_cmd(
+            trivial_help,
+            missing_class,
+            "-m name",
+            "",
+            "test_key",
+            "test_value",
+            expect_error=True,
+            error_string=missing_class_error,
+        )
 
         trivial_id = self.add_override_cmd(
             trivial_help,


        


More information about the lldb-commits mailing list