mib updated this revision to Diff 216745.
mib added a comment.

Rename `cli` to `use_interpreter` in test.

Use early returns on SB API classes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66248/new/

https://reviews.llvm.org/D66248

Files:
  lldb/include/lldb/API/SBBreakpoint.h
  lldb/include/lldb/API/SBBreakpointLocation.h
  lldb/include/lldb/Breakpoint/Breakpoint.h
  lldb/include/lldb/Breakpoint/BreakpointLocation.h
  lldb/include/lldb/Breakpoint/BreakpointOptions.h
  lldb/include/lldb/Target/Target.h
  lldb/include/lldb/lldb-enumerations.h
  
lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py
  
lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/fast_conditional_breakpoints/Makefile
  
lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/fast_conditional_breakpoints/TestFastConditionalBreakpoints.py
  
lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/fast_conditional_breakpoints/main.c
  lldb/scripts/interface/SBBreakpoint.i
  lldb/scripts/interface/SBBreakpointLocation.i
  lldb/source/API/SBBreakpoint.cpp
  lldb/source/API/SBBreakpointLocation.cpp
  lldb/source/Breakpoint/Breakpoint.cpp
  lldb/source/Breakpoint/BreakpointLocation.cpp
  lldb/source/Breakpoint/BreakpointOptions.cpp
  lldb/source/Commands/CommandObjectBreakpoint.cpp
  lldb/source/Commands/Options.td

Index: lldb/source/Commands/Options.td
===================================================================
--- lldb/source/Commands/Options.td
+++ lldb/source/Commands/Options.td
@@ -87,6 +87,9 @@
     Arg<"Command">,
     Desc<"A command to run when the breakpoint is hit, can be provided more "
     "than once, the commands will get run in order left to right.">;
+  def breakpoint_modify_inject_condition : Option<"inject-condition", "I">,
+      Desc<"The breakpoint injects the condition expression into the process "
+      "machine code. Enables Fast Conditional Breakpoints.">;
 }
 
 let Command = "breakpoint dummy" in {
Index: lldb/source/Commands/CommandObjectBreakpoint.cpp
===================================================================
--- lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -102,6 +102,13 @@
         m_bp_opts.SetIgnoreCount(ignore_count);
     }
     break;
+    case 'I': {
+      if (!m_bp_opts.IsOptionSet(BreakpointOptions::eCondition))
+        error.SetErrorString("inject-condition option only available for "
+                             "conditional breakpoints");
+      else
+        m_bp_opts.SetInjectCondition(true);
+    } break;
     case 'o': {
       bool value, success;
       value = OptionArgParser::ToBoolean(option_arg, false, &success);
Index: lldb/source/Breakpoint/BreakpointOptions.cpp
===================================================================
--- lldb/source/Breakpoint/BreakpointOptions.cpp
+++ lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -109,8 +109,8 @@
 
 const char *BreakpointOptions::g_option_names[(
     size_t)BreakpointOptions::OptionNames::LastOptionName]{
-    "ConditionText", "IgnoreCount", 
-    "EnabledState", "OneShotState", "AutoContinue"};
+    "ConditionText", "IgnoreCount",  "EnabledState",
+    "OneShotState",  "AutoContinue", "JITCondition"};
 
 bool BreakpointOptions::NullCallback(void *baton,
                                      StoppointCallbackContext *context,
@@ -124,25 +124,23 @@
     : m_callback(BreakpointOptions::NullCallback), m_callback_baton_sp(),
       m_baton_is_command_baton(false), m_callback_is_synchronous(false),
       m_enabled(true), m_one_shot(false), m_ignore_count(0), m_thread_spec_up(),
-      m_condition_text(), m_condition_text_hash(0), m_auto_continue(false),
-      m_set_flags(0) {
+      m_condition_text(), m_condition_text_hash(0), m_inject_condition(false),
+      m_auto_continue(false), m_set_flags(0) {
   if (all_flags_set)
     m_set_flags.Set(~((Flags::ValueType)0));
 }
 
 BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
-                                     int32_t ignore, bool one_shot, 
-                                     bool auto_continue)
+                                     int32_t ignore, bool one_shot,
+                                     bool auto_continue, bool inject_condition)
     : m_callback(nullptr), m_baton_is_command_baton(false),
       m_callback_is_synchronous(false), m_enabled(enabled),
