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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits