summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/API/SBBreakpoint.h4
-rw-r--r--lldb/include/lldb/API/SBBreakpointLocation.h4
-rw-r--r--lldb/include/lldb/Breakpoint/Breakpoint.h12
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointLocation.h13
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointOptions.h33
-rw-r--r--lldb/include/lldb/lldb-enumerations.h4
-rw-r--r--lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py31
-rw-r--r--lldb/scripts/interface/SBBreakpoint.i4
-rw-r--r--lldb/scripts/interface/SBBreakpointLocation.i4
-rw-r--r--lldb/source/API/SBBreakpoint.cpp19
-rw-r--r--lldb/source/API/SBBreakpointLocation.cpp19
-rw-r--r--lldb/source/Breakpoint/Breakpoint.cpp8
-rw-r--r--lldb/source/Breakpoint/BreakpointLocation.cpp13
-rw-r--r--lldb/source/Breakpoint/BreakpointOptions.cpp38
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp53
-rw-r--r--lldb/source/Target/StopInfo.cpp43
16 files changed, 273 insertions, 29 deletions
diff --git a/lldb/include/lldb/API/SBBreakpoint.h b/lldb/include/lldb/API/SBBreakpoint.h
index 9abc9cd39dc..bdf2f650b52 100644
--- a/lldb/include/lldb/API/SBBreakpoint.h
+++ b/lldb/include/lldb/API/SBBreakpoint.h
@@ -70,6 +70,10 @@ public:
const char *GetCondition();
+ void SetAutoContinue(bool auto_continue);
+
+ bool GetAutoContinue();
+
void SetThreadID(lldb::tid_t sb_thread_id);
lldb::tid_t GetThreadID();
diff --git a/lldb/include/lldb/API/SBBreakpointLocation.h b/lldb/include/lldb/API/SBBreakpointLocation.h
index c8fa4a1934d..5b942f362ea 100644
--- a/lldb/include/lldb/API/SBBreakpointLocation.h
+++ b/lldb/include/lldb/API/SBBreakpointLocation.h
@@ -47,6 +47,10 @@ public:
void SetCondition(const char *condition);
const char *GetCondition();
+
+ void SetAutoContinue(bool auto_continue);
+
+ bool GetAutoContinue();
void SetScriptCallbackFunction(const char *callback_function_name);
diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h
index 41241334dcf..6deaeaad2b9 100644
--- a/lldb/include/lldb/Breakpoint/Breakpoint.h
+++ b/lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -421,6 +421,18 @@ public:
bool IsOneShot() const;
//------------------------------------------------------------------
+ /// If \a auto_continue is \b true, breakpoint will auto-continue when on hit.
+ //------------------------------------------------------------------
+ void SetAutoContinue(bool auto_continue);
+
+ //------------------------------------------------------------------
+ /// Check the AutoContinue state.
+ /// @return
+ /// \b true if the breakpoint is set to auto-continue, \b false otherwise.
+ //------------------------------------------------------------------
+ bool IsAutoContinue() const;
+
+ //------------------------------------------------------------------
/// Set the valid thread to be checked when the breakpoint is hit.
/// @param[in] thread_id
/// If this thread hits the breakpoint, we stop, otherwise not.
diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
index 2a94f3c2a2b..b68a9ffad04 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
@@ -107,6 +107,19 @@ public:
bool IsEnabled() const;
//------------------------------------------------------------------
+ /// If \a auto_continue is \b true, set the breakpoint to continue when hit.
+ //------------------------------------------------------------------
+ void SetAutoContinue(bool auto_continue);
+
+ //------------------------------------------------------------------
+ /// Check the AutoContinue state.
+ ///
+ /// @return
+ /// \b true if the breakpoint is set to auto-continue, \b false if not.
+ //------------------------------------------------------------------
+ bool IsAutoContinue() const;
+
+ //------------------------------------------------------------------
/// Return the current Ignore Count.
///
/// @return
diff --git a/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
index cb379a9103a..b0276cb1568 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointOptions.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
@@ -38,12 +38,13 @@ friend class Breakpoint;
public:
enum OptionKind {
- eCallback = 1 << 0,
- eEnabled = 1 << 1,
- eOneShot = 1 << 2,
- eIgnoreCount = 1 << 3,
- eThreadSpec = 1 << 4,
- eCondition = 1 << 5
+ eCallback = 1 << 0,
+ eEnabled = 1 << 1,
+ eOneShot = 1 << 2,
+ eIgnoreCount = 1 << 3,
+ eThreadSpec = 1 << 4,
+ eCondition = 1 << 5,
+ eAutoContinue = 1 << 6
};
struct CommandData {
CommandData()
@@ -112,7 +113,8 @@ public:
///
//------------------------------------------------------------------
BreakpointOptions(const char *condition, bool enabled = true,
- int32_t ignore = 0, bool one_shot = false);
+ int32_t ignore = 0, bool one_shot = false,
+ bool auto_continue = false);
virtual ~BreakpointOptions();
@@ -296,6 +298,21 @@ public:
}
//------------------------------------------------------------------
+ /// Check the auto-continue state.
+ /// @return
+ /// \b true if the breakpoint is set to auto-continue, \b false otherwise.
+ //------------------------------------------------------------------
+ bool IsAutoContinue() const { return m_auto_continue; }
+
+ //------------------------------------------------------------------
+ /// Set the auto-continue state.
+ //------------------------------------------------------------------
+ void SetAutoContinue(bool auto_continue) {
+ m_auto_continue = auto_continue;
+ m_set_flags.Set(eAutoContinue);
+ }
+
+ //------------------------------------------------------------------
/// Check the One-shot state.
/// @return
/// \b true if the breakpoint is one-shot, \b false otherwise.
@@ -394,6 +411,7 @@ protected:
IgnoreCount,
EnabledState,
OneShotState,
+ AutoContinue,
LastOptionName
};
static const char *g_option_names[(size_t)OptionNames::LastOptionName];
@@ -424,6 +442,7 @@ private:
std::string m_condition_text; // The condition to test.
size_t m_condition_text_hash; // Its hash, so that locations know when the
// condition is updated.
+ bool m_auto_continue; // If set, auto-continue from breakpoint.
Flags m_set_flags; // Which options are set at this level. Drawn
// from BreakpointOptions::SetOptionsFlags.
};
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 14bae6ca206..c6cd98806a2 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -380,7 +380,8 @@ FLAGS_ENUM(BreakpointEventType){
eBreakpointEventTypeCommandChanged = (1u << 8),
eBreakpointEventTypeConditionChanged = (1u << 9),
eBreakpointEventTypeIgnoreChanged = (1u << 10),
- eBreakpointEventTypeThreadChanged = (1u << 11)};
+ eBreakpointEventTypeThreadChanged = (1u << 11),
+ eBreakpointEventTypeAutoContinueChanged = (1u << 12)};
FLAGS_ENUM(WatchpointEventType){
eWatchpointEventTypeInvalidType = (1u << 0),
@@ -566,6 +567,7 @@ enum CommandArgumentType {
eArgTypeWatchpointIDRange,
eArgTypeWatchType,
eArgRawInput,
+ eArgTypeCommand,
eArgTypeLastArg // Always keep this entry as the last entry in this
// enumeration!!
};
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
index e67a6332d9d..cb4aeadbf93 100644
--- a/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
+++ b/lldb/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
@@ -24,12 +24,21 @@ class BreakpointCommandTestCase(TestBase):
cls.RemoveTempFile("output2.txt")
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
- def test(self):
+ def test_breakpoint_command_sequence(self):
"""Test a sequence of breakpoint command add, list, and delete."""
self.build()
self.breakpoint_command_sequence()
+
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
+ def test_script_parameters(self):
+ """Test a sequence of breakpoint command add, list, and delete."""
+ self.build()
self.breakpoint_command_script_parameters()
+ def test_commands_on_creation(self):
+ self.build()
+ self.breakpoint_commands_on_creation()
+
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
@@ -268,3 +277,23 @@ class BreakpointCommandTestCase(TestBase):
# Now remove 'output-2.txt'
os.remove('output-2.txt')
+
+ def breakpoint_commands_on_creation(self):
+ """Test that setting breakpoint commands when creating the breakpoint works"""
+ exe = os.path.join(os.getcwd(), "a.out")
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target.IsValid(), "Created an invalid target.")
+
+ # Add a breakpoint.
+ lldbutil.run_break_set_by_file_and_line(
+ self, "main.c", self.line, num_expected_locations=1, loc_exact=True,
+ extra_options='-d bt -d "thread list" -d continue')
+
+ bkpt = target.FindBreakpointByID(1)
+ self.assertTrue(bkpt.IsValid(), "Couldn't find breakpoint 1")
+ com_list = lldb.SBStringList()
+ bkpt.GetCommandLineCommands(com_list)
+ self.assertEqual(com_list.GetSize(), 3, "Got the wrong number of commands")
+ self.assertEqual(com_list.GetStringAtIndex(0), "bt", "First bt")
+ self.assertEqual(com_list.GetStringAtIndex(1), "thread list", "Next thread list")
+ self.assertEqual(com_list.GetStringAtIndex(2), "continue", "Last continue")
diff --git a/lldb/scripts/interface/SBBreakpoint.i b/lldb/scripts/interface/SBBreakpoint.i
index e3b1eea0630..76ddd7259e9 100644
--- a/lldb/scripts/interface/SBBreakpoint.i
+++ b/lldb/scripts/interface/SBBreakpoint.i
@@ -153,6 +153,10 @@ public:
const char *
GetCondition ();
+ void SetAutoContinue(bool auto_continue);
+
+ bool GetAutoContinue();
+
void
SetThreadID (lldb::tid_t sb_thread_id);
diff --git a/lldb/scripts/interface/SBBreakpointLocation.i b/lldb/scripts/interface/SBBreakpointLocation.i
index 5609c1f84f8..7a9a15db8ff 100644
--- a/lldb/scripts/interface/SBBreakpointLocation.i
+++ b/lldb/scripts/interface/SBBreakpointLocation.i
@@ -73,6 +73,10 @@ public:
const char *
GetCondition ();
+ bool GetAutoContinue();
+
+ void SetAutoContinue(bool auto_continue);
+
%feature("docstring", "
//------------------------------------------------------------------
/// Set the callback to the given Python function name.
diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp
index bf9603248d7..c7d6d6c5b18 100644
--- a/lldb/source/API/SBBreakpoint.cpp
+++ b/lldb/source/API/SBBreakpoint.cpp
@@ -264,6 +264,25 @@ const char *SBBreakpoint::GetCondition() {
return nullptr;
}
+void SBBreakpoint::SetAutoContinue(bool auto_continue) {
+ BreakpointSP bkpt_sp = GetSP();
+ if (bkpt_sp) {
+ std::lock_guard<std::recursive_mutex> guard(
+ bkpt_sp->GetTarget().GetAPIMutex());
+ bkpt_sp->SetAutoContinue(auto_continue);
+ }
+}
+
+bool SBBreakpoint::GetAutoContinue() {
+ BreakpointSP bkpt_sp = GetSP();
+ if (bkpt_sp) {
+ std::lock_guard<std::recursive_mutex> guard(
+ bkpt_sp->GetTarget().GetAPIMutex());
+ return bkpt_sp->IsAutoContinue();
+ }
+ return nullptr;
+}
+
uint32_t SBBreakpoint::GetHitCount() const {
uint32_t count = 0;
BreakpointSP bkpt_sp = GetSP();
diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp
index f5e0b91483e..2678e1ea758 100644
--- a/lldb/source/API/SBBreakpointLocation.cpp
+++ b/lldb/source/API/SBBreakpointLocation.cpp
@@ -149,6 +149,25 @@ const char *SBBreakpointLocation::GetCondition() {
return NULL;
}
+void SBBreakpointLocation::SetAutoContinue(bool auto_continue) {
+ BreakpointLocationSP loc_sp = GetSP();
+ if (loc_sp) {
+ std::lock_guard<std::recursive_mutex> guard(
+ loc_sp->GetTarget().GetAPIMutex());
+ loc_sp->SetAutoContinue(auto_continue);
+ }
+}
+
+bool SBBreakpointLocation::GetAutoContinue() {
+ BreakpointLocationSP loc_sp = GetSP();
+ if (loc_sp) {
+ std::lock_guard<std::recursive_mutex> guard(
+ loc_sp->GetTarget().GetAPIMutex());
+ return loc_sp->IsAutoContinue();
+ }
+ return NULL;
+}
+
void SBBreakpointLocation::SetScriptCallbackFunction(
const char *callback_function_name) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp
index 043e5e8f591..fd606aa83d6 100644
--- a/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -348,6 +348,14 @@ void Breakpoint::SetOneShot(bool one_shot) {
m_options_up->SetOneShot(one_shot);
}
+bool Breakpoint::IsAutoContinue() const {
+ return m_options_up->IsAutoContinue();
+}
+
+void Breakpoint::SetAutoContinue(bool auto_continue) {
+ m_options_up->SetAutoContinue(auto_continue);
+}
+
void Breakpoint::SetThreadID(lldb::tid_t thread_id) {
if (m_options_up->GetThreadSpec()->GetTID() == thread_id)
return;
diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp
index 15865be3f9a..f59c334fe5c 100644
--- a/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -93,6 +93,19 @@ void BreakpointLocation::SetEnabled(bool enabled) {
: eBreakpointEventTypeDisabled);
}
+bool BreakpointLocation::IsAutoContinue() const {
+ if (m_options_ap
+ && m_options_ap->IsOptionSet(BreakpointOptions::eAutoContinue))
+ return m_options_ap->IsAutoContinue();
+ else
+ return m_owner.IsAutoContinue();
+}
+
+void BreakpointLocation::SetAutoContinue(bool auto_continue) {
+ GetLocationOptions()->SetAutoContinue(auto_continue);
+ SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
+}
+
void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
if (thread_id != LLDB_INVALID_THREAD_ID)
GetLocationOptions()->SetThreadID(thread_id);
diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp
index 3e8d3dd41f3..7159688102d 100644
--- a/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -114,7 +114,8 @@ BreakpointOptions::CommandData::CreateFromStructuredData(
const char *BreakpointOptions::g_option_names[(
size_t)BreakpointOptions::OptionNames::LastOptionName]{
- "ConditionText", "IgnoreCount", "EnabledState", "OneShotState"};
+ "ConditionText", "IgnoreCount",
+ "EnabledState", "OneShotState", "AutoContinue"};
bool BreakpointOptions::NullCallback(void *baton,
StoppointCallbackContext *context,
@@ -130,20 +131,22 @@ BreakpointOptions::BreakpointOptions(bool all_flags_set)
: 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_ap(),
- m_condition_text(), m_condition_text_hash(0),
+ m_condition_text(), m_condition_text_hash(0), m_auto_continue(false),
m_set_flags() {
if (all_flags_set)
m_set_flags.Set(~((Flags::ValueType) 0));
}
BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
- int32_t ignore, bool one_shot)
+ int32_t ignore, bool one_shot,
+ bool auto_continue)
: 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(condition),
- m_condition_text_hash(0)
+ m_condition_text_hash(0), m_auto_continue(auto_continue)
{
- m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot | eCondition);
+ m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot
+ | eCondition | eAutoContinue);
}
//----------------------------------------------------------------------
@@ -155,6 +158,7 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs)
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_ap(),
+ m_auto_continue(rhs.m_auto_continue),
m_set_flags(rhs.m_set_flags) {
if (rhs.m_thread_spec_ap.get() != nullptr)
m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
@@ -178,6 +182,7 @@ operator=(const BreakpointOptions &rhs) {
m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
m_condition_text = rhs.m_condition_text;
m_condition_text_hash = rhs.m_condition_text_hash;
+ m_auto_continue = rhs.m_auto_continue;
m_set_flags = rhs.m_set_flags;
return *this;
}
@@ -192,6 +197,7 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
Status &error) {
bool enabled = true;
bool one_shot = false;
+ bool auto_continue = false;
int32_t ignore_count = 0;
llvm::StringRef condition_ref("");
Flags set_options;
@@ -219,6 +225,17 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
set_options.Set(eOneShot);
}
+ key = GetKey(OptionNames::AutoContinue);
+ if (key) {
+ success = options_dict.GetValueForKeyAsBoolean(key, auto_continue);
+ if (!success) {
+ error.SetErrorStringWithFormat("%s key is not a boolean.",
+ GetKey(OptionNames::AutoContinue));
+ return nullptr;
+ }
+ set_options.Set(eAutoContinue);
+ }
+
key = GetKey(OptionNames::IgnoreCount);
if (key) {
success = options_dict.GetValueForKeyAsInteger(key, ignore_count);
@@ -257,7 +274,8 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
}
auto bp_options = llvm::make_unique<BreakpointOptions>(
- condition_ref.str().c_str(), enabled, ignore_count, one_shot);
+ condition_ref.str().c_str(), enabled,
+ ignore_count, one_shot, auto_continue);
if (cmd_data_up.get()) {
if (cmd_data_up->interpreter == eScriptLanguageNone)
bp_options->SetCommandDataCallback(cmd_data_up);
@@ -315,6 +333,9 @@ StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
if (m_set_flags.Set(eOneShot))
options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
m_one_shot);
+ if (m_set_flags.Set(eAutoContinue))
+ options_dict_sp->AddBooleanItem(GetKey(OptionNames::AutoContinue),
+ m_auto_continue);
if (m_set_flags.Set(eIgnoreCount))
options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
m_ignore_count);
@@ -471,7 +492,7 @@ void BreakpointOptions::GetDescription(Stream *s,
// print
// anything if there are:
- if (m_ignore_count != 0 || !m_enabled || m_one_shot ||
+ if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue ||
(GetThreadSpecNoCreate() != nullptr &&
GetThreadSpecNoCreate()->HasSpecification())) {
if (level == lldb::eDescriptionLevelVerbose) {
@@ -491,6 +512,9 @@ void BreakpointOptions::GetDescription(Stream *s,
if (m_one_shot)
s->Printf("one-shot ");
+ if (m_auto_continue)
+ s->Printf("auto-continue ");
+
if (m_thread_spec_ap.get())
m_thread_spec_ap->GetDescription(s, level);
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index 266864d1a1f..d53e681514d 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -60,7 +60,9 @@ static OptionDefinition g_breakpoint_set_options[] = {
"multiple times to specify multiple shared libraries." },
{ LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
{ LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "The breakpoint is deleted the first time it causes a stop." },
+ { LLDB_OPT_SET_ALL, false, "auto-continue", 'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
{ LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
+ { LLDB_OPT_SET_ALL, false, "command", 'd', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommand, "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." },
{ LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose indeX matches this argument." },
{ LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
{ LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this "
@@ -208,6 +210,10 @@ public:
m_condition.assign(option_arg);
break;
+ case 'd':
+ m_commands.push_back(option_arg);
+ break;
+
case 'D':
m_use_dummy = true;
break;
@@ -255,6 +261,15 @@ public:
m_func_names.push_back(option_arg);
m_func_name_type_mask |= eFunctionNameTypeFull;
break;
+
+ case 'G' : {
+ bool success;
+ m_auto_continue = Args::StringToBoolean(option_arg, true, &success);
+ if (!success)
+ error.SetErrorStringWithFormat(
+ "Invalid boolean value for auto-continue option: '%s'",
+ option_arg.str().c_str());
+ } break;
case 'h': {
bool success;
@@ -445,6 +460,8 @@ public:
m_exception_extra_args.Clear();
m_move_to_nearest_code = eLazyBoolCalculate;
m_source_regex_func_names.clear();
+ m_commands.clear();
+ m_auto_continue = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -482,6 +499,8 @@ public:
Args m_exception_extra_args;
LazyBool m_move_to_nearest_code;
std::unordered_set<std::string> m_source_regex_func_names;
+ std::vector<std::string> m_commands;
+ bool m_auto_continue;
};
protected:
@@ -719,6 +738,18 @@ protected:
}
bp->SetOneShot(m_options.m_one_shot);
+ bp->SetAutoContinue(m_options.m_auto_continue);
+
+ if (!m_options.m_commands.empty())
+ {
+ auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
+
+ for (std::string &str : m_options.m_commands)
+ cmd_data->user_source.AppendString(str);
+
+ cmd_data->stop_on_error = true;
+ bp->GetOptions()->SetCommandDataCallback(cmd_data);
+ }
}
if (bp) {
@@ -802,6 +833,7 @@ static OptionDefinition g_breakpoint_modify_options[] = {
{ LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." },
{ LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." },
{ LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
+ { LLDB_OPT_SET_ALL, false, "auto-continue", 'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
// clang-format on
};
@@ -865,6 +897,17 @@ public:
m_enable_passed = true;
m_enable_value = true;
break;
+ case 'G': {
+ bool value, success;
+ value = Args::StringToBoolean(option_arg, false, &success);
+ if (success) {
+ m_auto_continue_passed = true;
+ m_auto_continue = value;
+ } else
+ error.SetErrorStringWithFormat(
+ "invalid boolean value '%s' passed for -G option",
+ option_arg.str().c_str());
+ } break;
case 'i':
if (option_arg.getAsInteger(0, m_ignore_count))
error.SetErrorStringWithFormat("invalid ignore count '%s'",
@@ -938,6 +981,8 @@ public:
m_condition_passed = false;
m_one_shot_passed = false;
m_use_dummy = false;
+ m_auto_continue = false;
+ m_auto_continue_passed = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -962,6 +1007,8 @@ public:
bool m_condition_passed;
bool m_one_shot_passed;
bool m_use_dummy;
+ bool m_auto_continue;
+ bool m_auto_continue_passed;
};
protected:
@@ -1013,6 +1060,9 @@ protected:
if (m_options.m_condition_passed)
location->SetCondition(m_options.m_condition.c_str());
+
+ if (m_options.m_auto_continue_passed)
+ location->SetAutoContinue(m_options.m_auto_continue);
}
} else {
if (m_options.m_thread_id_passed)
@@ -1035,6 +1085,9 @@ protected:
if (m_options.m_condition_passed)
bp->SetCondition(m_options.m_condition.c_str());
+
+ if (m_options.m_auto_continue_passed)
+ bp->SetAutoContinue(m_options.m_auto_continue);
}
}
}
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 6af5ce1b2eb..8dbcec9fa81 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -393,7 +393,10 @@ protected:
for (size_t j = 0; j < num_owners; j++) {
lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j);
-
+ StreamString loc_desc;
+ if (log) {
+ bp_loc_sp->GetDescription(&loc_desc, eDescriptionLevelBrief);
+ }
// If another action disabled this breakpoint or its location, then
// don't run the actions.
if (!bp_loc_sp->IsEnabled() ||
@@ -405,16 +408,16 @@ protected:
// this thread. Skip the ones that aren't:
if (!bp_loc_sp->ValidForThisThread(thread_sp.get())) {
if (log) {
- StreamString s;
- bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief);
log->Printf("Breakpoint %s hit on thread 0x%llx but it was not "
"for this thread, continuing.",
- s.GetData(), static_cast<unsigned long long>(
+ loc_desc.GetData(), static_cast<unsigned long long>(
thread_sp->GetID()));
}
continue;
}
+ internal_breakpoint = bp_loc_sp->GetBreakpoint().IsInternal();
+
// First run the precondition, but since the precondition is per
// breakpoint, only run it once
// per breakpoint.
@@ -458,11 +461,10 @@ protected:
error_sp->Flush();
} else {
if (log) {
- StreamString s;
- bp_loc_sp->GetDescription(&s, eDescriptionLevelBrief);
log->Printf("Condition evaluated for breakpoint %s on thread "
"0x%llx conditon_says_stop: %i.",
- s.GetData(), static_cast<unsigned long long>(
+ loc_desc.GetData(),
+ static_cast<unsigned long long>(
thread_sp->GetID()),
condition_says_stop);
}
@@ -477,7 +479,26 @@ protected:
}
}
- bool callback_says_stop;
+ // Check the auto-continue bit on the location, do this before the
+ // callback since it may change this, but that would be for the
+ // NEXT hit. Note, you might think you could check auto-continue
+ // before the condition, and not evaluate the condition if it says
+ // to continue. But failing the condition means the breakpoint was
+ // effectively NOT HIT. So these two states are different.
+ bool auto_continue_says_stop = true;
+ if (bp_loc_sp->IsAutoContinue())
+ {
+ if (log)
+ log->Printf("Continuing breakpoint %s as AutoContinue was set.",
+ loc_desc.GetData());
+ // We want this stop reported, so you will know we auto-continued
+ // but only for external breakpoints:
+ if (!internal_breakpoint)
+ thread_sp->SetShouldReportStop(eVoteYes);
+ auto_continue_says_stop = false;
+ }
+
+ bool callback_says_stop = true;
// FIXME: For now the callbacks have to run in async mode - the
// first time we restart we need
@@ -493,11 +514,8 @@ protected:
debugger.SetAsyncExecution(old_async);
- if (callback_says_stop)
+ if (callback_says_stop && auto_continue_says_stop)
m_should_stop = true;
-
- if (m_should_stop && !bp_loc_sp->GetBreakpoint().IsInternal())
- internal_breakpoint = false;
// If we are going to stop for this breakpoint, then remove the
// breakpoint.
@@ -506,7 +524,6 @@ protected:
thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID(
bp_loc_sp->GetBreakpoint().GetID());
}
-
// Also make sure that the callback hasn't continued the target.
// If it did, when we'll set m_should_start to false and get out of
// here.
OpenPOWER on IntegriCloud