-      m_one_shot(one_shot), m_ignore_count(ignore),
-      m_condition_text_hash(0), m_auto_continue(auto_continue)
-{
-    m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot 
-                   | eAutoContinue);
-    if (condition && *condition != '\0') {
-      SetCondition(condition);
-    }
+      m_one_shot(one_shot), m_ignore_count(ignore), m_condition_text_hash(0),
+      m_inject_condition(inject_condition), m_auto_continue(auto_continue) {
+  m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot | eAutoContinue);
+  if (condition && *condition != '\0') {
+    SetCondition(condition);
+  }
 }
 
 // BreakpointOptions copy constructor
@@ -152,6 +150,7 @@
       m_callback_is_synchronous(rhs.m_callback_is_synchronous),
       m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot),
       m_ignore_count(rhs.m_ignore_count), m_thread_spec_up(),
+      m_inject_condition(rhs.m_inject_condition),
       m_auto_continue(rhs.m_auto_continue), m_set_flags(rhs.m_set_flags) {
   if (rhs.m_thread_spec_up != nullptr)
     m_thread_spec_up.reset(new ThreadSpec(*rhs.m_thread_spec_up));
@@ -175,6 +174,7 @@
   m_condition_text_hash = rhs.m_condition_text_hash;
   m_auto_continue = rhs.m_auto_continue;
   m_set_flags = rhs.m_set_flags;
+  m_inject_condition = rhs.m_inject_condition;
   return *this;
 }
 
@@ -210,12 +210,18 @@
       m_condition_text.clear();
       m_condition_text_hash = 0;
       m_set_flags.Clear(eCondition);
+      m_inject_condition = false;
     } else {
       m_condition_text = incoming.m_condition_text;
       m_condition_text_hash = incoming.m_condition_text_hash;
       m_set_flags.Set(eCondition);
+      m_inject_condition = incoming.m_inject_condition;
     }
   }
+  if (incoming.m_set_flags.Test(eInjectCondition)) {
+    m_inject_condition = incoming.m_inject_condition;
+    m_set_flags.Set(eInjectCondition);
+  }
   if (incoming.m_set_flags.Test(eAutoContinue))
   {
     m_auto_continue = incoming.m_auto_continue;
@@ -374,10 +380,14 @@
   if (m_set_flags.Test(eIgnoreCount))
     options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
                                     m_ignore_count);
-  if (m_set_flags.Test(eCondition))
+  if (m_set_flags.Test(eCondition)) {
     options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
                                    m_condition_text);
-         
+    if (m_set_flags.Test(eInjectCondition))
+      options_dict_sp->AddBooleanItem(GetKey(OptionNames::InjectCondition),
+                                      m_inject_condition);
+  }
+
   if (m_set_flags.Test(eCallback) && m_baton_is_command_baton) {
     auto cmd_baton =
         std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
@@ -464,6 +474,10 @@
   return m_callback != BreakpointOptions::NullCallback;
 }
 
+bool BreakpointOptions::GetInjectCondition() const {
+  return m_inject_condition;
+}
+
 bool BreakpointOptions::GetCommandLineCallbacks(StringList &command_list) {
   if (!HasCallback())
     return false;
@@ -482,6 +496,7 @@
   if (!condition || condition[0] == '\0') {
     condition = "";
     m_set_flags.Clear(eCondition);
+    m_set_flags.Clear(eInjectCondition);
   }
   else
     m_set_flags.Set(eCondition);
@@ -571,8 +586,9 @@
   }
   if (!m_condition_text.empty()) {
     if (level != eDescriptionLevelBrief) {
+      std::string fast = (m_inject_condition) ? " (FAST)" : "";
       s->EOL();
-      s->Printf("Condition: %s\n", m_condition_text.c_str());
+      s->Printf("Condition: %s%s\n", m_condition_text.c_str(), fast.c_str());
     }
   }
 }
@@ -671,4 +687,5 @@
   m_callback_is_synchronous = false;
   m_enabled = false;
   m_condition_text.clear();
+  m_inject_condition = false;
 }
Index: lldb/source/Breakpoint/BreakpointLocation.cpp
===================================================================
--- lldb/source/Breakpoint/BreakpointLocation.cpp
+++ lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -226,6 +226,19 @@
       ->GetConditionText(hash);
 }
 
