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" 20bc0a9a17SJim Ingham #include "lldb/Interpreter/OptionValueFileColonLine.h" 215e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h" 225e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h" 23b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 240e0984eeSJim Ingham #include "lldb/Target/Language.h" 25b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 26b9c1b51eSKate Stone #include "lldb/Target/Target.h" 271b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h" 28bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h" 29bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 3030fdc8d8SChris Lattner 31796ac80bSJonas Devlieghere #include <memory> 32796ac80bSJonas Devlieghere #include <vector> 33796ac80bSJonas Devlieghere 3430fdc8d8SChris Lattner using namespace lldb; 3530fdc8d8SChris Lattner using namespace lldb_private; 3630fdc8d8SChris Lattner 37b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp, 38b9c1b51eSKate Stone lldb::DescriptionLevel level) { 3930fdc8d8SChris Lattner s->IndentMore(); 4030fdc8d8SChris Lattner bp->GetDescription(s, level, true); 4130fdc8d8SChris Lattner s->IndentLess(); 4230fdc8d8SChris Lattner s->EOL(); 4330fdc8d8SChris Lattner } 4430fdc8d8SChris Lattner 45b842f2ecSJim Ingham // Modifiable Breakpoint Options 46b842f2ecSJim Ingham #pragma mark Modify::CommandOptions 47f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify 48f94668e3SRaphael Isemann #include "CommandOptions.inc" 49bd68a052SRaphael Isemann 50a925974bSAdrian Prantl class lldb_private::BreakpointOptionGroup : public OptionGroup { 51b842f2ecSJim Ingham public: 52a925974bSAdrian Prantl BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {} 53b842f2ecSJim Ingham 54b842f2ecSJim Ingham ~BreakpointOptionGroup() override = default; 55b842f2ecSJim Ingham 56b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 57b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_modify_options); 58b842f2ecSJim Ingham } 59b842f2ecSJim Ingham 60b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 61b842f2ecSJim Ingham ExecutionContext *execution_context) override { 62b842f2ecSJim Ingham Status error; 63a925974bSAdrian Prantl const int short_option = 64a925974bSAdrian Prantl g_breakpoint_modify_options[option_idx].short_option; 65b842f2ecSJim Ingham 66b842f2ecSJim Ingham switch (short_option) { 67b842f2ecSJim Ingham case 'c': 6805097246SAdrian Prantl // Normally an empty breakpoint condition marks is as unset. But we need 6905097246SAdrian Prantl // to say it was passed in. 70b842f2ecSJim Ingham m_bp_opts.SetCondition(option_arg.str().c_str()); 71b842f2ecSJim Ingham m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition); 72b842f2ecSJim Ingham break; 73b842f2ecSJim Ingham case 'C': 74adcd0268SBenjamin Kramer m_commands.push_back(std::string(option_arg)); 75b842f2ecSJim Ingham break; 76b842f2ecSJim Ingham case 'd': 77b842f2ecSJim Ingham m_bp_opts.SetEnabled(false); 78b842f2ecSJim Ingham break; 79b842f2ecSJim Ingham case 'e': 80b842f2ecSJim Ingham m_bp_opts.SetEnabled(true); 81b842f2ecSJim Ingham break; 82b842f2ecSJim Ingham case 'G': { 83b842f2ecSJim Ingham bool value, success; 8447cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 85b842f2ecSJim Ingham if (success) { 86b842f2ecSJim Ingham m_bp_opts.SetAutoContinue(value); 87b842f2ecSJim Ingham } else 88b842f2ecSJim Ingham error.SetErrorStringWithFormat( 89b842f2ecSJim Ingham "invalid boolean value '%s' passed for -G option", 90b842f2ecSJim Ingham option_arg.str().c_str()); 91a925974bSAdrian Prantl } break; 92a925974bSAdrian Prantl case 'i': { 93b842f2ecSJim Ingham uint32_t ignore_count; 94b842f2ecSJim Ingham if (option_arg.getAsInteger(0, ignore_count)) 95b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid ignore count '%s'", 96b842f2ecSJim Ingham option_arg.str().c_str()); 97b842f2ecSJim Ingham else 98b842f2ecSJim Ingham m_bp_opts.SetIgnoreCount(ignore_count); 99a925974bSAdrian Prantl } break; 100b842f2ecSJim Ingham case 'o': { 101b842f2ecSJim Ingham bool value, success; 10247cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 103b842f2ecSJim Ingham if (success) { 104b842f2ecSJim Ingham m_bp_opts.SetOneShot(value); 105b842f2ecSJim Ingham } else 106b842f2ecSJim Ingham error.SetErrorStringWithFormat( 107b842f2ecSJim Ingham "invalid boolean value '%s' passed for -o option", 108b842f2ecSJim Ingham option_arg.str().c_str()); 109b842f2ecSJim Ingham } break; 110a925974bSAdrian Prantl case 't': { 111b842f2ecSJim Ingham lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID; 112b842f2ecSJim Ingham if (option_arg[0] != '\0') { 113b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_id)) 114b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread id string '%s'", 115b842f2ecSJim Ingham option_arg.str().c_str()); 116b842f2ecSJim Ingham } 117b842f2ecSJim Ingham m_bp_opts.SetThreadID(thread_id); 118a925974bSAdrian Prantl } break; 119b842f2ecSJim Ingham case 'T': 120b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); 121b842f2ecSJim Ingham break; 122b842f2ecSJim Ingham case 'q': 123b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str()); 124b842f2ecSJim Ingham break; 125a925974bSAdrian Prantl case 'x': { 126b842f2ecSJim Ingham uint32_t thread_index = UINT32_MAX; 127b842f2ecSJim Ingham if (option_arg[0] != '\n') { 128b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_index)) 129b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread index string '%s'", 130b842f2ecSJim Ingham option_arg.str().c_str()); 131b842f2ecSJim Ingham } 132b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetIndex(thread_index); 133a925974bSAdrian Prantl } break; 134b842f2ecSJim Ingham default: 13536162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 136b842f2ecSJim Ingham } 137b842f2ecSJim Ingham 138b842f2ecSJim Ingham return error; 139b842f2ecSJim Ingham } 140b842f2ecSJim Ingham 141b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 142b842f2ecSJim Ingham m_bp_opts.Clear(); 143b842f2ecSJim Ingham m_commands.clear(); 144b842f2ecSJim Ingham } 145b842f2ecSJim Ingham 146b842f2ecSJim Ingham Status OptionParsingFinished(ExecutionContext *execution_context) override { 147a925974bSAdrian Prantl if (!m_commands.empty()) { 148a8f3ae7cSJonas Devlieghere auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); 149b842f2ecSJim Ingham 150b842f2ecSJim Ingham for (std::string &str : m_commands) 151b842f2ecSJim Ingham cmd_data->user_source.AppendString(str); 152b842f2ecSJim Ingham 153b842f2ecSJim Ingham cmd_data->stop_on_error = true; 154b842f2ecSJim Ingham m_bp_opts.SetCommandDataCallback(cmd_data); 155b842f2ecSJim Ingham } 156b842f2ecSJim Ingham return Status(); 157b842f2ecSJim Ingham } 158b842f2ecSJim Ingham 159a925974bSAdrian Prantl const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; } 160b842f2ecSJim Ingham 161b842f2ecSJim Ingham std::vector<std::string> m_commands; 162b842f2ecSJim Ingham BreakpointOptions m_bp_opts; 163b842f2ecSJim Ingham }; 164bd68a052SRaphael Isemann 165f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy 166f94668e3SRaphael Isemann #include "CommandOptions.inc" 167b842f2ecSJim Ingham 168a925974bSAdrian Prantl class BreakpointDummyOptionGroup : public OptionGroup { 169b842f2ecSJim Ingham public: 170a925974bSAdrian Prantl BreakpointDummyOptionGroup() : OptionGroup() {} 171b842f2ecSJim Ingham 172b842f2ecSJim Ingham ~BreakpointDummyOptionGroup() override = default; 173b842f2ecSJim Ingham 174b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 175b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_dummy_options); 176b842f2ecSJim Ingham } 177b842f2ecSJim Ingham 178b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 179b842f2ecSJim Ingham ExecutionContext *execution_context) override { 180b842f2ecSJim Ingham Status error; 181a925974bSAdrian Prantl const int short_option = 182f1539b9dSJim Ingham g_breakpoint_dummy_options[option_idx].short_option; 183b842f2ecSJim Ingham 184b842f2ecSJim Ingham switch (short_option) { 185b842f2ecSJim Ingham case 'D': 186b842f2ecSJim Ingham m_use_dummy = true; 187b842f2ecSJim Ingham break; 188b842f2ecSJim Ingham default: 18936162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 190b842f2ecSJim Ingham } 191b842f2ecSJim Ingham 192b842f2ecSJim Ingham return error; 193b842f2ecSJim Ingham } 194b842f2ecSJim Ingham 195b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 196b842f2ecSJim Ingham m_use_dummy = false; 197b842f2ecSJim Ingham } 198b842f2ecSJim Ingham 199b842f2ecSJim Ingham bool m_use_dummy; 200b842f2ecSJim Ingham }; 201b842f2ecSJim Ingham 202f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set 203f94668e3SRaphael Isemann #include "CommandOptions.inc" 2041f0f5b5bSZachary Turner 2055a988416SJim Ingham // CommandObjectBreakpointSet 20630fdc8d8SChris Lattner 207b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 2085a988416SJim Ingham public: 209efe8e7e3SFangrui Song enum BreakpointSetType { 2105a988416SJim Ingham eSetTypeInvalid, 2115a988416SJim Ingham eSetTypeFileAndLine, 2125a988416SJim Ingham eSetTypeAddress, 2135a988416SJim Ingham eSetTypeFunctionName, 2145a988416SJim Ingham eSetTypeFunctionRegexp, 2155a988416SJim Ingham eSetTypeSourceRegexp, 2163815e702SJim Ingham eSetTypeException, 2173815e702SJim Ingham eSetTypeScripted, 218efe8e7e3SFangrui Song }; 2195a988416SJim Ingham 220b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 221b9c1b51eSKate Stone : CommandObjectParsed( 222b9c1b51eSKate Stone interpreter, "breakpoint set", 2235a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 2245a988416SJim Ingham "breakpoint set <cmd-options>"), 225738af7a6SJim Ingham m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'), 226f6a2086dSSam McCall m_options() { 227b842f2ecSJim Ingham // We're picking up all the normal options, commands and disable. 228a925974bSAdrian Prantl m_all_options.Append(&m_python_class_options, 229a925974bSAdrian Prantl LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11); 230b842f2ecSJim Ingham m_all_options.Append(&m_bp_opts, 231b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, 232b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 233f6a2086dSSam McCall m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 234b842f2ecSJim Ingham m_all_options.Append(&m_options); 235b842f2ecSJim Ingham m_all_options.Finalize(); 236b842f2ecSJim Ingham } 2375a988416SJim Ingham 2389e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 2395a988416SJim Ingham 240b842f2ecSJim Ingham Options *GetOptions() override { return &m_all_options; } 2415a988416SJim Ingham 242b842f2ecSJim Ingham class CommandOptions : public OptionGroup { 2435a988416SJim Ingham public: 244b9c1b51eSKate Stone CommandOptions() 245a925974bSAdrian Prantl : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), 246a925974bSAdrian Prantl m_column(0), m_func_names(), 247a925974bSAdrian Prantl m_func_name_type_mask(eFunctionNameTypeNone), m_func_regexp(), 248a925974bSAdrian Prantl m_source_text_regexp(), m_modules(), m_load_addr(), m_catch_bp(false), 249a925974bSAdrian Prantl m_throw_bp(true), m_hardware(false), 250a72b31c7SJim Ingham m_exception_language(eLanguageTypeUnknown), 25123b1decbSDawn Perchik m_language(lldb::eLanguageTypeUnknown), 252a925974bSAdrian Prantl m_skip_prologue(eLazyBoolCalculate), m_all_files(false), 253a925974bSAdrian Prantl m_move_to_nearest_code(eLazyBoolCalculate) {} 25430fdc8d8SChris Lattner 2559e85e5a8SEugene Zelenko ~CommandOptions() override = default; 25687df91b8SJim Ingham 25797206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 258b9c1b51eSKate Stone ExecutionContext *execution_context) override { 25997206d57SZachary Turner Status error; 260a925974bSAdrian Prantl const int short_option = 261a925974bSAdrian Prantl g_breakpoint_set_options[option_idx].short_option; 26230fdc8d8SChris Lattner 263b9c1b51eSKate Stone switch (short_option) { 264b9c1b51eSKate Stone case 'a': { 26547cbf4a0SPavel Labath m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 266e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 267b9c1b51eSKate Stone } break; 26830fdc8d8SChris Lattner 269e732052fSJim Ingham case 'A': 270e732052fSJim Ingham m_all_files = true; 271e732052fSJim Ingham break; 272e732052fSJim Ingham 273ca36cd16SJim Ingham case 'b': 274adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 275ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 276ca36cd16SJim Ingham break; 277ca36cd16SJim Ingham 2786672a4f5SJonas Devlieghere case 'u': 279fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_column)) 280b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 281fe11483bSZachary Turner option_arg.str().c_str()); 28230fdc8d8SChris Lattner break; 2839e85e5a8SEugene Zelenko 284b9c1b51eSKate Stone case 'E': { 285fe11483bSZachary Turner LanguageType language = Language::GetLanguageTypeFromString(option_arg); 286fab10e89SJim Ingham 287b9c1b51eSKate Stone switch (language) { 288fab10e89SJim Ingham case eLanguageTypeC89: 289fab10e89SJim Ingham case eLanguageTypeC: 290fab10e89SJim Ingham case eLanguageTypeC99: 2911d0089faSBruce Mitchener case eLanguageTypeC11: 292a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 293fab10e89SJim Ingham break; 294fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 2951d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 2961d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 2972ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 298a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 299fab10e89SJim Ingham break; 300fab10e89SJim Ingham case eLanguageTypeObjC: 301a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 302fab10e89SJim Ingham break; 303fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 304b9c1b51eSKate Stone error.SetErrorStringWithFormat( 305b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 306fab10e89SJim Ingham break; 307fab10e89SJim Ingham case eLanguageTypeUnknown: 308b9c1b51eSKate Stone error.SetErrorStringWithFormat( 309b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 310fe11483bSZachary Turner option_arg.str().c_str()); 311fab10e89SJim Ingham break; 312fab10e89SJim Ingham default: 313b9c1b51eSKate Stone error.SetErrorStringWithFormat( 314b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 315fe11483bSZachary Turner option_arg.str().c_str()); 316fab10e89SJim Ingham } 317b9c1b51eSKate Stone } break; 318ca36cd16SJim Ingham 319ca36cd16SJim Ingham case 'f': 3208f3be7a3SJonas Devlieghere m_filenames.AppendIfUnique(FileSpec(option_arg)); 321fab10e89SJim Ingham break; 322ca36cd16SJim Ingham 323ca36cd16SJim Ingham case 'F': 324adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 325ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 326ca36cd16SJim Ingham break; 327ca36cd16SJim Ingham 328b9c1b51eSKate Stone case 'h': { 329fab10e89SJim Ingham bool success; 33047cbf4a0SPavel Labath m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 331fab10e89SJim Ingham if (!success) 332b9c1b51eSKate Stone error.SetErrorStringWithFormat( 333fe11483bSZachary Turner "Invalid boolean value for on-catch option: '%s'", 334fe11483bSZachary Turner option_arg.str().c_str()); 335b9c1b51eSKate Stone } break; 336eb023e75SGreg Clayton 337eb023e75SGreg Clayton case 'H': 338eb023e75SGreg Clayton m_hardware = true; 339eb023e75SGreg Clayton break; 340eb023e75SGreg Clayton 341b9c1b51eSKate Stone case 'K': { 342a8558b62SJim Ingham bool success; 343a8558b62SJim Ingham bool value; 34447cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 345a8558b62SJim Ingham if (value) 346a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 347a8558b62SJim Ingham else 348a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 349a8558b62SJim Ingham 350a8558b62SJim Ingham if (!success) 351b9c1b51eSKate Stone error.SetErrorStringWithFormat( 352b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 353fe11483bSZachary Turner option_arg.str().c_str()); 354b9c1b51eSKate Stone } break; 355ca36cd16SJim Ingham 356fe11483bSZachary Turner case 'l': 357fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_line_num)) 358b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 359fe11483bSZachary Turner option_arg.str().c_str()); 360ca36cd16SJim Ingham break; 361055ad9beSIlia K 36223b1decbSDawn Perchik case 'L': 363fe11483bSZachary Turner m_language = Language::GetLanguageTypeFromString(option_arg); 36423b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 365b9c1b51eSKate Stone error.SetErrorStringWithFormat( 366fe11483bSZachary Turner "Unknown language type: '%s' for breakpoint", 367fe11483bSZachary Turner option_arg.str().c_str()); 36823b1decbSDawn Perchik break; 36923b1decbSDawn Perchik 370b9c1b51eSKate Stone case 'm': { 371055ad9beSIlia K bool success; 372055ad9beSIlia K bool value; 37347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 374055ad9beSIlia K if (value) 375055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 376055ad9beSIlia K else 377055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 378055ad9beSIlia K 379055ad9beSIlia K if (!success) 380b9c1b51eSKate Stone error.SetErrorStringWithFormat( 381b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 382fe11483bSZachary Turner option_arg.str().c_str()); 383055ad9beSIlia K break; 384055ad9beSIlia K } 385055ad9beSIlia K 386ca36cd16SJim Ingham case 'M': 387adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 388ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 389ca36cd16SJim Ingham break; 390ca36cd16SJim Ingham 391ca36cd16SJim Ingham case 'n': 392adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 393ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 394ca36cd16SJim Ingham break; 395ca36cd16SJim Ingham 3966fa7681bSZachary Turner case 'N': { 397fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error)) 398adcd0268SBenjamin Kramer m_breakpoint_names.push_back(std::string(option_arg)); 399ff9a91eaSJim Ingham else 400ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 401fe11483bSZachary Turner option_arg.str().c_str()); 4025e09c8c3SJim Ingham break; 4036fa7681bSZachary Turner } 4045e09c8c3SJim Ingham 405b9c1b51eSKate Stone case 'R': { 4062411167fSJim Ingham lldb::addr_t tmp_offset_addr; 40747cbf4a0SPavel Labath tmp_offset_addr = OptionArgParser::ToAddress(execution_context, 40847cbf4a0SPavel Labath option_arg, 0, &error); 4092411167fSJim Ingham if (error.Success()) 4102411167fSJim Ingham m_offset_addr = tmp_offset_addr; 411b9c1b51eSKate Stone } break; 4122411167fSJim Ingham 413a72b31c7SJim Ingham case 'O': 414fe11483bSZachary Turner m_exception_extra_args.AppendArgument("-O"); 415fe11483bSZachary Turner m_exception_extra_args.AppendArgument(option_arg); 416a72b31c7SJim Ingham break; 417a72b31c7SJim Ingham 418ca36cd16SJim Ingham case 'p': 419adcd0268SBenjamin Kramer m_source_text_regexp.assign(std::string(option_arg)); 420ca36cd16SJim Ingham break; 421ca36cd16SJim Ingham 422ca36cd16SJim Ingham case 'r': 423adcd0268SBenjamin Kramer m_func_regexp.assign(std::string(option_arg)); 424ca36cd16SJim Ingham break; 425ca36cd16SJim Ingham 426ca36cd16SJim Ingham case 's': 4278f3be7a3SJonas Devlieghere m_modules.AppendIfUnique(FileSpec(option_arg)); 428ca36cd16SJim Ingham break; 429ca36cd16SJim Ingham 430ca36cd16SJim Ingham case 'S': 431adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 432ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 433ca36cd16SJim Ingham break; 434ca36cd16SJim Ingham 435b9c1b51eSKate Stone case 'w': { 436ca36cd16SJim Ingham bool success; 43747cbf4a0SPavel Labath m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 438ca36cd16SJim Ingham if (!success) 439b9c1b51eSKate Stone error.SetErrorStringWithFormat( 440fe11483bSZachary Turner "Invalid boolean value for on-throw option: '%s'", 441fe11483bSZachary Turner option_arg.str().c_str()); 442b9c1b51eSKate Stone } break; 443ca36cd16SJim Ingham 44476bb8d67SJim Ingham case 'X': 445adcd0268SBenjamin Kramer m_source_regex_func_names.insert(std::string(option_arg)); 44676bb8d67SJim Ingham break; 44776bb8d67SJim Ingham 448bc0a9a17SJim Ingham case 'y': 449bc0a9a17SJim Ingham { 450bc0a9a17SJim Ingham OptionValueFileColonLine value; 451bc0a9a17SJim Ingham Status fcl_err = value.SetValueFromString(option_arg); 452bc0a9a17SJim Ingham if (!fcl_err.Success()) { 453bc0a9a17SJim Ingham error.SetErrorStringWithFormat( 454bc0a9a17SJim Ingham "Invalid value for file:line specifier: %s", 455bc0a9a17SJim Ingham fcl_err.AsCString()); 456bc0a9a17SJim Ingham } else { 457bc0a9a17SJim Ingham m_filenames.AppendIfUnique(value.GetFileSpec()); 458bc0a9a17SJim Ingham m_line_num = value.GetLineNumber(); 459bc0a9a17SJim Ingham m_column = value.GetColumnNumber(); 460bc0a9a17SJim Ingham } 461bc0a9a17SJim Ingham } break; 462bc0a9a17SJim Ingham 46330fdc8d8SChris Lattner default: 46436162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 46530fdc8d8SChris Lattner } 46630fdc8d8SChris Lattner 46730fdc8d8SChris Lattner return error; 46830fdc8d8SChris Lattner } 4699e85e5a8SEugene Zelenko 470b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 47187df91b8SJim Ingham m_filenames.Clear(); 47230fdc8d8SChris Lattner m_line_num = 0; 47330fdc8d8SChris Lattner m_column = 0; 474fab10e89SJim Ingham m_func_names.clear(); 4751f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 47630fdc8d8SChris Lattner m_func_regexp.clear(); 4771f746071SGreg Clayton m_source_text_regexp.clear(); 47887df91b8SJim Ingham m_modules.Clear(); 4791f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 4802411167fSJim Ingham m_offset_addr = 0; 481fab10e89SJim Ingham m_catch_bp = false; 482fab10e89SJim Ingham m_throw_bp = true; 483eb023e75SGreg Clayton m_hardware = false; 484a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 48523b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 486a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 4875e09c8c3SJim Ingham m_breakpoint_names.clear(); 488e732052fSJim Ingham m_all_files = false; 489a72b31c7SJim Ingham m_exception_extra_args.Clear(); 490055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 49176bb8d67SJim Ingham m_source_regex_func_names.clear(); 4923815e702SJim Ingham m_current_key.clear(); 49330fdc8d8SChris Lattner } 49430fdc8d8SChris Lattner 4951f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 49670602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_set_options); 4971f0f5b5bSZachary Turner } 49830fdc8d8SChris Lattner 4995a988416SJim Ingham // Instance variables to hold the values for command options. 500969795f1SJim Ingham 5015a988416SJim Ingham std::string m_condition; 5025a988416SJim Ingham FileSpecList m_filenames; 5035a988416SJim Ingham uint32_t m_line_num; 5045a988416SJim Ingham uint32_t m_column; 5055a988416SJim Ingham std::vector<std::string> m_func_names; 5065e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 507117b1fa1SZachary Turner lldb::FunctionNameType m_func_name_type_mask; 5085a988416SJim Ingham std::string m_func_regexp; 5095a988416SJim Ingham std::string m_source_text_regexp; 5105a988416SJim Ingham FileSpecList m_modules; 5115a988416SJim Ingham lldb::addr_t m_load_addr; 5122411167fSJim Ingham lldb::addr_t m_offset_addr; 5135a988416SJim Ingham bool m_catch_bp; 5145a988416SJim Ingham bool m_throw_bp; 515eb023e75SGreg Clayton bool m_hardware; // Request to use hardware breakpoints 516a72b31c7SJim Ingham lldb::LanguageType m_exception_language; 51723b1decbSDawn Perchik lldb::LanguageType m_language; 5185a988416SJim Ingham LazyBool m_skip_prologue; 519e732052fSJim Ingham bool m_all_files; 520a72b31c7SJim Ingham Args m_exception_extra_args; 521055ad9beSIlia K LazyBool m_move_to_nearest_code; 52276bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 5233815e702SJim Ingham std::string m_current_key; 5245a988416SJim Ingham }; 5255a988416SJim Ingham 5265a988416SJim Ingham protected: 527b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 528cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); 52930fdc8d8SChris Lattner 53030fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 53130fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 53230fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 53330fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 534b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 535b9c1b51eSKate Stone // expression) 536b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 537b9c1b51eSKate Stone // to source text) 538b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 539b9c1b51eSKate Stone // given language.) 54030fdc8d8SChris Lattner 54130fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 54230fdc8d8SChris Lattner 543738af7a6SJim Ingham if (!m_python_class_options.GetName().empty()) 5443815e702SJim Ingham break_type = eSetTypeScripted; 5453815e702SJim Ingham else if (m_options.m_line_num != 0) 54630fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 54730fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 54830fdc8d8SChris Lattner break_type = eSetTypeAddress; 549fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 55030fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 55130fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 55230fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 553969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 554969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 555a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 556fab10e89SJim Ingham break_type = eSetTypeException; 55730fdc8d8SChris Lattner 558b842f2ecSJim Ingham BreakpointSP bp_sp = nullptr; 559274060b6SGreg Clayton FileSpec module_spec; 560a8558b62SJim Ingham const bool internal = false; 561a8558b62SJim Ingham 562b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 563b9c1b51eSKate Stone // that off. 564b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 565b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 5662411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 5672411167fSJim Ingham 568b9c1b51eSKate Stone switch (break_type) { 56930fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 57030fdc8d8SChris Lattner { 57130fdc8d8SChris Lattner FileSpec file; 572c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 573b9c1b51eSKate Stone if (num_files == 0) { 574b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 57587df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 57687df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 57787df91b8SJim Ingham return false; 57887df91b8SJim Ingham } 579b9c1b51eSKate Stone } else if (num_files > 1) { 580b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 581b9c1b51eSKate Stone "line breakpoints."); 58287df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 58387df91b8SJim Ingham return false; 584b9c1b51eSKate Stone } else 58587df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 58630fdc8d8SChris Lattner 5871f746071SGreg Clayton // Only check for inline functions if 5881f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 5891f746071SGreg Clayton 590cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint( 591cb2380c9SRaphael Isemann &(m_options.m_modules), file, m_options.m_line_num, 592cb2380c9SRaphael Isemann m_options.m_column, m_options.m_offset_addr, check_inlines, 593cb2380c9SRaphael Isemann m_options.m_skip_prologue, internal, m_options.m_hardware, 594b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 595b9c1b51eSKate Stone } break; 5966eee5aa0SGreg Clayton 59730fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 598055a08a4SJim Ingham { 599b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 600b842f2ecSJim Ingham // with the library, and use that. That way the address breakpoint 601b842f2ecSJim Ingham // will track the load location of the library. 602055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 603b9c1b51eSKate Stone if (num_modules_specified == 1) { 604b9c1b51eSKate Stone const FileSpec *file_spec = 605b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 606cb2380c9SRaphael Isemann bp_sp = target.CreateAddressInModuleBreakpoint( 607cb2380c9SRaphael Isemann m_options.m_load_addr, internal, file_spec, m_options.m_hardware); 608b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 609cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal, 610b842f2ecSJim Ingham m_options.m_hardware); 611b9c1b51eSKate Stone } else { 612b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 613b9c1b51eSKate Stone "address breakpoints."); 614055a08a4SJim Ingham result.SetStatus(eReturnStatusFailed); 615055a08a4SJim Ingham return false; 616055a08a4SJim Ingham } 61730fdc8d8SChris Lattner break; 618055a08a4SJim Ingham } 61930fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 6200c5cd90dSGreg Clayton { 621117b1fa1SZachary Turner FunctionNameType name_type_mask = m_options.m_func_name_type_mask; 6220c5cd90dSGreg Clayton 6230c5cd90dSGreg Clayton if (name_type_mask == 0) 624e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 6250c5cd90dSGreg Clayton 626cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint( 627cb2380c9SRaphael Isemann &(m_options.m_modules), &(m_options.m_filenames), 628cb2380c9SRaphael Isemann m_options.m_func_names, name_type_mask, m_options.m_language, 629cb2380c9SRaphael Isemann m_options.m_offset_addr, m_options.m_skip_prologue, internal, 630b842f2ecSJim Ingham m_options.m_hardware); 631b9c1b51eSKate Stone } break; 6320c5cd90dSGreg Clayton 633b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 634b9c1b51eSKate Stone // name 63530fdc8d8SChris Lattner { 63695eae423SZachary Turner RegularExpression regexp(m_options.m_func_regexp); 6373af3f1e8SJonas Devlieghere if (llvm::Error err = regexp.GetError()) { 638b9c1b51eSKate Stone result.AppendErrorWithFormat( 639b58af8d2SRaphael Isemann "Function name regular expression could not be compiled: %s", 6403af3f1e8SJonas Devlieghere llvm::toString(std::move(err)).c_str()); 641aaf68cd9SRaphael Isemann // Check if the incorrect regex looks like a globbing expression and 642aaf68cd9SRaphael Isemann // warn the user about it. 643aaf68cd9SRaphael Isemann if (!m_options.m_func_regexp.empty()) { 644aaf68cd9SRaphael Isemann if (m_options.m_func_regexp[0] == '*' || 645aaf68cd9SRaphael Isemann m_options.m_func_regexp[0] == '?') 646aaf68cd9SRaphael Isemann result.AppendWarning( 647aaf68cd9SRaphael Isemann "Function name regex does not accept glob patterns."); 648aaf68cd9SRaphael Isemann } 64930fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 650969795f1SJim Ingham return false; 65130fdc8d8SChris Lattner } 65287df91b8SJim Ingham 653cb2380c9SRaphael Isemann bp_sp = target.CreateFuncRegexBreakpoint( 6545aa1d819SJan Kratochvil &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp), 655cb2380c9SRaphael Isemann m_options.m_language, m_options.m_skip_prologue, internal, 656b842f2ecSJim Ingham m_options.m_hardware); 657a925974bSAdrian Prantl } break; 658969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 659969795f1SJim Ingham { 660c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 66187df91b8SJim Ingham 662b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 663969795f1SJim Ingham FileSpec file; 664b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 665b9c1b51eSKate Stone result.AppendError( 666b9c1b51eSKate Stone "No files provided and could not find default file."); 66787df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 66887df91b8SJim Ingham return false; 669b9c1b51eSKate Stone } else { 67087df91b8SJim Ingham m_options.m_filenames.Append(file); 67187df91b8SJim Ingham } 67287df91b8SJim Ingham } 6730c5cd90dSGreg Clayton 67495eae423SZachary Turner RegularExpression regexp(m_options.m_source_text_regexp); 6753af3f1e8SJonas Devlieghere if (llvm::Error err = regexp.GetError()) { 676b9c1b51eSKate Stone result.AppendErrorWithFormat( 677b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"", 6783af3f1e8SJonas Devlieghere llvm::toString(std::move(err)).c_str()); 679969795f1SJim Ingham result.SetStatus(eReturnStatusFailed); 680969795f1SJim Ingham return false; 681969795f1SJim Ingham } 682cb2380c9SRaphael Isemann bp_sp = target.CreateSourceRegexBreakpoint( 683cb2380c9SRaphael Isemann &(m_options.m_modules), &(m_options.m_filenames), 6845aa1d819SJan Kratochvil m_options.m_source_regex_func_names, std::move(regexp), internal, 685cb2380c9SRaphael Isemann m_options.m_hardware, m_options.m_move_to_nearest_code); 686b9c1b51eSKate Stone } break; 687b9c1b51eSKate Stone case eSetTypeException: { 68897206d57SZachary Turner Status precond_error; 689cb2380c9SRaphael Isemann bp_sp = target.CreateExceptionBreakpoint( 690cb2380c9SRaphael Isemann m_options.m_exception_language, m_options.m_catch_bp, 691cb2380c9SRaphael Isemann m_options.m_throw_bp, internal, &m_options.m_exception_extra_args, 692b842f2ecSJim Ingham &precond_error); 693b9c1b51eSKate Stone if (precond_error.Fail()) { 694b9c1b51eSKate Stone result.AppendErrorWithFormat( 695b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 696a72b31c7SJim Ingham precond_error.AsCString()); 697cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 698a72b31c7SJim Ingham result.SetStatus(eReturnStatusFailed); 699a72b31c7SJim Ingham return false; 700a72b31c7SJim Ingham } 701b9c1b51eSKate Stone } break; 7023815e702SJim Ingham case eSetTypeScripted: { 7033815e702SJim Ingham 7043815e702SJim Ingham Status error; 705cb2380c9SRaphael Isemann bp_sp = target.CreateScriptedBreakpoint( 706738af7a6SJim Ingham m_python_class_options.GetName().c_str(), &(m_options.m_modules), 707cb2380c9SRaphael Isemann &(m_options.m_filenames), false, m_options.m_hardware, 708943a2481SJim Ingham m_python_class_options.GetStructuredData(), &error); 7093815e702SJim Ingham if (error.Fail()) { 7103815e702SJim Ingham result.AppendErrorWithFormat( 711a925974bSAdrian Prantl "Error setting extra exception arguments: %s", error.AsCString()); 712cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 7133815e702SJim Ingham result.SetStatus(eReturnStatusFailed); 7143815e702SJim Ingham return false; 7153815e702SJim Ingham } 7163815e702SJim Ingham } break; 71730fdc8d8SChris Lattner default: 71830fdc8d8SChris Lattner break; 71930fdc8d8SChris Lattner } 72030fdc8d8SChris Lattner 7211b54c88cSJim Ingham // Now set the various options that were passed in: 722b842f2ecSJim Ingham if (bp_sp) { 723b842f2ecSJim Ingham bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 724ca36cd16SJim Ingham 725b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 72697206d57SZachary Turner Status name_error; 727ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) { 728cb2380c9SRaphael Isemann target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error); 729ff9a91eaSJim Ingham if (name_error.Fail()) { 730ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s", 731ff9a91eaSJim Ingham name.c_str()); 732cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 733ff9a91eaSJim Ingham result.SetStatus(eReturnStatusFailed); 734ff9a91eaSJim Ingham return false; 735ff9a91eaSJim Ingham } 736ff9a91eaSJim Ingham } 7375e09c8c3SJim Ingham } 7381b54c88cSJim Ingham } 7391b54c88cSJim Ingham 740b842f2ecSJim Ingham if (bp_sp) { 74185e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 7421391cc7dSJim Ingham const bool show_locations = false; 743b842f2ecSJim Ingham bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 744b9c1b51eSKate Stone show_locations); 745cb2380c9SRaphael Isemann if (&target == &GetDummyTarget()) 746b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 747b9c1b51eSKate Stone "into future targets.\n"); 748b9c1b51eSKate Stone else { 74905097246SAdrian Prantl // Don't print out this warning for exception breakpoints. They can 75005097246SAdrian Prantl // get set before the target is set, but we won't know how to actually 75105097246SAdrian Prantl // set the breakpoint till we run. 752b842f2ecSJim Ingham if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { 753b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 754b9c1b51eSKate Stone "actual locations.\n"); 7554aeb1989SJim Ingham } 7564aeb1989SJim Ingham } 75730fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 758b842f2ecSJim Ingham } else if (!bp_sp) { 75930fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 76030fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 76130fdc8d8SChris Lattner } 76230fdc8d8SChris Lattner 76330fdc8d8SChris Lattner return result.Succeeded(); 76430fdc8d8SChris Lattner } 76530fdc8d8SChris Lattner 7665a988416SJim Ingham private: 767cb2380c9SRaphael Isemann bool GetDefaultFile(Target &target, FileSpec &file, 768b9c1b51eSKate Stone CommandReturnObject &result) { 7695a988416SJim Ingham uint32_t default_line; 77005097246SAdrian Prantl // First use the Source Manager's default file. Then use the current stack 77105097246SAdrian Prantl // frame's file. 772cb2380c9SRaphael Isemann if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 773b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 774b9c1b51eSKate Stone if (cur_frame == nullptr) { 775b9c1b51eSKate Stone result.AppendError( 776b9c1b51eSKate Stone "No selected frame to use to find the default file."); 7775a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 7785a988416SJim Ingham return false; 779b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 780b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 781b9c1b51eSKate Stone "file, it has no debug info."); 7825a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 7835a988416SJim Ingham return false; 784b9c1b51eSKate Stone } else { 785b9c1b51eSKate Stone const SymbolContext &sc = 786b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 787b9c1b51eSKate Stone if (sc.line_entry.file) { 7885a988416SJim Ingham file = sc.line_entry.file; 789b9c1b51eSKate Stone } else { 790b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 791b9c1b51eSKate Stone "use as the default file."); 7925a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 7935a988416SJim Ingham return false; 7945a988416SJim Ingham } 7955a988416SJim Ingham } 7965a988416SJim Ingham } 7975a988416SJim Ingham return true; 7985a988416SJim Ingham } 7995a988416SJim Ingham 800b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 801b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_options; 802943a2481SJim Ingham OptionGroupPythonClassWithDict m_python_class_options; 8035a988416SJim Ingham CommandOptions m_options; 804b842f2ecSJim Ingham OptionGroupOptions m_all_options; 8055a988416SJim Ingham }; 8069e85e5a8SEugene Zelenko 8075a988416SJim Ingham // CommandObjectBreakpointModify 8085a988416SJim Ingham #pragma mark Modify 8095a988416SJim Ingham 810b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 8115a988416SJim Ingham public: 812b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 813b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 814b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 815b9c1b51eSKate Stone "breakpoints in the executable. " 816b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 817b9c1b51eSKate Stone "created breakpoint. " 818b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 819b9c1b51eSKate Stone "empty argument clears the modification.", 8209e85e5a8SEugene Zelenko nullptr), 821b9c1b51eSKate Stone m_options() { 8225a988416SJim Ingham CommandArgumentEntry arg; 823b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 824b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 825b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 826b9c1b51eSKate Stone // arguments vector. 8275a988416SJim Ingham m_arguments.push_back(arg); 828b842f2ecSJim Ingham 829b842f2ecSJim Ingham m_options.Append(&m_bp_opts, 830b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, 831b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 832b842f2ecSJim Ingham m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 833b842f2ecSJim Ingham m_options.Finalize(); 8345a988416SJim Ingham } 8355a988416SJim Ingham 8369e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 8375a988416SJim Ingham 8380e50b9a4SGongyu Deng void 8390e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 8400e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 8410e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 8420e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 8430e50b9a4SGongyu Deng request, nullptr); 8440e50b9a4SGongyu Deng } 8450e50b9a4SGongyu Deng 846b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 8475a988416SJim Ingham 8485a988416SJim Ingham protected: 849b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 850cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 8515a988416SJim Ingham 852bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 853cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 8545a988416SJim Ingham 8555a988416SJim Ingham BreakpointIDList valid_bp_ids; 8565a988416SJim Ingham 857b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 858cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 859b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 8605a988416SJim Ingham 861b9c1b51eSKate Stone if (result.Succeeded()) { 8625a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 863b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 8645a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 8655a988416SJim Ingham 866b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 867b9c1b51eSKate Stone Breakpoint *bp = 868cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 869b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 870b9c1b51eSKate Stone BreakpointLocation *location = 871b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 872b842f2ecSJim Ingham if (location) 873a925974bSAdrian Prantl location->GetLocationOptions()->CopyOverSetOptions( 874a925974bSAdrian Prantl m_bp_opts.GetBreakpointOptions()); 875b9c1b51eSKate Stone } else { 876a925974bSAdrian Prantl bp->GetOptions()->CopyOverSetOptions( 877a925974bSAdrian Prantl m_bp_opts.GetBreakpointOptions()); 8785a988416SJim Ingham } 8795a988416SJim Ingham } 8805a988416SJim Ingham } 8815a988416SJim Ingham } 8825a988416SJim Ingham 8835a988416SJim Ingham return result.Succeeded(); 8845a988416SJim Ingham } 8855a988416SJim Ingham 8865a988416SJim Ingham private: 887b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 888b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_opts; 889b842f2ecSJim Ingham OptionGroupOptions m_options; 8905a988416SJim Ingham }; 8915a988416SJim Ingham 8925a988416SJim Ingham // CommandObjectBreakpointEnable 8935a988416SJim Ingham #pragma mark Enable 8945a988416SJim Ingham 895b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 8965a988416SJim Ingham public: 897b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 898b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 899b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 900b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 901b9c1b51eSKate Stone nullptr) { 9025a988416SJim Ingham CommandArgumentEntry arg; 903b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 904b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 905b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 906b9c1b51eSKate Stone // arguments vector. 9075a988416SJim Ingham m_arguments.push_back(arg); 9085a988416SJim Ingham } 9095a988416SJim Ingham 9109e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 9115a988416SJim Ingham 9120e50b9a4SGongyu Deng void 9130e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 9140e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 9150e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 9160e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 9170e50b9a4SGongyu Deng request, nullptr); 9180e50b9a4SGongyu Deng } 9190e50b9a4SGongyu Deng 9205a988416SJim Ingham protected: 921b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 922cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 9235a988416SJim Ingham 924bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 925cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 9265a988416SJim Ingham 927cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 9285a988416SJim Ingham 9295a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 9305a988416SJim Ingham 931b9c1b51eSKate Stone if (num_breakpoints == 0) { 9325a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 9335a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9345a988416SJim Ingham return false; 9355a988416SJim Ingham } 9365a988416SJim Ingham 93711eb9c64SZachary Turner if (command.empty()) { 9385a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 939cb2380c9SRaphael Isemann target.EnableAllowedBreakpoints(); 940b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 941b9c1b51eSKate Stone " breakpoints)\n", 942b9c1b51eSKate Stone (uint64_t)num_breakpoints); 9435a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 944b9c1b51eSKate Stone } else { 9455a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 9465a988416SJim Ingham BreakpointIDList valid_bp_ids; 947b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 948cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 949b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 9505a988416SJim Ingham 951b9c1b51eSKate Stone if (result.Succeeded()) { 9525a988416SJim Ingham int enable_count = 0; 9535a988416SJim Ingham int loc_count = 0; 9545a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 955b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 9565a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 9575a988416SJim Ingham 958b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 959b9c1b51eSKate Stone Breakpoint *breakpoint = 960cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 961b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 962b9c1b51eSKate Stone BreakpointLocation *location = 963b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 964b9c1b51eSKate Stone if (location) { 9655a988416SJim Ingham location->SetEnabled(true); 9665a988416SJim Ingham ++loc_count; 9675a988416SJim Ingham } 968b9c1b51eSKate Stone } else { 9695a988416SJim Ingham breakpoint->SetEnabled(true); 9705a988416SJim Ingham ++enable_count; 9715a988416SJim Ingham } 9725a988416SJim Ingham } 9735a988416SJim Ingham } 974b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 975b9c1b51eSKate Stone enable_count + loc_count); 9765a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 9775a988416SJim Ingham } 9785a988416SJim Ingham } 9795a988416SJim Ingham 9805a988416SJim Ingham return result.Succeeded(); 9815a988416SJim Ingham } 9825a988416SJim Ingham }; 9835a988416SJim Ingham 9845a988416SJim Ingham // CommandObjectBreakpointDisable 9855a988416SJim Ingham #pragma mark Disable 9865a988416SJim Ingham 987b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 9885a988416SJim Ingham public: 9897428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 990b9c1b51eSKate Stone : CommandObjectParsed( 991b9c1b51eSKate Stone interpreter, "breakpoint disable", 992b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 9937428a18cSKate Stone "them. If none are specified, disable all " 9947428a18cSKate Stone "breakpoints.", 995b9c1b51eSKate Stone nullptr) { 996b9c1b51eSKate Stone SetHelpLong( 997b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 9987428a18cSKate Stone If none are specified, disable all breakpoints." 9997428a18cSKate Stone R"( 1000ea671fbdSKate Stone 10017428a18cSKate Stone )" 10027428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 10037428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 10047428a18cSKate Stone R"( 1005ea671fbdSKate Stone 1006ea671fbdSKate Stone (lldb) break disable 1 1007ea671fbdSKate Stone (lldb) break enable 1.1 1008ea671fbdSKate Stone 1009ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 1010ea671fbdSKate Stone 1011ea671fbdSKate Stone (lldb) break disable 1.* 1012ea671fbdSKate Stone (lldb) break enable 1.1 1013ea671fbdSKate Stone 10147428a18cSKate Stone )" 10157428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 10167428a18cSKate Stone the second re-enables the first location."); 1017b0fac509SJim Ingham 10185a988416SJim Ingham CommandArgumentEntry arg; 1019b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1020b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1021b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1022b9c1b51eSKate Stone // arguments vector. 10235a988416SJim Ingham m_arguments.push_back(arg); 10245a988416SJim Ingham } 10255a988416SJim Ingham 10269e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 10275a988416SJim Ingham 10280e50b9a4SGongyu Deng void 10290e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 10300e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 10310e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 10320e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 10330e50b9a4SGongyu Deng request, nullptr); 10340e50b9a4SGongyu Deng } 10350e50b9a4SGongyu Deng 10365a988416SJim Ingham protected: 1037b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1038cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 1039bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1040cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 10415a988416SJim Ingham 1042cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 10435a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 10445a988416SJim Ingham 1045b9c1b51eSKate Stone if (num_breakpoints == 0) { 10465a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 10475a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10485a988416SJim Ingham return false; 10495a988416SJim Ingham } 10505a988416SJim Ingham 105111eb9c64SZachary Turner if (command.empty()) { 10525a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 1053cb2380c9SRaphael Isemann target.DisableAllowedBreakpoints(); 1054b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1055b9c1b51eSKate Stone " breakpoints)\n", 1056b9c1b51eSKate Stone (uint64_t)num_breakpoints); 10575a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1058b9c1b51eSKate Stone } else { 10595a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 10605a988416SJim Ingham BreakpointIDList valid_bp_ids; 10615a988416SJim Ingham 1062b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1063cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1064b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 10655a988416SJim Ingham 1066b9c1b51eSKate Stone if (result.Succeeded()) { 10675a988416SJim Ingham int disable_count = 0; 10685a988416SJim Ingham int loc_count = 0; 10695a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1070b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 10715a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 10725a988416SJim Ingham 1073b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1074b9c1b51eSKate Stone Breakpoint *breakpoint = 1075cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1076b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1077b9c1b51eSKate Stone BreakpointLocation *location = 1078b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1079b9c1b51eSKate Stone if (location) { 10805a988416SJim Ingham location->SetEnabled(false); 10815a988416SJim Ingham ++loc_count; 10825a988416SJim Ingham } 1083b9c1b51eSKate Stone } else { 10845a988416SJim Ingham breakpoint->SetEnabled(false); 10855a988416SJim Ingham ++disable_count; 10865a988416SJim Ingham } 10875a988416SJim Ingham } 10885a988416SJim Ingham } 1089b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1090b9c1b51eSKate Stone disable_count + loc_count); 10915a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 10925a988416SJim Ingham } 10935a988416SJim Ingham } 10945a988416SJim Ingham 10955a988416SJim Ingham return result.Succeeded(); 10965a988416SJim Ingham } 10975a988416SJim Ingham }; 10985a988416SJim Ingham 10995a988416SJim Ingham // CommandObjectBreakpointList 11001f0f5b5bSZachary Turner 11011f0f5b5bSZachary Turner #pragma mark List::CommandOptions 11026f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list 1103c5a2d747SRaphael Isemann #include "CommandOptions.inc" 11041f0f5b5bSZachary Turner 11055a988416SJim Ingham #pragma mark List 11065a988416SJim Ingham 1107b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 11085a988416SJim Ingham public: 1109b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1110b9c1b51eSKate Stone : CommandObjectParsed( 1111b9c1b51eSKate Stone interpreter, "breakpoint list", 11125a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 11139e85e5a8SEugene Zelenko nullptr), 1114b9c1b51eSKate Stone m_options() { 11155a988416SJim Ingham CommandArgumentEntry arg; 11165a988416SJim Ingham CommandArgumentData bp_id_arg; 11175a988416SJim Ingham 11185a988416SJim Ingham // Define the first (and only) variant of this arg. 11195a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 11205a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 11215a988416SJim Ingham 1122b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1123b9c1b51eSKate Stone // argument entry. 11245a988416SJim Ingham arg.push_back(bp_id_arg); 11255a988416SJim Ingham 11265a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 11275a988416SJim Ingham m_arguments.push_back(arg); 11285a988416SJim Ingham } 11295a988416SJim Ingham 11309e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 11315a988416SJim Ingham 1132b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 11335a988416SJim Ingham 1134b9c1b51eSKate Stone class CommandOptions : public Options { 11355a988416SJim Ingham public: 1136b9c1b51eSKate Stone CommandOptions() 1137b9c1b51eSKate Stone : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 11385a988416SJim Ingham } 11395a988416SJim Ingham 11409e85e5a8SEugene Zelenko ~CommandOptions() override = default; 11415a988416SJim Ingham 114297206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1143b9c1b51eSKate Stone ExecutionContext *execution_context) override { 114497206d57SZachary Turner Status error; 11453bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 11465a988416SJim Ingham 1147b9c1b51eSKate Stone switch (short_option) { 11485a988416SJim Ingham case 'b': 11495a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 11505a988416SJim Ingham break; 115133df7cd3SJim Ingham case 'D': 115233df7cd3SJim Ingham m_use_dummy = true; 115333df7cd3SJim Ingham break; 11545a988416SJim Ingham case 'f': 11555a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 11565a988416SJim Ingham break; 11575a988416SJim Ingham case 'v': 11585a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 11595a988416SJim Ingham break; 11605a988416SJim Ingham case 'i': 11615a988416SJim Ingham m_internal = true; 11625a988416SJim Ingham break; 11635a988416SJim Ingham default: 116436162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 11655a988416SJim Ingham } 11665a988416SJim Ingham 11675a988416SJim Ingham return error; 11685a988416SJim Ingham } 11695a988416SJim Ingham 1170b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 11715a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 11725a988416SJim Ingham m_internal = false; 117333df7cd3SJim Ingham m_use_dummy = false; 11745a988416SJim Ingham } 11755a988416SJim Ingham 11761f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 117770602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_list_options); 11781f0f5b5bSZachary Turner } 11795a988416SJim Ingham 11805a988416SJim Ingham // Instance variables to hold the values for command options. 11815a988416SJim Ingham 11825a988416SJim Ingham lldb::DescriptionLevel m_level; 11835a988416SJim Ingham 11845a988416SJim Ingham bool m_internal; 118533df7cd3SJim Ingham bool m_use_dummy; 11865a988416SJim Ingham }; 11875a988416SJim Ingham 11885a988416SJim Ingham protected: 1189b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1190cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 11915a988416SJim Ingham 1192b9c1b51eSKate Stone const BreakpointList &breakpoints = 1193cb2380c9SRaphael Isemann target.GetBreakpointList(m_options.m_internal); 1194bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1195cb2380c9SRaphael Isemann target.GetBreakpointList(m_options.m_internal).GetListMutex(lock); 11965a988416SJim Ingham 11975a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 11985a988416SJim Ingham 1199b9c1b51eSKate Stone if (num_breakpoints == 0) { 12005a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 12015a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 12025a988416SJim Ingham return true; 12035a988416SJim Ingham } 12045a988416SJim Ingham 12055a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 12065a988416SJim Ingham 120711eb9c64SZachary Turner if (command.empty()) { 12085a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 12095a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1210b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 12115a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1212b842f2ecSJim Ingham if (breakpoint->AllowList()) 1213b842f2ecSJim Ingham AddBreakpointDescription(&output_stream, breakpoint, 1214b842f2ecSJim Ingham m_options.m_level); 12155a988416SJim Ingham } 12165a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1217b9c1b51eSKate Stone } else { 12185a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 12195a988416SJim Ingham BreakpointIDList valid_bp_ids; 1220b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1221cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1222b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 12235a988416SJim Ingham 1224b9c1b51eSKate Stone if (result.Succeeded()) { 1225b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 12265a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1227b9c1b51eSKate Stone Breakpoint *breakpoint = 1228cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1229b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1230b9c1b51eSKate Stone m_options.m_level); 12315a988416SJim Ingham } 12325a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1233b9c1b51eSKate Stone } else { 12347428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 12355a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 12365a988416SJim Ingham } 12375a988416SJim Ingham } 12385a988416SJim Ingham 12395a988416SJim Ingham return result.Succeeded(); 12405a988416SJim Ingham } 12415a988416SJim Ingham 12425a988416SJim Ingham private: 12435a988416SJim Ingham CommandOptions m_options; 12445a988416SJim Ingham }; 12455a988416SJim Ingham 12465a988416SJim Ingham // CommandObjectBreakpointClear 12471f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions 12481f0f5b5bSZachary Turner 1249f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear 1250f94668e3SRaphael Isemann #include "CommandOptions.inc" 12511f0f5b5bSZachary Turner 12525a988416SJim Ingham #pragma mark Clear 12535a988416SJim Ingham 1254b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed { 12555a988416SJim Ingham public: 1256efe8e7e3SFangrui Song enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine }; 12575a988416SJim Ingham 12587428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter) 12597428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear", 1260b9c1b51eSKate Stone "Delete or disable breakpoints matching the " 1261b9c1b51eSKate Stone "specified source file and line.", 12625a988416SJim Ingham "breakpoint clear <cmd-options>"), 1263b9c1b51eSKate Stone m_options() {} 12645a988416SJim Ingham 12659e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default; 12665a988416SJim Ingham 1267b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 12685a988416SJim Ingham 1269b9c1b51eSKate Stone class CommandOptions : public Options { 12705a988416SJim Ingham public: 1271b9c1b51eSKate Stone CommandOptions() : Options(), m_filename(), m_line_num(0) {} 12725a988416SJim Ingham 12739e85e5a8SEugene Zelenko ~CommandOptions() override = default; 12745a988416SJim Ingham 127597206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1276b9c1b51eSKate Stone ExecutionContext *execution_context) override { 127797206d57SZachary Turner Status error; 12783bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 12795a988416SJim Ingham 1280b9c1b51eSKate Stone switch (short_option) { 12815a988416SJim Ingham case 'f': 1282adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 12835a988416SJim Ingham break; 12845a988416SJim Ingham 12855a988416SJim Ingham case 'l': 1286fe11483bSZachary Turner option_arg.getAsInteger(0, m_line_num); 12875a988416SJim Ingham break; 12885a988416SJim Ingham 12895a988416SJim Ingham default: 129036162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 12915a988416SJim Ingham } 12925a988416SJim Ingham 12935a988416SJim Ingham return error; 12945a988416SJim Ingham } 12955a988416SJim Ingham 1296b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 12975a988416SJim Ingham m_filename.clear(); 12985a988416SJim Ingham m_line_num = 0; 12995a988416SJim Ingham } 13005a988416SJim Ingham 13011f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 130270602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_clear_options); 13031f0f5b5bSZachary Turner } 13045a988416SJim Ingham 13055a988416SJim Ingham // Instance variables to hold the values for command options. 13065a988416SJim Ingham 13075a988416SJim Ingham std::string m_filename; 13085a988416SJim Ingham uint32_t m_line_num; 13095a988416SJim Ingham }; 13105a988416SJim Ingham 13115a988416SJim Ingham protected: 1312b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1313cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 13145a988416SJim Ingham 131505097246SAdrian Prantl // The following are the various types of breakpoints that could be 131605097246SAdrian Prantl // cleared: 13175a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 13185a988416SJim Ingham 13195a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 13205a988416SJim Ingham 13215a988416SJim Ingham if (m_options.m_line_num != 0) 13225a988416SJim Ingham break_type = eClearTypeFileAndLine; 13235a988416SJim Ingham 1324bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1325cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 13265a988416SJim Ingham 1327cb2380c9SRaphael Isemann BreakpointList &breakpoints = target.GetBreakpointList(); 13285a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 13295a988416SJim Ingham 13305a988416SJim Ingham // Early return if there's no breakpoint at all. 1331b9c1b51eSKate Stone if (num_breakpoints == 0) { 13325a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 13335a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 13345a988416SJim Ingham return result.Succeeded(); 13355a988416SJim Ingham } 13365a988416SJim Ingham 13375a988416SJim Ingham // Find matching breakpoints and delete them. 13385a988416SJim Ingham 13395a988416SJim Ingham // First create a copy of all the IDs. 13405a988416SJim Ingham std::vector<break_id_t> BreakIDs; 13415a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 13429e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 13435a988416SJim Ingham 13445a988416SJim Ingham int num_cleared = 0; 13455a988416SJim Ingham StreamString ss; 1346b9c1b51eSKate Stone switch (break_type) { 13475a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 13485a988416SJim Ingham { 13495a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 13505a988416SJim Ingham BreakpointLocationCollection loc_coll; 13515a988416SJim Ingham 1352b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 13535a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 13545a988416SJim Ingham 1355b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1356b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1357b9c1b51eSKate Stone // remove the breakpoint. 1358b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 13595a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 13605a988416SJim Ingham ss.EOL(); 1361cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp->GetID()); 13625a988416SJim Ingham ++num_cleared; 13635a988416SJim Ingham } 13645a988416SJim Ingham } 13655a988416SJim Ingham } 1366b9c1b51eSKate Stone } break; 13675a988416SJim Ingham 13685a988416SJim Ingham default: 13695a988416SJim Ingham break; 13705a988416SJim Ingham } 13715a988416SJim Ingham 1372b9c1b51eSKate Stone if (num_cleared > 0) { 13735a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 13745a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1375c156427dSZachary Turner output_stream << ss.GetString(); 13765a988416SJim Ingham output_stream.EOL(); 13775a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1378b9c1b51eSKate Stone } else { 13795a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 13805a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 13815a988416SJim Ingham } 13825a988416SJim Ingham 13835a988416SJim Ingham return result.Succeeded(); 13845a988416SJim Ingham } 13855a988416SJim Ingham 13865a988416SJim Ingham private: 13875a988416SJim Ingham CommandOptions m_options; 13885a988416SJim Ingham }; 13895a988416SJim Ingham 13905a988416SJim Ingham // CommandObjectBreakpointDelete 1391f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete 1392f94668e3SRaphael Isemann #include "CommandOptions.inc" 13931f0f5b5bSZachary Turner 13945a988416SJim Ingham #pragma mark Delete 13955a988416SJim Ingham 1396b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 13975a988416SJim Ingham public: 1398b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1399b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1400b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1401b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 14029e85e5a8SEugene Zelenko nullptr), 1403b9c1b51eSKate Stone m_options() { 14045a988416SJim Ingham CommandArgumentEntry arg; 1405b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1406b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1407b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1408b9c1b51eSKate Stone // arguments vector. 14095a988416SJim Ingham m_arguments.push_back(arg); 14105a988416SJim Ingham } 14115a988416SJim Ingham 14129e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 14135a988416SJim Ingham 14140e50b9a4SGongyu Deng void 14150e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 14160e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 14170e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 14180e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 14190e50b9a4SGongyu Deng request, nullptr); 14200e50b9a4SGongyu Deng } 14210e50b9a4SGongyu Deng 1422b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 142333df7cd3SJim Ingham 1424b9c1b51eSKate Stone class CommandOptions : public Options { 142533df7cd3SJim Ingham public: 1426*3726ac41SJim Ingham CommandOptions() : Options(), m_use_dummy(false), m_force(false), 1427*3726ac41SJim Ingham m_delete_disabled(false) {} 142833df7cd3SJim Ingham 14299e85e5a8SEugene Zelenko ~CommandOptions() override = default; 143033df7cd3SJim Ingham 143197206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1432b9c1b51eSKate Stone ExecutionContext *execution_context) override { 143397206d57SZachary Turner Status error; 143433df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 143533df7cd3SJim Ingham 1436b9c1b51eSKate Stone switch (short_option) { 143733df7cd3SJim Ingham case 'f': 143833df7cd3SJim Ingham m_force = true; 143933df7cd3SJim Ingham break; 144033df7cd3SJim Ingham 144133df7cd3SJim Ingham case 'D': 144233df7cd3SJim Ingham m_use_dummy = true; 144333df7cd3SJim Ingham break; 144433df7cd3SJim Ingham 1445*3726ac41SJim Ingham case 'd': 1446*3726ac41SJim Ingham m_delete_disabled = true; 1447*3726ac41SJim Ingham break; 1448*3726ac41SJim Ingham 144933df7cd3SJim Ingham default: 145036162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 145133df7cd3SJim Ingham } 145233df7cd3SJim Ingham 145333df7cd3SJim Ingham return error; 145433df7cd3SJim Ingham } 145533df7cd3SJim Ingham 1456b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 145733df7cd3SJim Ingham m_use_dummy = false; 145833df7cd3SJim Ingham m_force = false; 1459*3726ac41SJim Ingham m_delete_disabled = false; 146033df7cd3SJim Ingham } 146133df7cd3SJim Ingham 14621f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 146370602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_delete_options); 14641f0f5b5bSZachary Turner } 146533df7cd3SJim Ingham 146633df7cd3SJim Ingham // Instance variables to hold the values for command options. 146733df7cd3SJim Ingham bool m_use_dummy; 146833df7cd3SJim Ingham bool m_force; 1469*3726ac41SJim Ingham bool m_delete_disabled; 147033df7cd3SJim Ingham }; 147133df7cd3SJim Ingham 14725a988416SJim Ingham protected: 1473b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1474cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1475*3726ac41SJim Ingham result.Clear(); 14765a988416SJim Ingham 1477bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1478cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 14795a988416SJim Ingham 1480*3726ac41SJim Ingham BreakpointList &breakpoints = target.GetBreakpointList(); 14815a988416SJim Ingham 14825a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 14835a988416SJim Ingham 1484b9c1b51eSKate Stone if (num_breakpoints == 0) { 14855a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 14865a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14875a988416SJim Ingham return false; 14885a988416SJim Ingham } 14895a988416SJim Ingham 1490*3726ac41SJim Ingham if (command.empty() && !m_options.m_delete_disabled) { 1491b9c1b51eSKate Stone if (!m_options.m_force && 1492b9c1b51eSKate Stone !m_interpreter.Confirm( 1493b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1494b9c1b51eSKate Stone true)) { 14955a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1496b9c1b51eSKate Stone } else { 1497cb2380c9SRaphael Isemann target.RemoveAllowedBreakpoints(); 1498b9c1b51eSKate Stone result.AppendMessageWithFormat( 1499b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1500b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 15015a988416SJim Ingham } 15025a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1503b9c1b51eSKate Stone } else { 15045a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 15055a988416SJim Ingham BreakpointIDList valid_bp_ids; 1506*3726ac41SJim Ingham 1507*3726ac41SJim Ingham if (m_options.m_delete_disabled) { 1508*3726ac41SJim Ingham BreakpointIDList excluded_bp_ids; 1509*3726ac41SJim Ingham 1510*3726ac41SJim Ingham if (!command.empty()) { 1511*3726ac41SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1512*3726ac41SJim Ingham command, &target, result, &excluded_bp_ids, 1513*3726ac41SJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 1514*3726ac41SJim Ingham } 1515*3726ac41SJim Ingham for (auto breakpoint_sp : breakpoints.Breakpoints()) { 1516*3726ac41SJim Ingham if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) { 1517*3726ac41SJim Ingham BreakpointID bp_id(breakpoint_sp->GetID()); 1518*3726ac41SJim Ingham size_t pos = 0; 1519*3726ac41SJim Ingham if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos)) 1520*3726ac41SJim Ingham valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID()); 1521*3726ac41SJim Ingham } 1522*3726ac41SJim Ingham } 1523*3726ac41SJim Ingham if (valid_bp_ids.GetSize() == 0) { 1524*3726ac41SJim Ingham result.AppendError("No disabled breakpoints."); 1525*3726ac41SJim Ingham result.SetStatus(eReturnStatusFailed); 1526*3726ac41SJim Ingham return false; 1527*3726ac41SJim Ingham } 1528*3726ac41SJim Ingham } else { 1529b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1530cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1531b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 1532*3726ac41SJim Ingham } 15335a988416SJim Ingham 1534b9c1b51eSKate Stone if (result.Succeeded()) { 15355a988416SJim Ingham int delete_count = 0; 15365a988416SJim Ingham int disable_count = 0; 15375a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1538b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 15395a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 15405a988416SJim Ingham 1541b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1542b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1543b9c1b51eSKate Stone Breakpoint *breakpoint = 1544cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1545b9c1b51eSKate Stone BreakpointLocation *location = 1546b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1547b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1548b9c1b51eSKate Stone // disable them instead. 1549b9c1b51eSKate Stone if (location) { 15505a988416SJim Ingham location->SetEnabled(false); 15515a988416SJim Ingham ++disable_count; 15525a988416SJim Ingham } 1553b9c1b51eSKate Stone } else { 1554cb2380c9SRaphael Isemann target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 15555a988416SJim Ingham ++delete_count; 15565a988416SJim Ingham } 15575a988416SJim Ingham } 15585a988416SJim Ingham } 1559b9c1b51eSKate Stone result.AppendMessageWithFormat( 1560b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 15615a988416SJim Ingham delete_count, disable_count); 15625a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 15635a988416SJim Ingham } 15645a988416SJim Ingham } 15655a988416SJim Ingham return result.Succeeded(); 15665a988416SJim Ingham } 15679e85e5a8SEugene Zelenko 156833df7cd3SJim Ingham private: 156933df7cd3SJim Ingham CommandOptions m_options; 157033df7cd3SJim Ingham }; 157133df7cd3SJim Ingham 15725e09c8c3SJim Ingham // CommandObjectBreakpointName 1573f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name 1574f94668e3SRaphael Isemann #include "CommandOptions.inc" 1575bd68a052SRaphael Isemann 1576b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 15775e09c8c3SJim Ingham public: 1578b9c1b51eSKate Stone BreakpointNameOptionGroup() 1579b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 15805e09c8c3SJim Ingham } 15815e09c8c3SJim Ingham 15829e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 15835e09c8c3SJim Ingham 15841f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 158570602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_name_options); 15865e09c8c3SJim Ingham } 15875e09c8c3SJim Ingham 158897206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1589b9c1b51eSKate Stone ExecutionContext *execution_context) override { 159097206d57SZachary Turner Status error; 15915e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 15925e09c8c3SJim Ingham 1593b9c1b51eSKate Stone switch (short_option) { 15945e09c8c3SJim Ingham case 'N': 1595fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1596b9c1b51eSKate Stone error.Success()) 1597fe11483bSZachary Turner m_name.SetValueFromString(option_arg); 15985e09c8c3SJim Ingham break; 15995e09c8c3SJim Ingham case 'B': 1600fe11483bSZachary Turner if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1601b9c1b51eSKate Stone error.SetErrorStringWithFormat( 16028cef4b0bSZachary Turner "unrecognized value \"%s\" for breakpoint", 1603fe11483bSZachary Turner option_arg.str().c_str()); 16045e09c8c3SJim Ingham break; 16055e09c8c3SJim Ingham case 'D': 1606fe11483bSZachary Turner if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1607b9c1b51eSKate Stone error.SetErrorStringWithFormat( 16088cef4b0bSZachary Turner "unrecognized value \"%s\" for use-dummy", 1609fe11483bSZachary Turner option_arg.str().c_str()); 16105e09c8c3SJim Ingham break; 1611e9632ebaSJim Ingham case 'H': 1612e9632ebaSJim Ingham m_help_string.SetValueFromString(option_arg); 1613e9632ebaSJim Ingham break; 16145e09c8c3SJim Ingham 16155e09c8c3SJim Ingham default: 161636162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 16175e09c8c3SJim Ingham } 16185e09c8c3SJim Ingham return error; 16195e09c8c3SJim Ingham } 16205e09c8c3SJim Ingham 1621b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 16225e09c8c3SJim Ingham m_name.Clear(); 16235e09c8c3SJim Ingham m_breakpoint.Clear(); 16245e09c8c3SJim Ingham m_use_dummy.Clear(); 16255e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 1626e9632ebaSJim Ingham m_help_string.Clear(); 16275e09c8c3SJim Ingham } 16285e09c8c3SJim Ingham 16295e09c8c3SJim Ingham OptionValueString m_name; 16305e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 16315e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 1632e9632ebaSJim Ingham OptionValueString m_help_string; 16335e09c8c3SJim Ingham }; 16345e09c8c3SJim Ingham 1635f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access 1636f94668e3SRaphael Isemann #include "CommandOptions.inc" 1637b842f2ecSJim Ingham 16388fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup { 1639b842f2ecSJim Ingham public: 16408fe53c49STatyana Krasnukha BreakpointAccessOptionGroup() : OptionGroup() {} 1641b842f2ecSJim Ingham 1642b842f2ecSJim Ingham ~BreakpointAccessOptionGroup() override = default; 1643b842f2ecSJim Ingham 1644b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1645b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_access_options); 1646b842f2ecSJim Ingham } 1647b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1648b842f2ecSJim Ingham ExecutionContext *execution_context) override { 1649b842f2ecSJim Ingham Status error; 1650a925974bSAdrian Prantl const int short_option = 1651a925974bSAdrian Prantl g_breakpoint_access_options[option_idx].short_option; 1652b842f2ecSJim Ingham 1653b842f2ecSJim Ingham switch (short_option) { 1654b842f2ecSJim Ingham case 'L': { 1655b842f2ecSJim Ingham bool value, success; 165647cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1657b842f2ecSJim Ingham if (success) { 1658b842f2ecSJim Ingham m_permissions.SetAllowList(value); 1659b842f2ecSJim Ingham } else 1660b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1661b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1662b842f2ecSJim Ingham option_arg.str().c_str()); 1663b842f2ecSJim Ingham } break; 1664b842f2ecSJim Ingham case 'A': { 1665b842f2ecSJim Ingham bool value, success; 166647cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1667b842f2ecSJim Ingham if (success) { 1668b842f2ecSJim Ingham m_permissions.SetAllowDisable(value); 1669b842f2ecSJim Ingham } else 1670b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1671b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1672b842f2ecSJim Ingham option_arg.str().c_str()); 1673b842f2ecSJim Ingham } break; 1674b842f2ecSJim Ingham case 'D': { 1675b842f2ecSJim Ingham bool value, success; 167647cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1677b842f2ecSJim Ingham if (success) { 1678b842f2ecSJim Ingham m_permissions.SetAllowDelete(value); 1679b842f2ecSJim Ingham } else 1680b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1681b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1682b842f2ecSJim Ingham option_arg.str().c_str()); 1683b842f2ecSJim Ingham } break; 168436162014SRaphael Isemann default: 168536162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 1686b842f2ecSJim Ingham } 1687b842f2ecSJim Ingham 1688b842f2ecSJim Ingham return error; 1689b842f2ecSJim Ingham } 1690b842f2ecSJim Ingham 1691a925974bSAdrian Prantl void OptionParsingStarting(ExecutionContext *execution_context) override {} 1692b842f2ecSJim Ingham 1693a925974bSAdrian Prantl const BreakpointName::Permissions &GetPermissions() const { 1694b842f2ecSJim Ingham return m_permissions; 1695b842f2ecSJim Ingham } 1696b842f2ecSJim Ingham BreakpointName::Permissions m_permissions; 1697b842f2ecSJim Ingham }; 1698b842f2ecSJim Ingham 1699b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1700b842f2ecSJim Ingham public: 1701b842f2ecSJim Ingham CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1702b842f2ecSJim Ingham : CommandObjectParsed( 1703a925974bSAdrian Prantl interpreter, "configure", 1704a925974bSAdrian Prantl "Configure the options for the breakpoint" 1705b842f2ecSJim Ingham " name provided. " 1706b842f2ecSJim Ingham "If you provide a breakpoint id, the options will be copied from " 1707b842f2ecSJim Ingham "the breakpoint, otherwise only the options specified will be set " 1708b842f2ecSJim Ingham "on the name.", 1709b842f2ecSJim Ingham "breakpoint name configure <command-options> " 1710b842f2ecSJim Ingham "<breakpoint-name-list>"), 1711b842f2ecSJim Ingham m_bp_opts(), m_option_group() { 1712b842f2ecSJim Ingham // Create the first variant for the first (and only) argument for this 1713b842f2ecSJim Ingham // command. 1714b842f2ecSJim Ingham CommandArgumentEntry arg1; 1715b842f2ecSJim Ingham CommandArgumentData id_arg; 1716b842f2ecSJim Ingham id_arg.arg_type = eArgTypeBreakpointName; 1717b842f2ecSJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 1718b842f2ecSJim Ingham arg1.push_back(id_arg); 1719b842f2ecSJim Ingham m_arguments.push_back(arg1); 1720b842f2ecSJim Ingham 1721a925974bSAdrian Prantl m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1722a925974bSAdrian Prantl m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL, 1723b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 1724a925974bSAdrian Prantl m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4, 1725e9632ebaSJim Ingham LLDB_OPT_SET_ALL); 1726b842f2ecSJim Ingham m_option_group.Finalize(); 1727b842f2ecSJim Ingham } 1728b842f2ecSJim Ingham 1729b842f2ecSJim Ingham ~CommandObjectBreakpointNameConfigure() override = default; 1730b842f2ecSJim Ingham 1731b842f2ecSJim Ingham Options *GetOptions() override { return &m_option_group; } 1732b842f2ecSJim Ingham 1733b842f2ecSJim Ingham protected: 1734b842f2ecSJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 1735b842f2ecSJim Ingham 1736b842f2ecSJim Ingham const size_t argc = command.GetArgumentCount(); 1737b842f2ecSJim Ingham if (argc == 0) { 1738b842f2ecSJim Ingham result.AppendError("No names provided."); 1739b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1740b842f2ecSJim Ingham return false; 1741b842f2ecSJim Ingham } 1742b842f2ecSJim Ingham 1743cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(false); 1744b842f2ecSJim Ingham 1745b842f2ecSJim Ingham std::unique_lock<std::recursive_mutex> lock; 1746cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 1747b842f2ecSJim Ingham 1748b842f2ecSJim Ingham // Make a pass through first to see that all the names are legal. 1749b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1750b842f2ecSJim Ingham Status error; 1751a925974bSAdrian Prantl if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) { 1752b842f2ecSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1753b842f2ecSJim Ingham entry.c_str(), error.AsCString()); 1754b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1755b842f2ecSJim Ingham return false; 1756b842f2ecSJim Ingham } 1757b842f2ecSJim Ingham } 175805097246SAdrian Prantl // Now configure them, we already pre-checked the names so we don't need to 175905097246SAdrian Prantl // check the error: 1760b842f2ecSJim Ingham BreakpointSP bp_sp; 1761a925974bSAdrian Prantl if (m_bp_id.m_breakpoint.OptionWasSet()) { 1762b842f2ecSJim Ingham lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1763cb2380c9SRaphael Isemann bp_sp = target.GetBreakpointByID(bp_id); 1764a925974bSAdrian Prantl if (!bp_sp) { 1765b842f2ecSJim Ingham result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1766b842f2ecSJim Ingham bp_id); 1767b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1768b842f2ecSJim Ingham return false; 1769b842f2ecSJim Ingham } 1770b842f2ecSJim Ingham } 1771b842f2ecSJim Ingham 1772b842f2ecSJim Ingham Status error; 1773b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1774b842f2ecSJim Ingham ConstString name(entry.c_str()); 1775cb2380c9SRaphael Isemann BreakpointName *bp_name = target.FindBreakpointName(name, true, error); 1776b842f2ecSJim Ingham if (!bp_name) 1777b842f2ecSJim Ingham continue; 1778e9632ebaSJim Ingham if (m_bp_id.m_help_string.OptionWasSet()) 1779e9632ebaSJim Ingham bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1780e9632ebaSJim Ingham 1781b842f2ecSJim Ingham if (bp_sp) 1782cb2380c9SRaphael Isemann target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(), 1783b842f2ecSJim Ingham m_access_options.GetPermissions()); 1784b842f2ecSJim Ingham else 1785cb2380c9SRaphael Isemann target.ConfigureBreakpointName(*bp_name, 1786b842f2ecSJim Ingham m_bp_opts.GetBreakpointOptions(), 1787b842f2ecSJim Ingham m_access_options.GetPermissions()); 1788b842f2ecSJim Ingham } 1789b842f2ecSJim Ingham return true; 1790b842f2ecSJim Ingham } 1791b842f2ecSJim Ingham 1792b842f2ecSJim Ingham private: 1793b842f2ecSJim Ingham BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1794b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 1795b842f2ecSJim Ingham BreakpointAccessOptionGroup m_access_options; 1796b842f2ecSJim Ingham OptionGroupOptions m_option_group; 1797b842f2ecSJim Ingham }; 1798b842f2ecSJim Ingham 1799b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 18005e09c8c3SJim Ingham public: 1801b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1802b9c1b51eSKate Stone : CommandObjectParsed( 1803b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 18045e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 1805b9c1b51eSKate Stone m_name_options(), m_option_group() { 1806b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1807b9c1b51eSKate Stone // command. 18085e09c8c3SJim Ingham CommandArgumentEntry arg1; 18095e09c8c3SJim Ingham CommandArgumentData id_arg; 18105e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 18115e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 18125e09c8c3SJim Ingham arg1.push_back(id_arg); 18135e09c8c3SJim Ingham m_arguments.push_back(arg1); 18145e09c8c3SJim Ingham 18155e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 18165e09c8c3SJim Ingham m_option_group.Finalize(); 18175e09c8c3SJim Ingham } 18185e09c8c3SJim Ingham 18199e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 18205e09c8c3SJim Ingham 1821e87362e6SGongyu Deng void 1822e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 1823e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 1824e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 1825e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 1826e87362e6SGongyu Deng request, nullptr); 1827e87362e6SGongyu Deng } 1828e87362e6SGongyu Deng 1829b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 18305e09c8c3SJim Ingham 18315e09c8c3SJim Ingham protected: 1832b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1833b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 18345e09c8c3SJim Ingham result.SetError("No name option provided."); 18355e09c8c3SJim Ingham return false; 18365e09c8c3SJim Ingham } 18375e09c8c3SJim Ingham 1838cb2380c9SRaphael Isemann Target &target = 1839b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 18405e09c8c3SJim Ingham 1841bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1842cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 18435e09c8c3SJim Ingham 1844cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 18455e09c8c3SJim Ingham 18465e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1847b9c1b51eSKate Stone if (num_breakpoints == 0) { 18485e09c8c3SJim Ingham result.SetError("No breakpoints, cannot add names."); 18495e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18505e09c8c3SJim Ingham return false; 18515e09c8c3SJim Ingham } 18525e09c8c3SJim Ingham 18535e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 18545e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1855b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1856cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1857b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 18585e09c8c3SJim Ingham 1859b9c1b51eSKate Stone if (result.Succeeded()) { 1860b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 18615e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot add names."); 18625e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18635e09c8c3SJim Ingham return false; 18645e09c8c3SJim Ingham } 18655e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1866b842f2ecSJim Ingham const char *bp_name = m_name_options.m_name.GetCurrentValue(); 1867b842f2ecSJim Ingham Status error; // This error reports illegal names, but we've already 1868b842f2ecSJim Ingham // checked that, so we don't need to check it again here. 1869b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1870b9c1b51eSKate Stone lldb::break_id_t bp_id = 1871b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 18725e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1873cb2380c9SRaphael Isemann target.AddNameToBreakpoint(bp_sp, bp_name, error); 18745e09c8c3SJim Ingham } 18755e09c8c3SJim Ingham } 18765e09c8c3SJim Ingham 18775e09c8c3SJim Ingham return true; 18785e09c8c3SJim Ingham } 18795e09c8c3SJim Ingham 18805e09c8c3SJim Ingham private: 18815e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 18825e09c8c3SJim Ingham OptionGroupOptions m_option_group; 18835e09c8c3SJim Ingham }; 18845e09c8c3SJim Ingham 1885b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 18865e09c8c3SJim Ingham public: 1887b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1888b9c1b51eSKate Stone : CommandObjectParsed( 1889b9c1b51eSKate Stone interpreter, "delete", 18905e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 18915e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 1892b9c1b51eSKate Stone m_name_options(), m_option_group() { 1893b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1894b9c1b51eSKate Stone // command. 18955e09c8c3SJim Ingham CommandArgumentEntry arg1; 18965e09c8c3SJim Ingham CommandArgumentData id_arg; 18975e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 18985e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 18995e09c8c3SJim Ingham arg1.push_back(id_arg); 19005e09c8c3SJim Ingham m_arguments.push_back(arg1); 19015e09c8c3SJim Ingham 19025e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 19035e09c8c3SJim Ingham m_option_group.Finalize(); 19045e09c8c3SJim Ingham } 19055e09c8c3SJim Ingham 19069e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 19075e09c8c3SJim Ingham 1908e87362e6SGongyu Deng void 1909e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 1910e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 1911e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 1912e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 1913e87362e6SGongyu Deng request, nullptr); 1914e87362e6SGongyu Deng } 1915e87362e6SGongyu Deng 1916b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19175e09c8c3SJim Ingham 19185e09c8c3SJim Ingham protected: 1919b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1920b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 19215e09c8c3SJim Ingham result.SetError("No name option provided."); 19225e09c8c3SJim Ingham return false; 19235e09c8c3SJim Ingham } 19245e09c8c3SJim Ingham 1925cb2380c9SRaphael Isemann Target &target = 1926b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19275e09c8c3SJim Ingham 1928bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1929cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 19305e09c8c3SJim Ingham 1931cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 19325e09c8c3SJim Ingham 19335e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1934b9c1b51eSKate Stone if (num_breakpoints == 0) { 19355e09c8c3SJim Ingham result.SetError("No breakpoints, cannot delete names."); 19365e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19375e09c8c3SJim Ingham return false; 19385e09c8c3SJim Ingham } 19395e09c8c3SJim Ingham 19405e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 19415e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1942b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1943cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1944b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 19455e09c8c3SJim Ingham 1946b9c1b51eSKate Stone if (result.Succeeded()) { 1947b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 19485e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot delete names."); 19495e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19505e09c8c3SJim Ingham return false; 19515e09c8c3SJim Ingham } 1952b842f2ecSJim Ingham ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 19535e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1954b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1955b9c1b51eSKate Stone lldb::break_id_t bp_id = 1956b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 19575e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1958cb2380c9SRaphael Isemann target.RemoveNameFromBreakpoint(bp_sp, bp_name); 19595e09c8c3SJim Ingham } 19605e09c8c3SJim Ingham } 19615e09c8c3SJim Ingham 19625e09c8c3SJim Ingham return true; 19635e09c8c3SJim Ingham } 19645e09c8c3SJim Ingham 19655e09c8c3SJim Ingham private: 19665e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19675e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19685e09c8c3SJim Ingham }; 19695e09c8c3SJim Ingham 1970b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 19715e09c8c3SJim Ingham public: 1972b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 1973b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 1974b842f2ecSJim Ingham "List either the names for a breakpoint or info " 1975b842f2ecSJim Ingham "about a given name. With no arguments, lists all " 1976b842f2ecSJim Ingham "names", 19775e09c8c3SJim Ingham "breakpoint name list <command-options>"), 1978b9c1b51eSKate Stone m_name_options(), m_option_group() { 1979b842f2ecSJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 19805e09c8c3SJim Ingham m_option_group.Finalize(); 19815e09c8c3SJim Ingham } 19825e09c8c3SJim Ingham 19839e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 19845e09c8c3SJim Ingham 1985b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19865e09c8c3SJim Ingham 19875e09c8c3SJim Ingham protected: 1988b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1989cb2380c9SRaphael Isemann Target &target = 1990b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19915e09c8c3SJim Ingham 1992b842f2ecSJim Ingham std::vector<std::string> name_list; 1993b842f2ecSJim Ingham if (command.empty()) { 1994cb2380c9SRaphael Isemann target.GetBreakpointNames(name_list); 1995b842f2ecSJim Ingham } else { 1996a925974bSAdrian Prantl for (const Args::ArgEntry &arg : command) { 1997b842f2ecSJim Ingham name_list.push_back(arg.c_str()); 1998b842f2ecSJim Ingham } 1999b842f2ecSJim Ingham } 2000b842f2ecSJim Ingham 2001b842f2ecSJim Ingham if (name_list.empty()) { 2002b842f2ecSJim Ingham result.AppendMessage("No breakpoint names found."); 2003b842f2ecSJim Ingham } else { 2004b842f2ecSJim Ingham for (const std::string &name_str : name_list) { 2005b842f2ecSJim Ingham const char *name = name_str.c_str(); 2006b842f2ecSJim Ingham // First print out the options for the name: 2007b842f2ecSJim Ingham Status error; 2008cb2380c9SRaphael Isemann BreakpointName *bp_name = 2009cb2380c9SRaphael Isemann target.FindBreakpointName(ConstString(name), false, error); 2010a925974bSAdrian Prantl if (bp_name) { 2011b842f2ecSJim Ingham StreamString s; 2012b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s\n", name); 2013a925974bSAdrian Prantl if (bp_name->GetDescription(&s, eDescriptionLevelFull)) { 2014b842f2ecSJim Ingham result.AppendMessage(s.GetString()); 2015b842f2ecSJim Ingham } 2016b842f2ecSJim Ingham 2017bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2018cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 20195e09c8c3SJim Ingham 2020cb2380c9SRaphael Isemann BreakpointList &breakpoints = target.GetBreakpointList(); 2021b842f2ecSJim Ingham bool any_set = false; 2022b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2023b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 20245e09c8c3SJim Ingham StreamString s; 2025b842f2ecSJim Ingham any_set = true; 20265e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 20275e09c8c3SJim Ingham s.EOL(); 2028c156427dSZachary Turner result.AppendMessage(s.GetString()); 20295e09c8c3SJim Ingham } 20305e09c8c3SJim Ingham } 2031b842f2ecSJim Ingham if (!any_set) 2032b842f2ecSJim Ingham result.AppendMessage("No breakpoints using this name."); 2033b9c1b51eSKate Stone } else { 2034b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s not found.\n", name); 20355e09c8c3SJim Ingham } 2036b842f2ecSJim Ingham } 20375e09c8c3SJim Ingham } 20385e09c8c3SJim Ingham return true; 20395e09c8c3SJim Ingham } 20405e09c8c3SJim Ingham 20415e09c8c3SJim Ingham private: 20425e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20435e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20445e09c8c3SJim Ingham }; 20455e09c8c3SJim Ingham 2046e14dc268SJim Ingham // CommandObjectBreakpointName 2047b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 20485e09c8c3SJim Ingham public: 20497428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2050b9c1b51eSKate Stone : CommandObjectMultiword( 2051b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2052b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2053b9c1b51eSKate Stone CommandObjectSP add_command_object( 2054b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2055b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2056b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2057b9c1b51eSKate Stone CommandObjectSP list_command_object( 2058b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 2059b842f2ecSJim Ingham CommandObjectSP configure_command_object( 2060b842f2ecSJim Ingham new CommandObjectBreakpointNameConfigure(interpreter)); 20615e09c8c3SJim Ingham 20625e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 20635e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 20645e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 2065b842f2ecSJim Ingham LoadSubCommand("configure", configure_command_object); 20665e09c8c3SJim Ingham } 20675e09c8c3SJim Ingham 20689e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 20695e09c8c3SJim Ingham }; 20705e09c8c3SJim Ingham 2071e14dc268SJim Ingham // CommandObjectBreakpointRead 20723acdf385SJim Ingham #pragma mark Read::CommandOptions 2073f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read 2074f94668e3SRaphael Isemann #include "CommandOptions.inc" 20751f0f5b5bSZachary Turner 20761f0f5b5bSZachary Turner #pragma mark Read 2077e14dc268SJim Ingham 2078e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed { 2079e14dc268SJim Ingham public: 2080e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2081e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read", 2082e14dc268SJim Ingham "Read and set the breakpoints previously saved to " 2083e14dc268SJim Ingham "a file with \"breakpoint write\". ", 2084e14dc268SJim Ingham nullptr), 20857c89297cSGongyu Deng m_options() {} 2086e14dc268SJim Ingham 2087e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default; 2088e14dc268SJim Ingham 2089e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2090e14dc268SJim Ingham 2091e14dc268SJim Ingham class CommandOptions : public Options { 2092e14dc268SJim Ingham public: 2093e14dc268SJim Ingham CommandOptions() : Options() {} 2094e14dc268SJim Ingham 2095e14dc268SJim Ingham ~CommandOptions() override = default; 2096e14dc268SJim Ingham 209797206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2098e14dc268SJim Ingham ExecutionContext *execution_context) override { 209997206d57SZachary Turner Status error; 2100e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2101e14dc268SJim Ingham 2102e14dc268SJim Ingham switch (short_option) { 2103e14dc268SJim Ingham case 'f': 2104adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 2105e14dc268SJim Ingham break; 21063acdf385SJim Ingham case 'N': { 210797206d57SZachary Turner Status name_error; 21083acdf385SJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 21093acdf385SJim Ingham name_error)) { 21103acdf385SJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 21113acdf385SJim Ingham name_error.AsCString()); 21123acdf385SJim Ingham } 2113adcd0268SBenjamin Kramer m_names.push_back(std::string(option_arg)); 21143acdf385SJim Ingham break; 21153acdf385SJim Ingham } 2116e14dc268SJim Ingham default: 211736162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 2118e14dc268SJim Ingham } 2119e14dc268SJim Ingham 2120e14dc268SJim Ingham return error; 2121e14dc268SJim Ingham } 2122e14dc268SJim Ingham 2123e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2124e14dc268SJim Ingham m_filename.clear(); 21253acdf385SJim Ingham m_names.clear(); 2126e14dc268SJim Ingham } 2127e14dc268SJim Ingham 21281f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 212970602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_read_options); 21301f0f5b5bSZachary Turner } 2131e14dc268SJim Ingham 213222e63cbaSGongyu Deng void HandleOptionArgumentCompletion( 213322e63cbaSGongyu Deng CompletionRequest &request, OptionElementVector &opt_element_vector, 213422e63cbaSGongyu Deng int opt_element_index, CommandInterpreter &interpreter) override { 213522e63cbaSGongyu Deng int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 213622e63cbaSGongyu Deng int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 213722e63cbaSGongyu Deng 213822e63cbaSGongyu Deng switch (GetDefinitions()[opt_defs_index].short_option) { 213922e63cbaSGongyu Deng case 'f': 214022e63cbaSGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 214122e63cbaSGongyu Deng interpreter, CommandCompletions::eDiskFileCompletion, request, 214222e63cbaSGongyu Deng nullptr); 214322e63cbaSGongyu Deng break; 214422e63cbaSGongyu Deng 214522e63cbaSGongyu Deng case 'N': 214622e63cbaSGongyu Deng llvm::Optional<FileSpec> file_spec; 214722e63cbaSGongyu Deng const llvm::StringRef dash_f("-f"); 214822e63cbaSGongyu Deng for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) { 214922e63cbaSGongyu Deng if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) { 215022e63cbaSGongyu Deng file_spec.emplace( 215122e63cbaSGongyu Deng request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1)); 215222e63cbaSGongyu Deng break; 215322e63cbaSGongyu Deng } 215422e63cbaSGongyu Deng } 215522e63cbaSGongyu Deng if (!file_spec) 215622e63cbaSGongyu Deng return; 215722e63cbaSGongyu Deng 215822e63cbaSGongyu Deng FileSystem::Instance().Resolve(*file_spec); 215922e63cbaSGongyu Deng Status error; 216022e63cbaSGongyu Deng StructuredData::ObjectSP input_data_sp = 216122e63cbaSGongyu Deng StructuredData::ParseJSONFromFile(*file_spec, error); 216222e63cbaSGongyu Deng if (!error.Success()) 216322e63cbaSGongyu Deng return; 216422e63cbaSGongyu Deng 216522e63cbaSGongyu Deng StructuredData::Array *bkpt_array = input_data_sp->GetAsArray(); 216622e63cbaSGongyu Deng if (!bkpt_array) 216722e63cbaSGongyu Deng return; 216822e63cbaSGongyu Deng 216922e63cbaSGongyu Deng const size_t num_bkpts = bkpt_array->GetSize(); 217022e63cbaSGongyu Deng for (size_t i = 0; i < num_bkpts; i++) { 217122e63cbaSGongyu Deng StructuredData::ObjectSP bkpt_object_sp = 217222e63cbaSGongyu Deng bkpt_array->GetItemAtIndex(i); 217322e63cbaSGongyu Deng if (!bkpt_object_sp) 217422e63cbaSGongyu Deng return; 217522e63cbaSGongyu Deng 217622e63cbaSGongyu Deng StructuredData::Dictionary *bkpt_dict = 217722e63cbaSGongyu Deng bkpt_object_sp->GetAsDictionary(); 217822e63cbaSGongyu Deng if (!bkpt_dict) 217922e63cbaSGongyu Deng return; 218022e63cbaSGongyu Deng 218122e63cbaSGongyu Deng StructuredData::ObjectSP bkpt_data_sp = 218222e63cbaSGongyu Deng bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey()); 218322e63cbaSGongyu Deng if (!bkpt_data_sp) 218422e63cbaSGongyu Deng return; 218522e63cbaSGongyu Deng 218622e63cbaSGongyu Deng bkpt_dict = bkpt_data_sp->GetAsDictionary(); 218722e63cbaSGongyu Deng if (!bkpt_dict) 218822e63cbaSGongyu Deng return; 218922e63cbaSGongyu Deng 219022e63cbaSGongyu Deng StructuredData::Array *names_array; 219122e63cbaSGongyu Deng 219222e63cbaSGongyu Deng if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array)) 219322e63cbaSGongyu Deng return; 219422e63cbaSGongyu Deng 219522e63cbaSGongyu Deng size_t num_names = names_array->GetSize(); 219622e63cbaSGongyu Deng 219722e63cbaSGongyu Deng for (size_t i = 0; i < num_names; i++) { 219822e63cbaSGongyu Deng llvm::StringRef name; 219922e63cbaSGongyu Deng if (names_array->GetItemAtIndexAsString(i, name)) 220022e63cbaSGongyu Deng request.TryCompleteCurrentArg(name); 220122e63cbaSGongyu Deng } 220222e63cbaSGongyu Deng } 220322e63cbaSGongyu Deng } 220422e63cbaSGongyu Deng } 2205e14dc268SJim Ingham 2206e14dc268SJim Ingham std::string m_filename; 22073acdf385SJim Ingham std::vector<std::string> m_names; 2208e14dc268SJim Ingham }; 2209e14dc268SJim Ingham 2210e14dc268SJim Ingham protected: 2211e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2212cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 2213e14dc268SJim Ingham 22143acdf385SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2215cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 22163acdf385SJim Ingham 22178f3be7a3SJonas Devlieghere FileSpec input_spec(m_options.m_filename); 22188f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(input_spec); 221901f16664SJim Ingham BreakpointIDList new_bps; 2220cb2380c9SRaphael Isemann Status error = target.CreateBreakpointsFromFile(input_spec, 2221cb2380c9SRaphael Isemann m_options.m_names, new_bps); 2222e14dc268SJim Ingham 2223e14dc268SJim Ingham if (!error.Success()) { 222401f16664SJim Ingham result.AppendError(error.AsCString()); 2225e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 222601f16664SJim Ingham return false; 2227e14dc268SJim Ingham } 22283acdf385SJim Ingham 22293acdf385SJim Ingham Stream &output_stream = result.GetOutputStream(); 22303acdf385SJim Ingham 22313acdf385SJim Ingham size_t num_breakpoints = new_bps.GetSize(); 22323acdf385SJim Ingham if (num_breakpoints == 0) { 22333acdf385SJim Ingham result.AppendMessage("No breakpoints added."); 22343acdf385SJim Ingham } else { 22353acdf385SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 22363acdf385SJim Ingham result.AppendMessage("New breakpoints:"); 22373acdf385SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) { 22383acdf385SJim Ingham BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 2239cb2380c9SRaphael Isemann Breakpoint *bp = target.GetBreakpointList() 22403acdf385SJim Ingham .FindBreakpointByID(bp_id.GetBreakpointID()) 22413acdf385SJim Ingham .get(); 22423acdf385SJim Ingham if (bp) 22433acdf385SJim Ingham bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 22443acdf385SJim Ingham false); 22453acdf385SJim Ingham } 22463acdf385SJim Ingham } 2247e14dc268SJim Ingham return result.Succeeded(); 2248e14dc268SJim Ingham } 2249e14dc268SJim Ingham 2250e14dc268SJim Ingham private: 2251e14dc268SJim Ingham CommandOptions m_options; 2252e14dc268SJim Ingham }; 2253e14dc268SJim Ingham 2254e14dc268SJim Ingham // CommandObjectBreakpointWrite 22551f0f5b5bSZachary Turner #pragma mark Write::CommandOptions 2256f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write 2257f94668e3SRaphael Isemann #include "CommandOptions.inc" 22581f0f5b5bSZachary Turner 22591f0f5b5bSZachary Turner #pragma mark Write 2260e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed { 2261e14dc268SJim Ingham public: 2262e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2263e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write", 2264e14dc268SJim Ingham "Write the breakpoints listed to a file that can " 2265e14dc268SJim Ingham "be read in with \"breakpoint read\". " 2266e14dc268SJim Ingham "If given no arguments, writes all breakpoints.", 2267e14dc268SJim Ingham nullptr), 2268e14dc268SJim Ingham m_options() { 2269e14dc268SJim Ingham CommandArgumentEntry arg; 2270e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2271e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2272e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2273e14dc268SJim Ingham // arguments vector. 2274e14dc268SJim Ingham m_arguments.push_back(arg); 2275e14dc268SJim Ingham } 2276e14dc268SJim Ingham 2277e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default; 2278e14dc268SJim Ingham 2279e87362e6SGongyu Deng void 2280e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 2281e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 2282e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 2283e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 2284e87362e6SGongyu Deng request, nullptr); 2285e87362e6SGongyu Deng } 2286e87362e6SGongyu Deng 2287e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2288e14dc268SJim Ingham 2289e14dc268SJim Ingham class CommandOptions : public Options { 2290e14dc268SJim Ingham public: 2291e14dc268SJim Ingham CommandOptions() : Options() {} 2292e14dc268SJim Ingham 2293e14dc268SJim Ingham ~CommandOptions() override = default; 2294e14dc268SJim Ingham 229597206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2296e14dc268SJim Ingham ExecutionContext *execution_context) override { 229797206d57SZachary Turner Status error; 2298e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2299e14dc268SJim Ingham 2300e14dc268SJim Ingham switch (short_option) { 2301e14dc268SJim Ingham case 'f': 2302adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 2303e14dc268SJim Ingham break; 23042d3628e1SJim Ingham case 'a': 23052d3628e1SJim Ingham m_append = true; 23062d3628e1SJim Ingham break; 2307e14dc268SJim Ingham default: 230836162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 2309e14dc268SJim Ingham } 2310e14dc268SJim Ingham 2311e14dc268SJim Ingham return error; 2312e14dc268SJim Ingham } 2313e14dc268SJim Ingham 2314e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2315e14dc268SJim Ingham m_filename.clear(); 23162d3628e1SJim Ingham m_append = false; 2317e14dc268SJim Ingham } 2318e14dc268SJim Ingham 23191f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 232070602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_write_options); 23211f0f5b5bSZachary Turner } 2322e14dc268SJim Ingham 2323e14dc268SJim Ingham // Instance variables to hold the values for command options. 2324e14dc268SJim Ingham 2325e14dc268SJim Ingham std::string m_filename; 23262d3628e1SJim Ingham bool m_append = false; 2327e14dc268SJim Ingham }; 2328e14dc268SJim Ingham 2329e14dc268SJim Ingham protected: 2330e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2331cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 2332e14dc268SJim Ingham 2333e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2334cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 2335e14dc268SJim Ingham 2336e14dc268SJim Ingham BreakpointIDList valid_bp_ids; 233711eb9c64SZachary Turner if (!command.empty()) { 2338e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2339cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 2340b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 2341e14dc268SJim Ingham 234201f16664SJim Ingham if (!result.Succeeded()) { 2343e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2344e14dc268SJim Ingham return false; 2345e14dc268SJim Ingham } 2346e14dc268SJim Ingham } 23478f3be7a3SJonas Devlieghere FileSpec file_spec(m_options.m_filename); 23488f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(file_spec); 2349cb2380c9SRaphael Isemann Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids, 23508f3be7a3SJonas Devlieghere m_options.m_append); 235101f16664SJim Ingham if (!error.Success()) { 235201f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.", 235301f16664SJim Ingham error.AsCString()); 235401f16664SJim Ingham result.SetStatus(eReturnStatusFailed); 2355e14dc268SJim Ingham } 2356e14dc268SJim Ingham return result.Succeeded(); 2357e14dc268SJim Ingham } 2358e14dc268SJim Ingham 2359e14dc268SJim Ingham private: 2360e14dc268SJim Ingham CommandOptions m_options; 2361e14dc268SJim Ingham }; 2362e14dc268SJim Ingham 236330fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 2364ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 236530fdc8d8SChris Lattner 2366b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2367b9c1b51eSKate Stone CommandInterpreter &interpreter) 2368b9c1b51eSKate Stone : CommandObjectMultiword( 2369b9c1b51eSKate Stone interpreter, "breakpoint", 23707428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2371b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2372b9c1b51eSKate Stone CommandObjectSP list_command_object( 2373b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2374b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2375b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2376b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2377b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2378b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2379b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2380b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2381b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2382b9c1b51eSKate Stone CommandObjectSP set_command_object( 2383b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2384b9c1b51eSKate Stone CommandObjectSP command_command_object( 2385b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2386b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2387b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2388b9c1b51eSKate Stone CommandObjectSP name_command_object( 2389b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 2390e14dc268SJim Ingham CommandObjectSP write_command_object( 2391e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter)); 2392e14dc268SJim Ingham CommandObjectSP read_command_object( 2393e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter)); 239430fdc8d8SChris Lattner 2395b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 239630fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 239730fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2398b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2399b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2400ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2401b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2402b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 24035e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 2404e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write"); 2405e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read"); 240630fdc8d8SChris Lattner 240723f59509SGreg Clayton LoadSubCommand("list", list_command_object); 240823f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 240923f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 241023f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 241123f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 241223f59509SGreg Clayton LoadSubCommand("set", set_command_object); 241323f59509SGreg Clayton LoadSubCommand("command", command_command_object); 241423f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 24155e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 2416e14dc268SJim Ingham LoadSubCommand("write", write_command_object); 2417e14dc268SJim Ingham LoadSubCommand("read", read_command_object); 241830fdc8d8SChris Lattner } 241930fdc8d8SChris Lattner 24209e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 242130fdc8d8SChris Lattner 2422a925974bSAdrian Prantl void CommandObjectMultiwordBreakpoint::VerifyIDs( 2423a925974bSAdrian Prantl Args &args, Target *target, bool allow_locations, 2424a925974bSAdrian Prantl CommandReturnObject &result, BreakpointIDList *valid_ids, 2425a925974bSAdrian Prantl BreakpointName::Permissions ::PermissionKinds purpose) { 242630fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2427b9c1b51eSKate Stone // 2). the full breakpoint & location 2428b9c1b51eSKate Stone // canonical representation 2429b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2430b9c1b51eSKate Stone // representing a range (in which case there 2431b9c1b51eSKate Stone // had *better* be an entry both before & 2432b9c1b51eSKate Stone // after of one of the first two types. 24335e09c8c3SJim Ingham // 4). A breakpoint name 2434b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2435b9c1b51eSKate Stone // one.) 243630fdc8d8SChris Lattner 243730fdc8d8SChris Lattner Args temp_args; 243830fdc8d8SChris Lattner 243911eb9c64SZachary Turner if (args.empty()) { 2440b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2441b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2442b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 244336f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2444b9c1b51eSKate Stone } else { 2445b9c1b51eSKate Stone result.AppendError( 2446b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 244736f3b369SJim Ingham result.SetStatus(eReturnStatusFailed); 244836f3b369SJim Ingham } 244936f3b369SJim Ingham return; 245036f3b369SJim Ingham } 245136f3b369SJim Ingham 2452b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 245305097246SAdrian Prantl // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 245405097246SAdrian Prantl // id range strings over; instead generate a list of strings for all the 245505097246SAdrian Prantl // breakpoint ids in the range, and shove all of those breakpoint id strings 245605097246SAdrian Prantl // into TEMP_ARGS. 245730fdc8d8SChris Lattner 2458b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2459b842f2ecSJim Ingham purpose, result, temp_args); 246030fdc8d8SChris Lattner 2461b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2462b9c1b51eSKate Stone // BreakpointIDList: 246330fdc8d8SChris Lattner 246416662f3cSPavel Labath valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 246530fdc8d8SChris Lattner 246605097246SAdrian Prantl // At this point, all of the breakpoint ids that the user passed in have 246705097246SAdrian Prantl // been converted to breakpoint IDs and put into valid_ids. 246830fdc8d8SChris Lattner 2469b9c1b51eSKate Stone if (result.Succeeded()) { 2470b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 247105097246SAdrian Prantl // ids, go through our tentative list of breakpoint id's and verify that 247205097246SAdrian Prantl // they correspond to valid/currently set breakpoints. 247330fdc8d8SChris Lattner 2474c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2475b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 247630fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2477b9c1b51eSKate Stone Breakpoint *breakpoint = 2478b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2479b9c1b51eSKate Stone if (breakpoint != nullptr) { 2480c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2481b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 248230fdc8d8SChris Lattner StreamString id_str; 2483b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2484b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2485c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2486b9c1b51eSKate Stone result.AppendErrorWithFormat( 2487b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 248830fdc8d8SChris Lattner id_str.GetData()); 248930fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 249030fdc8d8SChris Lattner } 2491b9c1b51eSKate Stone } else { 2492c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2493b9c1b51eSKate Stone result.AppendErrorWithFormat( 2494b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 24957428a18cSKate Stone cur_bp_id.GetBreakpointID()); 249630fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 249730fdc8d8SChris Lattner } 249830fdc8d8SChris Lattner } 249930fdc8d8SChris Lattner } 250030fdc8d8SChris Lattner } 2501