180814287SRaphael Isemann //===-- CommandObjectBreakpoint.cpp ---------------------------------------===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 99e85e5a8SEugene Zelenko #include "CommandObjectBreakpoint.h" 109e85e5a8SEugene Zelenko #include "CommandObjectBreakpointCommand.h" 1130fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h" 1230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h" 1330fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h" 143eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h" 15b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h" 16b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h" 1747cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h" 18943a2481SJim Ingham #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 1932abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h" 205e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h" 215e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h" 22b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 230e0984eeSJim Ingham #include "lldb/Target/Language.h" 24b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 25b9c1b51eSKate Stone #include "lldb/Target/Target.h" 261b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h" 27bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h" 28bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 2930fdc8d8SChris Lattner 30796ac80bSJonas Devlieghere #include <memory> 31796ac80bSJonas Devlieghere #include <vector> 32796ac80bSJonas Devlieghere 3330fdc8d8SChris Lattner using namespace lldb; 3430fdc8d8SChris Lattner using namespace lldb_private; 3530fdc8d8SChris Lattner 36b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp, 37b9c1b51eSKate Stone lldb::DescriptionLevel level) { 3830fdc8d8SChris Lattner s->IndentMore(); 3930fdc8d8SChris Lattner bp->GetDescription(s, level, true); 4030fdc8d8SChris Lattner s->IndentLess(); 4130fdc8d8SChris Lattner s->EOL(); 4230fdc8d8SChris Lattner } 4330fdc8d8SChris Lattner 44b842f2ecSJim Ingham // Modifiable Breakpoint Options 45b842f2ecSJim Ingham #pragma mark Modify::CommandOptions 46f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify 47f94668e3SRaphael Isemann #include "CommandOptions.inc" 48bd68a052SRaphael Isemann 49a925974bSAdrian Prantl class lldb_private::BreakpointOptionGroup : public OptionGroup { 50b842f2ecSJim Ingham public: 51a925974bSAdrian Prantl BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {} 52b842f2ecSJim Ingham 53b842f2ecSJim Ingham ~BreakpointOptionGroup() override = default; 54b842f2ecSJim Ingham 55b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 56b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_modify_options); 57b842f2ecSJim Ingham } 58b842f2ecSJim Ingham 59b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 60b842f2ecSJim Ingham ExecutionContext *execution_context) override { 61b842f2ecSJim Ingham Status error; 62a925974bSAdrian Prantl const int short_option = 63a925974bSAdrian Prantl g_breakpoint_modify_options[option_idx].short_option; 64b842f2ecSJim Ingham 65b842f2ecSJim Ingham switch (short_option) { 66b842f2ecSJim Ingham case 'c': 6705097246SAdrian Prantl // Normally an empty breakpoint condition marks is as unset. But we need 6805097246SAdrian Prantl // to say it was passed in. 69b842f2ecSJim Ingham m_bp_opts.SetCondition(option_arg.str().c_str()); 70b842f2ecSJim Ingham m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition); 71b842f2ecSJim Ingham break; 72b842f2ecSJim Ingham case 'C': 73adcd0268SBenjamin Kramer m_commands.push_back(std::string(option_arg)); 74b842f2ecSJim Ingham break; 75b842f2ecSJim Ingham case 'd': 76b842f2ecSJim Ingham m_bp_opts.SetEnabled(false); 77b842f2ecSJim Ingham break; 78b842f2ecSJim Ingham case 'e': 79b842f2ecSJim Ingham m_bp_opts.SetEnabled(true); 80b842f2ecSJim Ingham break; 81b842f2ecSJim Ingham case 'G': { 82b842f2ecSJim Ingham bool value, success; 8347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 84b842f2ecSJim Ingham if (success) { 85b842f2ecSJim Ingham m_bp_opts.SetAutoContinue(value); 86b842f2ecSJim Ingham } else 87b842f2ecSJim Ingham error.SetErrorStringWithFormat( 88b842f2ecSJim Ingham "invalid boolean value '%s' passed for -G option", 89b842f2ecSJim Ingham option_arg.str().c_str()); 90a925974bSAdrian Prantl } break; 91a925974bSAdrian Prantl case 'i': { 92b842f2ecSJim Ingham uint32_t ignore_count; 93b842f2ecSJim Ingham if (option_arg.getAsInteger(0, ignore_count)) 94b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid ignore count '%s'", 95b842f2ecSJim Ingham option_arg.str().c_str()); 96b842f2ecSJim Ingham else 97b842f2ecSJim Ingham m_bp_opts.SetIgnoreCount(ignore_count); 98a925974bSAdrian Prantl } break; 99b842f2ecSJim Ingham case 'o': { 100b842f2ecSJim Ingham bool value, success; 10147cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 102b842f2ecSJim Ingham if (success) { 103b842f2ecSJim Ingham m_bp_opts.SetOneShot(value); 104b842f2ecSJim Ingham } else 105b842f2ecSJim Ingham error.SetErrorStringWithFormat( 106b842f2ecSJim Ingham "invalid boolean value '%s' passed for -o option", 107b842f2ecSJim Ingham option_arg.str().c_str()); 108b842f2ecSJim Ingham } break; 109a925974bSAdrian Prantl case 't': { 110b842f2ecSJim Ingham lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID; 111b842f2ecSJim Ingham if (option_arg[0] != '\0') { 112b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_id)) 113b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread id string '%s'", 114b842f2ecSJim Ingham option_arg.str().c_str()); 115b842f2ecSJim Ingham } 116b842f2ecSJim Ingham m_bp_opts.SetThreadID(thread_id); 117a925974bSAdrian Prantl } break; 118b842f2ecSJim Ingham case 'T': 119b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); 120b842f2ecSJim Ingham break; 121b842f2ecSJim Ingham case 'q': 122b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str()); 123b842f2ecSJim Ingham break; 124a925974bSAdrian Prantl case 'x': { 125b842f2ecSJim Ingham uint32_t thread_index = UINT32_MAX; 126b842f2ecSJim Ingham if (option_arg[0] != '\n') { 127b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_index)) 128b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread index string '%s'", 129b842f2ecSJim Ingham option_arg.str().c_str()); 130b842f2ecSJim Ingham } 131b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetIndex(thread_index); 132a925974bSAdrian Prantl } break; 133b842f2ecSJim Ingham default: 13436162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 135b842f2ecSJim Ingham } 136b842f2ecSJim Ingham 137b842f2ecSJim Ingham return error; 138b842f2ecSJim Ingham } 139b842f2ecSJim Ingham 140b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 141b842f2ecSJim Ingham m_bp_opts.Clear(); 142b842f2ecSJim Ingham m_commands.clear(); 143b842f2ecSJim Ingham } 144b842f2ecSJim Ingham 145b842f2ecSJim Ingham Status OptionParsingFinished(ExecutionContext *execution_context) override { 146a925974bSAdrian Prantl if (!m_commands.empty()) { 147a8f3ae7cSJonas Devlieghere auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); 148b842f2ecSJim Ingham 149b842f2ecSJim Ingham for (std::string &str : m_commands) 150b842f2ecSJim Ingham cmd_data->user_source.AppendString(str); 151b842f2ecSJim Ingham 152b842f2ecSJim Ingham cmd_data->stop_on_error = true; 153b842f2ecSJim Ingham m_bp_opts.SetCommandDataCallback(cmd_data); 154b842f2ecSJim Ingham } 155b842f2ecSJim Ingham return Status(); 156b842f2ecSJim Ingham } 157b842f2ecSJim Ingham 158a925974bSAdrian Prantl const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; } 159b842f2ecSJim Ingham 160b842f2ecSJim Ingham std::vector<std::string> m_commands; 161b842f2ecSJim Ingham BreakpointOptions m_bp_opts; 162b842f2ecSJim Ingham }; 163bd68a052SRaphael Isemann 164f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy 165f94668e3SRaphael Isemann #include "CommandOptions.inc" 166b842f2ecSJim Ingham 167a925974bSAdrian Prantl class BreakpointDummyOptionGroup : public OptionGroup { 168b842f2ecSJim Ingham public: 169a925974bSAdrian Prantl BreakpointDummyOptionGroup() : OptionGroup() {} 170b842f2ecSJim Ingham 171b842f2ecSJim Ingham ~BreakpointDummyOptionGroup() override = default; 172b842f2ecSJim Ingham 173b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 174b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_dummy_options); 175b842f2ecSJim Ingham } 176b842f2ecSJim Ingham 177b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 178b842f2ecSJim Ingham ExecutionContext *execution_context) override { 179b842f2ecSJim Ingham Status error; 180a925974bSAdrian Prantl const int short_option = 181f1539b9dSJim Ingham g_breakpoint_dummy_options[option_idx].short_option; 182b842f2ecSJim Ingham 183b842f2ecSJim Ingham switch (short_option) { 184b842f2ecSJim Ingham case 'D': 185b842f2ecSJim Ingham m_use_dummy = true; 186b842f2ecSJim Ingham break; 187b842f2ecSJim Ingham default: 18836162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 189b842f2ecSJim Ingham } 190b842f2ecSJim Ingham 191b842f2ecSJim Ingham return error; 192b842f2ecSJim Ingham } 193b842f2ecSJim Ingham 194b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 195b842f2ecSJim Ingham m_use_dummy = false; 196b842f2ecSJim Ingham } 197b842f2ecSJim Ingham 198b842f2ecSJim Ingham bool m_use_dummy; 199b842f2ecSJim Ingham }; 200b842f2ecSJim Ingham 201f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set 202f94668e3SRaphael Isemann #include "CommandOptions.inc" 2031f0f5b5bSZachary Turner 2045a988416SJim Ingham // CommandObjectBreakpointSet 20530fdc8d8SChris Lattner 206b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 2075a988416SJim Ingham public: 208efe8e7e3SFangrui Song enum BreakpointSetType { 2095a988416SJim Ingham eSetTypeInvalid, 2105a988416SJim Ingham eSetTypeFileAndLine, 2115a988416SJim Ingham eSetTypeAddress, 2125a988416SJim Ingham eSetTypeFunctionName, 2135a988416SJim Ingham eSetTypeFunctionRegexp, 2145a988416SJim Ingham eSetTypeSourceRegexp, 2153815e702SJim Ingham eSetTypeException, 2163815e702SJim Ingham eSetTypeScripted, 217efe8e7e3SFangrui Song }; 2185a988416SJim Ingham 219b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 220b9c1b51eSKate Stone : CommandObjectParsed( 221b9c1b51eSKate Stone interpreter, "breakpoint set", 2225a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 2235a988416SJim Ingham "breakpoint set <cmd-options>"), 224738af7a6SJim Ingham m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'), 225f6a2086dSSam McCall m_options() { 226b842f2ecSJim Ingham // We're picking up all the normal options, commands and disable. 227a925974bSAdrian Prantl m_all_options.Append(&m_python_class_options, 228a925974bSAdrian Prantl LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11); 229b842f2ecSJim Ingham m_all_options.Append(&m_bp_opts, 230b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, 231b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 232f6a2086dSSam McCall m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 233b842f2ecSJim Ingham m_all_options.Append(&m_options); 234b842f2ecSJim Ingham m_all_options.Finalize(); 235b842f2ecSJim Ingham } 2365a988416SJim Ingham 2379e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 2385a988416SJim Ingham 239b842f2ecSJim Ingham Options *GetOptions() override { return &m_all_options; } 2405a988416SJim Ingham 241b842f2ecSJim Ingham class CommandOptions : public OptionGroup { 2425a988416SJim Ingham public: 243b9c1b51eSKate Stone CommandOptions() 244a925974bSAdrian Prantl : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), 245a925974bSAdrian Prantl m_column(0), m_func_names(), 246a925974bSAdrian Prantl m_func_name_type_mask(eFunctionNameTypeNone), m_func_regexp(), 247a925974bSAdrian Prantl m_source_text_regexp(), m_modules(), m_load_addr(), m_catch_bp(false), 248a925974bSAdrian Prantl m_throw_bp(true), m_hardware(false), 249a72b31c7SJim Ingham m_exception_language(eLanguageTypeUnknown), 25023b1decbSDawn Perchik m_language(lldb::eLanguageTypeUnknown), 251a925974bSAdrian Prantl m_skip_prologue(eLazyBoolCalculate), m_all_files(false), 252a925974bSAdrian Prantl m_move_to_nearest_code(eLazyBoolCalculate) {} 25330fdc8d8SChris Lattner 2549e85e5a8SEugene Zelenko ~CommandOptions() override = default; 25587df91b8SJim Ingham 25697206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 257b9c1b51eSKate Stone ExecutionContext *execution_context) override { 25897206d57SZachary Turner Status error; 259a925974bSAdrian Prantl const int short_option = 260a925974bSAdrian Prantl g_breakpoint_set_options[option_idx].short_option; 26130fdc8d8SChris Lattner 262b9c1b51eSKate Stone switch (short_option) { 263b9c1b51eSKate Stone case 'a': { 26447cbf4a0SPavel Labath m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 265e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 266b9c1b51eSKate Stone } break; 26730fdc8d8SChris Lattner 268e732052fSJim Ingham case 'A': 269e732052fSJim Ingham m_all_files = true; 270e732052fSJim Ingham break; 271e732052fSJim Ingham 272ca36cd16SJim Ingham case 'b': 273adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 274ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 275ca36cd16SJim Ingham break; 276ca36cd16SJim Ingham 2776672a4f5SJonas Devlieghere case 'u': 278fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_column)) 279b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 280fe11483bSZachary Turner option_arg.str().c_str()); 28130fdc8d8SChris Lattner break; 2829e85e5a8SEugene Zelenko 283b9c1b51eSKate Stone case 'E': { 284fe11483bSZachary Turner LanguageType language = Language::GetLanguageTypeFromString(option_arg); 285fab10e89SJim Ingham 286b9c1b51eSKate Stone switch (language) { 287fab10e89SJim Ingham case eLanguageTypeC89: 288fab10e89SJim Ingham case eLanguageTypeC: 289fab10e89SJim Ingham case eLanguageTypeC99: 2901d0089faSBruce Mitchener case eLanguageTypeC11: 291a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 292fab10e89SJim Ingham break; 293fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 2941d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 2951d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 2962ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 297a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 298fab10e89SJim Ingham break; 299fab10e89SJim Ingham case eLanguageTypeObjC: 300a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 301fab10e89SJim Ingham break; 302fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 303b9c1b51eSKate Stone error.SetErrorStringWithFormat( 304b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 305fab10e89SJim Ingham break; 306fab10e89SJim Ingham case eLanguageTypeUnknown: 307b9c1b51eSKate Stone error.SetErrorStringWithFormat( 308b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 309fe11483bSZachary Turner option_arg.str().c_str()); 310fab10e89SJim Ingham break; 311fab10e89SJim Ingham default: 312b9c1b51eSKate Stone error.SetErrorStringWithFormat( 313b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 314fe11483bSZachary Turner option_arg.str().c_str()); 315fab10e89SJim Ingham } 316b9c1b51eSKate Stone } break; 317ca36cd16SJim Ingham 318ca36cd16SJim Ingham case 'f': 3198f3be7a3SJonas Devlieghere m_filenames.AppendIfUnique(FileSpec(option_arg)); 320fab10e89SJim Ingham break; 321ca36cd16SJim Ingham 322ca36cd16SJim Ingham case 'F': 323adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 324ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 325ca36cd16SJim Ingham break; 326ca36cd16SJim Ingham 327b9c1b51eSKate Stone case 'h': { 328fab10e89SJim Ingham bool success; 32947cbf4a0SPavel Labath m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 330fab10e89SJim Ingham if (!success) 331b9c1b51eSKate Stone error.SetErrorStringWithFormat( 332fe11483bSZachary Turner "Invalid boolean value for on-catch option: '%s'", 333fe11483bSZachary Turner option_arg.str().c_str()); 334b9c1b51eSKate Stone } break; 335eb023e75SGreg Clayton 336eb023e75SGreg Clayton case 'H': 337eb023e75SGreg Clayton m_hardware = true; 338eb023e75SGreg Clayton break; 339eb023e75SGreg Clayton 340b9c1b51eSKate Stone case 'K': { 341a8558b62SJim Ingham bool success; 342a8558b62SJim Ingham bool value; 34347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 344a8558b62SJim Ingham if (value) 345a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 346a8558b62SJim Ingham else 347a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 348a8558b62SJim Ingham 349a8558b62SJim Ingham if (!success) 350b9c1b51eSKate Stone error.SetErrorStringWithFormat( 351b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 352fe11483bSZachary Turner option_arg.str().c_str()); 353b9c1b51eSKate Stone } break; 354ca36cd16SJim Ingham 355fe11483bSZachary Turner case 'l': 356fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_line_num)) 357b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 358fe11483bSZachary Turner option_arg.str().c_str()); 359ca36cd16SJim Ingham break; 360055ad9beSIlia K 36123b1decbSDawn Perchik case 'L': 362fe11483bSZachary Turner m_language = Language::GetLanguageTypeFromString(option_arg); 36323b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 364b9c1b51eSKate Stone error.SetErrorStringWithFormat( 365fe11483bSZachary Turner "Unknown language type: '%s' for breakpoint", 366fe11483bSZachary Turner option_arg.str().c_str()); 36723b1decbSDawn Perchik break; 36823b1decbSDawn Perchik 369b9c1b51eSKate Stone case 'm': { 370055ad9beSIlia K bool success; 371055ad9beSIlia K bool value; 37247cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 373055ad9beSIlia K if (value) 374055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 375055ad9beSIlia K else 376055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 377055ad9beSIlia K 378055ad9beSIlia K if (!success) 379b9c1b51eSKate Stone error.SetErrorStringWithFormat( 380b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 381fe11483bSZachary Turner option_arg.str().c_str()); 382055ad9beSIlia K break; 383055ad9beSIlia K } 384055ad9beSIlia K 385ca36cd16SJim Ingham case 'M': 386adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 387ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 388ca36cd16SJim Ingham break; 389ca36cd16SJim Ingham 390ca36cd16SJim Ingham case 'n': 391adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 392ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 393ca36cd16SJim Ingham break; 394ca36cd16SJim Ingham 3956fa7681bSZachary Turner case 'N': { 396fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error)) 397adcd0268SBenjamin Kramer m_breakpoint_names.push_back(std::string(option_arg)); 398ff9a91eaSJim Ingham else 399ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 400fe11483bSZachary Turner option_arg.str().c_str()); 4015e09c8c3SJim Ingham break; 4026fa7681bSZachary Turner } 4035e09c8c3SJim Ingham 404b9c1b51eSKate Stone case 'R': { 4052411167fSJim Ingham lldb::addr_t tmp_offset_addr; 40647cbf4a0SPavel Labath tmp_offset_addr = OptionArgParser::ToAddress(execution_context, 40747cbf4a0SPavel Labath option_arg, 0, &error); 4082411167fSJim Ingham if (error.Success()) 4092411167fSJim Ingham m_offset_addr = tmp_offset_addr; 410b9c1b51eSKate Stone } break; 4112411167fSJim Ingham 412a72b31c7SJim Ingham case 'O': 413fe11483bSZachary Turner m_exception_extra_args.AppendArgument("-O"); 414fe11483bSZachary Turner m_exception_extra_args.AppendArgument(option_arg); 415a72b31c7SJim Ingham break; 416a72b31c7SJim Ingham 417ca36cd16SJim Ingham case 'p': 418adcd0268SBenjamin Kramer m_source_text_regexp.assign(std::string(option_arg)); 419ca36cd16SJim Ingham break; 420ca36cd16SJim Ingham 421ca36cd16SJim Ingham case 'r': 422adcd0268SBenjamin Kramer m_func_regexp.assign(std::string(option_arg)); 423ca36cd16SJim Ingham break; 424ca36cd16SJim Ingham 425ca36cd16SJim Ingham case 's': 4268f3be7a3SJonas Devlieghere m_modules.AppendIfUnique(FileSpec(option_arg)); 427ca36cd16SJim Ingham break; 428ca36cd16SJim Ingham 429ca36cd16SJim Ingham case 'S': 430adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 431ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 432ca36cd16SJim Ingham break; 433ca36cd16SJim Ingham 434b9c1b51eSKate Stone case 'w': { 435ca36cd16SJim Ingham bool success; 43647cbf4a0SPavel Labath m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 437ca36cd16SJim Ingham if (!success) 438b9c1b51eSKate Stone error.SetErrorStringWithFormat( 439fe11483bSZachary Turner "Invalid boolean value for on-throw option: '%s'", 440fe11483bSZachary Turner option_arg.str().c_str()); 441b9c1b51eSKate Stone } break; 442ca36cd16SJim Ingham 44376bb8d67SJim Ingham case 'X': 444adcd0268SBenjamin Kramer m_source_regex_func_names.insert(std::string(option_arg)); 44576bb8d67SJim Ingham break; 44676bb8d67SJim Ingham 44730fdc8d8SChris Lattner default: 44836162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 44930fdc8d8SChris Lattner } 45030fdc8d8SChris Lattner 45130fdc8d8SChris Lattner return error; 45230fdc8d8SChris Lattner } 4539e85e5a8SEugene Zelenko 454b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 45587df91b8SJim Ingham m_filenames.Clear(); 45630fdc8d8SChris Lattner m_line_num = 0; 45730fdc8d8SChris Lattner m_column = 0; 458fab10e89SJim Ingham m_func_names.clear(); 4591f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 46030fdc8d8SChris Lattner m_func_regexp.clear(); 4611f746071SGreg Clayton m_source_text_regexp.clear(); 46287df91b8SJim Ingham m_modules.Clear(); 4631f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 4642411167fSJim Ingham m_offset_addr = 0; 465fab10e89SJim Ingham m_catch_bp = false; 466fab10e89SJim Ingham m_throw_bp = true; 467eb023e75SGreg Clayton m_hardware = false; 468a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 46923b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 470a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 4715e09c8c3SJim Ingham m_breakpoint_names.clear(); 472e732052fSJim Ingham m_all_files = false; 473a72b31c7SJim Ingham m_exception_extra_args.Clear(); 474055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 47576bb8d67SJim Ingham m_source_regex_func_names.clear(); 4763815e702SJim Ingham m_current_key.clear(); 47730fdc8d8SChris Lattner } 47830fdc8d8SChris Lattner 4791f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 48070602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_set_options); 4811f0f5b5bSZachary Turner } 48230fdc8d8SChris Lattner 4835a988416SJim Ingham // Instance variables to hold the values for command options. 484969795f1SJim Ingham 4855a988416SJim Ingham std::string m_condition; 4865a988416SJim Ingham FileSpecList m_filenames; 4875a988416SJim Ingham uint32_t m_line_num; 4885a988416SJim Ingham uint32_t m_column; 4895a988416SJim Ingham std::vector<std::string> m_func_names; 4905e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 491117b1fa1SZachary Turner lldb::FunctionNameType m_func_name_type_mask; 4925a988416SJim Ingham std::string m_func_regexp; 4935a988416SJim Ingham std::string m_source_text_regexp; 4945a988416SJim Ingham FileSpecList m_modules; 4955a988416SJim Ingham lldb::addr_t m_load_addr; 4962411167fSJim Ingham lldb::addr_t m_offset_addr; 4975a988416SJim Ingham bool m_catch_bp; 4985a988416SJim Ingham bool m_throw_bp; 499eb023e75SGreg Clayton bool m_hardware; // Request to use hardware breakpoints 500a72b31c7SJim Ingham lldb::LanguageType m_exception_language; 50123b1decbSDawn Perchik lldb::LanguageType m_language; 5025a988416SJim Ingham LazyBool m_skip_prologue; 503e732052fSJim Ingham bool m_all_files; 504a72b31c7SJim Ingham Args m_exception_extra_args; 505055ad9beSIlia K LazyBool m_move_to_nearest_code; 50676bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 5073815e702SJim Ingham std::string m_current_key; 5085a988416SJim Ingham }; 5095a988416SJim Ingham 5105a988416SJim Ingham protected: 511b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 512cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); 51330fdc8d8SChris Lattner 51430fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 51530fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 51630fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 51730fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 518b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 519b9c1b51eSKate Stone // expression) 520b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 521b9c1b51eSKate Stone // to source text) 522b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 523b9c1b51eSKate Stone // given language.) 52430fdc8d8SChris Lattner 52530fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 52630fdc8d8SChris Lattner 527738af7a6SJim Ingham if (!m_python_class_options.GetName().empty()) 5283815e702SJim Ingham break_type = eSetTypeScripted; 5293815e702SJim Ingham else if (m_options.m_line_num != 0) 53030fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 53130fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 53230fdc8d8SChris Lattner break_type = eSetTypeAddress; 533fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 53430fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 53530fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 53630fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 537969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 538969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 539a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 540fab10e89SJim Ingham break_type = eSetTypeException; 54130fdc8d8SChris Lattner 542b842f2ecSJim Ingham BreakpointSP bp_sp = nullptr; 543274060b6SGreg Clayton FileSpec module_spec; 544a8558b62SJim Ingham const bool internal = false; 545a8558b62SJim Ingham 546b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 547b9c1b51eSKate Stone // that off. 548b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 549b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 5502411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 5512411167fSJim Ingham 552b9c1b51eSKate Stone switch (break_type) { 55330fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 55430fdc8d8SChris Lattner { 55530fdc8d8SChris Lattner FileSpec file; 556c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 557b9c1b51eSKate Stone if (num_files == 0) { 558b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 55987df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 56087df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 56187df91b8SJim Ingham return false; 56287df91b8SJim Ingham } 563b9c1b51eSKate Stone } else if (num_files > 1) { 564b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 565b9c1b51eSKate Stone "line breakpoints."); 56687df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 56787df91b8SJim Ingham return false; 568b9c1b51eSKate Stone } else 56987df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 57030fdc8d8SChris Lattner 5711f746071SGreg Clayton // Only check for inline functions if 5721f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 5731f746071SGreg Clayton 574cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint( 575cb2380c9SRaphael Isemann &(m_options.m_modules), file, m_options.m_line_num, 576cb2380c9SRaphael Isemann m_options.m_column, m_options.m_offset_addr, check_inlines, 577cb2380c9SRaphael Isemann m_options.m_skip_prologue, internal, m_options.m_hardware, 578b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 579b9c1b51eSKate Stone } break; 5806eee5aa0SGreg Clayton 58130fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 582055a08a4SJim Ingham { 583b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 584b842f2ecSJim Ingham // with the library, and use that. That way the address breakpoint 585b842f2ecSJim Ingham // will track the load location of the library. 586055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 587b9c1b51eSKate Stone if (num_modules_specified == 1) { 588b9c1b51eSKate Stone const FileSpec *file_spec = 589b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 590cb2380c9SRaphael Isemann bp_sp = target.CreateAddressInModuleBreakpoint( 591cb2380c9SRaphael Isemann m_options.m_load_addr, internal, file_spec, m_options.m_hardware); 592b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 593cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal, 594b842f2ecSJim Ingham m_options.m_hardware); 595b9c1b51eSKate Stone } else { 596b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 597b9c1b51eSKate Stone "address breakpoints."); 598055a08a4SJim Ingham result.SetStatus(eReturnStatusFailed); 599055a08a4SJim Ingham return false; 600055a08a4SJim Ingham } 60130fdc8d8SChris Lattner break; 602055a08a4SJim Ingham } 60330fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 6040c5cd90dSGreg Clayton { 605117b1fa1SZachary Turner FunctionNameType name_type_mask = m_options.m_func_name_type_mask; 6060c5cd90dSGreg Clayton 6070c5cd90dSGreg Clayton if (name_type_mask == 0) 608e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 6090c5cd90dSGreg Clayton 610cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint( 611cb2380c9SRaphael Isemann &(m_options.m_modules), &(m_options.m_filenames), 612cb2380c9SRaphael Isemann m_options.m_func_names, name_type_mask, m_options.m_language, 613cb2380c9SRaphael Isemann m_options.m_offset_addr, m_options.m_skip_prologue, internal, 614b842f2ecSJim Ingham m_options.m_hardware); 615b9c1b51eSKate Stone } break; 6160c5cd90dSGreg Clayton 617b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 618b9c1b51eSKate Stone // name 61930fdc8d8SChris Lattner { 62095eae423SZachary Turner RegularExpression regexp(m_options.m_func_regexp); 6213af3f1e8SJonas Devlieghere if (llvm::Error err = regexp.GetError()) { 622b9c1b51eSKate Stone result.AppendErrorWithFormat( 623b58af8d2SRaphael Isemann "Function name regular expression could not be compiled: %s", 6243af3f1e8SJonas Devlieghere llvm::toString(std::move(err)).c_str()); 625aaf68cd9SRaphael Isemann // Check if the incorrect regex looks like a globbing expression and 626aaf68cd9SRaphael Isemann // warn the user about it. 627aaf68cd9SRaphael Isemann if (!m_options.m_func_regexp.empty()) { 628aaf68cd9SRaphael Isemann if (m_options.m_func_regexp[0] == '*' || 629aaf68cd9SRaphael Isemann m_options.m_func_regexp[0] == '?') 630aaf68cd9SRaphael Isemann result.AppendWarning( 631aaf68cd9SRaphael Isemann "Function name regex does not accept glob patterns."); 632aaf68cd9SRaphael Isemann } 63330fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 634969795f1SJim Ingham return false; 63530fdc8d8SChris Lattner } 63687df91b8SJim Ingham 637cb2380c9SRaphael Isemann bp_sp = target.CreateFuncRegexBreakpoint( 6385aa1d819SJan Kratochvil &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp), 639cb2380c9SRaphael Isemann m_options.m_language, m_options.m_skip_prologue, internal, 640b842f2ecSJim Ingham m_options.m_hardware); 641a925974bSAdrian Prantl } break; 642969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 643969795f1SJim Ingham { 644c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 64587df91b8SJim Ingham 646b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 647969795f1SJim Ingham FileSpec file; 648b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 649b9c1b51eSKate Stone result.AppendError( 650b9c1b51eSKate Stone "No files provided and could not find default file."); 65187df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 65287df91b8SJim Ingham return false; 653b9c1b51eSKate Stone } else { 65487df91b8SJim Ingham m_options.m_filenames.Append(file); 65587df91b8SJim Ingham } 65687df91b8SJim Ingham } 6570c5cd90dSGreg Clayton 65895eae423SZachary Turner RegularExpression regexp(m_options.m_source_text_regexp); 6593af3f1e8SJonas Devlieghere if (llvm::Error err = regexp.GetError()) { 660b9c1b51eSKate Stone result.AppendErrorWithFormat( 661b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"", 6623af3f1e8SJonas Devlieghere llvm::toString(std::move(err)).c_str()); 663969795f1SJim Ingham result.SetStatus(eReturnStatusFailed); 664969795f1SJim Ingham return false; 665969795f1SJim Ingham } 666cb2380c9SRaphael Isemann bp_sp = target.CreateSourceRegexBreakpoint( 667cb2380c9SRaphael Isemann &(m_options.m_modules), &(m_options.m_filenames), 6685aa1d819SJan Kratochvil m_options.m_source_regex_func_names, std::move(regexp), internal, 669cb2380c9SRaphael Isemann m_options.m_hardware, m_options.m_move_to_nearest_code); 670b9c1b51eSKate Stone } break; 671b9c1b51eSKate Stone case eSetTypeException: { 67297206d57SZachary Turner Status precond_error; 673cb2380c9SRaphael Isemann bp_sp = target.CreateExceptionBreakpoint( 674cb2380c9SRaphael Isemann m_options.m_exception_language, m_options.m_catch_bp, 675cb2380c9SRaphael Isemann m_options.m_throw_bp, internal, &m_options.m_exception_extra_args, 676b842f2ecSJim Ingham &precond_error); 677b9c1b51eSKate Stone if (precond_error.Fail()) { 678b9c1b51eSKate Stone result.AppendErrorWithFormat( 679b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 680a72b31c7SJim Ingham precond_error.AsCString()); 681cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 682a72b31c7SJim Ingham result.SetStatus(eReturnStatusFailed); 683a72b31c7SJim Ingham return false; 684a72b31c7SJim Ingham } 685b9c1b51eSKate Stone } break; 6863815e702SJim Ingham case eSetTypeScripted: { 6873815e702SJim Ingham 6883815e702SJim Ingham Status error; 689cb2380c9SRaphael Isemann bp_sp = target.CreateScriptedBreakpoint( 690738af7a6SJim Ingham m_python_class_options.GetName().c_str(), &(m_options.m_modules), 691cb2380c9SRaphael Isemann &(m_options.m_filenames), false, m_options.m_hardware, 692943a2481SJim Ingham m_python_class_options.GetStructuredData(), &error); 6933815e702SJim Ingham if (error.Fail()) { 6943815e702SJim Ingham result.AppendErrorWithFormat( 695a925974bSAdrian Prantl "Error setting extra exception arguments: %s", error.AsCString()); 696cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 6973815e702SJim Ingham result.SetStatus(eReturnStatusFailed); 6983815e702SJim Ingham return false; 6993815e702SJim Ingham } 7003815e702SJim Ingham } break; 70130fdc8d8SChris Lattner default: 70230fdc8d8SChris Lattner break; 70330fdc8d8SChris Lattner } 70430fdc8d8SChris Lattner 7051b54c88cSJim Ingham // Now set the various options that were passed in: 706b842f2ecSJim Ingham if (bp_sp) { 707b842f2ecSJim Ingham bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 708ca36cd16SJim Ingham 709b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 71097206d57SZachary Turner Status name_error; 711ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) { 712cb2380c9SRaphael Isemann target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error); 713ff9a91eaSJim Ingham if (name_error.Fail()) { 714ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s", 715ff9a91eaSJim Ingham name.c_str()); 716cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 717ff9a91eaSJim Ingham result.SetStatus(eReturnStatusFailed); 718ff9a91eaSJim Ingham return false; 719ff9a91eaSJim Ingham } 720ff9a91eaSJim Ingham } 7215e09c8c3SJim Ingham } 7221b54c88cSJim Ingham } 7231b54c88cSJim Ingham 724b842f2ecSJim Ingham if (bp_sp) { 72585e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 7261391cc7dSJim Ingham const bool show_locations = false; 727b842f2ecSJim Ingham bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 728b9c1b51eSKate Stone show_locations); 729cb2380c9SRaphael Isemann if (&target == &GetDummyTarget()) 730b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 731b9c1b51eSKate Stone "into future targets.\n"); 732b9c1b51eSKate Stone else { 73305097246SAdrian Prantl // Don't print out this warning for exception breakpoints. They can 73405097246SAdrian Prantl // get set before the target is set, but we won't know how to actually 73505097246SAdrian Prantl // set the breakpoint till we run. 736b842f2ecSJim Ingham if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { 737b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 738b9c1b51eSKate Stone "actual locations.\n"); 7394aeb1989SJim Ingham } 7404aeb1989SJim Ingham } 74130fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 742b842f2ecSJim Ingham } else if (!bp_sp) { 74330fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 74430fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 74530fdc8d8SChris Lattner } 74630fdc8d8SChris Lattner 74730fdc8d8SChris Lattner return result.Succeeded(); 74830fdc8d8SChris Lattner } 74930fdc8d8SChris Lattner 7505a988416SJim Ingham private: 751cb2380c9SRaphael Isemann bool GetDefaultFile(Target &target, FileSpec &file, 752b9c1b51eSKate Stone CommandReturnObject &result) { 7535a988416SJim Ingham uint32_t default_line; 75405097246SAdrian Prantl // First use the Source Manager's default file. Then use the current stack 75505097246SAdrian Prantl // frame's file. 756cb2380c9SRaphael Isemann if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 757b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 758b9c1b51eSKate Stone if (cur_frame == nullptr) { 759b9c1b51eSKate Stone result.AppendError( 760b9c1b51eSKate Stone "No selected frame to use to find the default file."); 7615a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 7625a988416SJim Ingham return false; 763b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 764b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 765b9c1b51eSKate Stone "file, it has no debug info."); 7665a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 7675a988416SJim Ingham return false; 768b9c1b51eSKate Stone } else { 769b9c1b51eSKate Stone const SymbolContext &sc = 770b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 771b9c1b51eSKate Stone if (sc.line_entry.file) { 7725a988416SJim Ingham file = sc.line_entry.file; 773b9c1b51eSKate Stone } else { 774b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 775b9c1b51eSKate Stone "use as the default file."); 7765a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 7775a988416SJim Ingham return false; 7785a988416SJim Ingham } 7795a988416SJim Ingham } 7805a988416SJim Ingham } 7815a988416SJim Ingham return true; 7825a988416SJim Ingham } 7835a988416SJim Ingham 784b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 785b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_options; 786943a2481SJim Ingham OptionGroupPythonClassWithDict m_python_class_options; 7875a988416SJim Ingham CommandOptions m_options; 788b842f2ecSJim Ingham OptionGroupOptions m_all_options; 7895a988416SJim Ingham }; 7909e85e5a8SEugene Zelenko 7915a988416SJim Ingham // CommandObjectBreakpointModify 7925a988416SJim Ingham #pragma mark Modify 7935a988416SJim Ingham 794b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 7955a988416SJim Ingham public: 796b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 797b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 798b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 799b9c1b51eSKate Stone "breakpoints in the executable. " 800b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 801b9c1b51eSKate Stone "created breakpoint. " 802b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 803b9c1b51eSKate Stone "empty argument clears the modification.", 8049e85e5a8SEugene Zelenko nullptr), 805b9c1b51eSKate Stone m_options() { 8065a988416SJim Ingham CommandArgumentEntry arg; 807b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 808b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 809b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 810b9c1b51eSKate Stone // arguments vector. 8115a988416SJim Ingham m_arguments.push_back(arg); 812b842f2ecSJim Ingham 813b842f2ecSJim Ingham m_options.Append(&m_bp_opts, 814b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, 815b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 816b842f2ecSJim Ingham m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 817b842f2ecSJim Ingham m_options.Finalize(); 8185a988416SJim Ingham } 8195a988416SJim Ingham 8209e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 8215a988416SJim Ingham 8220e50b9a4SGongyu Deng void 8230e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 8240e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 8250e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 8260e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 8270e50b9a4SGongyu Deng request, nullptr); 8280e50b9a4SGongyu Deng } 8290e50b9a4SGongyu Deng 830b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 8315a988416SJim Ingham 8325a988416SJim Ingham protected: 833b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 834cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 8355a988416SJim Ingham 836bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 837cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 8385a988416SJim Ingham 8395a988416SJim Ingham BreakpointIDList valid_bp_ids; 8405a988416SJim Ingham 841b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 842cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 843b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 8445a988416SJim Ingham 845b9c1b51eSKate Stone if (result.Succeeded()) { 8465a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 847b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 8485a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 8495a988416SJim Ingham 850b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 851b9c1b51eSKate Stone Breakpoint *bp = 852cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 853b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 854b9c1b51eSKate Stone BreakpointLocation *location = 855b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 856b842f2ecSJim Ingham if (location) 857a925974bSAdrian Prantl location->GetLocationOptions()->CopyOverSetOptions( 858a925974bSAdrian Prantl m_bp_opts.GetBreakpointOptions()); 859b9c1b51eSKate Stone } else { 860a925974bSAdrian Prantl bp->GetOptions()->CopyOverSetOptions( 861a925974bSAdrian Prantl m_bp_opts.GetBreakpointOptions()); 8625a988416SJim Ingham } 8635a988416SJim Ingham } 8645a988416SJim Ingham } 8655a988416SJim Ingham } 8665a988416SJim Ingham 8675a988416SJim Ingham return result.Succeeded(); 8685a988416SJim Ingham } 8695a988416SJim Ingham 8705a988416SJim Ingham private: 871b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 872b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_opts; 873b842f2ecSJim Ingham OptionGroupOptions m_options; 8745a988416SJim Ingham }; 8755a988416SJim Ingham 8765a988416SJim Ingham // CommandObjectBreakpointEnable 8775a988416SJim Ingham #pragma mark Enable 8785a988416SJim Ingham 879b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 8805a988416SJim Ingham public: 881b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 882b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 883b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 884b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 885b9c1b51eSKate Stone nullptr) { 8865a988416SJim Ingham CommandArgumentEntry arg; 887b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 888b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 889b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 890b9c1b51eSKate Stone // arguments vector. 8915a988416SJim Ingham m_arguments.push_back(arg); 8925a988416SJim Ingham } 8935a988416SJim Ingham 8949e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 8955a988416SJim Ingham 8960e50b9a4SGongyu Deng void 8970e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 8980e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 8990e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 9000e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 9010e50b9a4SGongyu Deng request, nullptr); 9020e50b9a4SGongyu Deng } 9030e50b9a4SGongyu Deng 9045a988416SJim Ingham protected: 905b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 906cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 9075a988416SJim Ingham 908bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 909cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 9105a988416SJim Ingham 911cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 9125a988416SJim Ingham 9135a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 9145a988416SJim Ingham 915b9c1b51eSKate Stone if (num_breakpoints == 0) { 9165a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 9175a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9185a988416SJim Ingham return false; 9195a988416SJim Ingham } 9205a988416SJim Ingham 92111eb9c64SZachary Turner if (command.empty()) { 9225a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 923cb2380c9SRaphael Isemann target.EnableAllowedBreakpoints(); 924b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 925b9c1b51eSKate Stone " breakpoints)\n", 926b9c1b51eSKate Stone (uint64_t)num_breakpoints); 9275a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 928b9c1b51eSKate Stone } else { 9295a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 9305a988416SJim Ingham BreakpointIDList valid_bp_ids; 931b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 932cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 933b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 9345a988416SJim Ingham 935b9c1b51eSKate Stone if (result.Succeeded()) { 9365a988416SJim Ingham int enable_count = 0; 9375a988416SJim Ingham int loc_count = 0; 9385a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 939b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 9405a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 9415a988416SJim Ingham 942b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 943b9c1b51eSKate Stone Breakpoint *breakpoint = 944cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 945b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 946b9c1b51eSKate Stone BreakpointLocation *location = 947b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 948b9c1b51eSKate Stone if (location) { 9495a988416SJim Ingham location->SetEnabled(true); 9505a988416SJim Ingham ++loc_count; 9515a988416SJim Ingham } 952b9c1b51eSKate Stone } else { 9535a988416SJim Ingham breakpoint->SetEnabled(true); 9545a988416SJim Ingham ++enable_count; 9555a988416SJim Ingham } 9565a988416SJim Ingham } 9575a988416SJim Ingham } 958b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 959b9c1b51eSKate Stone enable_count + loc_count); 9605a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 9615a988416SJim Ingham } 9625a988416SJim Ingham } 9635a988416SJim Ingham 9645a988416SJim Ingham return result.Succeeded(); 9655a988416SJim Ingham } 9665a988416SJim Ingham }; 9675a988416SJim Ingham 9685a988416SJim Ingham // CommandObjectBreakpointDisable 9695a988416SJim Ingham #pragma mark Disable 9705a988416SJim Ingham 971b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 9725a988416SJim Ingham public: 9737428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 974b9c1b51eSKate Stone : CommandObjectParsed( 975b9c1b51eSKate Stone interpreter, "breakpoint disable", 976b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 9777428a18cSKate Stone "them. If none are specified, disable all " 9787428a18cSKate Stone "breakpoints.", 979b9c1b51eSKate Stone nullptr) { 980b9c1b51eSKate Stone SetHelpLong( 981b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 9827428a18cSKate Stone If none are specified, disable all breakpoints." 9837428a18cSKate Stone R"( 984ea671fbdSKate Stone 9857428a18cSKate Stone )" 9867428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 9877428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 9887428a18cSKate Stone R"( 989ea671fbdSKate Stone 990ea671fbdSKate Stone (lldb) break disable 1 991ea671fbdSKate Stone (lldb) break enable 1.1 992ea671fbdSKate Stone 993ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 994ea671fbdSKate Stone 995ea671fbdSKate Stone (lldb) break disable 1.* 996ea671fbdSKate Stone (lldb) break enable 1.1 997ea671fbdSKate Stone 9987428a18cSKate Stone )" 9997428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 10007428a18cSKate Stone the second re-enables the first location."); 1001b0fac509SJim Ingham 10025a988416SJim Ingham CommandArgumentEntry arg; 1003b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1004b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1005b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1006b9c1b51eSKate Stone // arguments vector. 10075a988416SJim Ingham m_arguments.push_back(arg); 10085a988416SJim Ingham } 10095a988416SJim Ingham 10109e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 10115a988416SJim Ingham 10120e50b9a4SGongyu Deng void 10130e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 10140e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 10150e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 10160e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 10170e50b9a4SGongyu Deng request, nullptr); 10180e50b9a4SGongyu Deng } 10190e50b9a4SGongyu Deng 10205a988416SJim Ingham protected: 1021b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1022cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 1023bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1024cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 10255a988416SJim Ingham 1026cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 10275a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 10285a988416SJim Ingham 1029b9c1b51eSKate Stone if (num_breakpoints == 0) { 10305a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 10315a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10325a988416SJim Ingham return false; 10335a988416SJim Ingham } 10345a988416SJim Ingham 103511eb9c64SZachary Turner if (command.empty()) { 10365a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 1037cb2380c9SRaphael Isemann target.DisableAllowedBreakpoints(); 1038b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1039b9c1b51eSKate Stone " breakpoints)\n", 1040b9c1b51eSKate Stone (uint64_t)num_breakpoints); 10415a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1042b9c1b51eSKate Stone } else { 10435a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 10445a988416SJim Ingham BreakpointIDList valid_bp_ids; 10455a988416SJim Ingham 1046b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1047cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1048b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 10495a988416SJim Ingham 1050b9c1b51eSKate Stone if (result.Succeeded()) { 10515a988416SJim Ingham int disable_count = 0; 10525a988416SJim Ingham int loc_count = 0; 10535a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1054b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 10555a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 10565a988416SJim Ingham 1057b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1058b9c1b51eSKate Stone Breakpoint *breakpoint = 1059cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1060b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1061b9c1b51eSKate Stone BreakpointLocation *location = 1062b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1063b9c1b51eSKate Stone if (location) { 10645a988416SJim Ingham location->SetEnabled(false); 10655a988416SJim Ingham ++loc_count; 10665a988416SJim Ingham } 1067b9c1b51eSKate Stone } else { 10685a988416SJim Ingham breakpoint->SetEnabled(false); 10695a988416SJim Ingham ++disable_count; 10705a988416SJim Ingham } 10715a988416SJim Ingham } 10725a988416SJim Ingham } 1073b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1074b9c1b51eSKate Stone disable_count + loc_count); 10755a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 10765a988416SJim Ingham } 10775a988416SJim Ingham } 10785a988416SJim Ingham 10795a988416SJim Ingham return result.Succeeded(); 10805a988416SJim Ingham } 10815a988416SJim Ingham }; 10825a988416SJim Ingham 10835a988416SJim Ingham // CommandObjectBreakpointList 10841f0f5b5bSZachary Turner 10851f0f5b5bSZachary Turner #pragma mark List::CommandOptions 10866f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list 1087c5a2d747SRaphael Isemann #include "CommandOptions.inc" 10881f0f5b5bSZachary Turner 10895a988416SJim Ingham #pragma mark List 10905a988416SJim Ingham 1091b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 10925a988416SJim Ingham public: 1093b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1094b9c1b51eSKate Stone : CommandObjectParsed( 1095b9c1b51eSKate Stone interpreter, "breakpoint list", 10965a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 10979e85e5a8SEugene Zelenko nullptr), 1098b9c1b51eSKate Stone m_options() { 10995a988416SJim Ingham CommandArgumentEntry arg; 11005a988416SJim Ingham CommandArgumentData bp_id_arg; 11015a988416SJim Ingham 11025a988416SJim Ingham // Define the first (and only) variant of this arg. 11035a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 11045a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 11055a988416SJim Ingham 1106b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1107b9c1b51eSKate Stone // argument entry. 11085a988416SJim Ingham arg.push_back(bp_id_arg); 11095a988416SJim Ingham 11105a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 11115a988416SJim Ingham m_arguments.push_back(arg); 11125a988416SJim Ingham } 11135a988416SJim Ingham 11149e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 11155a988416SJim Ingham 1116b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 11175a988416SJim Ingham 1118b9c1b51eSKate Stone class CommandOptions : public Options { 11195a988416SJim Ingham public: 1120b9c1b51eSKate Stone CommandOptions() 1121b9c1b51eSKate Stone : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 11225a988416SJim Ingham } 11235a988416SJim Ingham 11249e85e5a8SEugene Zelenko ~CommandOptions() override = default; 11255a988416SJim Ingham 112697206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1127b9c1b51eSKate Stone ExecutionContext *execution_context) override { 112897206d57SZachary Turner Status error; 11293bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 11305a988416SJim Ingham 1131b9c1b51eSKate Stone switch (short_option) { 11325a988416SJim Ingham case 'b': 11335a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 11345a988416SJim Ingham break; 113533df7cd3SJim Ingham case 'D': 113633df7cd3SJim Ingham m_use_dummy = true; 113733df7cd3SJim Ingham break; 11385a988416SJim Ingham case 'f': 11395a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 11405a988416SJim Ingham break; 11415a988416SJim Ingham case 'v': 11425a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 11435a988416SJim Ingham break; 11445a988416SJim Ingham case 'i': 11455a988416SJim Ingham m_internal = true; 11465a988416SJim Ingham break; 11475a988416SJim Ingham default: 114836162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 11495a988416SJim Ingham } 11505a988416SJim Ingham 11515a988416SJim Ingham return error; 11525a988416SJim Ingham } 11535a988416SJim Ingham 1154b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 11555a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 11565a988416SJim Ingham m_internal = false; 115733df7cd3SJim Ingham m_use_dummy = false; 11585a988416SJim Ingham } 11595a988416SJim Ingham 11601f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 116170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_list_options); 11621f0f5b5bSZachary Turner } 11635a988416SJim Ingham 11645a988416SJim Ingham // Instance variables to hold the values for command options. 11655a988416SJim Ingham 11665a988416SJim Ingham lldb::DescriptionLevel m_level; 11675a988416SJim Ingham 11685a988416SJim Ingham bool m_internal; 116933df7cd3SJim Ingham bool m_use_dummy; 11705a988416SJim Ingham }; 11715a988416SJim Ingham 11725a988416SJim Ingham protected: 1173b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1174cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 11755a988416SJim Ingham 1176b9c1b51eSKate Stone const BreakpointList &breakpoints = 1177cb2380c9SRaphael Isemann target.GetBreakpointList(m_options.m_internal); 1178bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1179cb2380c9SRaphael Isemann target.GetBreakpointList(m_options.m_internal).GetListMutex(lock); 11805a988416SJim Ingham 11815a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 11825a988416SJim Ingham 1183b9c1b51eSKate Stone if (num_breakpoints == 0) { 11845a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 11855a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 11865a988416SJim Ingham return true; 11875a988416SJim Ingham } 11885a988416SJim Ingham 11895a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 11905a988416SJim Ingham 119111eb9c64SZachary Turner if (command.empty()) { 11925a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 11935a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1194b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 11955a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1196b842f2ecSJim Ingham if (breakpoint->AllowList()) 1197b842f2ecSJim Ingham AddBreakpointDescription(&output_stream, breakpoint, 1198b842f2ecSJim Ingham m_options.m_level); 11995a988416SJim Ingham } 12005a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1201b9c1b51eSKate Stone } else { 12025a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 12035a988416SJim Ingham BreakpointIDList valid_bp_ids; 1204b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1205cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1206b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 12075a988416SJim Ingham 1208b9c1b51eSKate Stone if (result.Succeeded()) { 1209b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 12105a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1211b9c1b51eSKate Stone Breakpoint *breakpoint = 1212cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1213b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1214b9c1b51eSKate Stone m_options.m_level); 12155a988416SJim Ingham } 12165a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1217b9c1b51eSKate Stone } else { 12187428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 12195a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 12205a988416SJim Ingham } 12215a988416SJim Ingham } 12225a988416SJim Ingham 12235a988416SJim Ingham return result.Succeeded(); 12245a988416SJim Ingham } 12255a988416SJim Ingham 12265a988416SJim Ingham private: 12275a988416SJim Ingham CommandOptions m_options; 12285a988416SJim Ingham }; 12295a988416SJim Ingham 12305a988416SJim Ingham // CommandObjectBreakpointClear 12311f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions 12321f0f5b5bSZachary Turner 1233f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear 1234f94668e3SRaphael Isemann #include "CommandOptions.inc" 12351f0f5b5bSZachary Turner 12365a988416SJim Ingham #pragma mark Clear 12375a988416SJim Ingham 1238b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed { 12395a988416SJim Ingham public: 1240efe8e7e3SFangrui Song enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine }; 12415a988416SJim Ingham 12427428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter) 12437428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear", 1244b9c1b51eSKate Stone "Delete or disable breakpoints matching the " 1245b9c1b51eSKate Stone "specified source file and line.", 12465a988416SJim Ingham "breakpoint clear <cmd-options>"), 1247b9c1b51eSKate Stone m_options() {} 12485a988416SJim Ingham 12499e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default; 12505a988416SJim Ingham 1251b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 12525a988416SJim Ingham 1253b9c1b51eSKate Stone class CommandOptions : public Options { 12545a988416SJim Ingham public: 1255b9c1b51eSKate Stone CommandOptions() : Options(), m_filename(), m_line_num(0) {} 12565a988416SJim Ingham 12579e85e5a8SEugene Zelenko ~CommandOptions() override = default; 12585a988416SJim Ingham 125997206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1260b9c1b51eSKate Stone ExecutionContext *execution_context) override { 126197206d57SZachary Turner Status error; 12623bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 12635a988416SJim Ingham 1264b9c1b51eSKate Stone switch (short_option) { 12655a988416SJim Ingham case 'f': 1266adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 12675a988416SJim Ingham break; 12685a988416SJim Ingham 12695a988416SJim Ingham case 'l': 1270fe11483bSZachary Turner option_arg.getAsInteger(0, m_line_num); 12715a988416SJim Ingham break; 12725a988416SJim Ingham 12735a988416SJim Ingham default: 127436162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 12755a988416SJim Ingham } 12765a988416SJim Ingham 12775a988416SJim Ingham return error; 12785a988416SJim Ingham } 12795a988416SJim Ingham 1280b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 12815a988416SJim Ingham m_filename.clear(); 12825a988416SJim Ingham m_line_num = 0; 12835a988416SJim Ingham } 12845a988416SJim Ingham 12851f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 128670602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_clear_options); 12871f0f5b5bSZachary Turner } 12885a988416SJim Ingham 12895a988416SJim Ingham // Instance variables to hold the values for command options. 12905a988416SJim Ingham 12915a988416SJim Ingham std::string m_filename; 12925a988416SJim Ingham uint32_t m_line_num; 12935a988416SJim Ingham }; 12945a988416SJim Ingham 12955a988416SJim Ingham protected: 1296b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1297cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 12985a988416SJim Ingham 129905097246SAdrian Prantl // The following are the various types of breakpoints that could be 130005097246SAdrian Prantl // cleared: 13015a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 13025a988416SJim Ingham 13035a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 13045a988416SJim Ingham 13055a988416SJim Ingham if (m_options.m_line_num != 0) 13065a988416SJim Ingham break_type = eClearTypeFileAndLine; 13075a988416SJim Ingham 1308bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1309cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 13105a988416SJim Ingham 1311cb2380c9SRaphael Isemann BreakpointList &breakpoints = target.GetBreakpointList(); 13125a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 13135a988416SJim Ingham 13145a988416SJim Ingham // Early return if there's no breakpoint at all. 1315b9c1b51eSKate Stone if (num_breakpoints == 0) { 13165a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 13175a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 13185a988416SJim Ingham return result.Succeeded(); 13195a988416SJim Ingham } 13205a988416SJim Ingham 13215a988416SJim Ingham // Find matching breakpoints and delete them. 13225a988416SJim Ingham 13235a988416SJim Ingham // First create a copy of all the IDs. 13245a988416SJim Ingham std::vector<break_id_t> BreakIDs; 13255a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 13269e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 13275a988416SJim Ingham 13285a988416SJim Ingham int num_cleared = 0; 13295a988416SJim Ingham StreamString ss; 1330b9c1b51eSKate Stone switch (break_type) { 13315a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 13325a988416SJim Ingham { 13335a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 13345a988416SJim Ingham BreakpointLocationCollection loc_coll; 13355a988416SJim Ingham 1336b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 13375a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 13385a988416SJim Ingham 1339b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1340b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1341b9c1b51eSKate Stone // remove the breakpoint. 1342b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 13435a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 13445a988416SJim Ingham ss.EOL(); 1345cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp->GetID()); 13465a988416SJim Ingham ++num_cleared; 13475a988416SJim Ingham } 13485a988416SJim Ingham } 13495a988416SJim Ingham } 1350b9c1b51eSKate Stone } break; 13515a988416SJim Ingham 13525a988416SJim Ingham default: 13535a988416SJim Ingham break; 13545a988416SJim Ingham } 13555a988416SJim Ingham 1356b9c1b51eSKate Stone if (num_cleared > 0) { 13575a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 13585a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1359c156427dSZachary Turner output_stream << ss.GetString(); 13605a988416SJim Ingham output_stream.EOL(); 13615a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1362b9c1b51eSKate Stone } else { 13635a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 13645a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 13655a988416SJim Ingham } 13665a988416SJim Ingham 13675a988416SJim Ingham return result.Succeeded(); 13685a988416SJim Ingham } 13695a988416SJim Ingham 13705a988416SJim Ingham private: 13715a988416SJim Ingham CommandOptions m_options; 13725a988416SJim Ingham }; 13735a988416SJim Ingham 13745a988416SJim Ingham // CommandObjectBreakpointDelete 1375f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete 1376f94668e3SRaphael Isemann #include "CommandOptions.inc" 13771f0f5b5bSZachary Turner 13785a988416SJim Ingham #pragma mark Delete 13795a988416SJim Ingham 1380b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 13815a988416SJim Ingham public: 1382b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1383b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1384b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1385b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 13869e85e5a8SEugene Zelenko nullptr), 1387b9c1b51eSKate Stone m_options() { 13885a988416SJim Ingham CommandArgumentEntry arg; 1389b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1390b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1391b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1392b9c1b51eSKate Stone // arguments vector. 13935a988416SJim Ingham m_arguments.push_back(arg); 13945a988416SJim Ingham } 13955a988416SJim Ingham 13969e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 13975a988416SJim Ingham 13980e50b9a4SGongyu Deng void 13990e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 14000e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 14010e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 14020e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 14030e50b9a4SGongyu Deng request, nullptr); 14040e50b9a4SGongyu Deng } 14050e50b9a4SGongyu Deng 1406b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 140733df7cd3SJim Ingham 1408b9c1b51eSKate Stone class CommandOptions : public Options { 140933df7cd3SJim Ingham public: 1410b9c1b51eSKate Stone CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 141133df7cd3SJim Ingham 14129e85e5a8SEugene Zelenko ~CommandOptions() override = default; 141333df7cd3SJim Ingham 141497206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1415b9c1b51eSKate Stone ExecutionContext *execution_context) override { 141697206d57SZachary Turner Status error; 141733df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 141833df7cd3SJim Ingham 1419b9c1b51eSKate Stone switch (short_option) { 142033df7cd3SJim Ingham case 'f': 142133df7cd3SJim Ingham m_force = true; 142233df7cd3SJim Ingham break; 142333df7cd3SJim Ingham 142433df7cd3SJim Ingham case 'D': 142533df7cd3SJim Ingham m_use_dummy = true; 142633df7cd3SJim Ingham break; 142733df7cd3SJim Ingham 142833df7cd3SJim Ingham default: 142936162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 143033df7cd3SJim Ingham } 143133df7cd3SJim Ingham 143233df7cd3SJim Ingham return error; 143333df7cd3SJim Ingham } 143433df7cd3SJim Ingham 1435b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 143633df7cd3SJim Ingham m_use_dummy = false; 143733df7cd3SJim Ingham m_force = false; 143833df7cd3SJim Ingham } 143933df7cd3SJim Ingham 14401f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 144170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_delete_options); 14421f0f5b5bSZachary Turner } 144333df7cd3SJim Ingham 144433df7cd3SJim Ingham // Instance variables to hold the values for command options. 144533df7cd3SJim Ingham bool m_use_dummy; 144633df7cd3SJim Ingham bool m_force; 144733df7cd3SJim Ingham }; 144833df7cd3SJim Ingham 14495a988416SJim Ingham protected: 1450b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1451cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 14525a988416SJim Ingham 1453bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1454cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 14555a988416SJim Ingham 1456cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 14575a988416SJim Ingham 14585a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 14595a988416SJim Ingham 1460b9c1b51eSKate Stone if (num_breakpoints == 0) { 14615a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 14625a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14635a988416SJim Ingham return false; 14645a988416SJim Ingham } 14655a988416SJim Ingham 146611eb9c64SZachary Turner if (command.empty()) { 1467b9c1b51eSKate Stone if (!m_options.m_force && 1468b9c1b51eSKate Stone !m_interpreter.Confirm( 1469b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1470b9c1b51eSKate Stone true)) { 14715a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1472b9c1b51eSKate Stone } else { 1473cb2380c9SRaphael Isemann target.RemoveAllowedBreakpoints(); 1474b9c1b51eSKate Stone result.AppendMessageWithFormat( 1475b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1476b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 14775a988416SJim Ingham } 14785a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1479b9c1b51eSKate Stone } else { 14805a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 14815a988416SJim Ingham BreakpointIDList valid_bp_ids; 1482b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1483cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1484b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 14855a988416SJim Ingham 1486b9c1b51eSKate Stone if (result.Succeeded()) { 14875a988416SJim Ingham int delete_count = 0; 14885a988416SJim Ingham int disable_count = 0; 14895a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1490b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 14915a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 14925a988416SJim Ingham 1493b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1494b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1495b9c1b51eSKate Stone Breakpoint *breakpoint = 1496cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1497b9c1b51eSKate Stone BreakpointLocation *location = 1498b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1499b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1500b9c1b51eSKate Stone // disable them instead. 1501b9c1b51eSKate Stone if (location) { 15025a988416SJim Ingham location->SetEnabled(false); 15035a988416SJim Ingham ++disable_count; 15045a988416SJim Ingham } 1505b9c1b51eSKate Stone } else { 1506cb2380c9SRaphael Isemann target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 15075a988416SJim Ingham ++delete_count; 15085a988416SJim Ingham } 15095a988416SJim Ingham } 15105a988416SJim Ingham } 1511b9c1b51eSKate Stone result.AppendMessageWithFormat( 1512b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 15135a988416SJim Ingham delete_count, disable_count); 15145a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 15155a988416SJim Ingham } 15165a988416SJim Ingham } 15175a988416SJim Ingham return result.Succeeded(); 15185a988416SJim Ingham } 15199e85e5a8SEugene Zelenko 152033df7cd3SJim Ingham private: 152133df7cd3SJim Ingham CommandOptions m_options; 152233df7cd3SJim Ingham }; 152333df7cd3SJim Ingham 15245e09c8c3SJim Ingham // CommandObjectBreakpointName 1525f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name 1526f94668e3SRaphael Isemann #include "CommandOptions.inc" 1527bd68a052SRaphael Isemann 1528b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 15295e09c8c3SJim Ingham public: 1530b9c1b51eSKate Stone BreakpointNameOptionGroup() 1531b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 15325e09c8c3SJim Ingham } 15335e09c8c3SJim Ingham 15349e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 15355e09c8c3SJim Ingham 15361f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 153770602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_name_options); 15385e09c8c3SJim Ingham } 15395e09c8c3SJim Ingham 154097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1541b9c1b51eSKate Stone ExecutionContext *execution_context) override { 154297206d57SZachary Turner Status error; 15435e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 15445e09c8c3SJim Ingham 1545b9c1b51eSKate Stone switch (short_option) { 15465e09c8c3SJim Ingham case 'N': 1547fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1548b9c1b51eSKate Stone error.Success()) 1549fe11483bSZachary Turner m_name.SetValueFromString(option_arg); 15505e09c8c3SJim Ingham break; 15515e09c8c3SJim Ingham case 'B': 1552fe11483bSZachary Turner if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1553b9c1b51eSKate Stone error.SetErrorStringWithFormat( 15548cef4b0bSZachary Turner "unrecognized value \"%s\" for breakpoint", 1555fe11483bSZachary Turner option_arg.str().c_str()); 15565e09c8c3SJim Ingham break; 15575e09c8c3SJim Ingham case 'D': 1558fe11483bSZachary Turner if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1559b9c1b51eSKate Stone error.SetErrorStringWithFormat( 15608cef4b0bSZachary Turner "unrecognized value \"%s\" for use-dummy", 1561fe11483bSZachary Turner option_arg.str().c_str()); 15625e09c8c3SJim Ingham break; 1563e9632ebaSJim Ingham case 'H': 1564e9632ebaSJim Ingham m_help_string.SetValueFromString(option_arg); 1565e9632ebaSJim Ingham break; 15665e09c8c3SJim Ingham 15675e09c8c3SJim Ingham default: 156836162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 15695e09c8c3SJim Ingham } 15705e09c8c3SJim Ingham return error; 15715e09c8c3SJim Ingham } 15725e09c8c3SJim Ingham 1573b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 15745e09c8c3SJim Ingham m_name.Clear(); 15755e09c8c3SJim Ingham m_breakpoint.Clear(); 15765e09c8c3SJim Ingham m_use_dummy.Clear(); 15775e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 1578e9632ebaSJim Ingham m_help_string.Clear(); 15795e09c8c3SJim Ingham } 15805e09c8c3SJim Ingham 15815e09c8c3SJim Ingham OptionValueString m_name; 15825e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 15835e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 1584e9632ebaSJim Ingham OptionValueString m_help_string; 15855e09c8c3SJim Ingham }; 15865e09c8c3SJim Ingham 1587f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access 1588f94668e3SRaphael Isemann #include "CommandOptions.inc" 1589b842f2ecSJim Ingham 15908fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup { 1591b842f2ecSJim Ingham public: 15928fe53c49STatyana Krasnukha BreakpointAccessOptionGroup() : OptionGroup() {} 1593b842f2ecSJim Ingham 1594b842f2ecSJim Ingham ~BreakpointAccessOptionGroup() override = default; 1595b842f2ecSJim Ingham 1596b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1597b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_access_options); 1598b842f2ecSJim Ingham } 1599b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1600b842f2ecSJim Ingham ExecutionContext *execution_context) override { 1601b842f2ecSJim Ingham Status error; 1602a925974bSAdrian Prantl const int short_option = 1603a925974bSAdrian Prantl g_breakpoint_access_options[option_idx].short_option; 1604b842f2ecSJim Ingham 1605b842f2ecSJim Ingham switch (short_option) { 1606b842f2ecSJim Ingham case 'L': { 1607b842f2ecSJim Ingham bool value, success; 160847cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1609b842f2ecSJim Ingham if (success) { 1610b842f2ecSJim Ingham m_permissions.SetAllowList(value); 1611b842f2ecSJim Ingham } else 1612b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1613b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1614b842f2ecSJim Ingham option_arg.str().c_str()); 1615b842f2ecSJim Ingham } break; 1616b842f2ecSJim Ingham case 'A': { 1617b842f2ecSJim Ingham bool value, success; 161847cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1619b842f2ecSJim Ingham if (success) { 1620b842f2ecSJim Ingham m_permissions.SetAllowDisable(value); 1621b842f2ecSJim Ingham } else 1622b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1623b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1624b842f2ecSJim Ingham option_arg.str().c_str()); 1625b842f2ecSJim Ingham } break; 1626b842f2ecSJim Ingham case 'D': { 1627b842f2ecSJim Ingham bool value, success; 162847cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1629b842f2ecSJim Ingham if (success) { 1630b842f2ecSJim Ingham m_permissions.SetAllowDelete(value); 1631b842f2ecSJim Ingham } else 1632b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1633b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1634b842f2ecSJim Ingham option_arg.str().c_str()); 1635b842f2ecSJim Ingham } break; 163636162014SRaphael Isemann default: 163736162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 1638b842f2ecSJim Ingham } 1639b842f2ecSJim Ingham 1640b842f2ecSJim Ingham return error; 1641b842f2ecSJim Ingham } 1642b842f2ecSJim Ingham 1643a925974bSAdrian Prantl void OptionParsingStarting(ExecutionContext *execution_context) override {} 1644b842f2ecSJim Ingham 1645a925974bSAdrian Prantl const BreakpointName::Permissions &GetPermissions() const { 1646b842f2ecSJim Ingham return m_permissions; 1647b842f2ecSJim Ingham } 1648b842f2ecSJim Ingham BreakpointName::Permissions m_permissions; 1649b842f2ecSJim Ingham }; 1650b842f2ecSJim Ingham 1651b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1652b842f2ecSJim Ingham public: 1653b842f2ecSJim Ingham CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1654b842f2ecSJim Ingham : CommandObjectParsed( 1655a925974bSAdrian Prantl interpreter, "configure", 1656a925974bSAdrian Prantl "Configure the options for the breakpoint" 1657b842f2ecSJim Ingham " name provided. " 1658b842f2ecSJim Ingham "If you provide a breakpoint id, the options will be copied from " 1659b842f2ecSJim Ingham "the breakpoint, otherwise only the options specified will be set " 1660b842f2ecSJim Ingham "on the name.", 1661b842f2ecSJim Ingham "breakpoint name configure <command-options> " 1662b842f2ecSJim Ingham "<breakpoint-name-list>"), 1663b842f2ecSJim Ingham m_bp_opts(), m_option_group() { 1664b842f2ecSJim Ingham // Create the first variant for the first (and only) argument for this 1665b842f2ecSJim Ingham // command. 1666b842f2ecSJim Ingham CommandArgumentEntry arg1; 1667b842f2ecSJim Ingham CommandArgumentData id_arg; 1668b842f2ecSJim Ingham id_arg.arg_type = eArgTypeBreakpointName; 1669b842f2ecSJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 1670b842f2ecSJim Ingham arg1.push_back(id_arg); 1671b842f2ecSJim Ingham m_arguments.push_back(arg1); 1672b842f2ecSJim Ingham 1673a925974bSAdrian Prantl m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1674a925974bSAdrian Prantl m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL, 1675b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 1676a925974bSAdrian Prantl m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4, 1677e9632ebaSJim Ingham LLDB_OPT_SET_ALL); 1678b842f2ecSJim Ingham m_option_group.Finalize(); 1679b842f2ecSJim Ingham } 1680b842f2ecSJim Ingham 1681b842f2ecSJim Ingham ~CommandObjectBreakpointNameConfigure() override = default; 1682b842f2ecSJim Ingham 1683b842f2ecSJim Ingham Options *GetOptions() override { return &m_option_group; } 1684b842f2ecSJim Ingham 1685b842f2ecSJim Ingham protected: 1686b842f2ecSJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 1687b842f2ecSJim Ingham 1688b842f2ecSJim Ingham const size_t argc = command.GetArgumentCount(); 1689b842f2ecSJim Ingham if (argc == 0) { 1690b842f2ecSJim Ingham result.AppendError("No names provided."); 1691b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1692b842f2ecSJim Ingham return false; 1693b842f2ecSJim Ingham } 1694b842f2ecSJim Ingham 1695cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(false); 1696b842f2ecSJim Ingham 1697b842f2ecSJim Ingham std::unique_lock<std::recursive_mutex> lock; 1698cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 1699b842f2ecSJim Ingham 1700b842f2ecSJim Ingham // Make a pass through first to see that all the names are legal. 1701b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1702b842f2ecSJim Ingham Status error; 1703a925974bSAdrian Prantl if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) { 1704b842f2ecSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1705b842f2ecSJim Ingham entry.c_str(), error.AsCString()); 1706b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1707b842f2ecSJim Ingham return false; 1708b842f2ecSJim Ingham } 1709b842f2ecSJim Ingham } 171005097246SAdrian Prantl // Now configure them, we already pre-checked the names so we don't need to 171105097246SAdrian Prantl // check the error: 1712b842f2ecSJim Ingham BreakpointSP bp_sp; 1713a925974bSAdrian Prantl if (m_bp_id.m_breakpoint.OptionWasSet()) { 1714b842f2ecSJim Ingham lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1715cb2380c9SRaphael Isemann bp_sp = target.GetBreakpointByID(bp_id); 1716a925974bSAdrian Prantl if (!bp_sp) { 1717b842f2ecSJim Ingham result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1718b842f2ecSJim Ingham bp_id); 1719b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1720b842f2ecSJim Ingham return false; 1721b842f2ecSJim Ingham } 1722b842f2ecSJim Ingham } 1723b842f2ecSJim Ingham 1724b842f2ecSJim Ingham Status error; 1725b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1726b842f2ecSJim Ingham ConstString name(entry.c_str()); 1727cb2380c9SRaphael Isemann BreakpointName *bp_name = target.FindBreakpointName(name, true, error); 1728b842f2ecSJim Ingham if (!bp_name) 1729b842f2ecSJim Ingham continue; 1730e9632ebaSJim Ingham if (m_bp_id.m_help_string.OptionWasSet()) 1731e9632ebaSJim Ingham bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1732e9632ebaSJim Ingham 1733b842f2ecSJim Ingham if (bp_sp) 1734cb2380c9SRaphael Isemann target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(), 1735b842f2ecSJim Ingham m_access_options.GetPermissions()); 1736b842f2ecSJim Ingham else 1737cb2380c9SRaphael Isemann target.ConfigureBreakpointName(*bp_name, 1738b842f2ecSJim Ingham m_bp_opts.GetBreakpointOptions(), 1739b842f2ecSJim Ingham m_access_options.GetPermissions()); 1740b842f2ecSJim Ingham } 1741b842f2ecSJim Ingham return true; 1742b842f2ecSJim Ingham } 1743b842f2ecSJim Ingham 1744b842f2ecSJim Ingham private: 1745b842f2ecSJim Ingham BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1746b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 1747b842f2ecSJim Ingham BreakpointAccessOptionGroup m_access_options; 1748b842f2ecSJim Ingham OptionGroupOptions m_option_group; 1749b842f2ecSJim Ingham }; 1750b842f2ecSJim Ingham 1751b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 17525e09c8c3SJim Ingham public: 1753b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1754b9c1b51eSKate Stone : CommandObjectParsed( 1755b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 17565e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 1757b9c1b51eSKate Stone m_name_options(), m_option_group() { 1758b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1759b9c1b51eSKate Stone // command. 17605e09c8c3SJim Ingham CommandArgumentEntry arg1; 17615e09c8c3SJim Ingham CommandArgumentData id_arg; 17625e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 17635e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 17645e09c8c3SJim Ingham arg1.push_back(id_arg); 17655e09c8c3SJim Ingham m_arguments.push_back(arg1); 17665e09c8c3SJim Ingham 17675e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 17685e09c8c3SJim Ingham m_option_group.Finalize(); 17695e09c8c3SJim Ingham } 17705e09c8c3SJim Ingham 17719e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 17725e09c8c3SJim Ingham 1773*e87362e6SGongyu Deng void 1774*e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 1775*e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 1776*e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 1777*e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 1778*e87362e6SGongyu Deng request, nullptr); 1779*e87362e6SGongyu Deng } 1780*e87362e6SGongyu Deng 1781b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 17825e09c8c3SJim Ingham 17835e09c8c3SJim Ingham protected: 1784b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1785b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 17865e09c8c3SJim Ingham result.SetError("No name option provided."); 17875e09c8c3SJim Ingham return false; 17885e09c8c3SJim Ingham } 17895e09c8c3SJim Ingham 1790cb2380c9SRaphael Isemann Target &target = 1791b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 17925e09c8c3SJim Ingham 1793bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1794cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 17955e09c8c3SJim Ingham 1796cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 17975e09c8c3SJim Ingham 17985e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1799b9c1b51eSKate Stone if (num_breakpoints == 0) { 18005e09c8c3SJim Ingham result.SetError("No breakpoints, cannot add names."); 18015e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18025e09c8c3SJim Ingham return false; 18035e09c8c3SJim Ingham } 18045e09c8c3SJim Ingham 18055e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 18065e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1807b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1808cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1809b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 18105e09c8c3SJim Ingham 1811b9c1b51eSKate Stone if (result.Succeeded()) { 1812b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 18135e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot add names."); 18145e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18155e09c8c3SJim Ingham return false; 18165e09c8c3SJim Ingham } 18175e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1818b842f2ecSJim Ingham const char *bp_name = m_name_options.m_name.GetCurrentValue(); 1819b842f2ecSJim Ingham Status error; // This error reports illegal names, but we've already 1820b842f2ecSJim Ingham // checked that, so we don't need to check it again here. 1821b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1822b9c1b51eSKate Stone lldb::break_id_t bp_id = 1823b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 18245e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1825cb2380c9SRaphael Isemann target.AddNameToBreakpoint(bp_sp, bp_name, error); 18265e09c8c3SJim Ingham } 18275e09c8c3SJim Ingham } 18285e09c8c3SJim Ingham 18295e09c8c3SJim Ingham return true; 18305e09c8c3SJim Ingham } 18315e09c8c3SJim Ingham 18325e09c8c3SJim Ingham private: 18335e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 18345e09c8c3SJim Ingham OptionGroupOptions m_option_group; 18355e09c8c3SJim Ingham }; 18365e09c8c3SJim Ingham 1837b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 18385e09c8c3SJim Ingham public: 1839b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1840b9c1b51eSKate Stone : CommandObjectParsed( 1841b9c1b51eSKate Stone interpreter, "delete", 18425e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 18435e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 1844b9c1b51eSKate Stone m_name_options(), m_option_group() { 1845b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1846b9c1b51eSKate Stone // command. 18475e09c8c3SJim Ingham CommandArgumentEntry arg1; 18485e09c8c3SJim Ingham CommandArgumentData id_arg; 18495e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 18505e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 18515e09c8c3SJim Ingham arg1.push_back(id_arg); 18525e09c8c3SJim Ingham m_arguments.push_back(arg1); 18535e09c8c3SJim Ingham 18545e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 18555e09c8c3SJim Ingham m_option_group.Finalize(); 18565e09c8c3SJim Ingham } 18575e09c8c3SJim Ingham 18589e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 18595e09c8c3SJim Ingham 1860*e87362e6SGongyu Deng void 1861*e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 1862*e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 1863*e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 1864*e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 1865*e87362e6SGongyu Deng request, nullptr); 1866*e87362e6SGongyu Deng } 1867*e87362e6SGongyu Deng 1868b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 18695e09c8c3SJim Ingham 18705e09c8c3SJim Ingham protected: 1871b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1872b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 18735e09c8c3SJim Ingham result.SetError("No name option provided."); 18745e09c8c3SJim Ingham return false; 18755e09c8c3SJim Ingham } 18765e09c8c3SJim Ingham 1877cb2380c9SRaphael Isemann Target &target = 1878b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 18795e09c8c3SJim Ingham 1880bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1881cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 18825e09c8c3SJim Ingham 1883cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 18845e09c8c3SJim Ingham 18855e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1886b9c1b51eSKate Stone if (num_breakpoints == 0) { 18875e09c8c3SJim Ingham result.SetError("No breakpoints, cannot delete names."); 18885e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18895e09c8c3SJim Ingham return false; 18905e09c8c3SJim Ingham } 18915e09c8c3SJim Ingham 18925e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 18935e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1894b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1895cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1896b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 18975e09c8c3SJim Ingham 1898b9c1b51eSKate Stone if (result.Succeeded()) { 1899b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 19005e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot delete names."); 19015e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19025e09c8c3SJim Ingham return false; 19035e09c8c3SJim Ingham } 1904b842f2ecSJim Ingham ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 19055e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1906b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1907b9c1b51eSKate Stone lldb::break_id_t bp_id = 1908b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 19095e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1910cb2380c9SRaphael Isemann target.RemoveNameFromBreakpoint(bp_sp, bp_name); 19115e09c8c3SJim Ingham } 19125e09c8c3SJim Ingham } 19135e09c8c3SJim Ingham 19145e09c8c3SJim Ingham return true; 19155e09c8c3SJim Ingham } 19165e09c8c3SJim Ingham 19175e09c8c3SJim Ingham private: 19185e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19195e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19205e09c8c3SJim Ingham }; 19215e09c8c3SJim Ingham 1922b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 19235e09c8c3SJim Ingham public: 1924b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 1925b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 1926b842f2ecSJim Ingham "List either the names for a breakpoint or info " 1927b842f2ecSJim Ingham "about a given name. With no arguments, lists all " 1928b842f2ecSJim Ingham "names", 19295e09c8c3SJim Ingham "breakpoint name list <command-options>"), 1930b9c1b51eSKate Stone m_name_options(), m_option_group() { 1931b842f2ecSJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 19325e09c8c3SJim Ingham m_option_group.Finalize(); 19335e09c8c3SJim Ingham } 19345e09c8c3SJim Ingham 19359e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 19365e09c8c3SJim Ingham 1937b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19385e09c8c3SJim Ingham 19395e09c8c3SJim Ingham protected: 1940b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1941cb2380c9SRaphael Isemann Target &target = 1942b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19435e09c8c3SJim Ingham 1944b842f2ecSJim Ingham std::vector<std::string> name_list; 1945b842f2ecSJim Ingham if (command.empty()) { 1946cb2380c9SRaphael Isemann target.GetBreakpointNames(name_list); 1947b842f2ecSJim Ingham } else { 1948a925974bSAdrian Prantl for (const Args::ArgEntry &arg : command) { 1949b842f2ecSJim Ingham name_list.push_back(arg.c_str()); 1950b842f2ecSJim Ingham } 1951b842f2ecSJim Ingham } 1952b842f2ecSJim Ingham 1953b842f2ecSJim Ingham if (name_list.empty()) { 1954b842f2ecSJim Ingham result.AppendMessage("No breakpoint names found."); 1955b842f2ecSJim Ingham } else { 1956b842f2ecSJim Ingham for (const std::string &name_str : name_list) { 1957b842f2ecSJim Ingham const char *name = name_str.c_str(); 1958b842f2ecSJim Ingham // First print out the options for the name: 1959b842f2ecSJim Ingham Status error; 1960cb2380c9SRaphael Isemann BreakpointName *bp_name = 1961cb2380c9SRaphael Isemann target.FindBreakpointName(ConstString(name), false, error); 1962a925974bSAdrian Prantl if (bp_name) { 1963b842f2ecSJim Ingham StreamString s; 1964b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s\n", name); 1965a925974bSAdrian Prantl if (bp_name->GetDescription(&s, eDescriptionLevelFull)) { 1966b842f2ecSJim Ingham result.AppendMessage(s.GetString()); 1967b842f2ecSJim Ingham } 1968b842f2ecSJim Ingham 1969bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1970cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 19715e09c8c3SJim Ingham 1972cb2380c9SRaphael Isemann BreakpointList &breakpoints = target.GetBreakpointList(); 1973b842f2ecSJim Ingham bool any_set = false; 1974b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 1975b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 19765e09c8c3SJim Ingham StreamString s; 1977b842f2ecSJim Ingham any_set = true; 19785e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 19795e09c8c3SJim Ingham s.EOL(); 1980c156427dSZachary Turner result.AppendMessage(s.GetString()); 19815e09c8c3SJim Ingham } 19825e09c8c3SJim Ingham } 1983b842f2ecSJim Ingham if (!any_set) 1984b842f2ecSJim Ingham result.AppendMessage("No breakpoints using this name."); 1985b9c1b51eSKate Stone } else { 1986b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s not found.\n", name); 19875e09c8c3SJim Ingham } 1988b842f2ecSJim Ingham } 19895e09c8c3SJim Ingham } 19905e09c8c3SJim Ingham return true; 19915e09c8c3SJim Ingham } 19925e09c8c3SJim Ingham 19935e09c8c3SJim Ingham private: 19945e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19955e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19965e09c8c3SJim Ingham }; 19975e09c8c3SJim Ingham 1998e14dc268SJim Ingham // CommandObjectBreakpointName 1999b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 20005e09c8c3SJim Ingham public: 20017428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2002b9c1b51eSKate Stone : CommandObjectMultiword( 2003b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2004b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2005b9c1b51eSKate Stone CommandObjectSP add_command_object( 2006b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2007b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2008b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2009b9c1b51eSKate Stone CommandObjectSP list_command_object( 2010b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 2011b842f2ecSJim Ingham CommandObjectSP configure_command_object( 2012b842f2ecSJim Ingham new CommandObjectBreakpointNameConfigure(interpreter)); 20135e09c8c3SJim Ingham 20145e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 20155e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 20165e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 2017b842f2ecSJim Ingham LoadSubCommand("configure", configure_command_object); 20185e09c8c3SJim Ingham } 20195e09c8c3SJim Ingham 20209e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 20215e09c8c3SJim Ingham }; 20225e09c8c3SJim Ingham 2023e14dc268SJim Ingham // CommandObjectBreakpointRead 20243acdf385SJim Ingham #pragma mark Read::CommandOptions 2025f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read 2026f94668e3SRaphael Isemann #include "CommandOptions.inc" 20271f0f5b5bSZachary Turner 20281f0f5b5bSZachary Turner #pragma mark Read 2029e14dc268SJim Ingham 2030e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed { 2031e14dc268SJim Ingham public: 2032e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2033e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read", 2034e14dc268SJim Ingham "Read and set the breakpoints previously saved to " 2035e14dc268SJim Ingham "a file with \"breakpoint write\". ", 2036e14dc268SJim Ingham nullptr), 2037e14dc268SJim Ingham m_options() { 2038e14dc268SJim Ingham CommandArgumentEntry arg; 2039e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2040e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2041e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2042e14dc268SJim Ingham // arguments vector. 2043e14dc268SJim Ingham m_arguments.push_back(arg); 2044e14dc268SJim Ingham } 2045e14dc268SJim Ingham 2046e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default; 2047e14dc268SJim Ingham 2048e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2049e14dc268SJim Ingham 2050e14dc268SJim Ingham class CommandOptions : public Options { 2051e14dc268SJim Ingham public: 2052e14dc268SJim Ingham CommandOptions() : Options() {} 2053e14dc268SJim Ingham 2054e14dc268SJim Ingham ~CommandOptions() override = default; 2055e14dc268SJim Ingham 205697206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2057e14dc268SJim Ingham ExecutionContext *execution_context) override { 205897206d57SZachary Turner Status error; 2059e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2060e14dc268SJim Ingham 2061e14dc268SJim Ingham switch (short_option) { 2062e14dc268SJim Ingham case 'f': 2063adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 2064e14dc268SJim Ingham break; 20653acdf385SJim Ingham case 'N': { 206697206d57SZachary Turner Status name_error; 20673acdf385SJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 20683acdf385SJim Ingham name_error)) { 20693acdf385SJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 20703acdf385SJim Ingham name_error.AsCString()); 20713acdf385SJim Ingham } 2072adcd0268SBenjamin Kramer m_names.push_back(std::string(option_arg)); 20733acdf385SJim Ingham break; 20743acdf385SJim Ingham } 2075e14dc268SJim Ingham default: 207636162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 2077e14dc268SJim Ingham } 2078e14dc268SJim Ingham 2079e14dc268SJim Ingham return error; 2080e14dc268SJim Ingham } 2081e14dc268SJim Ingham 2082e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2083e14dc268SJim Ingham m_filename.clear(); 20843acdf385SJim Ingham m_names.clear(); 2085e14dc268SJim Ingham } 2086e14dc268SJim Ingham 20871f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 208870602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_read_options); 20891f0f5b5bSZachary Turner } 2090e14dc268SJim Ingham 2091e14dc268SJim Ingham // Instance variables to hold the values for command options. 2092e14dc268SJim Ingham 2093e14dc268SJim Ingham std::string m_filename; 20943acdf385SJim Ingham std::vector<std::string> m_names; 2095e14dc268SJim Ingham }; 2096e14dc268SJim Ingham 2097e14dc268SJim Ingham protected: 2098e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2099cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 2100e14dc268SJim Ingham 21013acdf385SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2102cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 21033acdf385SJim Ingham 21048f3be7a3SJonas Devlieghere FileSpec input_spec(m_options.m_filename); 21058f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(input_spec); 210601f16664SJim Ingham BreakpointIDList new_bps; 2107cb2380c9SRaphael Isemann Status error = target.CreateBreakpointsFromFile(input_spec, 2108cb2380c9SRaphael Isemann m_options.m_names, new_bps); 2109e14dc268SJim Ingham 2110e14dc268SJim Ingham if (!error.Success()) { 211101f16664SJim Ingham result.AppendError(error.AsCString()); 2112e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 211301f16664SJim Ingham return false; 2114e14dc268SJim Ingham } 21153acdf385SJim Ingham 21163acdf385SJim Ingham Stream &output_stream = result.GetOutputStream(); 21173acdf385SJim Ingham 21183acdf385SJim Ingham size_t num_breakpoints = new_bps.GetSize(); 21193acdf385SJim Ingham if (num_breakpoints == 0) { 21203acdf385SJim Ingham result.AppendMessage("No breakpoints added."); 21213acdf385SJim Ingham } else { 21223acdf385SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 21233acdf385SJim Ingham result.AppendMessage("New breakpoints:"); 21243acdf385SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) { 21253acdf385SJim Ingham BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 2126cb2380c9SRaphael Isemann Breakpoint *bp = target.GetBreakpointList() 21273acdf385SJim Ingham .FindBreakpointByID(bp_id.GetBreakpointID()) 21283acdf385SJim Ingham .get(); 21293acdf385SJim Ingham if (bp) 21303acdf385SJim Ingham bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 21313acdf385SJim Ingham false); 21323acdf385SJim Ingham } 21333acdf385SJim Ingham } 2134e14dc268SJim Ingham return result.Succeeded(); 2135e14dc268SJim Ingham } 2136e14dc268SJim Ingham 2137e14dc268SJim Ingham private: 2138e14dc268SJim Ingham CommandOptions m_options; 2139e14dc268SJim Ingham }; 2140e14dc268SJim Ingham 2141e14dc268SJim Ingham // CommandObjectBreakpointWrite 21421f0f5b5bSZachary Turner #pragma mark Write::CommandOptions 2143f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write 2144f94668e3SRaphael Isemann #include "CommandOptions.inc" 21451f0f5b5bSZachary Turner 21461f0f5b5bSZachary Turner #pragma mark Write 2147e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed { 2148e14dc268SJim Ingham public: 2149e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2150e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write", 2151e14dc268SJim Ingham "Write the breakpoints listed to a file that can " 2152e14dc268SJim Ingham "be read in with \"breakpoint read\". " 2153e14dc268SJim Ingham "If given no arguments, writes all breakpoints.", 2154e14dc268SJim Ingham nullptr), 2155e14dc268SJim Ingham m_options() { 2156e14dc268SJim Ingham CommandArgumentEntry arg; 2157e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2158e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2159e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2160e14dc268SJim Ingham // arguments vector. 2161e14dc268SJim Ingham m_arguments.push_back(arg); 2162e14dc268SJim Ingham } 2163e14dc268SJim Ingham 2164e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default; 2165e14dc268SJim Ingham 2166*e87362e6SGongyu Deng void 2167*e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 2168*e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 2169*e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 2170*e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 2171*e87362e6SGongyu Deng request, nullptr); 2172*e87362e6SGongyu Deng } 2173*e87362e6SGongyu Deng 2174e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2175e14dc268SJim Ingham 2176e14dc268SJim Ingham class CommandOptions : public Options { 2177e14dc268SJim Ingham public: 2178e14dc268SJim Ingham CommandOptions() : Options() {} 2179e14dc268SJim Ingham 2180e14dc268SJim Ingham ~CommandOptions() override = default; 2181e14dc268SJim Ingham 218297206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2183e14dc268SJim Ingham ExecutionContext *execution_context) override { 218497206d57SZachary Turner Status error; 2185e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2186e14dc268SJim Ingham 2187e14dc268SJim Ingham switch (short_option) { 2188e14dc268SJim Ingham case 'f': 2189adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 2190e14dc268SJim Ingham break; 21912d3628e1SJim Ingham case 'a': 21922d3628e1SJim Ingham m_append = true; 21932d3628e1SJim Ingham break; 2194e14dc268SJim Ingham default: 219536162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 2196e14dc268SJim Ingham } 2197e14dc268SJim Ingham 2198e14dc268SJim Ingham return error; 2199e14dc268SJim Ingham } 2200e14dc268SJim Ingham 2201e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2202e14dc268SJim Ingham m_filename.clear(); 22032d3628e1SJim Ingham m_append = false; 2204e14dc268SJim Ingham } 2205e14dc268SJim Ingham 22061f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 220770602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_write_options); 22081f0f5b5bSZachary Turner } 2209e14dc268SJim Ingham 2210e14dc268SJim Ingham // Instance variables to hold the values for command options. 2211e14dc268SJim Ingham 2212e14dc268SJim Ingham std::string m_filename; 22132d3628e1SJim Ingham bool m_append = false; 2214e14dc268SJim Ingham }; 2215e14dc268SJim Ingham 2216e14dc268SJim Ingham protected: 2217e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2218cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 2219e14dc268SJim Ingham 2220e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2221cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 2222e14dc268SJim Ingham 2223e14dc268SJim Ingham BreakpointIDList valid_bp_ids; 222411eb9c64SZachary Turner if (!command.empty()) { 2225e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2226cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 2227b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 2228e14dc268SJim Ingham 222901f16664SJim Ingham if (!result.Succeeded()) { 2230e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2231e14dc268SJim Ingham return false; 2232e14dc268SJim Ingham } 2233e14dc268SJim Ingham } 22348f3be7a3SJonas Devlieghere FileSpec file_spec(m_options.m_filename); 22358f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(file_spec); 2236cb2380c9SRaphael Isemann Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids, 22378f3be7a3SJonas Devlieghere m_options.m_append); 223801f16664SJim Ingham if (!error.Success()) { 223901f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.", 224001f16664SJim Ingham error.AsCString()); 224101f16664SJim Ingham result.SetStatus(eReturnStatusFailed); 2242e14dc268SJim Ingham } 2243e14dc268SJim Ingham return result.Succeeded(); 2244e14dc268SJim Ingham } 2245e14dc268SJim Ingham 2246e14dc268SJim Ingham private: 2247e14dc268SJim Ingham CommandOptions m_options; 2248e14dc268SJim Ingham }; 2249e14dc268SJim Ingham 225030fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 2251ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 225230fdc8d8SChris Lattner 2253b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2254b9c1b51eSKate Stone CommandInterpreter &interpreter) 2255b9c1b51eSKate Stone : CommandObjectMultiword( 2256b9c1b51eSKate Stone interpreter, "breakpoint", 22577428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2258b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2259b9c1b51eSKate Stone CommandObjectSP list_command_object( 2260b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2261b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2262b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2263b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2264b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2265b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2266b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2267b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2268b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2269b9c1b51eSKate Stone CommandObjectSP set_command_object( 2270b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2271b9c1b51eSKate Stone CommandObjectSP command_command_object( 2272b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2273b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2274b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2275b9c1b51eSKate Stone CommandObjectSP name_command_object( 2276b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 2277e14dc268SJim Ingham CommandObjectSP write_command_object( 2278e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter)); 2279e14dc268SJim Ingham CommandObjectSP read_command_object( 2280e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter)); 228130fdc8d8SChris Lattner 2282b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 228330fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 228430fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2285b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2286b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2287ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2288b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2289b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 22905e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 2291e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write"); 2292e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read"); 229330fdc8d8SChris Lattner 229423f59509SGreg Clayton LoadSubCommand("list", list_command_object); 229523f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 229623f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 229723f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 229823f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 229923f59509SGreg Clayton LoadSubCommand("set", set_command_object); 230023f59509SGreg Clayton LoadSubCommand("command", command_command_object); 230123f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 23025e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 2303e14dc268SJim Ingham LoadSubCommand("write", write_command_object); 2304e14dc268SJim Ingham LoadSubCommand("read", read_command_object); 230530fdc8d8SChris Lattner } 230630fdc8d8SChris Lattner 23079e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 230830fdc8d8SChris Lattner 2309a925974bSAdrian Prantl void CommandObjectMultiwordBreakpoint::VerifyIDs( 2310a925974bSAdrian Prantl Args &args, Target *target, bool allow_locations, 2311a925974bSAdrian Prantl CommandReturnObject &result, BreakpointIDList *valid_ids, 2312a925974bSAdrian Prantl BreakpointName::Permissions ::PermissionKinds purpose) { 231330fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2314b9c1b51eSKate Stone // 2). the full breakpoint & location 2315b9c1b51eSKate Stone // canonical representation 2316b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2317b9c1b51eSKate Stone // representing a range (in which case there 2318b9c1b51eSKate Stone // had *better* be an entry both before & 2319b9c1b51eSKate Stone // after of one of the first two types. 23205e09c8c3SJim Ingham // 4). A breakpoint name 2321b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2322b9c1b51eSKate Stone // one.) 232330fdc8d8SChris Lattner 232430fdc8d8SChris Lattner Args temp_args; 232530fdc8d8SChris Lattner 232611eb9c64SZachary Turner if (args.empty()) { 2327b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2328b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2329b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 233036f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2331b9c1b51eSKate Stone } else { 2332b9c1b51eSKate Stone result.AppendError( 2333b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 233436f3b369SJim Ingham result.SetStatus(eReturnStatusFailed); 233536f3b369SJim Ingham } 233636f3b369SJim Ingham return; 233736f3b369SJim Ingham } 233836f3b369SJim Ingham 2339b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 234005097246SAdrian Prantl // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 234105097246SAdrian Prantl // id range strings over; instead generate a list of strings for all the 234205097246SAdrian Prantl // breakpoint ids in the range, and shove all of those breakpoint id strings 234305097246SAdrian Prantl // into TEMP_ARGS. 234430fdc8d8SChris Lattner 2345b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2346b842f2ecSJim Ingham purpose, result, temp_args); 234730fdc8d8SChris Lattner 2348b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2349b9c1b51eSKate Stone // BreakpointIDList: 235030fdc8d8SChris Lattner 235116662f3cSPavel Labath valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 235230fdc8d8SChris Lattner 235305097246SAdrian Prantl // At this point, all of the breakpoint ids that the user passed in have 235405097246SAdrian Prantl // been converted to breakpoint IDs and put into valid_ids. 235530fdc8d8SChris Lattner 2356b9c1b51eSKate Stone if (result.Succeeded()) { 2357b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 235805097246SAdrian Prantl // ids, go through our tentative list of breakpoint id's and verify that 235905097246SAdrian Prantl // they correspond to valid/currently set breakpoints. 236030fdc8d8SChris Lattner 2361c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2362b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 236330fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2364b9c1b51eSKate Stone Breakpoint *breakpoint = 2365b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2366b9c1b51eSKate Stone if (breakpoint != nullptr) { 2367c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2368b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 236930fdc8d8SChris Lattner StreamString id_str; 2370b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2371b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2372c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2373b9c1b51eSKate Stone result.AppendErrorWithFormat( 2374b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 237530fdc8d8SChris Lattner id_str.GetData()); 237630fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 237730fdc8d8SChris Lattner } 2378b9c1b51eSKate Stone } else { 2379c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2380b9c1b51eSKate Stone result.AppendErrorWithFormat( 2381b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 23827428a18cSKate Stone cur_bp_id.GetBreakpointID()); 238330fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 238430fdc8d8SChris Lattner } 238530fdc8d8SChris Lattner } 238630fdc8d8SChris Lattner } 238730fdc8d8SChris Lattner } 2388