+bool BreakpointLocation::GetInjectCondition() const {
+  if (m_options_up &&
+      m_options_up->IsOptionSet(BreakpointOptions::eInjectCondition))
+    return m_options_up->GetInjectCondition();
+  return m_owner.GetInjectCondition();
+}
+
+void BreakpointLocation::SetInjectCondition(bool inject_condition) {
+  m_owner.SetInjectCondition(inject_condition);
+  GetLocationOptions()->SetInjectCondition(inject_condition);
+  SendBreakpointLocationChangedEvent(eBreakpointEventTypeInjectedCondition);
+}
+
 bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
                                            Status &error) {
   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
@@ -240,6 +253,8 @@
     return false;
   }
 
+  bool inject_condition = GetInjectCondition();
+
   error.Clear();
 
   DiagnosticManager diagnostics;
@@ -263,9 +278,12 @@
       return true;
     }
 
-    if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
-                                     eExecutionPolicyOnlyWhenNeeded, true,
-                                     false)) {
+    ExecutionPolicy execution_policy = inject_condition
+                                           ? eExecutionPolicyAlways
+                                           : eExecutionPolicyOnlyWhenNeeded;
+
+    if (!m_user_expression_sp->Parse(diagnostics, exe_ctx, execution_policy,
+                                     true, false)) {
       error.SetErrorStringWithFormat(
           "Couldn't parse conditional expression:\n%s",
           diagnostics.GetString().c_str());
@@ -287,6 +305,7 @@
   options.SetTryAllThreads(true);
   options.SetResultIsInternal(
       true); // Don't generate a user variable for condition expressions.
+  options.SetInjectCondition(inject_condition);
 
   Status expr_error;
 
Index: lldb/source/Breakpoint/Breakpoint.cpp
===================================================================
--- lldb/source/Breakpoint/Breakpoint.cpp
+++ lldb/source/Breakpoint/Breakpoint.cpp
@@ -418,6 +418,14 @@
   return m_options_up->GetConditionText();
 }
 
+void Breakpoint::SetInjectCondition(bool inject_condition) {
+  m_options_up->SetInjectCondition(inject_condition);
+}
+
+bool Breakpoint::GetInjectCondition() const {
+  return m_options_up->GetInjectCondition();
+}
+
 // This function is used when "baton" doesn't need to be freed
 void Breakpoint::SetCallback(BreakpointHitCallback callback, void *baton,
                              bool is_synchronous) {
Index: lldb/source/API/SBBreakpointLocation.cpp
===================================================================
--- lldb/source/API/SBBreakpointLocation.cpp
+++ lldb/source/API/SBBreakpointLocation.cpp
@@ -206,6 +206,32 @@
   return false;
 }
 
+void SBBreakpointLocation::SetInjectCondition(bool inject_condition) {
+  LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetInjectCondition, (bool),
+                     inject_condition);
+
+  BreakpointLocationSP loc_sp = GetSP();
+  if (!loc_sp)
+    return;
+  
+  std::lock_guard<std::recursive_mutex> guard(
+      loc_sp->GetTarget().GetAPIMutex());
+  loc_sp->SetInjectCondition(inject_condition);
+  loc_sp->GetBreakpoint().SetInjectCondition(inject_condition);
+}
+
+bool SBBreakpointLocation::GetInjectCondition() {
+  LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpointLocation, GetInjectCondition);
+
+  BreakpointLocationSP loc_sp = GetSP();
+  if (!loc_sp)
+    return false;
+  
+  std::lock_guard<std::recursive_mutex> guard(
+      loc_sp->GetTarget().GetAPIMutex());
+  return loc_sp->GetInjectCondition();
+}
+
 void SBBreakpointLocation::SetScriptCallbackFunction(
     const char *callback_function_name) {
   LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetScriptCallbackFunction,
@@ -480,6 +506,8 @@
   LLDB_REGISTER_METHOD(const char *, SBBreakpointLocation, GetCondition, ());
   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetAutoContinue, (bool));
   LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, GetAutoContinue, ());
+  LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetInjectCondition, (bool));
+  LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, GetInjectCondition, ());
   LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetScriptCallbackFunction,
                        (const char *));
   LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpointLocation,
