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') { 113*f362b05dSJim Ingham if (option_arg == "current") { 114*f362b05dSJim Ingham if (!execution_context) { 115*f362b05dSJim Ingham error.SetErrorStringWithFormat("No context to determine current " 116*f362b05dSJim Ingham "thread"); 117*f362b05dSJim Ingham } else { 118*f362b05dSJim Ingham ThreadSP ctx_thread_sp = execution_context->GetThreadSP(); 119*f362b05dSJim Ingham if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) { 120*f362b05dSJim Ingham error.SetErrorStringWithFormat("No currently selected thread"); 121*f362b05dSJim Ingham } else { 122*f362b05dSJim Ingham thread_id = ctx_thread_sp->GetID(); 123*f362b05dSJim Ingham } 124*f362b05dSJim Ingham } 125*f362b05dSJim Ingham } else if (option_arg.getAsInteger(0, thread_id)) 126b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread id string '%s'", 127b842f2ecSJim Ingham option_arg.str().c_str()); 128b842f2ecSJim Ingham } 129b842f2ecSJim Ingham m_bp_opts.SetThreadID(thread_id); 130a925974bSAdrian Prantl } break; 131b842f2ecSJim Ingham case 'T': 132b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); 133b842f2ecSJim Ingham break; 134b842f2ecSJim Ingham case 'q': 135b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str()); 136b842f2ecSJim Ingham break; 137a925974bSAdrian Prantl case 'x': { 138b842f2ecSJim Ingham uint32_t thread_index = UINT32_MAX; 139b842f2ecSJim Ingham if (option_arg[0] != '\n') { 140b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_index)) 141b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread index string '%s'", 142b842f2ecSJim Ingham option_arg.str().c_str()); 143b842f2ecSJim Ingham } 144b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetIndex(thread_index); 145a925974bSAdrian Prantl } break; 146b842f2ecSJim Ingham default: 14736162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 148b842f2ecSJim Ingham } 149b842f2ecSJim Ingham 150b842f2ecSJim Ingham return error; 151b842f2ecSJim Ingham } 152b842f2ecSJim Ingham 153b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 154b842f2ecSJim Ingham m_bp_opts.Clear(); 155b842f2ecSJim Ingham m_commands.clear(); 156b842f2ecSJim Ingham } 157b842f2ecSJim Ingham 158b842f2ecSJim Ingham Status OptionParsingFinished(ExecutionContext *execution_context) override { 159a925974bSAdrian Prantl if (!m_commands.empty()) { 160a8f3ae7cSJonas Devlieghere auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); 161b842f2ecSJim Ingham 162b842f2ecSJim Ingham for (std::string &str : m_commands) 163b842f2ecSJim Ingham cmd_data->user_source.AppendString(str); 164b842f2ecSJim Ingham 165b842f2ecSJim Ingham cmd_data->stop_on_error = true; 166b842f2ecSJim Ingham m_bp_opts.SetCommandDataCallback(cmd_data); 167b842f2ecSJim Ingham } 168b842f2ecSJim Ingham return Status(); 169b842f2ecSJim Ingham } 170b842f2ecSJim Ingham 171a925974bSAdrian Prantl const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; } 172b842f2ecSJim Ingham 173b842f2ecSJim Ingham std::vector<std::string> m_commands; 174b842f2ecSJim Ingham BreakpointOptions m_bp_opts; 175b842f2ecSJim Ingham }; 176bd68a052SRaphael Isemann 177f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy 178f94668e3SRaphael Isemann #include "CommandOptions.inc" 179b842f2ecSJim Ingham 180a925974bSAdrian Prantl class BreakpointDummyOptionGroup : public OptionGroup { 181b842f2ecSJim Ingham public: 182a925974bSAdrian Prantl BreakpointDummyOptionGroup() : OptionGroup() {} 183b842f2ecSJim Ingham 184b842f2ecSJim Ingham ~BreakpointDummyOptionGroup() override = default; 185b842f2ecSJim Ingham 186b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 187b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_dummy_options); 188b842f2ecSJim Ingham } 189b842f2ecSJim Ingham 190b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 191b842f2ecSJim Ingham ExecutionContext *execution_context) override { 192b842f2ecSJim Ingham Status error; 193a925974bSAdrian Prantl const int short_option = 194f1539b9dSJim Ingham g_breakpoint_dummy_options[option_idx].short_option; 195b842f2ecSJim Ingham 196b842f2ecSJim Ingham switch (short_option) { 197b842f2ecSJim Ingham case 'D': 198b842f2ecSJim Ingham m_use_dummy = true; 199b842f2ecSJim Ingham break; 200b842f2ecSJim Ingham default: 20136162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 202b842f2ecSJim Ingham } 203b842f2ecSJim Ingham 204b842f2ecSJim Ingham return error; 205b842f2ecSJim Ingham } 206b842f2ecSJim Ingham 207b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 208b842f2ecSJim Ingham m_use_dummy = false; 209b842f2ecSJim Ingham } 210b842f2ecSJim Ingham 211b842f2ecSJim Ingham bool m_use_dummy; 212b842f2ecSJim Ingham }; 213b842f2ecSJim Ingham 214f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set 215f94668e3SRaphael Isemann #include "CommandOptions.inc" 2161f0f5b5bSZachary Turner 2175a988416SJim Ingham // CommandObjectBreakpointSet 21830fdc8d8SChris Lattner 219b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 2205a988416SJim Ingham public: 221efe8e7e3SFangrui Song enum BreakpointSetType { 2225a988416SJim Ingham eSetTypeInvalid, 2235a988416SJim Ingham eSetTypeFileAndLine, 2245a988416SJim Ingham eSetTypeAddress, 2255a988416SJim Ingham eSetTypeFunctionName, 2265a988416SJim Ingham eSetTypeFunctionRegexp, 2275a988416SJim Ingham eSetTypeSourceRegexp, 2283815e702SJim Ingham eSetTypeException, 2293815e702SJim Ingham eSetTypeScripted, 230efe8e7e3SFangrui Song }; 2315a988416SJim Ingham 232b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 233b9c1b51eSKate Stone : CommandObjectParsed( 234b9c1b51eSKate Stone interpreter, "breakpoint set", 2355a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 2365a988416SJim Ingham "breakpoint set <cmd-options>"), 237738af7a6SJim Ingham m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'), 238f6a2086dSSam McCall m_options() { 239b842f2ecSJim Ingham // We're picking up all the normal options, commands and disable. 240a925974bSAdrian Prantl m_all_options.Append(&m_python_class_options, 241a925974bSAdrian Prantl LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11); 242b842f2ecSJim Ingham m_all_options.Append(&m_bp_opts, 243b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, 244b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 245f6a2086dSSam McCall m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 246b842f2ecSJim Ingham m_all_options.Append(&m_options); 247b842f2ecSJim Ingham m_all_options.Finalize(); 248b842f2ecSJim Ingham } 2495a988416SJim Ingham 2509e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 2515a988416SJim Ingham 252b842f2ecSJim Ingham Options *GetOptions() override { return &m_all_options; } 2535a988416SJim Ingham 254b842f2ecSJim Ingham class CommandOptions : public OptionGroup { 2555a988416SJim Ingham public: 256b9c1b51eSKate Stone CommandOptions() 2579494c510SJonas Devlieghere : OptionGroup(), m_condition(), m_filenames(), m_func_names(), 2589494c510SJonas Devlieghere m_func_regexp(), m_source_text_regexp(), m_modules() {} 25930fdc8d8SChris Lattner 2609e85e5a8SEugene Zelenko ~CommandOptions() override = default; 26187df91b8SJim Ingham 26297206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 263b9c1b51eSKate Stone ExecutionContext *execution_context) override { 26497206d57SZachary Turner Status error; 265a925974bSAdrian Prantl const int short_option = 266a925974bSAdrian Prantl g_breakpoint_set_options[option_idx].short_option; 26730fdc8d8SChris Lattner 268b9c1b51eSKate Stone switch (short_option) { 269b9c1b51eSKate Stone case 'a': { 27047cbf4a0SPavel Labath m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 271e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 272b9c1b51eSKate Stone } break; 27330fdc8d8SChris Lattner 274e732052fSJim Ingham case 'A': 275e732052fSJim Ingham m_all_files = true; 276e732052fSJim Ingham break; 277e732052fSJim Ingham 278ca36cd16SJim Ingham case 'b': 279adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 280ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 281ca36cd16SJim Ingham break; 282ca36cd16SJim Ingham 2836672a4f5SJonas Devlieghere case 'u': 284fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_column)) 285b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 286fe11483bSZachary Turner option_arg.str().c_str()); 28730fdc8d8SChris Lattner break; 2889e85e5a8SEugene Zelenko 289b9c1b51eSKate Stone case 'E': { 290fe11483bSZachary Turner LanguageType language = Language::GetLanguageTypeFromString(option_arg); 291fab10e89SJim Ingham 292b9c1b51eSKate Stone switch (language) { 293fab10e89SJim Ingham case eLanguageTypeC89: 294fab10e89SJim Ingham case eLanguageTypeC: 295fab10e89SJim Ingham case eLanguageTypeC99: 2961d0089faSBruce Mitchener case eLanguageTypeC11: 297a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 298fab10e89SJim Ingham break; 299fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 3001d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 3011d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 3022ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 303a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 304fab10e89SJim Ingham break; 305fab10e89SJim Ingham case eLanguageTypeObjC: 306a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 307fab10e89SJim Ingham break; 308fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 309b9c1b51eSKate Stone error.SetErrorStringWithFormat( 310b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 311fab10e89SJim Ingham break; 312fab10e89SJim Ingham case eLanguageTypeUnknown: 313b9c1b51eSKate Stone error.SetErrorStringWithFormat( 314b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 315fe11483bSZachary Turner option_arg.str().c_str()); 316fab10e89SJim Ingham break; 317fab10e89SJim Ingham default: 318b9c1b51eSKate Stone error.SetErrorStringWithFormat( 319b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 320fe11483bSZachary Turner option_arg.str().c_str()); 321fab10e89SJim Ingham } 322b9c1b51eSKate Stone } break; 323ca36cd16SJim Ingham 324ca36cd16SJim Ingham case 'f': 3258f3be7a3SJonas Devlieghere m_filenames.AppendIfUnique(FileSpec(option_arg)); 326fab10e89SJim Ingham break; 327ca36cd16SJim Ingham 328ca36cd16SJim Ingham case 'F': 329adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 330ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 331ca36cd16SJim Ingham break; 332ca36cd16SJim Ingham 333b9c1b51eSKate Stone case 'h': { 334fab10e89SJim Ingham bool success; 33547cbf4a0SPavel Labath m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 336fab10e89SJim Ingham if (!success) 337b9c1b51eSKate Stone error.SetErrorStringWithFormat( 338fe11483bSZachary Turner "Invalid boolean value for on-catch option: '%s'", 339fe11483bSZachary Turner option_arg.str().c_str()); 340b9c1b51eSKate Stone } break; 341eb023e75SGreg Clayton 342eb023e75SGreg Clayton case 'H': 343eb023e75SGreg Clayton m_hardware = true; 344eb023e75SGreg Clayton break; 345eb023e75SGreg Clayton 346b9c1b51eSKate Stone case 'K': { 347a8558b62SJim Ingham bool success; 348a8558b62SJim Ingham bool value; 34947cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 350a8558b62SJim Ingham if (value) 351a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 352a8558b62SJim Ingham else 353a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 354a8558b62SJim Ingham 355a8558b62SJim Ingham if (!success) 356b9c1b51eSKate Stone error.SetErrorStringWithFormat( 357b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 358fe11483bSZachary Turner option_arg.str().c_str()); 359b9c1b51eSKate Stone } break; 360ca36cd16SJim Ingham 361fe11483bSZachary Turner case 'l': 362fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_line_num)) 363b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 364fe11483bSZachary Turner option_arg.str().c_str()); 365ca36cd16SJim Ingham break; 366055ad9beSIlia K 36723b1decbSDawn Perchik case 'L': 368fe11483bSZachary Turner m_language = Language::GetLanguageTypeFromString(option_arg); 36923b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 370b9c1b51eSKate Stone error.SetErrorStringWithFormat( 371fe11483bSZachary Turner "Unknown language type: '%s' for breakpoint", 372fe11483bSZachary Turner option_arg.str().c_str()); 37323b1decbSDawn Perchik break; 37423b1decbSDawn Perchik 375b9c1b51eSKate Stone case 'm': { 376055ad9beSIlia K bool success; 377055ad9beSIlia K bool value; 37847cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 379055ad9beSIlia K if (value) 380055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 381055ad9beSIlia K else 382055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 383055ad9beSIlia K 384055ad9beSIlia K if (!success) 385b9c1b51eSKate Stone error.SetErrorStringWithFormat( 386b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 387fe11483bSZachary Turner option_arg.str().c_str()); 388055ad9beSIlia K break; 389055ad9beSIlia K } 390055ad9beSIlia K 391ca36cd16SJim Ingham case 'M': 392adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 393ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 394ca36cd16SJim Ingham break; 395ca36cd16SJim Ingham 396ca36cd16SJim Ingham case 'n': 397adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 398ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 399ca36cd16SJim Ingham break; 400ca36cd16SJim Ingham 4016fa7681bSZachary Turner case 'N': { 402fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error)) 403adcd0268SBenjamin Kramer m_breakpoint_names.push_back(std::string(option_arg)); 404ff9a91eaSJim Ingham else 405ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 406fe11483bSZachary Turner option_arg.str().c_str()); 4075e09c8c3SJim Ingham break; 4086fa7681bSZachary Turner } 4095e09c8c3SJim Ingham 410b9c1b51eSKate Stone case 'R': { 4112411167fSJim Ingham lldb::addr_t tmp_offset_addr; 41247cbf4a0SPavel Labath tmp_offset_addr = OptionArgParser::ToAddress(execution_context, 41347cbf4a0SPavel Labath option_arg, 0, &error); 4142411167fSJim Ingham if (error.Success()) 4152411167fSJim Ingham m_offset_addr = tmp_offset_addr; 416b9c1b51eSKate Stone } break; 4172411167fSJim Ingham 418a72b31c7SJim Ingham case 'O': 419fe11483bSZachary Turner m_exception_extra_args.AppendArgument("-O"); 420fe11483bSZachary Turner m_exception_extra_args.AppendArgument(option_arg); 421a72b31c7SJim Ingham break; 422a72b31c7SJim Ingham 423ca36cd16SJim Ingham case 'p': 424adcd0268SBenjamin Kramer m_source_text_regexp.assign(std::string(option_arg)); 425ca36cd16SJim Ingham break; 426ca36cd16SJim Ingham 427ca36cd16SJim Ingham case 'r': 428adcd0268SBenjamin Kramer m_func_regexp.assign(std::string(option_arg)); 429ca36cd16SJim Ingham break; 430ca36cd16SJim Ingham 431ca36cd16SJim Ingham case 's': 4328f3be7a3SJonas Devlieghere m_modules.AppendIfUnique(FileSpec(option_arg)); 433ca36cd16SJim Ingham break; 434ca36cd16SJim Ingham 435ca36cd16SJim Ingham case 'S': 436adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 437ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 438ca36cd16SJim Ingham break; 439ca36cd16SJim Ingham 440b9c1b51eSKate Stone case 'w': { 441ca36cd16SJim Ingham bool success; 44247cbf4a0SPavel Labath m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 443ca36cd16SJim Ingham if (!success) 444b9c1b51eSKate Stone error.SetErrorStringWithFormat( 445fe11483bSZachary Turner "Invalid boolean value for on-throw option: '%s'", 446fe11483bSZachary Turner option_arg.str().c_str()); 447b9c1b51eSKate Stone } break; 448ca36cd16SJim Ingham 44976bb8d67SJim Ingham case 'X': 450adcd0268SBenjamin Kramer m_source_regex_func_names.insert(std::string(option_arg)); 45176bb8d67SJim Ingham break; 45276bb8d67SJim Ingham 453bc0a9a17SJim Ingham case 'y': 454bc0a9a17SJim Ingham { 455bc0a9a17SJim Ingham OptionValueFileColonLine value; 456bc0a9a17SJim Ingham Status fcl_err = value.SetValueFromString(option_arg); 457bc0a9a17SJim Ingham if (!fcl_err.Success()) { 458bc0a9a17SJim Ingham error.SetErrorStringWithFormat( 459bc0a9a17SJim Ingham "Invalid value for file:line specifier: %s", 460bc0a9a17SJim Ingham fcl_err.AsCString()); 461bc0a9a17SJim Ingham } else { 462bc0a9a17SJim Ingham m_filenames.AppendIfUnique(value.GetFileSpec()); 463bc0a9a17SJim Ingham m_line_num = value.GetLineNumber(); 464bc0a9a17SJim Ingham m_column = value.GetColumnNumber(); 465bc0a9a17SJim Ingham } 466bc0a9a17SJim Ingham } break; 467bc0a9a17SJim Ingham 46830fdc8d8SChris Lattner default: 46936162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 47030fdc8d8SChris Lattner } 47130fdc8d8SChris Lattner 47230fdc8d8SChris Lattner return error; 47330fdc8d8SChris Lattner } 4749e85e5a8SEugene Zelenko 475b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 47687df91b8SJim Ingham m_filenames.Clear(); 47730fdc8d8SChris Lattner m_line_num = 0; 47830fdc8d8SChris Lattner m_column = 0; 479fab10e89SJim Ingham m_func_names.clear(); 4801f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 48130fdc8d8SChris Lattner m_func_regexp.clear(); 4821f746071SGreg Clayton m_source_text_regexp.clear(); 48387df91b8SJim Ingham m_modules.Clear(); 4841f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 4852411167fSJim Ingham m_offset_addr = 0; 486fab10e89SJim Ingham m_catch_bp = false; 487fab10e89SJim Ingham m_throw_bp = true; 488eb023e75SGreg Clayton m_hardware = false; 489a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 49023b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 491a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 4925e09c8c3SJim Ingham m_breakpoint_names.clear(); 493e732052fSJim Ingham m_all_files = false; 494a72b31c7SJim Ingham m_exception_extra_args.Clear(); 495055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 49676bb8d67SJim Ingham m_source_regex_func_names.clear(); 4973815e702SJim Ingham m_current_key.clear(); 49830fdc8d8SChris Lattner } 49930fdc8d8SChris Lattner 5001f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 50170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_set_options); 5021f0f5b5bSZachary Turner } 50330fdc8d8SChris Lattner 5045a988416SJim Ingham // Instance variables to hold the values for command options. 505969795f1SJim Ingham 5065a988416SJim Ingham std::string m_condition; 5075a988416SJim Ingham FileSpecList m_filenames; 5089494c510SJonas Devlieghere uint32_t m_line_num = 0; 5099494c510SJonas Devlieghere uint32_t m_column = 0; 5105a988416SJim Ingham std::vector<std::string> m_func_names; 5115e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 5129494c510SJonas Devlieghere lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone; 5135a988416SJim Ingham std::string m_func_regexp; 5145a988416SJim Ingham std::string m_source_text_regexp; 5155a988416SJim Ingham FileSpecList m_modules; 5169494c510SJonas Devlieghere lldb::addr_t m_load_addr = 0; 5172411167fSJim Ingham lldb::addr_t m_offset_addr; 5189494c510SJonas Devlieghere bool m_catch_bp = false; 5199494c510SJonas Devlieghere bool m_throw_bp = true; 5209494c510SJonas Devlieghere bool m_hardware = false; // Request to use hardware breakpoints 5219494c510SJonas Devlieghere lldb::LanguageType m_exception_language = eLanguageTypeUnknown; 5229494c510SJonas Devlieghere lldb::LanguageType m_language = lldb::eLanguageTypeUnknown; 5239494c510SJonas Devlieghere LazyBool m_skip_prologue = eLazyBoolCalculate; 5249494c510SJonas Devlieghere bool m_all_files = false; 525a72b31c7SJim Ingham Args m_exception_extra_args; 5269494c510SJonas Devlieghere LazyBool m_move_to_nearest_code = eLazyBoolCalculate; 52776bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 5283815e702SJim Ingham std::string m_current_key; 5295a988416SJim Ingham }; 5305a988416SJim Ingham 5315a988416SJim Ingham protected: 532b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 533cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); 53430fdc8d8SChris Lattner 53530fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 53630fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 53730fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 53830fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 539b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 540b9c1b51eSKate Stone // expression) 541b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 542b9c1b51eSKate Stone // to source text) 543b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 544b9c1b51eSKate Stone // given language.) 54530fdc8d8SChris Lattner 54630fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 54730fdc8d8SChris Lattner 548738af7a6SJim Ingham if (!m_python_class_options.GetName().empty()) 5493815e702SJim Ingham break_type = eSetTypeScripted; 5503815e702SJim Ingham else if (m_options.m_line_num != 0) 55130fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 55230fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 55330fdc8d8SChris Lattner break_type = eSetTypeAddress; 554fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 55530fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 55630fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 55730fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 558969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 559969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 560a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 561fab10e89SJim Ingham break_type = eSetTypeException; 56230fdc8d8SChris Lattner 563b842f2ecSJim Ingham BreakpointSP bp_sp = nullptr; 564274060b6SGreg Clayton FileSpec module_spec; 565a8558b62SJim Ingham const bool internal = false; 566a8558b62SJim Ingham 567b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 568b9c1b51eSKate Stone // that off. 569b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 570b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 5712411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 5722411167fSJim Ingham 573b9c1b51eSKate Stone switch (break_type) { 57430fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 57530fdc8d8SChris Lattner { 57630fdc8d8SChris Lattner FileSpec file; 577c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 578b9c1b51eSKate Stone if (num_files == 0) { 579b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 58087df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 58187df91b8SJim Ingham return false; 58287df91b8SJim Ingham } 583b9c1b51eSKate Stone } else if (num_files > 1) { 584b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 585b9c1b51eSKate Stone "line breakpoints."); 58687df91b8SJim Ingham return false; 587b9c1b51eSKate Stone } else 58887df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 58930fdc8d8SChris Lattner 5901f746071SGreg Clayton // Only check for inline functions if 5911f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 5921f746071SGreg Clayton 593cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint( 594cb2380c9SRaphael Isemann &(m_options.m_modules), file, m_options.m_line_num, 595cb2380c9SRaphael Isemann m_options.m_column, m_options.m_offset_addr, check_inlines, 596cb2380c9SRaphael Isemann m_options.m_skip_prologue, internal, m_options.m_hardware, 597b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 598b9c1b51eSKate Stone } break; 5996eee5aa0SGreg Clayton 60030fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 601055a08a4SJim Ingham { 602b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 603b842f2ecSJim Ingham // with the library, and use that. That way the address breakpoint 604b842f2ecSJim Ingham // will track the load location of the library. 605055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 606b9c1b51eSKate Stone if (num_modules_specified == 1) { 607b9c1b51eSKate Stone const FileSpec *file_spec = 608b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 609cb2380c9SRaphael Isemann bp_sp = target.CreateAddressInModuleBreakpoint( 610cb2380c9SRaphael Isemann m_options.m_load_addr, internal, file_spec, m_options.m_hardware); 611b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 612cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal, 613b842f2ecSJim Ingham m_options.m_hardware); 614b9c1b51eSKate Stone } else { 615b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 616b9c1b51eSKate Stone "address breakpoints."); 617055a08a4SJim Ingham return false; 618055a08a4SJim Ingham } 61930fdc8d8SChris Lattner break; 620055a08a4SJim Ingham } 62130fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 6220c5cd90dSGreg Clayton { 623117b1fa1SZachary Turner FunctionNameType name_type_mask = m_options.m_func_name_type_mask; 6240c5cd90dSGreg Clayton 6250c5cd90dSGreg Clayton if (name_type_mask == 0) 626e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 6270c5cd90dSGreg Clayton 628cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint( 629cb2380c9SRaphael Isemann &(m_options.m_modules), &(m_options.m_filenames), 630cb2380c9SRaphael Isemann m_options.m_func_names, name_type_mask, m_options.m_language, 631cb2380c9SRaphael Isemann m_options.m_offset_addr, m_options.m_skip_prologue, internal, 632b842f2ecSJim Ingham m_options.m_hardware); 633b9c1b51eSKate Stone } break; 6340c5cd90dSGreg Clayton 635b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 636b9c1b51eSKate Stone // name 63730fdc8d8SChris Lattner { 63895eae423SZachary Turner RegularExpression regexp(m_options.m_func_regexp); 6393af3f1e8SJonas Devlieghere if (llvm::Error err = regexp.GetError()) { 640b9c1b51eSKate Stone result.AppendErrorWithFormat( 641b58af8d2SRaphael Isemann "Function name regular expression could not be compiled: %s", 6423af3f1e8SJonas Devlieghere llvm::toString(std::move(err)).c_str()); 643aaf68cd9SRaphael Isemann // Check if the incorrect regex looks like a globbing expression and 644aaf68cd9SRaphael Isemann // warn the user about it. 645aaf68cd9SRaphael Isemann if (!m_options.m_func_regexp.empty()) { 646aaf68cd9SRaphael Isemann if (m_options.m_func_regexp[0] == '*' || 647aaf68cd9SRaphael Isemann m_options.m_func_regexp[0] == '?') 648aaf68cd9SRaphael Isemann result.AppendWarning( 649aaf68cd9SRaphael Isemann "Function name regex does not accept glob patterns."); 650aaf68cd9SRaphael Isemann } 651969795f1SJim Ingham return false; 65230fdc8d8SChris Lattner } 65387df91b8SJim Ingham 654cb2380c9SRaphael Isemann bp_sp = target.CreateFuncRegexBreakpoint( 6555aa1d819SJan Kratochvil &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp), 656cb2380c9SRaphael Isemann m_options.m_language, m_options.m_skip_prologue, internal, 657b842f2ecSJim Ingham m_options.m_hardware); 658a925974bSAdrian Prantl } break; 659969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 660969795f1SJim Ingham { 661c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 66287df91b8SJim Ingham 663b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 664969795f1SJim Ingham FileSpec file; 665b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 666b9c1b51eSKate Stone result.AppendError( 667b9c1b51eSKate Stone "No files provided and could not find default file."); 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 return false; 680969795f1SJim Ingham } 681cb2380c9SRaphael Isemann bp_sp = target.CreateSourceRegexBreakpoint( 682cb2380c9SRaphael Isemann &(m_options.m_modules), &(m_options.m_filenames), 6835aa1d819SJan Kratochvil m_options.m_source_regex_func_names, std::move(regexp), internal, 684cb2380c9SRaphael Isemann m_options.m_hardware, m_options.m_move_to_nearest_code); 685b9c1b51eSKate Stone } break; 686b9c1b51eSKate Stone case eSetTypeException: { 68797206d57SZachary Turner Status precond_error; 688cb2380c9SRaphael Isemann bp_sp = target.CreateExceptionBreakpoint( 689cb2380c9SRaphael Isemann m_options.m_exception_language, m_options.m_catch_bp, 690cb2380c9SRaphael Isemann m_options.m_throw_bp, internal, &m_options.m_exception_extra_args, 691b842f2ecSJim Ingham &precond_error); 692b9c1b51eSKate Stone if (precond_error.Fail()) { 693b9c1b51eSKate Stone result.AppendErrorWithFormat( 694b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 695a72b31c7SJim Ingham precond_error.AsCString()); 696cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 697a72b31c7SJim Ingham return false; 698a72b31c7SJim Ingham } 699b9c1b51eSKate Stone } break; 7003815e702SJim Ingham case eSetTypeScripted: { 7013815e702SJim Ingham 7023815e702SJim Ingham Status error; 703cb2380c9SRaphael Isemann bp_sp = target.CreateScriptedBreakpoint( 704738af7a6SJim Ingham m_python_class_options.GetName().c_str(), &(m_options.m_modules), 705cb2380c9SRaphael Isemann &(m_options.m_filenames), false, m_options.m_hardware, 706943a2481SJim Ingham m_python_class_options.GetStructuredData(), &error); 7073815e702SJim Ingham if (error.Fail()) { 7083815e702SJim Ingham result.AppendErrorWithFormat( 709a925974bSAdrian Prantl "Error setting extra exception arguments: %s", error.AsCString()); 710cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 7113815e702SJim Ingham return false; 7123815e702SJim Ingham } 7133815e702SJim Ingham } break; 71430fdc8d8SChris Lattner default: 71530fdc8d8SChris Lattner break; 71630fdc8d8SChris Lattner } 71730fdc8d8SChris Lattner 7181b54c88cSJim Ingham // Now set the various options that were passed in: 719b842f2ecSJim Ingham if (bp_sp) { 720cfb96d84SJim Ingham bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 721ca36cd16SJim Ingham 722b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 72397206d57SZachary Turner Status name_error; 724ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) { 725cb2380c9SRaphael Isemann target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error); 726ff9a91eaSJim Ingham if (name_error.Fail()) { 727ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s", 728ff9a91eaSJim Ingham name.c_str()); 729cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 730ff9a91eaSJim Ingham return false; 731ff9a91eaSJim Ingham } 732ff9a91eaSJim Ingham } 7335e09c8c3SJim Ingham } 7341b54c88cSJim Ingham } 7351b54c88cSJim Ingham 736b842f2ecSJim Ingham if (bp_sp) { 73785e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 7381391cc7dSJim Ingham const bool show_locations = false; 739b842f2ecSJim Ingham bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 740b9c1b51eSKate Stone show_locations); 741cb2380c9SRaphael Isemann if (&target == &GetDummyTarget()) 742b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 743b9c1b51eSKate Stone "into future targets.\n"); 744b9c1b51eSKate Stone else { 74505097246SAdrian Prantl // Don't print out this warning for exception breakpoints. They can 74605097246SAdrian Prantl // get set before the target is set, but we won't know how to actually 74705097246SAdrian Prantl // set the breakpoint till we run. 748b842f2ecSJim Ingham if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { 749b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 750b9c1b51eSKate Stone "actual locations.\n"); 7514aeb1989SJim Ingham } 7524aeb1989SJim Ingham } 75330fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 754b842f2ecSJim Ingham } else if (!bp_sp) { 75530fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 75630fdc8d8SChris Lattner } 75730fdc8d8SChris Lattner 75830fdc8d8SChris Lattner return result.Succeeded(); 75930fdc8d8SChris Lattner } 76030fdc8d8SChris Lattner 7615a988416SJim Ingham private: 762cb2380c9SRaphael Isemann bool GetDefaultFile(Target &target, FileSpec &file, 763b9c1b51eSKate Stone CommandReturnObject &result) { 7645a988416SJim Ingham uint32_t default_line; 76505097246SAdrian Prantl // First use the Source Manager's default file. Then use the current stack 76605097246SAdrian Prantl // frame's file. 767cb2380c9SRaphael Isemann if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 768b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 769b9c1b51eSKate Stone if (cur_frame == nullptr) { 770b9c1b51eSKate Stone result.AppendError( 771b9c1b51eSKate Stone "No selected frame to use to find the default file."); 7725a988416SJim Ingham return false; 773b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 774b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 775b9c1b51eSKate Stone "file, it has no debug info."); 7765a988416SJim Ingham return false; 777b9c1b51eSKate Stone } else { 778b9c1b51eSKate Stone const SymbolContext &sc = 779b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 780b9c1b51eSKate Stone if (sc.line_entry.file) { 7815a988416SJim Ingham file = sc.line_entry.file; 782b9c1b51eSKate Stone } else { 783b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 784b9c1b51eSKate Stone "use as the default file."); 7855a988416SJim Ingham return false; 7865a988416SJim Ingham } 7875a988416SJim Ingham } 7885a988416SJim Ingham } 7895a988416SJim Ingham return true; 7905a988416SJim Ingham } 7915a988416SJim Ingham 792b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 793b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_options; 794943a2481SJim Ingham OptionGroupPythonClassWithDict m_python_class_options; 7955a988416SJim Ingham CommandOptions m_options; 796b842f2ecSJim Ingham OptionGroupOptions m_all_options; 7975a988416SJim Ingham }; 7989e85e5a8SEugene Zelenko 7995a988416SJim Ingham // CommandObjectBreakpointModify 8005a988416SJim Ingham #pragma mark Modify 8015a988416SJim Ingham 802b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 8035a988416SJim Ingham public: 804b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 805b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 806b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 807b9c1b51eSKate Stone "breakpoints in the executable. " 808b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 809b9c1b51eSKate Stone "created breakpoint. " 810b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 811b9c1b51eSKate Stone "empty argument clears the modification.", 8129e85e5a8SEugene Zelenko nullptr), 813b9c1b51eSKate Stone m_options() { 8145a988416SJim Ingham CommandArgumentEntry arg; 815b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 816b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 817b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 818b9c1b51eSKate Stone // arguments vector. 8195a988416SJim Ingham m_arguments.push_back(arg); 820b842f2ecSJim Ingham 821b842f2ecSJim Ingham m_options.Append(&m_bp_opts, 822b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, 823b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 824b842f2ecSJim Ingham m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 825b842f2ecSJim Ingham m_options.Finalize(); 8265a988416SJim Ingham } 8275a988416SJim Ingham 8289e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 8295a988416SJim Ingham 8300e50b9a4SGongyu Deng void 8310e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 8320e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 8330e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 8340e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 8350e50b9a4SGongyu Deng request, nullptr); 8360e50b9a4SGongyu Deng } 8370e50b9a4SGongyu Deng 838b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 8395a988416SJim Ingham 8405a988416SJim Ingham protected: 841b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 842cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 8435a988416SJim Ingham 844bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 845cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 8465a988416SJim Ingham 8475a988416SJim Ingham BreakpointIDList valid_bp_ids; 8485a988416SJim Ingham 849b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 850cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 851b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 8525a988416SJim Ingham 853b9c1b51eSKate Stone if (result.Succeeded()) { 8545a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 855b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 8565a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 8575a988416SJim Ingham 858b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 859b9c1b51eSKate Stone Breakpoint *bp = 860cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 861b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 862b9c1b51eSKate Stone BreakpointLocation *location = 863b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 864b842f2ecSJim Ingham if (location) 865cfb96d84SJim Ingham location->GetLocationOptions().CopyOverSetOptions( 866a925974bSAdrian Prantl m_bp_opts.GetBreakpointOptions()); 867b9c1b51eSKate Stone } else { 868cfb96d84SJim Ingham bp->GetOptions().CopyOverSetOptions( 869a925974bSAdrian Prantl m_bp_opts.GetBreakpointOptions()); 8705a988416SJim Ingham } 8715a988416SJim Ingham } 8725a988416SJim Ingham } 8735a988416SJim Ingham } 8745a988416SJim Ingham 8755a988416SJim Ingham return result.Succeeded(); 8765a988416SJim Ingham } 8775a988416SJim Ingham 8785a988416SJim Ingham private: 879b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 880b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_opts; 881b842f2ecSJim Ingham OptionGroupOptions m_options; 8825a988416SJim Ingham }; 8835a988416SJim Ingham 8845a988416SJim Ingham // CommandObjectBreakpointEnable 8855a988416SJim Ingham #pragma mark Enable 8865a988416SJim Ingham 887b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 8885a988416SJim Ingham public: 889b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 890b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 891b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 892b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 893b9c1b51eSKate Stone nullptr) { 8945a988416SJim Ingham CommandArgumentEntry arg; 895b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 896b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 897b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 898b9c1b51eSKate Stone // arguments vector. 8995a988416SJim Ingham m_arguments.push_back(arg); 9005a988416SJim Ingham } 9015a988416SJim Ingham 9029e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 9035a988416SJim Ingham 9040e50b9a4SGongyu Deng void 9050e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 9060e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 9070e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 9080e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 9090e50b9a4SGongyu Deng request, nullptr); 9100e50b9a4SGongyu Deng } 9110e50b9a4SGongyu Deng 9125a988416SJim Ingham protected: 913b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 914cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 9155a988416SJim Ingham 916bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 917cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 9185a988416SJim Ingham 919cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 9205a988416SJim Ingham 9215a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 9225a988416SJim Ingham 923b9c1b51eSKate Stone if (num_breakpoints == 0) { 9245a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 9255a988416SJim Ingham return false; 9265a988416SJim Ingham } 9275a988416SJim Ingham 92811eb9c64SZachary Turner if (command.empty()) { 9295a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 930cb2380c9SRaphael Isemann target.EnableAllowedBreakpoints(); 931b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 932b9c1b51eSKate Stone " breakpoints)\n", 933b9c1b51eSKate Stone (uint64_t)num_breakpoints); 9345a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 935b9c1b51eSKate Stone } else { 9365a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 9375a988416SJim Ingham BreakpointIDList valid_bp_ids; 938b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 939cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 940b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 9415a988416SJim Ingham 942b9c1b51eSKate Stone if (result.Succeeded()) { 9435a988416SJim Ingham int enable_count = 0; 9445a988416SJim Ingham int loc_count = 0; 9455a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 946b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 9475a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 9485a988416SJim Ingham 949b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 950b9c1b51eSKate Stone Breakpoint *breakpoint = 951cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 952b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 953b9c1b51eSKate Stone BreakpointLocation *location = 954b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 955b9c1b51eSKate Stone if (location) { 9565a988416SJim Ingham location->SetEnabled(true); 9575a988416SJim Ingham ++loc_count; 9585a988416SJim Ingham } 959b9c1b51eSKate Stone } else { 9605a988416SJim Ingham breakpoint->SetEnabled(true); 9615a988416SJim Ingham ++enable_count; 9625a988416SJim Ingham } 9635a988416SJim Ingham } 9645a988416SJim Ingham } 965b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 966b9c1b51eSKate Stone enable_count + loc_count); 9675a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 9685a988416SJim Ingham } 9695a988416SJim Ingham } 9705a988416SJim Ingham 9715a988416SJim Ingham return result.Succeeded(); 9725a988416SJim Ingham } 9735a988416SJim Ingham }; 9745a988416SJim Ingham 9755a988416SJim Ingham // CommandObjectBreakpointDisable 9765a988416SJim Ingham #pragma mark Disable 9775a988416SJim Ingham 978b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 9795a988416SJim Ingham public: 9807428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 981b9c1b51eSKate Stone : CommandObjectParsed( 982b9c1b51eSKate Stone interpreter, "breakpoint disable", 983b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 9847428a18cSKate Stone "them. If none are specified, disable all " 9857428a18cSKate Stone "breakpoints.", 986b9c1b51eSKate Stone nullptr) { 987b9c1b51eSKate Stone SetHelpLong( 988b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 9897428a18cSKate Stone If none are specified, disable all breakpoints." 9907428a18cSKate Stone R"( 991ea671fbdSKate Stone 9927428a18cSKate Stone )" 9937428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 9947428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 9957428a18cSKate Stone R"( 996ea671fbdSKate Stone 997ea671fbdSKate Stone (lldb) break disable 1 998ea671fbdSKate Stone (lldb) break enable 1.1 999ea671fbdSKate Stone 1000ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 1001ea671fbdSKate Stone 1002ea671fbdSKate Stone (lldb) break disable 1.* 1003ea671fbdSKate Stone (lldb) break enable 1.1 1004ea671fbdSKate Stone 10057428a18cSKate Stone )" 10067428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 10077428a18cSKate Stone the second re-enables the first location."); 1008b0fac509SJim Ingham 10095a988416SJim Ingham CommandArgumentEntry arg; 1010b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1011b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1012b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1013b9c1b51eSKate Stone // arguments vector. 10145a988416SJim Ingham m_arguments.push_back(arg); 10155a988416SJim Ingham } 10165a988416SJim Ingham 10179e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 10185a988416SJim Ingham 10190e50b9a4SGongyu Deng void 10200e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 10210e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 10220e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 10230e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 10240e50b9a4SGongyu Deng request, nullptr); 10250e50b9a4SGongyu Deng } 10260e50b9a4SGongyu Deng 10275a988416SJim Ingham protected: 1028b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1029cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 1030bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1031cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 10325a988416SJim Ingham 1033cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 10345a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 10355a988416SJim Ingham 1036b9c1b51eSKate Stone if (num_breakpoints == 0) { 10375a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 10385a988416SJim Ingham return false; 10395a988416SJim Ingham } 10405a988416SJim Ingham 104111eb9c64SZachary Turner if (command.empty()) { 10425a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 1043cb2380c9SRaphael Isemann target.DisableAllowedBreakpoints(); 1044b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1045b9c1b51eSKate Stone " breakpoints)\n", 1046b9c1b51eSKate Stone (uint64_t)num_breakpoints); 10475a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1048b9c1b51eSKate Stone } else { 10495a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 10505a988416SJim Ingham BreakpointIDList valid_bp_ids; 10515a988416SJim Ingham 1052b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1053cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1054b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 10555a988416SJim Ingham 1056b9c1b51eSKate Stone if (result.Succeeded()) { 10575a988416SJim Ingham int disable_count = 0; 10585a988416SJim Ingham int loc_count = 0; 10595a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1060b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 10615a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 10625a988416SJim Ingham 1063b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1064b9c1b51eSKate Stone Breakpoint *breakpoint = 1065cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1066b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1067b9c1b51eSKate Stone BreakpointLocation *location = 1068b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1069b9c1b51eSKate Stone if (location) { 10705a988416SJim Ingham location->SetEnabled(false); 10715a988416SJim Ingham ++loc_count; 10725a988416SJim Ingham } 1073b9c1b51eSKate Stone } else { 10745a988416SJim Ingham breakpoint->SetEnabled(false); 10755a988416SJim Ingham ++disable_count; 10765a988416SJim Ingham } 10775a988416SJim Ingham } 10785a988416SJim Ingham } 1079b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1080b9c1b51eSKate Stone disable_count + loc_count); 10815a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 10825a988416SJim Ingham } 10835a988416SJim Ingham } 10845a988416SJim Ingham 10855a988416SJim Ingham return result.Succeeded(); 10865a988416SJim Ingham } 10875a988416SJim Ingham }; 10885a988416SJim Ingham 10895a988416SJim Ingham // CommandObjectBreakpointList 10901f0f5b5bSZachary Turner 10911f0f5b5bSZachary Turner #pragma mark List::CommandOptions 10926f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list 1093c5a2d747SRaphael Isemann #include "CommandOptions.inc" 10941f0f5b5bSZachary Turner 10955a988416SJim Ingham #pragma mark List 10965a988416SJim Ingham 1097b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 10985a988416SJim Ingham public: 1099b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1100b9c1b51eSKate Stone : CommandObjectParsed( 1101b9c1b51eSKate Stone interpreter, "breakpoint list", 11025a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 11039e85e5a8SEugene Zelenko nullptr), 1104b9c1b51eSKate Stone m_options() { 11055a988416SJim Ingham CommandArgumentEntry arg; 11065a988416SJim Ingham CommandArgumentData bp_id_arg; 11075a988416SJim Ingham 11085a988416SJim Ingham // Define the first (and only) variant of this arg. 11095a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 11105a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 11115a988416SJim Ingham 1112b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1113b9c1b51eSKate Stone // argument entry. 11145a988416SJim Ingham arg.push_back(bp_id_arg); 11155a988416SJim Ingham 11165a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 11175a988416SJim Ingham m_arguments.push_back(arg); 11185a988416SJim Ingham } 11195a988416SJim Ingham 11209e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 11215a988416SJim Ingham 1122b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 11235a988416SJim Ingham 1124b9c1b51eSKate Stone class CommandOptions : public Options { 11255a988416SJim Ingham public: 11269494c510SJonas Devlieghere CommandOptions() : Options() {} 11275a988416SJim Ingham 11289e85e5a8SEugene Zelenko ~CommandOptions() override = default; 11295a988416SJim Ingham 113097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1131b9c1b51eSKate Stone ExecutionContext *execution_context) override { 113297206d57SZachary Turner Status error; 11333bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 11345a988416SJim Ingham 1135b9c1b51eSKate Stone switch (short_option) { 11365a988416SJim Ingham case 'b': 11375a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 11385a988416SJim Ingham break; 113933df7cd3SJim Ingham case 'D': 114033df7cd3SJim Ingham m_use_dummy = true; 114133df7cd3SJim Ingham break; 11425a988416SJim Ingham case 'f': 11435a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 11445a988416SJim Ingham break; 11455a988416SJim Ingham case 'v': 11465a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 11475a988416SJim Ingham break; 11485a988416SJim Ingham case 'i': 11495a988416SJim Ingham m_internal = true; 11505a988416SJim Ingham break; 11515a988416SJim Ingham default: 115236162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 11535a988416SJim Ingham } 11545a988416SJim Ingham 11555a988416SJim Ingham return error; 11565a988416SJim Ingham } 11575a988416SJim Ingham 1158b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 11595a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 11605a988416SJim Ingham m_internal = false; 116133df7cd3SJim Ingham m_use_dummy = false; 11625a988416SJim Ingham } 11635a988416SJim Ingham 11641f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 116570602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_list_options); 11661f0f5b5bSZachary Turner } 11675a988416SJim Ingham 11685a988416SJim Ingham // Instance variables to hold the values for command options. 11695a988416SJim Ingham 11709494c510SJonas Devlieghere lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief; 11715a988416SJim Ingham 11725a988416SJim Ingham bool m_internal; 11739494c510SJonas Devlieghere bool m_use_dummy = false; 11745a988416SJim Ingham }; 11755a988416SJim Ingham 11765a988416SJim Ingham protected: 1177b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1178cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 11795a988416SJim Ingham 1180b9c1b51eSKate Stone const BreakpointList &breakpoints = 1181cb2380c9SRaphael Isemann target.GetBreakpointList(m_options.m_internal); 1182bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1183cb2380c9SRaphael Isemann target.GetBreakpointList(m_options.m_internal).GetListMutex(lock); 11845a988416SJim Ingham 11855a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 11865a988416SJim Ingham 1187b9c1b51eSKate Stone if (num_breakpoints == 0) { 11885a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 11895a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 11905a988416SJim Ingham return true; 11915a988416SJim Ingham } 11925a988416SJim Ingham 11935a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 11945a988416SJim Ingham 119511eb9c64SZachary Turner if (command.empty()) { 11965a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 11975a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1198b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 11995a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1200b842f2ecSJim Ingham if (breakpoint->AllowList()) 1201b842f2ecSJim Ingham AddBreakpointDescription(&output_stream, breakpoint, 1202b842f2ecSJim Ingham m_options.m_level); 12035a988416SJim Ingham } 12045a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1205b9c1b51eSKate Stone } else { 12065a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 12075a988416SJim Ingham BreakpointIDList valid_bp_ids; 1208b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1209cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1210b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 12115a988416SJim Ingham 1212b9c1b51eSKate Stone if (result.Succeeded()) { 1213b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 12145a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1215b9c1b51eSKate Stone Breakpoint *breakpoint = 1216cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1217b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1218b9c1b51eSKate Stone m_options.m_level); 12195a988416SJim Ingham } 12205a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1221b9c1b51eSKate Stone } else { 12227428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 12235a988416SJim Ingham } 12245a988416SJim Ingham } 12255a988416SJim Ingham 12265a988416SJim Ingham return result.Succeeded(); 12275a988416SJim Ingham } 12285a988416SJim Ingham 12295a988416SJim Ingham private: 12305a988416SJim Ingham CommandOptions m_options; 12315a988416SJim Ingham }; 12325a988416SJim Ingham 12335a988416SJim Ingham // CommandObjectBreakpointClear 12341f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions 12351f0f5b5bSZachary Turner 1236f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear 1237f94668e3SRaphael Isemann #include "CommandOptions.inc" 12381f0f5b5bSZachary Turner 12395a988416SJim Ingham #pragma mark Clear 12405a988416SJim Ingham 1241b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed { 12425a988416SJim Ingham public: 1243efe8e7e3SFangrui Song enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine }; 12445a988416SJim Ingham 12457428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter) 12467428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear", 1247b9c1b51eSKate Stone "Delete or disable breakpoints matching the " 1248b9c1b51eSKate Stone "specified source file and line.", 12495a988416SJim Ingham "breakpoint clear <cmd-options>"), 1250b9c1b51eSKate Stone m_options() {} 12515a988416SJim Ingham 12529e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default; 12535a988416SJim Ingham 1254b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 12555a988416SJim Ingham 1256b9c1b51eSKate Stone class CommandOptions : public Options { 12575a988416SJim Ingham public: 12589494c510SJonas Devlieghere CommandOptions() : Options(), m_filename() {} 12595a988416SJim Ingham 12609e85e5a8SEugene Zelenko ~CommandOptions() override = default; 12615a988416SJim Ingham 126297206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1263b9c1b51eSKate Stone ExecutionContext *execution_context) override { 126497206d57SZachary Turner Status error; 12653bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 12665a988416SJim Ingham 1267b9c1b51eSKate Stone switch (short_option) { 12685a988416SJim Ingham case 'f': 1269adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 12705a988416SJim Ingham break; 12715a988416SJim Ingham 12725a988416SJim Ingham case 'l': 1273fe11483bSZachary Turner option_arg.getAsInteger(0, m_line_num); 12745a988416SJim Ingham break; 12755a988416SJim Ingham 12765a988416SJim Ingham default: 127736162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 12785a988416SJim Ingham } 12795a988416SJim Ingham 12805a988416SJim Ingham return error; 12815a988416SJim Ingham } 12825a988416SJim Ingham 1283b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 12845a988416SJim Ingham m_filename.clear(); 12855a988416SJim Ingham m_line_num = 0; 12865a988416SJim Ingham } 12875a988416SJim Ingham 12881f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 128970602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_clear_options); 12901f0f5b5bSZachary Turner } 12915a988416SJim Ingham 12925a988416SJim Ingham // Instance variables to hold the values for command options. 12935a988416SJim Ingham 12945a988416SJim Ingham std::string m_filename; 12959494c510SJonas Devlieghere uint32_t m_line_num = 0; 12965a988416SJim Ingham }; 12975a988416SJim Ingham 12985a988416SJim Ingham protected: 1299b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1300cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 13015a988416SJim Ingham 130205097246SAdrian Prantl // The following are the various types of breakpoints that could be 130305097246SAdrian Prantl // cleared: 13045a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 13055a988416SJim Ingham 13065a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 13075a988416SJim Ingham 13085a988416SJim Ingham if (m_options.m_line_num != 0) 13095a988416SJim Ingham break_type = eClearTypeFileAndLine; 13105a988416SJim Ingham 1311bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1312cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 13135a988416SJim Ingham 1314cb2380c9SRaphael Isemann BreakpointList &breakpoints = target.GetBreakpointList(); 13155a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 13165a988416SJim Ingham 13175a988416SJim Ingham // Early return if there's no breakpoint at all. 1318b9c1b51eSKate Stone if (num_breakpoints == 0) { 13195a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 13205a988416SJim Ingham return result.Succeeded(); 13215a988416SJim Ingham } 13225a988416SJim Ingham 13235a988416SJim Ingham // Find matching breakpoints and delete them. 13245a988416SJim Ingham 13255a988416SJim Ingham // First create a copy of all the IDs. 13265a988416SJim Ingham std::vector<break_id_t> BreakIDs; 13275a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 13289e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 13295a988416SJim Ingham 13305a988416SJim Ingham int num_cleared = 0; 13315a988416SJim Ingham StreamString ss; 1332b9c1b51eSKate Stone switch (break_type) { 13335a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 13345a988416SJim Ingham { 13355a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 13365a988416SJim Ingham BreakpointLocationCollection loc_coll; 13375a988416SJim Ingham 1338b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 13395a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 13405a988416SJim Ingham 1341b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1342b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1343b9c1b51eSKate Stone // remove the breakpoint. 1344b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 13455a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 13465a988416SJim Ingham ss.EOL(); 1347cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp->GetID()); 13485a988416SJim Ingham ++num_cleared; 13495a988416SJim Ingham } 13505a988416SJim Ingham } 13515a988416SJim Ingham } 1352b9c1b51eSKate Stone } break; 13535a988416SJim Ingham 13545a988416SJim Ingham default: 13555a988416SJim Ingham break; 13565a988416SJim Ingham } 13575a988416SJim Ingham 1358b9c1b51eSKate Stone if (num_cleared > 0) { 13595a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 13605a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1361c156427dSZachary Turner output_stream << ss.GetString(); 13625a988416SJim Ingham output_stream.EOL(); 13635a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1364b9c1b51eSKate Stone } else { 13655a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 13665a988416SJim Ingham } 13675a988416SJim Ingham 13685a988416SJim Ingham return result.Succeeded(); 13695a988416SJim Ingham } 13705a988416SJim Ingham 13715a988416SJim Ingham private: 13725a988416SJim Ingham CommandOptions m_options; 13735a988416SJim Ingham }; 13745a988416SJim Ingham 13755a988416SJim Ingham // CommandObjectBreakpointDelete 1376f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete 1377f94668e3SRaphael Isemann #include "CommandOptions.inc" 13781f0f5b5bSZachary Turner 13795a988416SJim Ingham #pragma mark Delete 13805a988416SJim Ingham 1381b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 13825a988416SJim Ingham public: 1383b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1384b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1385b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1386b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 13879e85e5a8SEugene Zelenko nullptr), 1388b9c1b51eSKate Stone m_options() { 13895a988416SJim Ingham CommandArgumentEntry arg; 1390b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1391b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1392b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1393b9c1b51eSKate Stone // arguments vector. 13945a988416SJim Ingham m_arguments.push_back(arg); 13955a988416SJim Ingham } 13965a988416SJim Ingham 13979e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 13985a988416SJim Ingham 13990e50b9a4SGongyu Deng void 14000e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 14010e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 14020e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 14030e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 14040e50b9a4SGongyu Deng request, nullptr); 14050e50b9a4SGongyu Deng } 14060e50b9a4SGongyu Deng 1407b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 140833df7cd3SJim Ingham 1409b9c1b51eSKate Stone class CommandOptions : public Options { 141033df7cd3SJim Ingham public: 14119494c510SJonas Devlieghere CommandOptions() : Options() {} 141233df7cd3SJim Ingham 14139e85e5a8SEugene Zelenko ~CommandOptions() override = default; 141433df7cd3SJim Ingham 141597206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1416b9c1b51eSKate Stone ExecutionContext *execution_context) override { 141797206d57SZachary Turner Status error; 141833df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 141933df7cd3SJim Ingham 1420b9c1b51eSKate Stone switch (short_option) { 142133df7cd3SJim Ingham case 'f': 142233df7cd3SJim Ingham m_force = true; 142333df7cd3SJim Ingham break; 142433df7cd3SJim Ingham 142533df7cd3SJim Ingham case 'D': 142633df7cd3SJim Ingham m_use_dummy = true; 142733df7cd3SJim Ingham break; 142833df7cd3SJim Ingham 14293726ac41SJim Ingham case 'd': 14303726ac41SJim Ingham m_delete_disabled = true; 14313726ac41SJim Ingham break; 14323726ac41SJim Ingham 143333df7cd3SJim Ingham default: 143436162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 143533df7cd3SJim Ingham } 143633df7cd3SJim Ingham 143733df7cd3SJim Ingham return error; 143833df7cd3SJim Ingham } 143933df7cd3SJim Ingham 1440b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 144133df7cd3SJim Ingham m_use_dummy = false; 144233df7cd3SJim Ingham m_force = false; 14433726ac41SJim Ingham m_delete_disabled = false; 144433df7cd3SJim Ingham } 144533df7cd3SJim Ingham 14461f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 144770602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_delete_options); 14481f0f5b5bSZachary Turner } 144933df7cd3SJim Ingham 145033df7cd3SJim Ingham // Instance variables to hold the values for command options. 14519494c510SJonas Devlieghere bool m_use_dummy = false; 14529494c510SJonas Devlieghere bool m_force = false; 14539494c510SJonas Devlieghere bool m_delete_disabled = false; 145433df7cd3SJim Ingham }; 145533df7cd3SJim Ingham 14565a988416SJim Ingham protected: 1457b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1458cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 14593726ac41SJim Ingham result.Clear(); 14605a988416SJim Ingham 1461bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1462cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 14635a988416SJim Ingham 14643726ac41SJim Ingham BreakpointList &breakpoints = target.GetBreakpointList(); 14655a988416SJim Ingham 14665a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 14675a988416SJim Ingham 1468b9c1b51eSKate Stone if (num_breakpoints == 0) { 14695a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 14705a988416SJim Ingham return false; 14715a988416SJim Ingham } 14725a988416SJim Ingham 14730018c712SJim Ingham // Handle the delete all breakpoints case: 14743726ac41SJim Ingham if (command.empty() && !m_options.m_delete_disabled) { 1475b9c1b51eSKate Stone if (!m_options.m_force && 1476b9c1b51eSKate Stone !m_interpreter.Confirm( 1477b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1478b9c1b51eSKate Stone true)) { 14795a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1480b9c1b51eSKate Stone } else { 1481cb2380c9SRaphael Isemann target.RemoveAllowedBreakpoints(); 1482b9c1b51eSKate Stone result.AppendMessageWithFormat( 1483b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1484b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 14855a988416SJim Ingham } 14865a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 14870018c712SJim Ingham return result.Succeeded(); 14880018c712SJim Ingham } 14890018c712SJim Ingham 14900018c712SJim Ingham // Either we have some kind of breakpoint specification(s), 14910018c712SJim Ingham // or we are handling "break disable --deleted". Gather the list 14920018c712SJim Ingham // of breakpoints to delete here, the we'll delete them below. 14935a988416SJim Ingham BreakpointIDList valid_bp_ids; 14943726ac41SJim Ingham 14953726ac41SJim Ingham if (m_options.m_delete_disabled) { 14963726ac41SJim Ingham BreakpointIDList excluded_bp_ids; 14973726ac41SJim Ingham 14983726ac41SJim Ingham if (!command.empty()) { 14993726ac41SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 15003726ac41SJim Ingham command, &target, result, &excluded_bp_ids, 15013726ac41SJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 15020018c712SJim Ingham if (!result.Succeeded()) 15030018c712SJim Ingham return false; 15043726ac41SJim Ingham } 15050018c712SJim Ingham 15063726ac41SJim Ingham for (auto breakpoint_sp : breakpoints.Breakpoints()) { 15073726ac41SJim Ingham if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) { 15083726ac41SJim Ingham BreakpointID bp_id(breakpoint_sp->GetID()); 15093726ac41SJim Ingham size_t pos = 0; 15103726ac41SJim Ingham if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos)) 15113726ac41SJim Ingham valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID()); 15123726ac41SJim Ingham } 15133726ac41SJim Ingham } 15143726ac41SJim Ingham if (valid_bp_ids.GetSize() == 0) { 15153726ac41SJim Ingham result.AppendError("No disabled breakpoints."); 15163726ac41SJim Ingham return false; 15173726ac41SJim Ingham } 15183726ac41SJim Ingham } else { 1519b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1520cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1521b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 15220018c712SJim Ingham if (!result.Succeeded()) 15230018c712SJim Ingham return false; 15243726ac41SJim Ingham } 15255a988416SJim Ingham 15265a988416SJim Ingham int delete_count = 0; 15275a988416SJim Ingham int disable_count = 0; 15285a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1529b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 15305a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 15315a988416SJim Ingham 1532b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1533b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1534b9c1b51eSKate Stone Breakpoint *breakpoint = 1535cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1536b9c1b51eSKate Stone BreakpointLocation *location = 1537b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1538b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1539b9c1b51eSKate Stone // disable them instead. 1540b9c1b51eSKate Stone if (location) { 15415a988416SJim Ingham location->SetEnabled(false); 15425a988416SJim Ingham ++disable_count; 15435a988416SJim Ingham } 1544b9c1b51eSKate Stone } else { 1545cb2380c9SRaphael Isemann target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 15465a988416SJim Ingham ++delete_count; 15475a988416SJim Ingham } 15485a988416SJim Ingham } 15495a988416SJim Ingham } 1550b9c1b51eSKate Stone result.AppendMessageWithFormat( 1551b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 15525a988416SJim Ingham delete_count, disable_count); 15535a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 15545a988416SJim Ingham return result.Succeeded(); 15555a988416SJim Ingham } 15569e85e5a8SEugene Zelenko 155733df7cd3SJim Ingham private: 155833df7cd3SJim Ingham CommandOptions m_options; 155933df7cd3SJim Ingham }; 156033df7cd3SJim Ingham 15615e09c8c3SJim Ingham // CommandObjectBreakpointName 1562f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name 1563f94668e3SRaphael Isemann #include "CommandOptions.inc" 1564bd68a052SRaphael Isemann 1565b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 15665e09c8c3SJim Ingham public: 1567b9c1b51eSKate Stone BreakpointNameOptionGroup() 1568b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 15695e09c8c3SJim Ingham } 15705e09c8c3SJim Ingham 15719e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 15725e09c8c3SJim Ingham 15731f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 157470602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_name_options); 15755e09c8c3SJim Ingham } 15765e09c8c3SJim Ingham 157797206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1578b9c1b51eSKate Stone ExecutionContext *execution_context) override { 157997206d57SZachary Turner Status error; 15805e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 15815e09c8c3SJim Ingham 1582b9c1b51eSKate Stone switch (short_option) { 15835e09c8c3SJim Ingham case 'N': 1584fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1585b9c1b51eSKate Stone error.Success()) 1586fe11483bSZachary Turner m_name.SetValueFromString(option_arg); 15875e09c8c3SJim Ingham break; 15885e09c8c3SJim Ingham case 'B': 1589fe11483bSZachary Turner if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1590b9c1b51eSKate Stone error.SetErrorStringWithFormat( 15918cef4b0bSZachary Turner "unrecognized value \"%s\" for breakpoint", 1592fe11483bSZachary Turner option_arg.str().c_str()); 15935e09c8c3SJim Ingham break; 15945e09c8c3SJim Ingham case 'D': 1595fe11483bSZachary Turner if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1596b9c1b51eSKate Stone error.SetErrorStringWithFormat( 15978cef4b0bSZachary Turner "unrecognized value \"%s\" for use-dummy", 1598fe11483bSZachary Turner option_arg.str().c_str()); 15995e09c8c3SJim Ingham break; 1600e9632ebaSJim Ingham case 'H': 1601e9632ebaSJim Ingham m_help_string.SetValueFromString(option_arg); 1602e9632ebaSJim Ingham break; 16035e09c8c3SJim Ingham 16045e09c8c3SJim Ingham default: 160536162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 16065e09c8c3SJim Ingham } 16075e09c8c3SJim Ingham return error; 16085e09c8c3SJim Ingham } 16095e09c8c3SJim Ingham 1610b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 16115e09c8c3SJim Ingham m_name.Clear(); 16125e09c8c3SJim Ingham m_breakpoint.Clear(); 16135e09c8c3SJim Ingham m_use_dummy.Clear(); 16145e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 1615e9632ebaSJim Ingham m_help_string.Clear(); 16165e09c8c3SJim Ingham } 16175e09c8c3SJim Ingham 16185e09c8c3SJim Ingham OptionValueString m_name; 16195e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 16205e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 1621e9632ebaSJim Ingham OptionValueString m_help_string; 16225e09c8c3SJim Ingham }; 16235e09c8c3SJim Ingham 1624f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access 1625f94668e3SRaphael Isemann #include "CommandOptions.inc" 1626b842f2ecSJim Ingham 16278fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup { 1628b842f2ecSJim Ingham public: 16298fe53c49STatyana Krasnukha BreakpointAccessOptionGroup() : OptionGroup() {} 1630b842f2ecSJim Ingham 1631b842f2ecSJim Ingham ~BreakpointAccessOptionGroup() override = default; 1632b842f2ecSJim Ingham 1633b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1634b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_access_options); 1635b842f2ecSJim Ingham } 1636b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1637b842f2ecSJim Ingham ExecutionContext *execution_context) override { 1638b842f2ecSJim Ingham Status error; 1639a925974bSAdrian Prantl const int short_option = 1640a925974bSAdrian Prantl g_breakpoint_access_options[option_idx].short_option; 1641b842f2ecSJim Ingham 1642b842f2ecSJim Ingham switch (short_option) { 1643b842f2ecSJim Ingham case 'L': { 1644b842f2ecSJim Ingham bool value, success; 164547cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1646b842f2ecSJim Ingham if (success) { 1647b842f2ecSJim Ingham m_permissions.SetAllowList(value); 1648b842f2ecSJim Ingham } else 1649b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1650b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1651b842f2ecSJim Ingham option_arg.str().c_str()); 1652b842f2ecSJim Ingham } break; 1653b842f2ecSJim Ingham case 'A': { 1654b842f2ecSJim Ingham bool value, success; 165547cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1656b842f2ecSJim Ingham if (success) { 1657b842f2ecSJim Ingham m_permissions.SetAllowDisable(value); 1658b842f2ecSJim Ingham } else 1659b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1660b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1661b842f2ecSJim Ingham option_arg.str().c_str()); 1662b842f2ecSJim Ingham } break; 1663b842f2ecSJim Ingham case 'D': { 1664b842f2ecSJim Ingham bool value, success; 166547cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1666b842f2ecSJim Ingham if (success) { 1667b842f2ecSJim Ingham m_permissions.SetAllowDelete(value); 1668b842f2ecSJim Ingham } else 1669b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1670b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1671b842f2ecSJim Ingham option_arg.str().c_str()); 1672b842f2ecSJim Ingham } break; 167336162014SRaphael Isemann default: 167436162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 1675b842f2ecSJim Ingham } 1676b842f2ecSJim Ingham 1677b842f2ecSJim Ingham return error; 1678b842f2ecSJim Ingham } 1679b842f2ecSJim Ingham 1680a925974bSAdrian Prantl void OptionParsingStarting(ExecutionContext *execution_context) override {} 1681b842f2ecSJim Ingham 1682a925974bSAdrian Prantl const BreakpointName::Permissions &GetPermissions() const { 1683b842f2ecSJim Ingham return m_permissions; 1684b842f2ecSJim Ingham } 1685b842f2ecSJim Ingham BreakpointName::Permissions m_permissions; 1686b842f2ecSJim Ingham }; 1687b842f2ecSJim Ingham 1688b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1689b842f2ecSJim Ingham public: 1690b842f2ecSJim Ingham CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1691b842f2ecSJim Ingham : CommandObjectParsed( 1692a925974bSAdrian Prantl interpreter, "configure", 1693a925974bSAdrian Prantl "Configure the options for the breakpoint" 1694b842f2ecSJim Ingham " name provided. " 1695b842f2ecSJim Ingham "If you provide a breakpoint id, the options will be copied from " 1696b842f2ecSJim Ingham "the breakpoint, otherwise only the options specified will be set " 1697b842f2ecSJim Ingham "on the name.", 1698b842f2ecSJim Ingham "breakpoint name configure <command-options> " 1699b842f2ecSJim Ingham "<breakpoint-name-list>"), 1700b842f2ecSJim Ingham m_bp_opts(), m_option_group() { 1701b842f2ecSJim Ingham // Create the first variant for the first (and only) argument for this 1702b842f2ecSJim Ingham // command. 1703b842f2ecSJim Ingham CommandArgumentEntry arg1; 1704b842f2ecSJim Ingham CommandArgumentData id_arg; 1705b842f2ecSJim Ingham id_arg.arg_type = eArgTypeBreakpointName; 1706b842f2ecSJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 1707b842f2ecSJim Ingham arg1.push_back(id_arg); 1708b842f2ecSJim Ingham m_arguments.push_back(arg1); 1709b842f2ecSJim Ingham 1710a925974bSAdrian Prantl m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1711a925974bSAdrian Prantl m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL, 1712b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 1713a925974bSAdrian Prantl m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4, 1714e9632ebaSJim Ingham LLDB_OPT_SET_ALL); 1715b842f2ecSJim Ingham m_option_group.Finalize(); 1716b842f2ecSJim Ingham } 1717b842f2ecSJim Ingham 1718b842f2ecSJim Ingham ~CommandObjectBreakpointNameConfigure() override = default; 1719b842f2ecSJim Ingham 1720b842f2ecSJim Ingham Options *GetOptions() override { return &m_option_group; } 1721b842f2ecSJim Ingham 1722b842f2ecSJim Ingham protected: 1723b842f2ecSJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 1724b842f2ecSJim Ingham 1725b842f2ecSJim Ingham const size_t argc = command.GetArgumentCount(); 1726b842f2ecSJim Ingham if (argc == 0) { 1727b842f2ecSJim Ingham result.AppendError("No names provided."); 1728b842f2ecSJim Ingham return false; 1729b842f2ecSJim Ingham } 1730b842f2ecSJim Ingham 1731cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(false); 1732b842f2ecSJim Ingham 1733b842f2ecSJim Ingham std::unique_lock<std::recursive_mutex> lock; 1734cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 1735b842f2ecSJim Ingham 1736b842f2ecSJim Ingham // Make a pass through first to see that all the names are legal. 1737b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1738b842f2ecSJim Ingham Status error; 1739a925974bSAdrian Prantl if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) { 1740b842f2ecSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1741b842f2ecSJim Ingham entry.c_str(), error.AsCString()); 1742b842f2ecSJim Ingham return false; 1743b842f2ecSJim Ingham } 1744b842f2ecSJim Ingham } 174505097246SAdrian Prantl // Now configure them, we already pre-checked the names so we don't need to 174605097246SAdrian Prantl // check the error: 1747b842f2ecSJim Ingham BreakpointSP bp_sp; 1748a925974bSAdrian Prantl if (m_bp_id.m_breakpoint.OptionWasSet()) { 1749b842f2ecSJim Ingham lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1750cb2380c9SRaphael Isemann bp_sp = target.GetBreakpointByID(bp_id); 1751a925974bSAdrian Prantl if (!bp_sp) { 1752b842f2ecSJim Ingham result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1753b842f2ecSJim Ingham bp_id); 1754b842f2ecSJim Ingham return false; 1755b842f2ecSJim Ingham } 1756b842f2ecSJim Ingham } 1757b842f2ecSJim Ingham 1758b842f2ecSJim Ingham Status error; 1759b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1760b842f2ecSJim Ingham ConstString name(entry.c_str()); 1761cb2380c9SRaphael Isemann BreakpointName *bp_name = target.FindBreakpointName(name, true, error); 1762b842f2ecSJim Ingham if (!bp_name) 1763b842f2ecSJim Ingham continue; 1764e9632ebaSJim Ingham if (m_bp_id.m_help_string.OptionWasSet()) 1765e9632ebaSJim Ingham bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1766e9632ebaSJim Ingham 1767b842f2ecSJim Ingham if (bp_sp) 1768cfb96d84SJim Ingham target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(), 1769b842f2ecSJim Ingham m_access_options.GetPermissions()); 1770b842f2ecSJim Ingham else 1771cb2380c9SRaphael Isemann target.ConfigureBreakpointName(*bp_name, 1772b842f2ecSJim Ingham m_bp_opts.GetBreakpointOptions(), 1773b842f2ecSJim Ingham m_access_options.GetPermissions()); 1774b842f2ecSJim Ingham } 1775b842f2ecSJim Ingham return true; 1776b842f2ecSJim Ingham } 1777b842f2ecSJim Ingham 1778b842f2ecSJim Ingham private: 1779b842f2ecSJim Ingham BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1780b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 1781b842f2ecSJim Ingham BreakpointAccessOptionGroup m_access_options; 1782b842f2ecSJim Ingham OptionGroupOptions m_option_group; 1783b842f2ecSJim Ingham }; 1784b842f2ecSJim Ingham 1785b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 17865e09c8c3SJim Ingham public: 1787b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1788b9c1b51eSKate Stone : CommandObjectParsed( 1789b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 17905e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 1791b9c1b51eSKate Stone m_name_options(), m_option_group() { 1792b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1793b9c1b51eSKate Stone // command. 17945e09c8c3SJim Ingham CommandArgumentEntry arg1; 17955e09c8c3SJim Ingham CommandArgumentData id_arg; 17965e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 17975e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 17985e09c8c3SJim Ingham arg1.push_back(id_arg); 17995e09c8c3SJim Ingham m_arguments.push_back(arg1); 18005e09c8c3SJim Ingham 18015e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 18025e09c8c3SJim Ingham m_option_group.Finalize(); 18035e09c8c3SJim Ingham } 18045e09c8c3SJim Ingham 18059e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 18065e09c8c3SJim Ingham 1807e87362e6SGongyu Deng void 1808e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 1809e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 1810e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 1811e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 1812e87362e6SGongyu Deng request, nullptr); 1813e87362e6SGongyu Deng } 1814e87362e6SGongyu Deng 1815b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 18165e09c8c3SJim Ingham 18175e09c8c3SJim Ingham protected: 1818b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1819b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 18201b1c8e4aSDavid Spickett result.AppendError("No name option provided."); 18215e09c8c3SJim Ingham return false; 18225e09c8c3SJim Ingham } 18235e09c8c3SJim Ingham 1824cb2380c9SRaphael Isemann Target &target = 1825b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 18265e09c8c3SJim Ingham 1827bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1828cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 18295e09c8c3SJim Ingham 1830cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 18315e09c8c3SJim Ingham 18325e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1833b9c1b51eSKate Stone if (num_breakpoints == 0) { 18341b1c8e4aSDavid Spickett result.AppendError("No breakpoints, cannot add names."); 18355e09c8c3SJim Ingham return false; 18365e09c8c3SJim Ingham } 18375e09c8c3SJim Ingham 18385e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 18395e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1840b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1841cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1842b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 18435e09c8c3SJim Ingham 1844b9c1b51eSKate Stone if (result.Succeeded()) { 1845b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 18461b1c8e4aSDavid Spickett result.AppendError("No breakpoints specified, cannot add names."); 18475e09c8c3SJim Ingham return false; 18485e09c8c3SJim Ingham } 18495e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1850b842f2ecSJim Ingham const char *bp_name = m_name_options.m_name.GetCurrentValue(); 1851b842f2ecSJim Ingham Status error; // This error reports illegal names, but we've already 1852b842f2ecSJim Ingham // checked that, so we don't need to check it again here. 1853b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1854b9c1b51eSKate Stone lldb::break_id_t bp_id = 1855b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 18565e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1857cb2380c9SRaphael Isemann target.AddNameToBreakpoint(bp_sp, bp_name, error); 18585e09c8c3SJim Ingham } 18595e09c8c3SJim Ingham } 18605e09c8c3SJim Ingham 18615e09c8c3SJim Ingham return true; 18625e09c8c3SJim Ingham } 18635e09c8c3SJim Ingham 18645e09c8c3SJim Ingham private: 18655e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 18665e09c8c3SJim Ingham OptionGroupOptions m_option_group; 18675e09c8c3SJim Ingham }; 18685e09c8c3SJim Ingham 1869b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 18705e09c8c3SJim Ingham public: 1871b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1872b9c1b51eSKate Stone : CommandObjectParsed( 1873b9c1b51eSKate Stone interpreter, "delete", 18745e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 18755e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 1876b9c1b51eSKate Stone m_name_options(), m_option_group() { 1877b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1878b9c1b51eSKate Stone // command. 18795e09c8c3SJim Ingham CommandArgumentEntry arg1; 18805e09c8c3SJim Ingham CommandArgumentData id_arg; 18815e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 18825e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 18835e09c8c3SJim Ingham arg1.push_back(id_arg); 18845e09c8c3SJim Ingham m_arguments.push_back(arg1); 18855e09c8c3SJim Ingham 18865e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 18875e09c8c3SJim Ingham m_option_group.Finalize(); 18885e09c8c3SJim Ingham } 18895e09c8c3SJim Ingham 18909e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 18915e09c8c3SJim Ingham 1892e87362e6SGongyu Deng void 1893e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 1894e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 1895e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 1896e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 1897e87362e6SGongyu Deng request, nullptr); 1898e87362e6SGongyu Deng } 1899e87362e6SGongyu Deng 1900b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19015e09c8c3SJim Ingham 19025e09c8c3SJim Ingham protected: 1903b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1904b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 19051b1c8e4aSDavid Spickett result.AppendError("No name option provided."); 19065e09c8c3SJim Ingham return false; 19075e09c8c3SJim Ingham } 19085e09c8c3SJim Ingham 1909cb2380c9SRaphael Isemann Target &target = 1910b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19115e09c8c3SJim Ingham 1912bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1913cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 19145e09c8c3SJim Ingham 1915cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 19165e09c8c3SJim Ingham 19175e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1918b9c1b51eSKate Stone if (num_breakpoints == 0) { 19191b1c8e4aSDavid Spickett result.AppendError("No breakpoints, cannot delete names."); 19205e09c8c3SJim Ingham return false; 19215e09c8c3SJim Ingham } 19225e09c8c3SJim Ingham 19235e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 19245e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1925b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1926cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1927b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 19285e09c8c3SJim Ingham 1929b9c1b51eSKate Stone if (result.Succeeded()) { 1930b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 19311b1c8e4aSDavid Spickett result.AppendError("No breakpoints specified, cannot delete names."); 19325e09c8c3SJim Ingham return false; 19335e09c8c3SJim Ingham } 1934b842f2ecSJim Ingham ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 19355e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1936b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1937b9c1b51eSKate Stone lldb::break_id_t bp_id = 1938b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 19395e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1940cb2380c9SRaphael Isemann target.RemoveNameFromBreakpoint(bp_sp, bp_name); 19415e09c8c3SJim Ingham } 19425e09c8c3SJim Ingham } 19435e09c8c3SJim Ingham 19445e09c8c3SJim Ingham return true; 19455e09c8c3SJim Ingham } 19465e09c8c3SJim Ingham 19475e09c8c3SJim Ingham private: 19485e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19495e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19505e09c8c3SJim Ingham }; 19515e09c8c3SJim Ingham 1952b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 19535e09c8c3SJim Ingham public: 1954b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 1955b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 1956b842f2ecSJim Ingham "List either the names for a breakpoint or info " 1957b842f2ecSJim Ingham "about a given name. With no arguments, lists all " 1958b842f2ecSJim Ingham "names", 19595e09c8c3SJim Ingham "breakpoint name list <command-options>"), 1960b9c1b51eSKate Stone m_name_options(), m_option_group() { 1961b842f2ecSJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 19625e09c8c3SJim Ingham m_option_group.Finalize(); 19635e09c8c3SJim Ingham } 19645e09c8c3SJim Ingham 19659e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 19665e09c8c3SJim Ingham 1967b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19685e09c8c3SJim Ingham 19695e09c8c3SJim Ingham protected: 1970b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1971cb2380c9SRaphael Isemann Target &target = 1972b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19735e09c8c3SJim Ingham 1974b842f2ecSJim Ingham std::vector<std::string> name_list; 1975b842f2ecSJim Ingham if (command.empty()) { 1976cb2380c9SRaphael Isemann target.GetBreakpointNames(name_list); 1977b842f2ecSJim Ingham } else { 1978a925974bSAdrian Prantl for (const Args::ArgEntry &arg : command) { 1979b842f2ecSJim Ingham name_list.push_back(arg.c_str()); 1980b842f2ecSJim Ingham } 1981b842f2ecSJim Ingham } 1982b842f2ecSJim Ingham 1983b842f2ecSJim Ingham if (name_list.empty()) { 1984b842f2ecSJim Ingham result.AppendMessage("No breakpoint names found."); 1985b842f2ecSJim Ingham } else { 1986b842f2ecSJim Ingham for (const std::string &name_str : name_list) { 1987b842f2ecSJim Ingham const char *name = name_str.c_str(); 1988b842f2ecSJim Ingham // First print out the options for the name: 1989b842f2ecSJim Ingham Status error; 1990cb2380c9SRaphael Isemann BreakpointName *bp_name = 1991cb2380c9SRaphael Isemann target.FindBreakpointName(ConstString(name), false, error); 1992a925974bSAdrian Prantl if (bp_name) { 1993b842f2ecSJim Ingham StreamString s; 1994b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s\n", name); 1995a925974bSAdrian Prantl if (bp_name->GetDescription(&s, eDescriptionLevelFull)) { 1996b842f2ecSJim Ingham result.AppendMessage(s.GetString()); 1997b842f2ecSJim Ingham } 1998b842f2ecSJim Ingham 1999bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2000cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 20015e09c8c3SJim Ingham 2002cb2380c9SRaphael Isemann BreakpointList &breakpoints = target.GetBreakpointList(); 2003b842f2ecSJim Ingham bool any_set = false; 2004b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2005b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 20065e09c8c3SJim Ingham StreamString s; 2007b842f2ecSJim Ingham any_set = true; 20085e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 20095e09c8c3SJim Ingham s.EOL(); 2010c156427dSZachary Turner result.AppendMessage(s.GetString()); 20115e09c8c3SJim Ingham } 20125e09c8c3SJim Ingham } 2013b842f2ecSJim Ingham if (!any_set) 2014b842f2ecSJim Ingham result.AppendMessage("No breakpoints using this name."); 2015b9c1b51eSKate Stone } else { 2016b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s not found.\n", name); 20175e09c8c3SJim Ingham } 2018b842f2ecSJim Ingham } 20195e09c8c3SJim Ingham } 20205e09c8c3SJim Ingham return true; 20215e09c8c3SJim Ingham } 20225e09c8c3SJim Ingham 20235e09c8c3SJim Ingham private: 20245e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20255e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20265e09c8c3SJim Ingham }; 20275e09c8c3SJim Ingham 2028e14dc268SJim Ingham // CommandObjectBreakpointName 2029b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 20305e09c8c3SJim Ingham public: 20317428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2032b9c1b51eSKate Stone : CommandObjectMultiword( 2033b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2034b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2035b9c1b51eSKate Stone CommandObjectSP add_command_object( 2036b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2037b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2038b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2039b9c1b51eSKate Stone CommandObjectSP list_command_object( 2040b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 2041b842f2ecSJim Ingham CommandObjectSP configure_command_object( 2042b842f2ecSJim Ingham new CommandObjectBreakpointNameConfigure(interpreter)); 20435e09c8c3SJim Ingham 20445e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 20455e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 20465e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 2047b842f2ecSJim Ingham LoadSubCommand("configure", configure_command_object); 20485e09c8c3SJim Ingham } 20495e09c8c3SJim Ingham 20509e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 20515e09c8c3SJim Ingham }; 20525e09c8c3SJim Ingham 2053e14dc268SJim Ingham // CommandObjectBreakpointRead 20543acdf385SJim Ingham #pragma mark Read::CommandOptions 2055f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read 2056f94668e3SRaphael Isemann #include "CommandOptions.inc" 20571f0f5b5bSZachary Turner 20581f0f5b5bSZachary Turner #pragma mark Read 2059e14dc268SJim Ingham 2060e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed { 2061e14dc268SJim Ingham public: 2062e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2063e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read", 2064e14dc268SJim Ingham "Read and set the breakpoints previously saved to " 2065e14dc268SJim Ingham "a file with \"breakpoint write\". ", 2066e14dc268SJim Ingham nullptr), 20677c89297cSGongyu Deng m_options() {} 2068e14dc268SJim Ingham 2069e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default; 2070e14dc268SJim Ingham 2071e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2072e14dc268SJim Ingham 2073e14dc268SJim Ingham class CommandOptions : public Options { 2074e14dc268SJim Ingham public: 2075e14dc268SJim Ingham CommandOptions() : Options() {} 2076e14dc268SJim Ingham 2077e14dc268SJim Ingham ~CommandOptions() override = default; 2078e14dc268SJim Ingham 207997206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2080e14dc268SJim Ingham ExecutionContext *execution_context) override { 208197206d57SZachary Turner Status error; 2082e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2083e14dc268SJim Ingham 2084e14dc268SJim Ingham switch (short_option) { 2085e14dc268SJim Ingham case 'f': 2086adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 2087e14dc268SJim Ingham break; 20883acdf385SJim Ingham case 'N': { 208997206d57SZachary Turner Status name_error; 20903acdf385SJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 20913acdf385SJim Ingham name_error)) { 20923acdf385SJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 20933acdf385SJim Ingham name_error.AsCString()); 20943acdf385SJim Ingham } 2095adcd0268SBenjamin Kramer m_names.push_back(std::string(option_arg)); 20963acdf385SJim Ingham break; 20973acdf385SJim Ingham } 2098e14dc268SJim Ingham default: 209936162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 2100e14dc268SJim Ingham } 2101e14dc268SJim Ingham 2102e14dc268SJim Ingham return error; 2103e14dc268SJim Ingham } 2104e14dc268SJim Ingham 2105e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2106e14dc268SJim Ingham m_filename.clear(); 21073acdf385SJim Ingham m_names.clear(); 2108e14dc268SJim Ingham } 2109e14dc268SJim Ingham 21101f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 211170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_read_options); 21121f0f5b5bSZachary Turner } 2113e14dc268SJim Ingham 211422e63cbaSGongyu Deng void HandleOptionArgumentCompletion( 211522e63cbaSGongyu Deng CompletionRequest &request, OptionElementVector &opt_element_vector, 211622e63cbaSGongyu Deng int opt_element_index, CommandInterpreter &interpreter) override { 211722e63cbaSGongyu Deng int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 211822e63cbaSGongyu Deng int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 211922e63cbaSGongyu Deng 212022e63cbaSGongyu Deng switch (GetDefinitions()[opt_defs_index].short_option) { 212122e63cbaSGongyu Deng case 'f': 212222e63cbaSGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 212322e63cbaSGongyu Deng interpreter, CommandCompletions::eDiskFileCompletion, request, 212422e63cbaSGongyu Deng nullptr); 212522e63cbaSGongyu Deng break; 212622e63cbaSGongyu Deng 212722e63cbaSGongyu Deng case 'N': 212822e63cbaSGongyu Deng llvm::Optional<FileSpec> file_spec; 212922e63cbaSGongyu Deng const llvm::StringRef dash_f("-f"); 213022e63cbaSGongyu Deng for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) { 213122e63cbaSGongyu Deng if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) { 213222e63cbaSGongyu Deng file_spec.emplace( 213322e63cbaSGongyu Deng request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1)); 213422e63cbaSGongyu Deng break; 213522e63cbaSGongyu Deng } 213622e63cbaSGongyu Deng } 213722e63cbaSGongyu Deng if (!file_spec) 213822e63cbaSGongyu Deng return; 213922e63cbaSGongyu Deng 214022e63cbaSGongyu Deng FileSystem::Instance().Resolve(*file_spec); 214122e63cbaSGongyu Deng Status error; 214222e63cbaSGongyu Deng StructuredData::ObjectSP input_data_sp = 214322e63cbaSGongyu Deng StructuredData::ParseJSONFromFile(*file_spec, error); 214422e63cbaSGongyu Deng if (!error.Success()) 214522e63cbaSGongyu Deng return; 214622e63cbaSGongyu Deng 214722e63cbaSGongyu Deng StructuredData::Array *bkpt_array = input_data_sp->GetAsArray(); 214822e63cbaSGongyu Deng if (!bkpt_array) 214922e63cbaSGongyu Deng return; 215022e63cbaSGongyu Deng 215122e63cbaSGongyu Deng const size_t num_bkpts = bkpt_array->GetSize(); 215222e63cbaSGongyu Deng for (size_t i = 0; i < num_bkpts; i++) { 215322e63cbaSGongyu Deng StructuredData::ObjectSP bkpt_object_sp = 215422e63cbaSGongyu Deng bkpt_array->GetItemAtIndex(i); 215522e63cbaSGongyu Deng if (!bkpt_object_sp) 215622e63cbaSGongyu Deng return; 215722e63cbaSGongyu Deng 215822e63cbaSGongyu Deng StructuredData::Dictionary *bkpt_dict = 215922e63cbaSGongyu Deng bkpt_object_sp->GetAsDictionary(); 216022e63cbaSGongyu Deng if (!bkpt_dict) 216122e63cbaSGongyu Deng return; 216222e63cbaSGongyu Deng 216322e63cbaSGongyu Deng StructuredData::ObjectSP bkpt_data_sp = 216422e63cbaSGongyu Deng bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey()); 216522e63cbaSGongyu Deng if (!bkpt_data_sp) 216622e63cbaSGongyu Deng return; 216722e63cbaSGongyu Deng 216822e63cbaSGongyu Deng bkpt_dict = bkpt_data_sp->GetAsDictionary(); 216922e63cbaSGongyu Deng if (!bkpt_dict) 217022e63cbaSGongyu Deng return; 217122e63cbaSGongyu Deng 217222e63cbaSGongyu Deng StructuredData::Array *names_array; 217322e63cbaSGongyu Deng 217422e63cbaSGongyu Deng if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array)) 217522e63cbaSGongyu Deng return; 217622e63cbaSGongyu Deng 217722e63cbaSGongyu Deng size_t num_names = names_array->GetSize(); 217822e63cbaSGongyu Deng 217922e63cbaSGongyu Deng for (size_t i = 0; i < num_names; i++) { 218022e63cbaSGongyu Deng llvm::StringRef name; 218122e63cbaSGongyu Deng if (names_array->GetItemAtIndexAsString(i, name)) 218222e63cbaSGongyu Deng request.TryCompleteCurrentArg(name); 218322e63cbaSGongyu Deng } 218422e63cbaSGongyu Deng } 218522e63cbaSGongyu Deng } 218622e63cbaSGongyu Deng } 2187e14dc268SJim Ingham 2188e14dc268SJim Ingham std::string m_filename; 21893acdf385SJim Ingham std::vector<std::string> m_names; 2190e14dc268SJim Ingham }; 2191e14dc268SJim Ingham 2192e14dc268SJim Ingham protected: 2193e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2194cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 2195e14dc268SJim Ingham 21963acdf385SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2197cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 21983acdf385SJim Ingham 21998f3be7a3SJonas Devlieghere FileSpec input_spec(m_options.m_filename); 22008f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(input_spec); 220101f16664SJim Ingham BreakpointIDList new_bps; 2202cb2380c9SRaphael Isemann Status error = target.CreateBreakpointsFromFile(input_spec, 2203cb2380c9SRaphael Isemann m_options.m_names, new_bps); 2204e14dc268SJim Ingham 2205e14dc268SJim Ingham if (!error.Success()) { 220601f16664SJim Ingham result.AppendError(error.AsCString()); 220701f16664SJim Ingham return false; 2208e14dc268SJim Ingham } 22093acdf385SJim Ingham 22103acdf385SJim Ingham Stream &output_stream = result.GetOutputStream(); 22113acdf385SJim Ingham 22123acdf385SJim Ingham size_t num_breakpoints = new_bps.GetSize(); 22133acdf385SJim Ingham if (num_breakpoints == 0) { 22143acdf385SJim Ingham result.AppendMessage("No breakpoints added."); 22153acdf385SJim Ingham } else { 22163acdf385SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 22173acdf385SJim Ingham result.AppendMessage("New breakpoints:"); 22183acdf385SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) { 22193acdf385SJim Ingham BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 2220cb2380c9SRaphael Isemann Breakpoint *bp = target.GetBreakpointList() 22213acdf385SJim Ingham .FindBreakpointByID(bp_id.GetBreakpointID()) 22223acdf385SJim Ingham .get(); 22233acdf385SJim Ingham if (bp) 22243acdf385SJim Ingham bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 22253acdf385SJim Ingham false); 22263acdf385SJim Ingham } 22273acdf385SJim Ingham } 2228e14dc268SJim Ingham return result.Succeeded(); 2229e14dc268SJim Ingham } 2230e14dc268SJim Ingham 2231e14dc268SJim Ingham private: 2232e14dc268SJim Ingham CommandOptions m_options; 2233e14dc268SJim Ingham }; 2234e14dc268SJim Ingham 2235e14dc268SJim Ingham // CommandObjectBreakpointWrite 22361f0f5b5bSZachary Turner #pragma mark Write::CommandOptions 2237f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write 2238f94668e3SRaphael Isemann #include "CommandOptions.inc" 22391f0f5b5bSZachary Turner 22401f0f5b5bSZachary Turner #pragma mark Write 2241e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed { 2242e14dc268SJim Ingham public: 2243e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2244e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write", 2245e14dc268SJim Ingham "Write the breakpoints listed to a file that can " 2246e14dc268SJim Ingham "be read in with \"breakpoint read\". " 2247e14dc268SJim Ingham "If given no arguments, writes all breakpoints.", 2248e14dc268SJim Ingham nullptr), 2249e14dc268SJim Ingham m_options() { 2250e14dc268SJim Ingham CommandArgumentEntry arg; 2251e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2252e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2253e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2254e14dc268SJim Ingham // arguments vector. 2255e14dc268SJim Ingham m_arguments.push_back(arg); 2256e14dc268SJim Ingham } 2257e14dc268SJim Ingham 2258e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default; 2259e14dc268SJim Ingham 2260e87362e6SGongyu Deng void 2261e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 2262e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 2263e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 2264e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 2265e87362e6SGongyu Deng request, nullptr); 2266e87362e6SGongyu Deng } 2267e87362e6SGongyu Deng 2268e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2269e14dc268SJim Ingham 2270e14dc268SJim Ingham class CommandOptions : public Options { 2271e14dc268SJim Ingham public: 2272e14dc268SJim Ingham CommandOptions() : Options() {} 2273e14dc268SJim Ingham 2274e14dc268SJim Ingham ~CommandOptions() override = default; 2275e14dc268SJim Ingham 227697206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2277e14dc268SJim Ingham ExecutionContext *execution_context) override { 227897206d57SZachary Turner Status error; 2279e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2280e14dc268SJim Ingham 2281e14dc268SJim Ingham switch (short_option) { 2282e14dc268SJim Ingham case 'f': 2283adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 2284e14dc268SJim Ingham break; 22852d3628e1SJim Ingham case 'a': 22862d3628e1SJim Ingham m_append = true; 22872d3628e1SJim Ingham break; 2288e14dc268SJim Ingham default: 228936162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 2290e14dc268SJim Ingham } 2291e14dc268SJim Ingham 2292e14dc268SJim Ingham return error; 2293e14dc268SJim Ingham } 2294e14dc268SJim Ingham 2295e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2296e14dc268SJim Ingham m_filename.clear(); 22972d3628e1SJim Ingham m_append = false; 2298e14dc268SJim Ingham } 2299e14dc268SJim Ingham 23001f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 230170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_write_options); 23021f0f5b5bSZachary Turner } 2303e14dc268SJim Ingham 2304e14dc268SJim Ingham // Instance variables to hold the values for command options. 2305e14dc268SJim Ingham 2306e14dc268SJim Ingham std::string m_filename; 23072d3628e1SJim Ingham bool m_append = false; 2308e14dc268SJim Ingham }; 2309e14dc268SJim Ingham 2310e14dc268SJim Ingham protected: 2311e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2312cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 2313e14dc268SJim Ingham 2314e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2315cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 2316e14dc268SJim Ingham 2317e14dc268SJim Ingham BreakpointIDList valid_bp_ids; 231811eb9c64SZachary Turner if (!command.empty()) { 2319e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2320cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 2321b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 2322e14dc268SJim Ingham 232301f16664SJim Ingham if (!result.Succeeded()) { 2324e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2325e14dc268SJim Ingham return false; 2326e14dc268SJim Ingham } 2327e14dc268SJim Ingham } 23288f3be7a3SJonas Devlieghere FileSpec file_spec(m_options.m_filename); 23298f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(file_spec); 2330cb2380c9SRaphael Isemann Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids, 23318f3be7a3SJonas Devlieghere m_options.m_append); 233201f16664SJim Ingham if (!error.Success()) { 233301f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.", 233401f16664SJim Ingham error.AsCString()); 2335e14dc268SJim Ingham } 2336e14dc268SJim Ingham return result.Succeeded(); 2337e14dc268SJim Ingham } 2338e14dc268SJim Ingham 2339e14dc268SJim Ingham private: 2340e14dc268SJim Ingham CommandOptions m_options; 2341e14dc268SJim Ingham }; 2342e14dc268SJim Ingham 234330fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 2344ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 234530fdc8d8SChris Lattner 2346b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2347b9c1b51eSKate Stone CommandInterpreter &interpreter) 2348b9c1b51eSKate Stone : CommandObjectMultiword( 2349b9c1b51eSKate Stone interpreter, "breakpoint", 23507428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2351b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2352b9c1b51eSKate Stone CommandObjectSP list_command_object( 2353b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2354b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2355b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2356b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2357b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2358b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2359b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2360b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2361b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2362b9c1b51eSKate Stone CommandObjectSP set_command_object( 2363b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2364b9c1b51eSKate Stone CommandObjectSP command_command_object( 2365b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2366b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2367b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2368b9c1b51eSKate Stone CommandObjectSP name_command_object( 2369b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 2370e14dc268SJim Ingham CommandObjectSP write_command_object( 2371e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter)); 2372e14dc268SJim Ingham CommandObjectSP read_command_object( 2373e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter)); 237430fdc8d8SChris Lattner 2375b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 237630fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 237730fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2378b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2379b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2380ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2381b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2382b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 23835e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 2384e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write"); 2385e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read"); 238630fdc8d8SChris Lattner 238723f59509SGreg Clayton LoadSubCommand("list", list_command_object); 238823f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 238923f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 239023f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 239123f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 239223f59509SGreg Clayton LoadSubCommand("set", set_command_object); 239323f59509SGreg Clayton LoadSubCommand("command", command_command_object); 239423f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 23955e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 2396e14dc268SJim Ingham LoadSubCommand("write", write_command_object); 2397e14dc268SJim Ingham LoadSubCommand("read", read_command_object); 239830fdc8d8SChris Lattner } 239930fdc8d8SChris Lattner 24009e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 240130fdc8d8SChris Lattner 2402a925974bSAdrian Prantl void CommandObjectMultiwordBreakpoint::VerifyIDs( 2403a925974bSAdrian Prantl Args &args, Target *target, bool allow_locations, 2404a925974bSAdrian Prantl CommandReturnObject &result, BreakpointIDList *valid_ids, 2405a925974bSAdrian Prantl BreakpointName::Permissions ::PermissionKinds purpose) { 240630fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2407b9c1b51eSKate Stone // 2). the full breakpoint & location 2408b9c1b51eSKate Stone // canonical representation 2409b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2410b9c1b51eSKate Stone // representing a range (in which case there 2411b9c1b51eSKate Stone // had *better* be an entry both before & 2412b9c1b51eSKate Stone // after of one of the first two types. 24135e09c8c3SJim Ingham // 4). A breakpoint name 2414b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2415b9c1b51eSKate Stone // one.) 241630fdc8d8SChris Lattner 241730fdc8d8SChris Lattner Args temp_args; 241830fdc8d8SChris Lattner 241911eb9c64SZachary Turner if (args.empty()) { 2420b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2421b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2422b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 242336f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2424b9c1b51eSKate Stone } else { 2425b9c1b51eSKate Stone result.AppendError( 2426b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 242736f3b369SJim Ingham } 242836f3b369SJim Ingham return; 242936f3b369SJim Ingham } 243036f3b369SJim Ingham 2431b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 243205097246SAdrian Prantl // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 243305097246SAdrian Prantl // id range strings over; instead generate a list of strings for all the 243405097246SAdrian Prantl // breakpoint ids in the range, and shove all of those breakpoint id strings 243505097246SAdrian Prantl // into TEMP_ARGS. 243630fdc8d8SChris Lattner 2437b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2438b842f2ecSJim Ingham purpose, result, temp_args); 243930fdc8d8SChris Lattner 2440b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2441b9c1b51eSKate Stone // BreakpointIDList: 244230fdc8d8SChris Lattner 244316662f3cSPavel Labath valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 244430fdc8d8SChris Lattner 244505097246SAdrian Prantl // At this point, all of the breakpoint ids that the user passed in have 244605097246SAdrian Prantl // been converted to breakpoint IDs and put into valid_ids. 244730fdc8d8SChris Lattner 2448b9c1b51eSKate Stone if (result.Succeeded()) { 2449b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 245005097246SAdrian Prantl // ids, go through our tentative list of breakpoint id's and verify that 245105097246SAdrian Prantl // they correspond to valid/currently set breakpoints. 245230fdc8d8SChris Lattner 2453c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2454b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 245530fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2456b9c1b51eSKate Stone Breakpoint *breakpoint = 2457b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2458b9c1b51eSKate Stone if (breakpoint != nullptr) { 2459c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2460b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 246130fdc8d8SChris Lattner StreamString id_str; 2462b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2463b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2464c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2465b9c1b51eSKate Stone result.AppendErrorWithFormat( 2466b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 246730fdc8d8SChris Lattner id_str.GetData()); 246830fdc8d8SChris Lattner } 2469b9c1b51eSKate Stone } else { 2470c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2471b9c1b51eSKate Stone result.AppendErrorWithFormat( 2472b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 24737428a18cSKate Stone cur_bp_id.GetBreakpointID()); 247430fdc8d8SChris Lattner } 247530fdc8d8SChris Lattner } 247630fdc8d8SChris Lattner } 247730fdc8d8SChris Lattner } 2478