diff options
author | Jim Ingham <jingham@apple.com> | 2017-08-03 18:13:24 +0000 |
---|---|---|
committer | Jim Ingham <jingham@apple.com> | 2017-08-03 18:13:24 +0000 |
commit | f08f5c99262ff9eaa08956334accbb2614b0f7a2 (patch) | |
tree | 7627308ccb3fc7ce52a6ea0ea45c0d948fcd66af /lldb/source/Commands/CommandObjectBreakpoint.cpp | |
parent | f0cadcd9f385d36dc751cdb32476b32ec43306b5 (diff) | |
download | llvm-f08f5c99262ff9eaa08956334accbb2614b0f7a2.zip llvm-f08f5c99262ff9eaa08956334accbb2614b0f7a2.tar.gz llvm-f08f5c99262ff9eaa08956334accbb2614b0f7a2.tar.bz2 |
Add an auto-continue flag to breakpoints & locations.
You can get a breakpoint to auto-continue by adding "continue"
as a command, but that has the disadvantage that if you hit two
breakpoints simultaneously, the continue will force the process
to continue, and maybe even forstalling the commands on the other.
The auto-continue flag means the breakpoints can negotiate about
whether to stop.
Writing tests, I wanted to supply some commands when I made the
breakpoints, so I also added that ability.
llvm-svn: 309969
Diffstat (limited to 'lldb/source/Commands/CommandObjectBreakpoint.cpp')
-rw-r--r-- | lldb/source/Commands/CommandObjectBreakpoint.cpp | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index 266864d..d53e681 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); } } } |