Index: lldb/source/API/SBBreakpoint.cpp
===================================================================
--- lldb/source/API/SBBreakpoint.cpp
+++ lldb/source/API/SBBreakpoint.cpp
@@ -312,6 +312,31 @@
   return false;
 }
 
+void SBBreakpoint::SetInjectCondition(bool inject_condition) {
+  LLDB_RECORD_METHOD(void, SBBreakpoint, SetInjectCondition, (bool),
+                     inject_condition);
+
+  BreakpointSP bkpt_sp = GetSP();
+  if (!bkpt_sp)
+    return;
+
+  std::lock_guard<std::recursive_mutex> guard(
+      bkpt_sp->GetTarget().GetAPIMutex());
+  bkpt_sp->SetInjectCondition(inject_condition);
+}
+
+bool SBBreakpoint::GetInjectCondition() {
+  LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpoint, GetInjectCondition);
+
+  BreakpointSP bkpt_sp = GetSP();
+  if (!bkpt_sp)
+    return false;
+
+  std::lock_guard<std::recursive_mutex> guard(
+      bkpt_sp->GetTarget().GetAPIMutex());
+  return bkpt_sp->GetInjectCondition();
+}
+
 uint32_t SBBreakpoint::GetHitCount() const {
   LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBBreakpoint, GetHitCount);
 
@@ -967,6 +992,8 @@
   LLDB_REGISTER_METHOD(const char *, SBBreakpoint, GetCondition, ());
   LLDB_REGISTER_METHOD(void, SBBreakpoint, SetAutoContinue, (bool));
   LLDB_REGISTER_METHOD(bool, SBBreakpoint, GetAutoContinue, ());
+  LLDB_REGISTER_METHOD(void, SBBreakpoint, SetInjectCondition, (bool));
+  LLDB_REGISTER_METHOD(bool, SBBreakpoint, GetInjectCondition, ());
   LLDB_REGISTER_METHOD_CONST(uint32_t, SBBreakpoint, GetHitCount, ());
   LLDB_REGISTER_METHOD_CONST(uint32_t, SBBreakpoint, GetIgnoreCount, ());
   LLDB_REGISTER_METHOD(void, SBBreakpoint, SetThreadID, (lldb::tid_t));
Index: lldb/scripts/interface/SBBreakpointLocation.i
===================================================================
--- lldb/scripts/interface/SBBreakpointLocation.i
+++ lldb/scripts/interface/SBBreakpointLocation.i
@@ -72,6 +72,15 @@
 
     void SetAutoContinue(bool auto_continue);
 
