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