+    %feature("docstring", "
+    *EXPERIMENTAL* Check if the condition expression is injected and checked in-process.") GetInjectCondition;
+    bool GetInjectCondition();
+
+    %feature("docstring", "
+    *EXPERIMENTAL* The condition expression in injected and checked in-process.
+    Enables Fast Conditional Breakpoint.") SetInjectCondition;
+    void SetInjectCondition(bool inject_condition);
+
     %feature("docstring", "
     Set the callback to the given Python function name.") SetScriptCallbackFunction;
     void
Index: lldb/scripts/interface/SBBreakpoint.i
===================================================================
--- lldb/scripts/interface/SBBreakpoint.i
+++ lldb/scripts/interface/SBBreakpoint.i
@@ -150,6 +150,15 @@
 
     bool GetAutoContinue();
 
+    %feature("docstring", "
+    *EXPERIMENTAL* Check if the condition expression is injected and checked in-process.") GetInjectCondition;
+    bool GetInjectCondition();
+
+    %feature("docstring", "
+    *EXPERIMENTAL* The condition expression in injected and checked in-process.
+    Toggles Fast Conditional Breakpoint.") SetInjectCondition;
+    void SetInjectCondition(bool inject_condition);
+
     void
     SetThreadID (lldb::tid_t sb_thread_id);
 
Index: lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/fast_conditional_breakpoints/main.c
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/fast_conditional_breakpoints/main.c
@@ -0,0 +1,24 @@
+// This simple program is to demonstrate the capability of the lldb command
+// "breakpoint set -c "condition() == 999999" -f main.c -l 29 -I" or
+// "breakpoint set -c "local_count == 999999" -f main.c -l 29 -I" to break
+// the condition for an inject breakpoint evaluate to true.
+
+#include <stdio.h>
+
+static int global_count = 0;
+
+int condition(void) {
+  printf("global_count = %d\n", global_count);
+  return global_count++;
+}
+
+int main(int argc, char *argv[])
+{
+  int local_count = 0;
+  for (int i = 0; i < 10000000; i++) {
+    printf("local_count = %d\n", local_count++);  // Find the line number of condition breakpoint for local_count
+  }
+
+  return 0;
+}
+
Index: lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/fast_conditional_breakpoints/TestFastConditionalBreakpoints.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/fast_conditional_breakpoints/TestFastConditionalBreakpoints.py
@@ -0,0 +1,101 @@
+"""
+Test Fast Conditional Breakpoints.
+"""
+
+from __future__ import print_function
+
+import os
+import time
+import re
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class FastConditionalBreakpoitsTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        self.file = lldb.SBFileSpec("main.c")
+        self.comment = "Find the line number of condition breakpoint for local_count"
+        self.condition = '"local_count == 9"'
+        self.extra_options = "-c " + self.condition + " -I"
+        self.binary = "a.out"
+
+    @skipIfWindows
+    def test_fast_conditional_breakpoint_flag_interpreter(self):
+        """Enable fast conditional breakpoints with 'breakpoint modify -c <expr> id -I'."""
+        self.build()
+        self.enable_fast_conditional_breakpoint(use_interpreter=True)
+
+    @skipIfWindows
+    @add_test_categories(["pyapi"])
+    def test_fast_conditional_breakpoint_flag_api(self):
+        """Exercise fast conditional breakpoints with SB API"""
+        self.build()
+        self.enable_fast_conditional_breakpoint(use_interpreter=False)
+
+    def enable_fast_conditional_breakpoint(self, use_interpreter):
+        exe = self.getBuildArtifact(self.binary)
+        self.target = self.dbg.CreateTarget(exe)
+        self.assertTrue(self.target, VALID_TARGET)
+
+        if use_interpreter:
+            lldbutil.run_break_set_by_source_regexp(
+                self, self.comment, self.extra_options
+            )
+
+            self.runCmd("breakpoint modify " + self.condition + " 1")
+
+            self.expect("breakpoint list -f", substrs=["(FAST)"])
+        else:
+            # Now create a breakpoint on main.c by source regex'.
+            breakpoint = self.target.BreakpointCreateBySourceRegex(
+                self.comment, self.file
+            )
+            self.assertTrue(
+                breakpoint and breakpoint.GetNumLocations() == 1,
+                VALID_BREAKPOINT)
+
+            # We didn't associate a thread index with the breakpoint, so it should
+            # be invalid.
+            self.assertTrue(
+                breakpoint.GetThreadIndex() == lldb.UINT32_MAX,
+                "the thread index should be invalid",
+            )
+            # The thread name should be invalid, too.
+            self.assertTrue(
+                breakpoint.GetThreadName() is None,
+                "the thread name should be invalid")
+
+            # Let's set the thread index for this breakpoint and verify that it is,
+            # indeed, being set correctly and there's only one thread for the process.
+            breakpoint.SetThreadIndex(1)
+            self.assertTrue(
+                breakpoint.GetThreadIndex() == 1,
+                "the thread index has been set correctly",
+            )
+
+            # Get the breakpoint location from breakpoint after we verified that,
+            # indeed, it has one location.
+            location = breakpoint.GetLocationAtIndex(0)
+            self.assertTrue(
+                location and location.IsEnabled(), VALID_BREAKPOINT_LOCATION
+            )
+
+            # Set the condition on the breakpoint.
+            location.SetCondition(self.condition)
+            self.expect(
+                location.GetCondition(),
+                exe=False,
+                startstr=self.condition)
+
+            # Set condition on the breakpoint to be injected in-process.
+            location.SetInjectCondition(True)
+            self.assertTrue(
+                location.GetInjectCondition(),
+                VALID_BREAKPOINT_LOCATION)
Index: lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/fast_conditional_breakpoints/Makefile
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/fast_conditional_breakpoints/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+CFLAGS_EXTRAS += -std=c99
+
+include $(LEVEL)/Makefile.rules
Index: lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py
@@ -15,30 +15,22 @@
 
     mydir = TestBase.compute_mydir(__file__)
 
-    # Requires EE to support COFF on Windows (http://llvm.org/pr22232)
-    @skipIfWindows
     def test_breakpoint_condition_and_run_command(self):
         """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'."""
         self.build()
         self.breakpoint_conditions()
 
-    # Requires EE to support COFF on Windows (http://llvm.org/pr22232)
-    @skipIfWindows
     def test_breakpoint_condition_inline_and_run_command(self):
         """Exercise breakpoint condition inline with 'breakpoint set'."""
         self.build()
         self.breakpoint_conditions(inline=True)
 
-    # Requires EE to support COFF on Windows (http://llvm.org/pr22232)
-    @skipIfWindows
     @add_test_categories(['pyapi'])
     def test_breakpoint_condition_and_python_api(self):
         """Use Python APIs to set breakpoint conditions."""
         self.build()
         self.breakpoint_conditions_python()
 
-    # Requires EE to support COFF on Windows (http://llvm.org/pr22232)
-    @skipIfWindows
     @add_test_categories(['pyapi'])
     def test_breakpoint_invalid_condition_and_python_api(self):
         """Use Python APIs to set breakpoint conditions."""
Index: lldb/include/lldb/lldb-enumerations.h
===================================================================
--- lldb/include/lldb/lldb-enumerations.h
+++ lldb/include/lldb/lldb-enumerations.h
@@ -402,7 +402,8 @@
     eBreakpointEventTypeConditionChanged = (1u << 9),
     eBreakpointEventTypeIgnoreChanged = (1u << 10),
     eBreakpointEventTypeThreadChanged = (1u << 11),
-    eBreakpointEventTypeAutoContinueChanged = (1u << 12)};
+    eBreakpointEventTypeAutoContinueChanged = (1u << 12),
+    eBreakpointEventTypeInjectedCondition = (1u << 13)};
 
 FLAGS_ENUM(WatchpointEventType){
     eWatchpointEventTypeInvalidType = (1u << 0),
Index: lldb/include/lldb/Target/Target.h
===================================================================
--- lldb/include/lldb/Target/Target.h
+++ lldb/include/lldb/Target/Target.h
@@ -290,6 +290,12 @@
     m_ignore_breakpoints = ignore;
   }
 
+  void SetInjectCondition(bool inject_condition) {
+    m_inject_condition = inject_condition;
+  }
+
+  bool GetInjectCondition() const { return m_inject_condition; }
+
   bool DoesKeepInMemory() const { return m_keep_in_memory; }
 
   void SetKeepInMemory(bool keep = true) { m_keep_in_memory = keep; }
@@ -403,6 +409,7 @@
   bool m_ansi_color_errors = false;
   bool m_result_is_internal = false;
   bool m_auto_apply_fixits = true;
+  bool m_inject_condition = false;
   /// True if the executed code should be treated as utility code that is only
   /// used by LLDB internally.
   bool m_running_utility_expression = false;
Index: lldb/include/lldb/Breakpoint/BreakpointOptions.h
===================================================================
--- lldb/include/lldb/Breakpoint/BreakpointOptions.h
+++ lldb/include/lldb/Breakpoint/BreakpointOptions.h
@@ -32,15 +32,16 @@
 
 public:
   enum OptionKind {
-    eCallback     = 1 << 0,
-    eEnabled      = 1 << 1,
-    eOneShot      = 1 << 2,
-    eIgnoreCount  = 1 << 3,
-    eThreadSpec   = 1 << 4,
-    eCondition    = 1 << 5,
-    eAutoContinue = 1 << 6,
-    eAllOptions   = (eCallback | eEnabled | eOneShot | eIgnoreCount | eThreadSpec
-                     | eCondition | eAutoContinue)
+    eCallback        = 1 << 0,
+    eEnabled         = 1 << 1,
+    eOneShot         = 1 << 2,
+    eIgnoreCount     = 1 << 3,
+    eThreadSpec      = 1 << 4,
+    eCondition       = 1 << 5,
+    eAutoContinue    = 1 << 6,
+    eInjectCondition = 1 << 7,
+    eAllOptions      = (eCallback | eEnabled | eOneShot | eIgnoreCount |
+                   eThreadSpec | eCondition | eAutoContinue | eInjectCondition)
   };
   struct CommandData {
     CommandData()
@@ -113,9 +114,12 @@
   /// \param[in] auto_continue
   ///    Should this breakpoint auto-continue after running its commands.
   ///
+  /// \param[in] inject_condition
+  ///    Should the condition be injected and checked in-process.
+  ///
   BreakpointOptions(const char *condition, bool enabled = true,
                     int32_t ignore = 0, bool one_shot = false,
-                    bool auto_continue = false);
+                    bool auto_continue = false, bool inject_condition = false);
 
   /// Breakpoints make options with all flags set.  Locations and Names make
   /// options with no flags set.
@@ -347,7 +351,20 @@
   bool AnySet() const {
     return m_set_flags.AnySet(eAllOptions);
   }
-  
+
+  /// Check if the breakpoint condition should be injected
+  ///
+  /// \return
+  ///    If condition is injected \b true, \b false otherwise.
+  bool GetInjectCondition() const;
+
+  /// If \a inject_condition is \b true, inject the breakpoint condition in the
+  /// process.
+  void SetInjectCondition(bool inject_condition) {
+    m_inject_condition = inject_condition;
+    m_set_flags.Set(eInjectCondition);
+  }
+
 protected:
   // Classes that inherit from BreakpointOptions can see and modify these
   bool IsOptionSet(OptionKind kind)
@@ -361,6 +378,7 @@
     EnabledState,
     OneShotState,
     AutoContinue,
+    InjectCondition,
     LastOptionName
   };
   static const char *g_option_names[(size_t)OptionNames::LastOptionName];
Index: lldb/include/lldb/Breakpoint/BreakpointLocation.h
===================================================================
--- lldb/include/lldb/Breakpoint/BreakpointLocation.h
+++ lldb/include/lldb/Breakpoint/BreakpointLocation.h
@@ -131,6 +131,16 @@
   //     condition has been set.
   const char *GetConditionText(size_t *hash = nullptr) const;
 
+  /// Check if the breakpoint condition should be injected
+  ///
+  /// \return
+  ///    If condition is injected \b true, \b false otherwise.
+  bool GetInjectCondition() const;
+
+  /// If \a inject_condition is \b true, inject the breakpoint condition in the
+  /// process.
+  void SetInjectCondition(bool inject_condition);
+
   bool ConditionSaysStop(ExecutionContext &exe_ctx, Status &error);
 
   /// Set the valid thread to be checked when the breakpoint is hit.
Index: lldb/include/lldb/Breakpoint/Breakpoint.h
===================================================================
--- lldb/include/lldb/Breakpoint/Breakpoint.h
+++ lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -63,6 +63,7 @@
 ///    \b Ignore Count
 ///    \b Callback
 ///    \b Condition
+///    \b Inject Condition
 /// Note, these options can be set on the breakpoint, and they can also be set
 /// on the individual locations.  The options set on the breakpoint take
 /// precedence over the options set on the individual location. So for
@@ -399,6 +400,16 @@
   //     condition has been set.
   const char *GetConditionText() const;
 
+  /// If \a inject_condition is \b true, inject the breakpoint condition in the
+  /// process.
+  void SetInjectCondition(bool inject_condition);
+
+  /// Check if the breakpoint condition should be injected
+  ///
+  /// \return
+  ///    If condition is injected \b true, \b false otherwise.
+  bool GetInjectCondition() const;
+
   // The next section are various utility functions.
 
   /// Return the number of breakpoint locations that have resolved to actual
Index: lldb/include/lldb/API/SBBreakpointLocation.h
===================================================================
--- lldb/include/lldb/API/SBBreakpointLocation.h
+++ lldb/include/lldb/API/SBBreakpointLocation.h
@@ -53,6 +53,10 @@
 
   bool GetAutoContinue();
 
+  void SetInjectCondition(bool inject_condition);
+
+  bool GetInjectCondition();
+
   void SetScriptCallbackFunction(const char *callback_function_name);
 
   SBError SetScriptCallbackBody(const char *script_body_text);
Index: lldb/include/lldb/API/SBBreakpoint.h
===================================================================
--- lldb/include/lldb/API/SBBreakpoint.h
+++ lldb/include/lldb/API/SBBreakpoint.h
@@ -74,6 +74,10 @@
 
   bool GetAutoContinue();
 
+  void SetInjectCondition(bool inject_condition);
+
+  bool GetInjectCondition();
+
   void SetThreadID(lldb::tid_t sb_thread_id);
 
   lldb::tid_t GetThreadID();
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to