180814287SRaphael Isemann //===-- CommandObjectBreakpoint.cpp ---------------------------------------===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 99e85e5a8SEugene Zelenko #include "CommandObjectBreakpoint.h" 109e85e5a8SEugene Zelenko #include "CommandObjectBreakpointCommand.h" 1130fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h" 1230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h" 1330fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h" 143eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h" 15b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h" 16b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h" 1747cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h" 18943a2481SJim Ingham #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 1932abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h" 20bc0a9a17SJim Ingham #include "lldb/Interpreter/OptionValueFileColonLine.h" 215e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h" 225e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h" 23b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 240e0984eeSJim Ingham #include "lldb/Target/Language.h" 25b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 26b9c1b51eSKate Stone #include "lldb/Target/Target.h" 271b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h" 28bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h" 29bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 3030fdc8d8SChris Lattner 31796ac80bSJonas Devlieghere #include <memory> 32796ac80bSJonas Devlieghere #include <vector> 33796ac80bSJonas Devlieghere 3430fdc8d8SChris Lattner using namespace lldb; 3530fdc8d8SChris Lattner using namespace lldb_private; 3630fdc8d8SChris Lattner 37b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp, 38b9c1b51eSKate Stone lldb::DescriptionLevel level) { 3930fdc8d8SChris Lattner s->IndentMore(); 4030fdc8d8SChris Lattner bp->GetDescription(s, level, true); 4130fdc8d8SChris Lattner s->IndentLess(); 4230fdc8d8SChris Lattner s->EOL(); 4330fdc8d8SChris Lattner } 4430fdc8d8SChris Lattner 45b842f2ecSJim Ingham // Modifiable Breakpoint Options 46b842f2ecSJim Ingham #pragma mark Modify::CommandOptions 47f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify 48f94668e3SRaphael Isemann #include "CommandOptions.inc" 49bd68a052SRaphael Isemann 50a925974bSAdrian Prantl class lldb_private::BreakpointOptionGroup : public OptionGroup { 51b842f2ecSJim Ingham public: 52a925974bSAdrian Prantl BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {} 53b842f2ecSJim Ingham 54b842f2ecSJim Ingham ~BreakpointOptionGroup() override = default; 55b842f2ecSJim Ingham 56b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 57b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_modify_options); 58b842f2ecSJim Ingham } 59b842f2ecSJim Ingham 60b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 61b842f2ecSJim Ingham ExecutionContext *execution_context) override { 62b842f2ecSJim Ingham Status error; 63a925974bSAdrian Prantl const int short_option = 64a925974bSAdrian Prantl g_breakpoint_modify_options[option_idx].short_option; 65b842f2ecSJim Ingham 66b842f2ecSJim Ingham switch (short_option) { 67b842f2ecSJim Ingham case 'c': 6805097246SAdrian Prantl // Normally an empty breakpoint condition marks is as unset. But we need 6905097246SAdrian Prantl // to say it was passed in. 70b842f2ecSJim Ingham m_bp_opts.SetCondition(option_arg.str().c_str()); 71b842f2ecSJim Ingham m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition); 72b842f2ecSJim Ingham break; 73b842f2ecSJim Ingham case 'C': 74adcd0268SBenjamin Kramer m_commands.push_back(std::string(option_arg)); 75b842f2ecSJim Ingham break; 76b842f2ecSJim Ingham case 'd': 77b842f2ecSJim Ingham m_bp_opts.SetEnabled(false); 78b842f2ecSJim Ingham break; 79b842f2ecSJim Ingham case 'e': 80b842f2ecSJim Ingham m_bp_opts.SetEnabled(true); 81b842f2ecSJim Ingham break; 82b842f2ecSJim Ingham case 'G': { 83b842f2ecSJim Ingham bool value, success; 8447cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 85b842f2ecSJim Ingham if (success) { 86b842f2ecSJim Ingham m_bp_opts.SetAutoContinue(value); 87b842f2ecSJim Ingham } else 88b842f2ecSJim Ingham error.SetErrorStringWithFormat( 89b842f2ecSJim Ingham "invalid boolean value '%s' passed for -G option", 90b842f2ecSJim Ingham option_arg.str().c_str()); 91a925974bSAdrian Prantl } break; 92a925974bSAdrian Prantl case 'i': { 93b842f2ecSJim Ingham uint32_t ignore_count; 94b842f2ecSJim Ingham if (option_arg.getAsInteger(0, ignore_count)) 95b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid ignore count '%s'", 96b842f2ecSJim Ingham option_arg.str().c_str()); 97b842f2ecSJim Ingham else 98b842f2ecSJim Ingham m_bp_opts.SetIgnoreCount(ignore_count); 99a925974bSAdrian Prantl } break; 100b842f2ecSJim Ingham case 'o': { 101b842f2ecSJim Ingham bool value, success; 10247cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 103b842f2ecSJim Ingham if (success) { 104b842f2ecSJim Ingham m_bp_opts.SetOneShot(value); 105b842f2ecSJim Ingham } else 106b842f2ecSJim Ingham error.SetErrorStringWithFormat( 107b842f2ecSJim Ingham "invalid boolean value '%s' passed for -o option", 108b842f2ecSJim Ingham option_arg.str().c_str()); 109b842f2ecSJim Ingham } break; 110a925974bSAdrian Prantl case 't': { 111b842f2ecSJim Ingham lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID; 112b842f2ecSJim Ingham if (option_arg[0] != '\0') { 113b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_id)) 114b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread id string '%s'", 115b842f2ecSJim Ingham option_arg.str().c_str()); 116b842f2ecSJim Ingham } 117b842f2ecSJim Ingham m_bp_opts.SetThreadID(thread_id); 118a925974bSAdrian Prantl } break; 119b842f2ecSJim Ingham case 'T': 120b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); 121b842f2ecSJim Ingham break; 122b842f2ecSJim Ingham case 'q': 123b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str()); 124b842f2ecSJim Ingham break; 125a925974bSAdrian Prantl case 'x': { 126b842f2ecSJim Ingham uint32_t thread_index = UINT32_MAX; 127b842f2ecSJim Ingham if (option_arg[0] != '\n') { 128b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_index)) 129b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread index string '%s'", 130b842f2ecSJim Ingham option_arg.str().c_str()); 131b842f2ecSJim Ingham } 132b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetIndex(thread_index); 133a925974bSAdrian Prantl } break; 134b842f2ecSJim Ingham default: 13536162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 136b842f2ecSJim Ingham } 137b842f2ecSJim Ingham 138b842f2ecSJim Ingham return error; 139b842f2ecSJim Ingham } 140b842f2ecSJim Ingham 141b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 142b842f2ecSJim Ingham m_bp_opts.Clear(); 143b842f2ecSJim Ingham m_commands.clear(); 144b842f2ecSJim Ingham } 145b842f2ecSJim Ingham 146b842f2ecSJim Ingham Status OptionParsingFinished(ExecutionContext *execution_context) override { 147a925974bSAdrian Prantl if (!m_commands.empty()) { 148a8f3ae7cSJonas Devlieghere auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); 149b842f2ecSJim Ingham 150b842f2ecSJim Ingham for (std::string &str : m_commands) 151b842f2ecSJim Ingham cmd_data->user_source.AppendString(str); 152b842f2ecSJim Ingham 153b842f2ecSJim Ingham cmd_data->stop_on_error = true; 154b842f2ecSJim Ingham m_bp_opts.SetCommandDataCallback(cmd_data); 155b842f2ecSJim Ingham } 156b842f2ecSJim Ingham return Status(); 157b842f2ecSJim Ingham } 158b842f2ecSJim Ingham 159a925974bSAdrian Prantl const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; } 160b842f2ecSJim Ingham 161b842f2ecSJim Ingham std::vector<std::string> m_commands; 162b842f2ecSJim Ingham BreakpointOptions m_bp_opts; 163b842f2ecSJim Ingham }; 164bd68a052SRaphael Isemann 165f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy 166f94668e3SRaphael Isemann #include "CommandOptions.inc" 167b842f2ecSJim Ingham 168a925974bSAdrian Prantl class BreakpointDummyOptionGroup : public OptionGroup { 169b842f2ecSJim Ingham public: 170a925974bSAdrian Prantl BreakpointDummyOptionGroup() : OptionGroup() {} 171b842f2ecSJim Ingham 172b842f2ecSJim Ingham ~BreakpointDummyOptionGroup() override = default; 173b842f2ecSJim Ingham 174b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 175b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_dummy_options); 176b842f2ecSJim Ingham } 177b842f2ecSJim Ingham 178b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 179b842f2ecSJim Ingham ExecutionContext *execution_context) override { 180b842f2ecSJim Ingham Status error; 181a925974bSAdrian Prantl const int short_option = 182f1539b9dSJim Ingham g_breakpoint_dummy_options[option_idx].short_option; 183b842f2ecSJim Ingham 184b842f2ecSJim Ingham switch (short_option) { 185b842f2ecSJim Ingham case 'D': 186b842f2ecSJim Ingham m_use_dummy = true; 187b842f2ecSJim Ingham break; 188b842f2ecSJim Ingham default: 18936162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 190b842f2ecSJim Ingham } 191b842f2ecSJim Ingham 192b842f2ecSJim Ingham return error; 193b842f2ecSJim Ingham } 194b842f2ecSJim Ingham 195b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 196b842f2ecSJim Ingham m_use_dummy = false; 197b842f2ecSJim Ingham } 198b842f2ecSJim Ingham 199b842f2ecSJim Ingham bool m_use_dummy; 200b842f2ecSJim Ingham }; 201b842f2ecSJim Ingham 202f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set 203f94668e3SRaphael Isemann #include "CommandOptions.inc" 2041f0f5b5bSZachary Turner 2055a988416SJim Ingham // CommandObjectBreakpointSet 20630fdc8d8SChris Lattner 207b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 2085a988416SJim Ingham public: 209efe8e7e3SFangrui Song enum BreakpointSetType { 2105a988416SJim Ingham eSetTypeInvalid, 2115a988416SJim Ingham eSetTypeFileAndLine, 2125a988416SJim Ingham eSetTypeAddress, 2135a988416SJim Ingham eSetTypeFunctionName, 2145a988416SJim Ingham eSetTypeFunctionRegexp, 2155a988416SJim Ingham eSetTypeSourceRegexp, 2163815e702SJim Ingham eSetTypeException, 2173815e702SJim Ingham eSetTypeScripted, 218efe8e7e3SFangrui Song }; 2195a988416SJim Ingham 220b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 221b9c1b51eSKate Stone : CommandObjectParsed( 222b9c1b51eSKate Stone interpreter, "breakpoint set", 2235a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 2245a988416SJim Ingham "breakpoint set <cmd-options>"), 225738af7a6SJim Ingham m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'), 226f6a2086dSSam McCall m_options() { 227b842f2ecSJim Ingham // We're picking up all the normal options, commands and disable. 228a925974bSAdrian Prantl m_all_options.Append(&m_python_class_options, 229a925974bSAdrian Prantl LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11); 230b842f2ecSJim Ingham m_all_options.Append(&m_bp_opts, 231b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, 232b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 233f6a2086dSSam McCall m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 234b842f2ecSJim Ingham m_all_options.Append(&m_options); 235b842f2ecSJim Ingham m_all_options.Finalize(); 236b842f2ecSJim Ingham } 2375a988416SJim Ingham 2389e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 2395a988416SJim Ingham 240b842f2ecSJim Ingham Options *GetOptions() override { return &m_all_options; } 2415a988416SJim Ingham 242b842f2ecSJim Ingham class CommandOptions : public OptionGroup { 2435a988416SJim Ingham public: 244b9c1b51eSKate Stone CommandOptions() 2459494c510SJonas Devlieghere : OptionGroup(), m_condition(), m_filenames(), m_func_names(), 2469494c510SJonas Devlieghere m_func_regexp(), m_source_text_regexp(), m_modules() {} 24730fdc8d8SChris Lattner 2489e85e5a8SEugene Zelenko ~CommandOptions() override = default; 24987df91b8SJim Ingham 25097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 251b9c1b51eSKate Stone ExecutionContext *execution_context) override { 25297206d57SZachary Turner Status error; 253a925974bSAdrian Prantl const int short_option = 254a925974bSAdrian Prantl g_breakpoint_set_options[option_idx].short_option; 25530fdc8d8SChris Lattner 256b9c1b51eSKate Stone switch (short_option) { 257b9c1b51eSKate Stone case 'a': { 25847cbf4a0SPavel Labath m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 259e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 260b9c1b51eSKate Stone } break; 26130fdc8d8SChris Lattner 262e732052fSJim Ingham case 'A': 263e732052fSJim Ingham m_all_files = true; 264e732052fSJim Ingham break; 265e732052fSJim Ingham 266ca36cd16SJim Ingham case 'b': 267adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 268ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 269ca36cd16SJim Ingham break; 270ca36cd16SJim Ingham 2716672a4f5SJonas Devlieghere case 'u': 272fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_column)) 273b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 274fe11483bSZachary Turner option_arg.str().c_str()); 27530fdc8d8SChris Lattner break; 2769e85e5a8SEugene Zelenko 277b9c1b51eSKate Stone case 'E': { 278fe11483bSZachary Turner LanguageType language = Language::GetLanguageTypeFromString(option_arg); 279fab10e89SJim Ingham 280b9c1b51eSKate Stone switch (language) { 281fab10e89SJim Ingham case eLanguageTypeC89: 282fab10e89SJim Ingham case eLanguageTypeC: 283fab10e89SJim Ingham case eLanguageTypeC99: 2841d0089faSBruce Mitchener case eLanguageTypeC11: 285a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 286fab10e89SJim Ingham break; 287fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 2881d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 2891d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 2902ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 291a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 292fab10e89SJim Ingham break; 293fab10e89SJim Ingham case eLanguageTypeObjC: 294a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 295fab10e89SJim Ingham break; 296fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 297b9c1b51eSKate Stone error.SetErrorStringWithFormat( 298b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 299fab10e89SJim Ingham break; 300fab10e89SJim Ingham case eLanguageTypeUnknown: 301b9c1b51eSKate Stone error.SetErrorStringWithFormat( 302b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 303fe11483bSZachary Turner option_arg.str().c_str()); 304fab10e89SJim Ingham break; 305fab10e89SJim Ingham default: 306b9c1b51eSKate Stone error.SetErrorStringWithFormat( 307b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 308fe11483bSZachary Turner option_arg.str().c_str()); 309fab10e89SJim Ingham } 310b9c1b51eSKate Stone } break; 311ca36cd16SJim Ingham 312ca36cd16SJim Ingham case 'f': 3138f3be7a3SJonas Devlieghere m_filenames.AppendIfUnique(FileSpec(option_arg)); 314fab10e89SJim Ingham break; 315ca36cd16SJim Ingham 316ca36cd16SJim Ingham case 'F': 317adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 318ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 319ca36cd16SJim Ingham break; 320ca36cd16SJim Ingham 321b9c1b51eSKate Stone case 'h': { 322fab10e89SJim Ingham bool success; 32347cbf4a0SPavel Labath m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 324fab10e89SJim Ingham if (!success) 325b9c1b51eSKate Stone error.SetErrorStringWithFormat( 326fe11483bSZachary Turner "Invalid boolean value for on-catch option: '%s'", 327fe11483bSZachary Turner option_arg.str().c_str()); 328b9c1b51eSKate Stone } break; 329eb023e75SGreg Clayton 330eb023e75SGreg Clayton case 'H': 331eb023e75SGreg Clayton m_hardware = true; 332eb023e75SGreg Clayton break; 333eb023e75SGreg Clayton 334b9c1b51eSKate Stone case 'K': { 335a8558b62SJim Ingham bool success; 336a8558b62SJim Ingham bool value; 33747cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 338a8558b62SJim Ingham if (value) 339a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 340a8558b62SJim Ingham else 341a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 342a8558b62SJim Ingham 343a8558b62SJim Ingham if (!success) 344b9c1b51eSKate Stone error.SetErrorStringWithFormat( 345b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 346fe11483bSZachary Turner option_arg.str().c_str()); 347b9c1b51eSKate Stone } break; 348ca36cd16SJim Ingham 349fe11483bSZachary Turner case 'l': 350fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_line_num)) 351b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 352fe11483bSZachary Turner option_arg.str().c_str()); 353ca36cd16SJim Ingham break; 354055ad9beSIlia K 35523b1decbSDawn Perchik case 'L': 356fe11483bSZachary Turner m_language = Language::GetLanguageTypeFromString(option_arg); 35723b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 358b9c1b51eSKate Stone error.SetErrorStringWithFormat( 359fe11483bSZachary Turner "Unknown language type: '%s' for breakpoint", 360fe11483bSZachary Turner option_arg.str().c_str()); 36123b1decbSDawn Perchik break; 36223b1decbSDawn Perchik 363b9c1b51eSKate Stone case 'm': { 364055ad9beSIlia K bool success; 365055ad9beSIlia K bool value; 36647cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 367055ad9beSIlia K if (value) 368055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 369055ad9beSIlia K else 370055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 371055ad9beSIlia K 372055ad9beSIlia K if (!success) 373b9c1b51eSKate Stone error.SetErrorStringWithFormat( 374b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 375fe11483bSZachary Turner option_arg.str().c_str()); 376055ad9beSIlia K break; 377055ad9beSIlia K } 378055ad9beSIlia K 379ca36cd16SJim Ingham case 'M': 380adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 381ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 382ca36cd16SJim Ingham break; 383ca36cd16SJim Ingham 384ca36cd16SJim Ingham case 'n': 385adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 386ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 387ca36cd16SJim Ingham break; 388ca36cd16SJim Ingham 3896fa7681bSZachary Turner case 'N': { 390fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error)) 391adcd0268SBenjamin Kramer m_breakpoint_names.push_back(std::string(option_arg)); 392ff9a91eaSJim Ingham else 393ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 394fe11483bSZachary Turner option_arg.str().c_str()); 3955e09c8c3SJim Ingham break; 3966fa7681bSZachary Turner } 3975e09c8c3SJim Ingham 398b9c1b51eSKate Stone case 'R': { 3992411167fSJim Ingham lldb::addr_t tmp_offset_addr; 40047cbf4a0SPavel Labath tmp_offset_addr = OptionArgParser::ToAddress(execution_context, 40147cbf4a0SPavel Labath option_arg, 0, &error); 4022411167fSJim Ingham if (error.Success()) 4032411167fSJim Ingham m_offset_addr = tmp_offset_addr; 404b9c1b51eSKate Stone } break; 4052411167fSJim Ingham 406a72b31c7SJim Ingham case 'O': 407fe11483bSZachary Turner m_exception_extra_args.AppendArgument("-O"); 408fe11483bSZachary Turner m_exception_extra_args.AppendArgument(option_arg); 409a72b31c7SJim Ingham break; 410a72b31c7SJim Ingham 411ca36cd16SJim Ingham case 'p': 412adcd0268SBenjamin Kramer m_source_text_regexp.assign(std::string(option_arg)); 413ca36cd16SJim Ingham break; 414ca36cd16SJim Ingham 415ca36cd16SJim Ingham case 'r': 416adcd0268SBenjamin Kramer m_func_regexp.assign(std::string(option_arg)); 417ca36cd16SJim Ingham break; 418ca36cd16SJim Ingham 419ca36cd16SJim Ingham case 's': 4208f3be7a3SJonas Devlieghere m_modules.AppendIfUnique(FileSpec(option_arg)); 421ca36cd16SJim Ingham break; 422ca36cd16SJim Ingham 423ca36cd16SJim Ingham case 'S': 424adcd0268SBenjamin Kramer m_func_names.push_back(std::string(option_arg)); 425ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 426ca36cd16SJim Ingham break; 427ca36cd16SJim Ingham 428b9c1b51eSKate Stone case 'w': { 429ca36cd16SJim Ingham bool success; 43047cbf4a0SPavel Labath m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 431ca36cd16SJim Ingham if (!success) 432b9c1b51eSKate Stone error.SetErrorStringWithFormat( 433fe11483bSZachary Turner "Invalid boolean value for on-throw option: '%s'", 434fe11483bSZachary Turner option_arg.str().c_str()); 435b9c1b51eSKate Stone } break; 436ca36cd16SJim Ingham 43776bb8d67SJim Ingham case 'X': 438adcd0268SBenjamin Kramer m_source_regex_func_names.insert(std::string(option_arg)); 43976bb8d67SJim Ingham break; 44076bb8d67SJim Ingham 441bc0a9a17SJim Ingham case 'y': 442bc0a9a17SJim Ingham { 443bc0a9a17SJim Ingham OptionValueFileColonLine value; 444bc0a9a17SJim Ingham Status fcl_err = value.SetValueFromString(option_arg); 445bc0a9a17SJim Ingham if (!fcl_err.Success()) { 446bc0a9a17SJim Ingham error.SetErrorStringWithFormat( 447bc0a9a17SJim Ingham "Invalid value for file:line specifier: %s", 448bc0a9a17SJim Ingham fcl_err.AsCString()); 449bc0a9a17SJim Ingham } else { 450bc0a9a17SJim Ingham m_filenames.AppendIfUnique(value.GetFileSpec()); 451bc0a9a17SJim Ingham m_line_num = value.GetLineNumber(); 452bc0a9a17SJim Ingham m_column = value.GetColumnNumber(); 453bc0a9a17SJim Ingham } 454bc0a9a17SJim Ingham } break; 455bc0a9a17SJim Ingham 45630fdc8d8SChris Lattner default: 45736162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 45830fdc8d8SChris Lattner } 45930fdc8d8SChris Lattner 46030fdc8d8SChris Lattner return error; 46130fdc8d8SChris Lattner } 4629e85e5a8SEugene Zelenko 463b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 46487df91b8SJim Ingham m_filenames.Clear(); 46530fdc8d8SChris Lattner m_line_num = 0; 46630fdc8d8SChris Lattner m_column = 0; 467fab10e89SJim Ingham m_func_names.clear(); 4681f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 46930fdc8d8SChris Lattner m_func_regexp.clear(); 4701f746071SGreg Clayton m_source_text_regexp.clear(); 47187df91b8SJim Ingham m_modules.Clear(); 4721f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 4732411167fSJim Ingham m_offset_addr = 0; 474fab10e89SJim Ingham m_catch_bp = false; 475fab10e89SJim Ingham m_throw_bp = true; 476eb023e75SGreg Clayton m_hardware = false; 477a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 47823b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 479a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 4805e09c8c3SJim Ingham m_breakpoint_names.clear(); 481e732052fSJim Ingham m_all_files = false; 482a72b31c7SJim Ingham m_exception_extra_args.Clear(); 483055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 48476bb8d67SJim Ingham m_source_regex_func_names.clear(); 4853815e702SJim Ingham m_current_key.clear(); 48630fdc8d8SChris Lattner } 48730fdc8d8SChris Lattner 4881f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 48970602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_set_options); 4901f0f5b5bSZachary Turner } 49130fdc8d8SChris Lattner 4925a988416SJim Ingham // Instance variables to hold the values for command options. 493969795f1SJim Ingham 4945a988416SJim Ingham std::string m_condition; 4955a988416SJim Ingham FileSpecList m_filenames; 4969494c510SJonas Devlieghere uint32_t m_line_num = 0; 4979494c510SJonas Devlieghere uint32_t m_column = 0; 4985a988416SJim Ingham std::vector<std::string> m_func_names; 4995e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 5009494c510SJonas Devlieghere lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone; 5015a988416SJim Ingham std::string m_func_regexp; 5025a988416SJim Ingham std::string m_source_text_regexp; 5035a988416SJim Ingham FileSpecList m_modules; 5049494c510SJonas Devlieghere lldb::addr_t m_load_addr = 0; 5052411167fSJim Ingham lldb::addr_t m_offset_addr; 5069494c510SJonas Devlieghere bool m_catch_bp = false; 5079494c510SJonas Devlieghere bool m_throw_bp = true; 5089494c510SJonas Devlieghere bool m_hardware = false; // Request to use hardware breakpoints 5099494c510SJonas Devlieghere lldb::LanguageType m_exception_language = eLanguageTypeUnknown; 5109494c510SJonas Devlieghere lldb::LanguageType m_language = lldb::eLanguageTypeUnknown; 5119494c510SJonas Devlieghere LazyBool m_skip_prologue = eLazyBoolCalculate; 5129494c510SJonas Devlieghere bool m_all_files = false; 513a72b31c7SJim Ingham Args m_exception_extra_args; 5149494c510SJonas Devlieghere LazyBool m_move_to_nearest_code = eLazyBoolCalculate; 51576bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 5163815e702SJim Ingham std::string m_current_key; 5175a988416SJim Ingham }; 5185a988416SJim Ingham 5195a988416SJim Ingham protected: 520b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 521cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); 52230fdc8d8SChris Lattner 52330fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 52430fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 52530fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 52630fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 527b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 528b9c1b51eSKate Stone // expression) 529b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 530b9c1b51eSKate Stone // to source text) 531b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 532b9c1b51eSKate Stone // given language.) 53330fdc8d8SChris Lattner 53430fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 53530fdc8d8SChris Lattner 536738af7a6SJim Ingham if (!m_python_class_options.GetName().empty()) 5373815e702SJim Ingham break_type = eSetTypeScripted; 5383815e702SJim Ingham else if (m_options.m_line_num != 0) 53930fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 54030fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 54130fdc8d8SChris Lattner break_type = eSetTypeAddress; 542fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 54330fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 54430fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 54530fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 546969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 547969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 548a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 549fab10e89SJim Ingham break_type = eSetTypeException; 55030fdc8d8SChris Lattner 551b842f2ecSJim Ingham BreakpointSP bp_sp = nullptr; 552274060b6SGreg Clayton FileSpec module_spec; 553a8558b62SJim Ingham const bool internal = false; 554a8558b62SJim Ingham 555b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 556b9c1b51eSKate Stone // that off. 557b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 558b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 5592411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 5602411167fSJim Ingham 561b9c1b51eSKate Stone switch (break_type) { 56230fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 56330fdc8d8SChris Lattner { 56430fdc8d8SChris Lattner FileSpec file; 565c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 566b9c1b51eSKate Stone if (num_files == 0) { 567b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 56887df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 56987df91b8SJim Ingham return false; 57087df91b8SJim Ingham } 571b9c1b51eSKate Stone } else if (num_files > 1) { 572b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 573b9c1b51eSKate Stone "line breakpoints."); 57487df91b8SJim Ingham return false; 575b9c1b51eSKate Stone } else 57687df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 57730fdc8d8SChris Lattner 5781f746071SGreg Clayton // Only check for inline functions if 5791f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 5801f746071SGreg Clayton 581cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint( 582cb2380c9SRaphael Isemann &(m_options.m_modules), file, m_options.m_line_num, 583cb2380c9SRaphael Isemann m_options.m_column, m_options.m_offset_addr, check_inlines, 584cb2380c9SRaphael Isemann m_options.m_skip_prologue, internal, m_options.m_hardware, 585b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 586b9c1b51eSKate Stone } break; 5876eee5aa0SGreg Clayton 58830fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 589055a08a4SJim Ingham { 590b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 591b842f2ecSJim Ingham // with the library, and use that. That way the address breakpoint 592b842f2ecSJim Ingham // will track the load location of the library. 593055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 594b9c1b51eSKate Stone if (num_modules_specified == 1) { 595b9c1b51eSKate Stone const FileSpec *file_spec = 596b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 597cb2380c9SRaphael Isemann bp_sp = target.CreateAddressInModuleBreakpoint( 598cb2380c9SRaphael Isemann m_options.m_load_addr, internal, file_spec, m_options.m_hardware); 599b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 600cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal, 601b842f2ecSJim Ingham m_options.m_hardware); 602b9c1b51eSKate Stone } else { 603b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 604b9c1b51eSKate Stone "address breakpoints."); 605055a08a4SJim Ingham return false; 606055a08a4SJim Ingham } 60730fdc8d8SChris Lattner break; 608055a08a4SJim Ingham } 60930fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 6100c5cd90dSGreg Clayton { 611117b1fa1SZachary Turner FunctionNameType name_type_mask = m_options.m_func_name_type_mask; 6120c5cd90dSGreg Clayton 6130c5cd90dSGreg Clayton if (name_type_mask == 0) 614e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 6150c5cd90dSGreg Clayton 616cb2380c9SRaphael Isemann bp_sp = target.CreateBreakpoint( 617cb2380c9SRaphael Isemann &(m_options.m_modules), &(m_options.m_filenames), 618cb2380c9SRaphael Isemann m_options.m_func_names, name_type_mask, m_options.m_language, 619cb2380c9SRaphael Isemann m_options.m_offset_addr, m_options.m_skip_prologue, internal, 620b842f2ecSJim Ingham m_options.m_hardware); 621b9c1b51eSKate Stone } break; 6220c5cd90dSGreg Clayton 623b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 624b9c1b51eSKate Stone // name 62530fdc8d8SChris Lattner { 62695eae423SZachary Turner RegularExpression regexp(m_options.m_func_regexp); 6273af3f1e8SJonas Devlieghere if (llvm::Error err = regexp.GetError()) { 628b9c1b51eSKate Stone result.AppendErrorWithFormat( 629b58af8d2SRaphael Isemann "Function name regular expression could not be compiled: %s", 6303af3f1e8SJonas Devlieghere llvm::toString(std::move(err)).c_str()); 631aaf68cd9SRaphael Isemann // Check if the incorrect regex looks like a globbing expression and 632aaf68cd9SRaphael Isemann // warn the user about it. 633aaf68cd9SRaphael Isemann if (!m_options.m_func_regexp.empty()) { 634aaf68cd9SRaphael Isemann if (m_options.m_func_regexp[0] == '*' || 635aaf68cd9SRaphael Isemann m_options.m_func_regexp[0] == '?') 636aaf68cd9SRaphael Isemann result.AppendWarning( 637aaf68cd9SRaphael Isemann "Function name regex does not accept glob patterns."); 638aaf68cd9SRaphael Isemann } 639969795f1SJim Ingham return false; 64030fdc8d8SChris Lattner } 64187df91b8SJim Ingham 642cb2380c9SRaphael Isemann bp_sp = target.CreateFuncRegexBreakpoint( 6435aa1d819SJan Kratochvil &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp), 644cb2380c9SRaphael Isemann m_options.m_language, m_options.m_skip_prologue, internal, 645b842f2ecSJim Ingham m_options.m_hardware); 646a925974bSAdrian Prantl } break; 647969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 648969795f1SJim Ingham { 649c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 65087df91b8SJim Ingham 651b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 652969795f1SJim Ingham FileSpec file; 653b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 654b9c1b51eSKate Stone result.AppendError( 655b9c1b51eSKate Stone "No files provided and could not find default file."); 65687df91b8SJim Ingham return false; 657b9c1b51eSKate Stone } else { 65887df91b8SJim Ingham m_options.m_filenames.Append(file); 65987df91b8SJim Ingham } 66087df91b8SJim Ingham } 6610c5cd90dSGreg Clayton 66295eae423SZachary Turner RegularExpression regexp(m_options.m_source_text_regexp); 6633af3f1e8SJonas Devlieghere if (llvm::Error err = regexp.GetError()) { 664b9c1b51eSKate Stone result.AppendErrorWithFormat( 665b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"", 6663af3f1e8SJonas Devlieghere llvm::toString(std::move(err)).c_str()); 667969795f1SJim Ingham return false; 668969795f1SJim Ingham } 669cb2380c9SRaphael Isemann bp_sp = target.CreateSourceRegexBreakpoint( 670cb2380c9SRaphael Isemann &(m_options.m_modules), &(m_options.m_filenames), 6715aa1d819SJan Kratochvil m_options.m_source_regex_func_names, std::move(regexp), internal, 672cb2380c9SRaphael Isemann m_options.m_hardware, m_options.m_move_to_nearest_code); 673b9c1b51eSKate Stone } break; 674b9c1b51eSKate Stone case eSetTypeException: { 67597206d57SZachary Turner Status precond_error; 676cb2380c9SRaphael Isemann bp_sp = target.CreateExceptionBreakpoint( 677cb2380c9SRaphael Isemann m_options.m_exception_language, m_options.m_catch_bp, 678cb2380c9SRaphael Isemann m_options.m_throw_bp, internal, &m_options.m_exception_extra_args, 679b842f2ecSJim Ingham &precond_error); 680b9c1b51eSKate Stone if (precond_error.Fail()) { 681b9c1b51eSKate Stone result.AppendErrorWithFormat( 682b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 683a72b31c7SJim Ingham precond_error.AsCString()); 684cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 685a72b31c7SJim Ingham return false; 686a72b31c7SJim Ingham } 687b9c1b51eSKate Stone } break; 6883815e702SJim Ingham case eSetTypeScripted: { 6893815e702SJim Ingham 6903815e702SJim Ingham Status error; 691cb2380c9SRaphael Isemann bp_sp = target.CreateScriptedBreakpoint( 692738af7a6SJim Ingham m_python_class_options.GetName().c_str(), &(m_options.m_modules), 693cb2380c9SRaphael Isemann &(m_options.m_filenames), false, m_options.m_hardware, 694943a2481SJim Ingham m_python_class_options.GetStructuredData(), &error); 6953815e702SJim Ingham if (error.Fail()) { 6963815e702SJim Ingham result.AppendErrorWithFormat( 697a925974bSAdrian Prantl "Error setting extra exception arguments: %s", error.AsCString()); 698cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 6993815e702SJim Ingham return false; 7003815e702SJim Ingham } 7013815e702SJim Ingham } break; 70230fdc8d8SChris Lattner default: 70330fdc8d8SChris Lattner break; 70430fdc8d8SChris Lattner } 70530fdc8d8SChris Lattner 7061b54c88cSJim Ingham // Now set the various options that were passed in: 707b842f2ecSJim Ingham if (bp_sp) { 708cfb96d84SJim Ingham bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 709ca36cd16SJim Ingham 710b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 71197206d57SZachary Turner Status name_error; 712ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) { 713cb2380c9SRaphael Isemann target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error); 714ff9a91eaSJim Ingham if (name_error.Fail()) { 715ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s", 716ff9a91eaSJim Ingham name.c_str()); 717cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp_sp->GetID()); 718ff9a91eaSJim Ingham return false; 719ff9a91eaSJim Ingham } 720ff9a91eaSJim Ingham } 7215e09c8c3SJim Ingham } 7221b54c88cSJim Ingham } 7231b54c88cSJim Ingham 724b842f2ecSJim Ingham if (bp_sp) { 72585e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 7261391cc7dSJim Ingham const bool show_locations = false; 727b842f2ecSJim Ingham bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 728b9c1b51eSKate Stone show_locations); 729cb2380c9SRaphael Isemann if (&target == &GetDummyTarget()) 730b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 731b9c1b51eSKate Stone "into future targets.\n"); 732b9c1b51eSKate Stone else { 73305097246SAdrian Prantl // Don't print out this warning for exception breakpoints. They can 73405097246SAdrian Prantl // get set before the target is set, but we won't know how to actually 73505097246SAdrian Prantl // set the breakpoint till we run. 736b842f2ecSJim Ingham if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { 737b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 738b9c1b51eSKate Stone "actual locations.\n"); 7394aeb1989SJim Ingham } 7404aeb1989SJim Ingham } 74130fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 742b842f2ecSJim Ingham } else if (!bp_sp) { 74330fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 74430fdc8d8SChris Lattner } 74530fdc8d8SChris Lattner 74630fdc8d8SChris Lattner return result.Succeeded(); 74730fdc8d8SChris Lattner } 74830fdc8d8SChris Lattner 7495a988416SJim Ingham private: 750cb2380c9SRaphael Isemann bool GetDefaultFile(Target &target, FileSpec &file, 751b9c1b51eSKate Stone CommandReturnObject &result) { 7525a988416SJim Ingham uint32_t default_line; 75305097246SAdrian Prantl // First use the Source Manager's default file. Then use the current stack 75405097246SAdrian Prantl // frame's file. 755cb2380c9SRaphael Isemann if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 756b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 757b9c1b51eSKate Stone if (cur_frame == nullptr) { 758b9c1b51eSKate Stone result.AppendError( 759b9c1b51eSKate Stone "No selected frame to use to find the default file."); 7605a988416SJim Ingham return false; 761b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 762b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 763b9c1b51eSKate Stone "file, it has no debug info."); 7645a988416SJim Ingham return false; 765b9c1b51eSKate Stone } else { 766b9c1b51eSKate Stone const SymbolContext &sc = 767b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 768b9c1b51eSKate Stone if (sc.line_entry.file) { 7695a988416SJim Ingham file = sc.line_entry.file; 770b9c1b51eSKate Stone } else { 771b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 772b9c1b51eSKate Stone "use as the default file."); 7735a988416SJim Ingham return false; 7745a988416SJim Ingham } 7755a988416SJim Ingham } 7765a988416SJim Ingham } 7775a988416SJim Ingham return true; 7785a988416SJim Ingham } 7795a988416SJim Ingham 780b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 781b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_options; 782943a2481SJim Ingham OptionGroupPythonClassWithDict m_python_class_options; 7835a988416SJim Ingham CommandOptions m_options; 784b842f2ecSJim Ingham OptionGroupOptions m_all_options; 7855a988416SJim Ingham }; 7869e85e5a8SEugene Zelenko 7875a988416SJim Ingham // CommandObjectBreakpointModify 7885a988416SJim Ingham #pragma mark Modify 7895a988416SJim Ingham 790b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 7915a988416SJim Ingham public: 792b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 793b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 794b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 795b9c1b51eSKate Stone "breakpoints in the executable. " 796b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 797b9c1b51eSKate Stone "created breakpoint. " 798b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 799b9c1b51eSKate Stone "empty argument clears the modification.", 8009e85e5a8SEugene Zelenko nullptr), 801b9c1b51eSKate Stone m_options() { 8025a988416SJim Ingham CommandArgumentEntry arg; 803b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 804b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 805b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 806b9c1b51eSKate Stone // arguments vector. 8075a988416SJim Ingham m_arguments.push_back(arg); 808b842f2ecSJim Ingham 809b842f2ecSJim Ingham m_options.Append(&m_bp_opts, 810b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, 811b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 812b842f2ecSJim Ingham m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 813b842f2ecSJim Ingham m_options.Finalize(); 8145a988416SJim Ingham } 8155a988416SJim Ingham 8169e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 8175a988416SJim Ingham 8180e50b9a4SGongyu Deng void 8190e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 8200e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 8210e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 8220e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 8230e50b9a4SGongyu Deng request, nullptr); 8240e50b9a4SGongyu Deng } 8250e50b9a4SGongyu Deng 826b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 8275a988416SJim Ingham 8285a988416SJim Ingham protected: 829b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 830cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 8315a988416SJim Ingham 832bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 833cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 8345a988416SJim Ingham 8355a988416SJim Ingham BreakpointIDList valid_bp_ids; 8365a988416SJim Ingham 837b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 838cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 839b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 8405a988416SJim Ingham 841b9c1b51eSKate Stone if (result.Succeeded()) { 8425a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 843b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 8445a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 8455a988416SJim Ingham 846b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 847b9c1b51eSKate Stone Breakpoint *bp = 848cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 849b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 850b9c1b51eSKate Stone BreakpointLocation *location = 851b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 852b842f2ecSJim Ingham if (location) 853cfb96d84SJim Ingham location->GetLocationOptions().CopyOverSetOptions( 854a925974bSAdrian Prantl m_bp_opts.GetBreakpointOptions()); 855b9c1b51eSKate Stone } else { 856cfb96d84SJim Ingham bp->GetOptions().CopyOverSetOptions( 857a925974bSAdrian Prantl m_bp_opts.GetBreakpointOptions()); 8585a988416SJim Ingham } 8595a988416SJim Ingham } 8605a988416SJim Ingham } 8615a988416SJim Ingham } 8625a988416SJim Ingham 8635a988416SJim Ingham return result.Succeeded(); 8645a988416SJim Ingham } 8655a988416SJim Ingham 8665a988416SJim Ingham private: 867b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 868b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_opts; 869b842f2ecSJim Ingham OptionGroupOptions m_options; 8705a988416SJim Ingham }; 8715a988416SJim Ingham 8725a988416SJim Ingham // CommandObjectBreakpointEnable 8735a988416SJim Ingham #pragma mark Enable 8745a988416SJim Ingham 875b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 8765a988416SJim Ingham public: 877b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 878b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 879b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 880b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 881b9c1b51eSKate Stone nullptr) { 8825a988416SJim Ingham CommandArgumentEntry arg; 883b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 884b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 885b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 886b9c1b51eSKate Stone // arguments vector. 8875a988416SJim Ingham m_arguments.push_back(arg); 8885a988416SJim Ingham } 8895a988416SJim Ingham 8909e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 8915a988416SJim Ingham 8920e50b9a4SGongyu Deng void 8930e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 8940e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 8950e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 8960e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 8970e50b9a4SGongyu Deng request, nullptr); 8980e50b9a4SGongyu Deng } 8990e50b9a4SGongyu Deng 9005a988416SJim Ingham protected: 901b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 902cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 9035a988416SJim Ingham 904bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 905cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 9065a988416SJim Ingham 907cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 9085a988416SJim Ingham 9095a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 9105a988416SJim Ingham 911b9c1b51eSKate Stone if (num_breakpoints == 0) { 9125a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 9135a988416SJim Ingham return false; 9145a988416SJim Ingham } 9155a988416SJim Ingham 91611eb9c64SZachary Turner if (command.empty()) { 9175a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 918cb2380c9SRaphael Isemann target.EnableAllowedBreakpoints(); 919b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 920b9c1b51eSKate Stone " breakpoints)\n", 921b9c1b51eSKate Stone (uint64_t)num_breakpoints); 9225a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 923b9c1b51eSKate Stone } else { 9245a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 9255a988416SJim Ingham BreakpointIDList valid_bp_ids; 926b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 927cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 928b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 9295a988416SJim Ingham 930b9c1b51eSKate Stone if (result.Succeeded()) { 9315a988416SJim Ingham int enable_count = 0; 9325a988416SJim Ingham int loc_count = 0; 9335a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 934b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 9355a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 9365a988416SJim Ingham 937b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 938b9c1b51eSKate Stone Breakpoint *breakpoint = 939cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 940b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 941b9c1b51eSKate Stone BreakpointLocation *location = 942b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 943b9c1b51eSKate Stone if (location) { 9445a988416SJim Ingham location->SetEnabled(true); 9455a988416SJim Ingham ++loc_count; 9465a988416SJim Ingham } 947b9c1b51eSKate Stone } else { 9485a988416SJim Ingham breakpoint->SetEnabled(true); 9495a988416SJim Ingham ++enable_count; 9505a988416SJim Ingham } 9515a988416SJim Ingham } 9525a988416SJim Ingham } 953b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 954b9c1b51eSKate Stone enable_count + loc_count); 9555a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 9565a988416SJim Ingham } 9575a988416SJim Ingham } 9585a988416SJim Ingham 9595a988416SJim Ingham return result.Succeeded(); 9605a988416SJim Ingham } 9615a988416SJim Ingham }; 9625a988416SJim Ingham 9635a988416SJim Ingham // CommandObjectBreakpointDisable 9645a988416SJim Ingham #pragma mark Disable 9655a988416SJim Ingham 966b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 9675a988416SJim Ingham public: 9687428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 969b9c1b51eSKate Stone : CommandObjectParsed( 970b9c1b51eSKate Stone interpreter, "breakpoint disable", 971b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 9727428a18cSKate Stone "them. If none are specified, disable all " 9737428a18cSKate Stone "breakpoints.", 974b9c1b51eSKate Stone nullptr) { 975b9c1b51eSKate Stone SetHelpLong( 976b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 9777428a18cSKate Stone If none are specified, disable all breakpoints." 9787428a18cSKate Stone R"( 979ea671fbdSKate Stone 9807428a18cSKate Stone )" 9817428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 9827428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 9837428a18cSKate Stone R"( 984ea671fbdSKate Stone 985ea671fbdSKate Stone (lldb) break disable 1 986ea671fbdSKate Stone (lldb) break enable 1.1 987ea671fbdSKate Stone 988ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 989ea671fbdSKate Stone 990ea671fbdSKate Stone (lldb) break disable 1.* 991ea671fbdSKate Stone (lldb) break enable 1.1 992ea671fbdSKate Stone 9937428a18cSKate Stone )" 9947428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 9957428a18cSKate Stone the second re-enables the first location."); 996b0fac509SJim Ingham 9975a988416SJim Ingham CommandArgumentEntry arg; 998b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 999b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1000b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1001b9c1b51eSKate Stone // arguments vector. 10025a988416SJim Ingham m_arguments.push_back(arg); 10035a988416SJim Ingham } 10045a988416SJim Ingham 10059e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 10065a988416SJim Ingham 10070e50b9a4SGongyu Deng void 10080e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 10090e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 10100e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 10110e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 10120e50b9a4SGongyu Deng request, nullptr); 10130e50b9a4SGongyu Deng } 10140e50b9a4SGongyu Deng 10155a988416SJim Ingham protected: 1016b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1017cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 1018bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1019cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 10205a988416SJim Ingham 1021cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 10225a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 10235a988416SJim Ingham 1024b9c1b51eSKate Stone if (num_breakpoints == 0) { 10255a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 10265a988416SJim Ingham return false; 10275a988416SJim Ingham } 10285a988416SJim Ingham 102911eb9c64SZachary Turner if (command.empty()) { 10305a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 1031cb2380c9SRaphael Isemann target.DisableAllowedBreakpoints(); 1032b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1033b9c1b51eSKate Stone " breakpoints)\n", 1034b9c1b51eSKate Stone (uint64_t)num_breakpoints); 10355a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1036b9c1b51eSKate Stone } else { 10375a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 10385a988416SJim Ingham BreakpointIDList valid_bp_ids; 10395a988416SJim Ingham 1040b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1041cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1042b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 10435a988416SJim Ingham 1044b9c1b51eSKate Stone if (result.Succeeded()) { 10455a988416SJim Ingham int disable_count = 0; 10465a988416SJim Ingham int loc_count = 0; 10475a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1048b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 10495a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 10505a988416SJim Ingham 1051b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1052b9c1b51eSKate Stone Breakpoint *breakpoint = 1053cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1054b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1055b9c1b51eSKate Stone BreakpointLocation *location = 1056b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1057b9c1b51eSKate Stone if (location) { 10585a988416SJim Ingham location->SetEnabled(false); 10595a988416SJim Ingham ++loc_count; 10605a988416SJim Ingham } 1061b9c1b51eSKate Stone } else { 10625a988416SJim Ingham breakpoint->SetEnabled(false); 10635a988416SJim Ingham ++disable_count; 10645a988416SJim Ingham } 10655a988416SJim Ingham } 10665a988416SJim Ingham } 1067b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1068b9c1b51eSKate Stone disable_count + loc_count); 10695a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 10705a988416SJim Ingham } 10715a988416SJim Ingham } 10725a988416SJim Ingham 10735a988416SJim Ingham return result.Succeeded(); 10745a988416SJim Ingham } 10755a988416SJim Ingham }; 10765a988416SJim Ingham 10775a988416SJim Ingham // CommandObjectBreakpointList 10781f0f5b5bSZachary Turner 10791f0f5b5bSZachary Turner #pragma mark List::CommandOptions 10806f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list 1081c5a2d747SRaphael Isemann #include "CommandOptions.inc" 10821f0f5b5bSZachary Turner 10835a988416SJim Ingham #pragma mark List 10845a988416SJim Ingham 1085b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 10865a988416SJim Ingham public: 1087b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1088b9c1b51eSKate Stone : CommandObjectParsed( 1089b9c1b51eSKate Stone interpreter, "breakpoint list", 10905a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 10919e85e5a8SEugene Zelenko nullptr), 1092b9c1b51eSKate Stone m_options() { 10935a988416SJim Ingham CommandArgumentEntry arg; 10945a988416SJim Ingham CommandArgumentData bp_id_arg; 10955a988416SJim Ingham 10965a988416SJim Ingham // Define the first (and only) variant of this arg. 10975a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 10985a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 10995a988416SJim Ingham 1100b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1101b9c1b51eSKate Stone // argument entry. 11025a988416SJim Ingham arg.push_back(bp_id_arg); 11035a988416SJim Ingham 11045a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 11055a988416SJim Ingham m_arguments.push_back(arg); 11065a988416SJim Ingham } 11075a988416SJim Ingham 11089e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 11095a988416SJim Ingham 1110b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 11115a988416SJim Ingham 1112b9c1b51eSKate Stone class CommandOptions : public Options { 11135a988416SJim Ingham public: 11149494c510SJonas Devlieghere CommandOptions() : Options() {} 11155a988416SJim Ingham 11169e85e5a8SEugene Zelenko ~CommandOptions() override = default; 11175a988416SJim Ingham 111897206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1119b9c1b51eSKate Stone ExecutionContext *execution_context) override { 112097206d57SZachary Turner Status error; 11213bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 11225a988416SJim Ingham 1123b9c1b51eSKate Stone switch (short_option) { 11245a988416SJim Ingham case 'b': 11255a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 11265a988416SJim Ingham break; 112733df7cd3SJim Ingham case 'D': 112833df7cd3SJim Ingham m_use_dummy = true; 112933df7cd3SJim Ingham break; 11305a988416SJim Ingham case 'f': 11315a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 11325a988416SJim Ingham break; 11335a988416SJim Ingham case 'v': 11345a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 11355a988416SJim Ingham break; 11365a988416SJim Ingham case 'i': 11375a988416SJim Ingham m_internal = true; 11385a988416SJim Ingham break; 11395a988416SJim Ingham default: 114036162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 11415a988416SJim Ingham } 11425a988416SJim Ingham 11435a988416SJim Ingham return error; 11445a988416SJim Ingham } 11455a988416SJim Ingham 1146b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 11475a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 11485a988416SJim Ingham m_internal = false; 114933df7cd3SJim Ingham m_use_dummy = false; 11505a988416SJim Ingham } 11515a988416SJim Ingham 11521f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 115370602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_list_options); 11541f0f5b5bSZachary Turner } 11555a988416SJim Ingham 11565a988416SJim Ingham // Instance variables to hold the values for command options. 11575a988416SJim Ingham 11589494c510SJonas Devlieghere lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief; 11595a988416SJim Ingham 11605a988416SJim Ingham bool m_internal; 11619494c510SJonas Devlieghere bool m_use_dummy = false; 11625a988416SJim Ingham }; 11635a988416SJim Ingham 11645a988416SJim Ingham protected: 1165b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1166cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 11675a988416SJim Ingham 1168b9c1b51eSKate Stone const BreakpointList &breakpoints = 1169cb2380c9SRaphael Isemann target.GetBreakpointList(m_options.m_internal); 1170bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1171cb2380c9SRaphael Isemann target.GetBreakpointList(m_options.m_internal).GetListMutex(lock); 11725a988416SJim Ingham 11735a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 11745a988416SJim Ingham 1175b9c1b51eSKate Stone if (num_breakpoints == 0) { 11765a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 11775a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 11785a988416SJim Ingham return true; 11795a988416SJim Ingham } 11805a988416SJim Ingham 11815a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 11825a988416SJim Ingham 118311eb9c64SZachary Turner if (command.empty()) { 11845a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 11855a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1186b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 11875a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1188b842f2ecSJim Ingham if (breakpoint->AllowList()) 1189b842f2ecSJim Ingham AddBreakpointDescription(&output_stream, breakpoint, 1190b842f2ecSJim Ingham m_options.m_level); 11915a988416SJim Ingham } 11925a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1193b9c1b51eSKate Stone } else { 11945a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 11955a988416SJim Ingham BreakpointIDList valid_bp_ids; 1196b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1197cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1198b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 11995a988416SJim Ingham 1200b9c1b51eSKate Stone if (result.Succeeded()) { 1201b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 12025a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1203b9c1b51eSKate Stone Breakpoint *breakpoint = 1204cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1205b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1206b9c1b51eSKate Stone m_options.m_level); 12075a988416SJim Ingham } 12085a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1209b9c1b51eSKate Stone } else { 12107428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 12115a988416SJim Ingham } 12125a988416SJim Ingham } 12135a988416SJim Ingham 12145a988416SJim Ingham return result.Succeeded(); 12155a988416SJim Ingham } 12165a988416SJim Ingham 12175a988416SJim Ingham private: 12185a988416SJim Ingham CommandOptions m_options; 12195a988416SJim Ingham }; 12205a988416SJim Ingham 12215a988416SJim Ingham // CommandObjectBreakpointClear 12221f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions 12231f0f5b5bSZachary Turner 1224f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear 1225f94668e3SRaphael Isemann #include "CommandOptions.inc" 12261f0f5b5bSZachary Turner 12275a988416SJim Ingham #pragma mark Clear 12285a988416SJim Ingham 1229b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed { 12305a988416SJim Ingham public: 1231efe8e7e3SFangrui Song enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine }; 12325a988416SJim Ingham 12337428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter) 12347428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear", 1235b9c1b51eSKate Stone "Delete or disable breakpoints matching the " 1236b9c1b51eSKate Stone "specified source file and line.", 12375a988416SJim Ingham "breakpoint clear <cmd-options>"), 1238b9c1b51eSKate Stone m_options() {} 12395a988416SJim Ingham 12409e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default; 12415a988416SJim Ingham 1242b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 12435a988416SJim Ingham 1244b9c1b51eSKate Stone class CommandOptions : public Options { 12455a988416SJim Ingham public: 12469494c510SJonas Devlieghere CommandOptions() : Options(), m_filename() {} 12475a988416SJim Ingham 12489e85e5a8SEugene Zelenko ~CommandOptions() override = default; 12495a988416SJim Ingham 125097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1251b9c1b51eSKate Stone ExecutionContext *execution_context) override { 125297206d57SZachary Turner Status error; 12533bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 12545a988416SJim Ingham 1255b9c1b51eSKate Stone switch (short_option) { 12565a988416SJim Ingham case 'f': 1257adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 12585a988416SJim Ingham break; 12595a988416SJim Ingham 12605a988416SJim Ingham case 'l': 1261fe11483bSZachary Turner option_arg.getAsInteger(0, m_line_num); 12625a988416SJim Ingham break; 12635a988416SJim Ingham 12645a988416SJim Ingham default: 126536162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 12665a988416SJim Ingham } 12675a988416SJim Ingham 12685a988416SJim Ingham return error; 12695a988416SJim Ingham } 12705a988416SJim Ingham 1271b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 12725a988416SJim Ingham m_filename.clear(); 12735a988416SJim Ingham m_line_num = 0; 12745a988416SJim Ingham } 12755a988416SJim Ingham 12761f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 127770602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_clear_options); 12781f0f5b5bSZachary Turner } 12795a988416SJim Ingham 12805a988416SJim Ingham // Instance variables to hold the values for command options. 12815a988416SJim Ingham 12825a988416SJim Ingham std::string m_filename; 12839494c510SJonas Devlieghere uint32_t m_line_num = 0; 12845a988416SJim Ingham }; 12855a988416SJim Ingham 12865a988416SJim Ingham protected: 1287b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1288cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 12895a988416SJim Ingham 129005097246SAdrian Prantl // The following are the various types of breakpoints that could be 129105097246SAdrian Prantl // cleared: 12925a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 12935a988416SJim Ingham 12945a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 12955a988416SJim Ingham 12965a988416SJim Ingham if (m_options.m_line_num != 0) 12975a988416SJim Ingham break_type = eClearTypeFileAndLine; 12985a988416SJim Ingham 1299bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1300cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 13015a988416SJim Ingham 1302cb2380c9SRaphael Isemann BreakpointList &breakpoints = target.GetBreakpointList(); 13035a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 13045a988416SJim Ingham 13055a988416SJim Ingham // Early return if there's no breakpoint at all. 1306b9c1b51eSKate Stone if (num_breakpoints == 0) { 13075a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 13085a988416SJim Ingham return result.Succeeded(); 13095a988416SJim Ingham } 13105a988416SJim Ingham 13115a988416SJim Ingham // Find matching breakpoints and delete them. 13125a988416SJim Ingham 13135a988416SJim Ingham // First create a copy of all the IDs. 13145a988416SJim Ingham std::vector<break_id_t> BreakIDs; 13155a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 13169e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 13175a988416SJim Ingham 13185a988416SJim Ingham int num_cleared = 0; 13195a988416SJim Ingham StreamString ss; 1320b9c1b51eSKate Stone switch (break_type) { 13215a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 13225a988416SJim Ingham { 13235a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 13245a988416SJim Ingham BreakpointLocationCollection loc_coll; 13255a988416SJim Ingham 1326b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 13275a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 13285a988416SJim Ingham 1329b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1330b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1331b9c1b51eSKate Stone // remove the breakpoint. 1332b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 13335a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 13345a988416SJim Ingham ss.EOL(); 1335cb2380c9SRaphael Isemann target.RemoveBreakpointByID(bp->GetID()); 13365a988416SJim Ingham ++num_cleared; 13375a988416SJim Ingham } 13385a988416SJim Ingham } 13395a988416SJim Ingham } 1340b9c1b51eSKate Stone } break; 13415a988416SJim Ingham 13425a988416SJim Ingham default: 13435a988416SJim Ingham break; 13445a988416SJim Ingham } 13455a988416SJim Ingham 1346b9c1b51eSKate Stone if (num_cleared > 0) { 13475a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 13485a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1349c156427dSZachary Turner output_stream << ss.GetString(); 13505a988416SJim Ingham output_stream.EOL(); 13515a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1352b9c1b51eSKate Stone } else { 13535a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 13545a988416SJim Ingham } 13555a988416SJim Ingham 13565a988416SJim Ingham return result.Succeeded(); 13575a988416SJim Ingham } 13585a988416SJim Ingham 13595a988416SJim Ingham private: 13605a988416SJim Ingham CommandOptions m_options; 13615a988416SJim Ingham }; 13625a988416SJim Ingham 13635a988416SJim Ingham // CommandObjectBreakpointDelete 1364f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete 1365f94668e3SRaphael Isemann #include "CommandOptions.inc" 13661f0f5b5bSZachary Turner 13675a988416SJim Ingham #pragma mark Delete 13685a988416SJim Ingham 1369b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 13705a988416SJim Ingham public: 1371b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1372b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1373b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1374b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 13759e85e5a8SEugene Zelenko nullptr), 1376b9c1b51eSKate Stone m_options() { 13775a988416SJim Ingham CommandArgumentEntry arg; 1378b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1379b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1380b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1381b9c1b51eSKate Stone // arguments vector. 13825a988416SJim Ingham m_arguments.push_back(arg); 13835a988416SJim Ingham } 13845a988416SJim Ingham 13859e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 13865a988416SJim Ingham 13870e50b9a4SGongyu Deng void 13880e50b9a4SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 13890e50b9a4SGongyu Deng OptionElementVector &opt_element_vector) override { 13900e50b9a4SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 13910e50b9a4SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 13920e50b9a4SGongyu Deng request, nullptr); 13930e50b9a4SGongyu Deng } 13940e50b9a4SGongyu Deng 1395b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 139633df7cd3SJim Ingham 1397b9c1b51eSKate Stone class CommandOptions : public Options { 139833df7cd3SJim Ingham public: 13999494c510SJonas Devlieghere CommandOptions() : Options() {} 140033df7cd3SJim Ingham 14019e85e5a8SEugene Zelenko ~CommandOptions() override = default; 140233df7cd3SJim Ingham 140397206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1404b9c1b51eSKate Stone ExecutionContext *execution_context) override { 140597206d57SZachary Turner Status error; 140633df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 140733df7cd3SJim Ingham 1408b9c1b51eSKate Stone switch (short_option) { 140933df7cd3SJim Ingham case 'f': 141033df7cd3SJim Ingham m_force = true; 141133df7cd3SJim Ingham break; 141233df7cd3SJim Ingham 141333df7cd3SJim Ingham case 'D': 141433df7cd3SJim Ingham m_use_dummy = true; 141533df7cd3SJim Ingham break; 141633df7cd3SJim Ingham 14173726ac41SJim Ingham case 'd': 14183726ac41SJim Ingham m_delete_disabled = true; 14193726ac41SJim Ingham break; 14203726ac41SJim Ingham 142133df7cd3SJim Ingham default: 142236162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 142333df7cd3SJim Ingham } 142433df7cd3SJim Ingham 142533df7cd3SJim Ingham return error; 142633df7cd3SJim Ingham } 142733df7cd3SJim Ingham 1428b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 142933df7cd3SJim Ingham m_use_dummy = false; 143033df7cd3SJim Ingham m_force = false; 14313726ac41SJim Ingham m_delete_disabled = false; 143233df7cd3SJim Ingham } 143333df7cd3SJim Ingham 14341f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 143570602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_delete_options); 14361f0f5b5bSZachary Turner } 143733df7cd3SJim Ingham 143833df7cd3SJim Ingham // Instance variables to hold the values for command options. 14399494c510SJonas Devlieghere bool m_use_dummy = false; 14409494c510SJonas Devlieghere bool m_force = false; 14419494c510SJonas Devlieghere bool m_delete_disabled = false; 144233df7cd3SJim Ingham }; 144333df7cd3SJim Ingham 14445a988416SJim Ingham protected: 1445b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1446cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 14473726ac41SJim Ingham result.Clear(); 14485a988416SJim Ingham 1449bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1450cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 14515a988416SJim Ingham 14523726ac41SJim Ingham BreakpointList &breakpoints = target.GetBreakpointList(); 14535a988416SJim Ingham 14545a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 14555a988416SJim Ingham 1456b9c1b51eSKate Stone if (num_breakpoints == 0) { 14575a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 14585a988416SJim Ingham return false; 14595a988416SJim Ingham } 14605a988416SJim Ingham 1461*0018c712SJim Ingham // Handle the delete all breakpoints case: 14623726ac41SJim Ingham if (command.empty() && !m_options.m_delete_disabled) { 1463b9c1b51eSKate Stone if (!m_options.m_force && 1464b9c1b51eSKate Stone !m_interpreter.Confirm( 1465b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1466b9c1b51eSKate Stone true)) { 14675a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1468b9c1b51eSKate Stone } else { 1469cb2380c9SRaphael Isemann target.RemoveAllowedBreakpoints(); 1470b9c1b51eSKate Stone result.AppendMessageWithFormat( 1471b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1472b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 14735a988416SJim Ingham } 14745a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1475*0018c712SJim Ingham return result.Succeeded(); 1476*0018c712SJim Ingham } 1477*0018c712SJim Ingham 1478*0018c712SJim Ingham // Either we have some kind of breakpoint specification(s), 1479*0018c712SJim Ingham // or we are handling "break disable --deleted". Gather the list 1480*0018c712SJim Ingham // of breakpoints to delete here, the we'll delete them below. 14815a988416SJim Ingham BreakpointIDList valid_bp_ids; 14823726ac41SJim Ingham 14833726ac41SJim Ingham if (m_options.m_delete_disabled) { 14843726ac41SJim Ingham BreakpointIDList excluded_bp_ids; 14853726ac41SJim Ingham 14863726ac41SJim Ingham if (!command.empty()) { 14873726ac41SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 14883726ac41SJim Ingham command, &target, result, &excluded_bp_ids, 14893726ac41SJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 1490*0018c712SJim Ingham if (!result.Succeeded()) 1491*0018c712SJim Ingham return false; 14923726ac41SJim Ingham } 1493*0018c712SJim Ingham 14943726ac41SJim Ingham for (auto breakpoint_sp : breakpoints.Breakpoints()) { 14953726ac41SJim Ingham if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) { 14963726ac41SJim Ingham BreakpointID bp_id(breakpoint_sp->GetID()); 14973726ac41SJim Ingham size_t pos = 0; 14983726ac41SJim Ingham if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos)) 14993726ac41SJim Ingham valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID()); 15003726ac41SJim Ingham } 15013726ac41SJim Ingham } 15023726ac41SJim Ingham if (valid_bp_ids.GetSize() == 0) { 15033726ac41SJim Ingham result.AppendError("No disabled breakpoints."); 15043726ac41SJim Ingham return false; 15053726ac41SJim Ingham } 15063726ac41SJim Ingham } else { 1507b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1508cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1509b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 1510*0018c712SJim Ingham if (!result.Succeeded()) 1511*0018c712SJim Ingham return false; 15123726ac41SJim Ingham } 15135a988416SJim Ingham 15145a988416SJim Ingham int delete_count = 0; 15155a988416SJim Ingham int disable_count = 0; 15165a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1517b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 15185a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 15195a988416SJim Ingham 1520b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1521b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1522b9c1b51eSKate Stone Breakpoint *breakpoint = 1523cb2380c9SRaphael Isemann target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1524b9c1b51eSKate Stone BreakpointLocation *location = 1525b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1526b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1527b9c1b51eSKate Stone // disable them instead. 1528b9c1b51eSKate Stone if (location) { 15295a988416SJim Ingham location->SetEnabled(false); 15305a988416SJim Ingham ++disable_count; 15315a988416SJim Ingham } 1532b9c1b51eSKate Stone } else { 1533cb2380c9SRaphael Isemann target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 15345a988416SJim Ingham ++delete_count; 15355a988416SJim Ingham } 15365a988416SJim Ingham } 15375a988416SJim Ingham } 1538b9c1b51eSKate Stone result.AppendMessageWithFormat( 1539b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 15405a988416SJim Ingham delete_count, disable_count); 15415a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 15425a988416SJim Ingham return result.Succeeded(); 15435a988416SJim Ingham } 15449e85e5a8SEugene Zelenko 154533df7cd3SJim Ingham private: 154633df7cd3SJim Ingham CommandOptions m_options; 154733df7cd3SJim Ingham }; 154833df7cd3SJim Ingham 15495e09c8c3SJim Ingham // CommandObjectBreakpointName 1550f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name 1551f94668e3SRaphael Isemann #include "CommandOptions.inc" 1552bd68a052SRaphael Isemann 1553b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 15545e09c8c3SJim Ingham public: 1555b9c1b51eSKate Stone BreakpointNameOptionGroup() 1556b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 15575e09c8c3SJim Ingham } 15585e09c8c3SJim Ingham 15599e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 15605e09c8c3SJim Ingham 15611f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 156270602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_name_options); 15635e09c8c3SJim Ingham } 15645e09c8c3SJim Ingham 156597206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1566b9c1b51eSKate Stone ExecutionContext *execution_context) override { 156797206d57SZachary Turner Status error; 15685e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 15695e09c8c3SJim Ingham 1570b9c1b51eSKate Stone switch (short_option) { 15715e09c8c3SJim Ingham case 'N': 1572fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1573b9c1b51eSKate Stone error.Success()) 1574fe11483bSZachary Turner m_name.SetValueFromString(option_arg); 15755e09c8c3SJim Ingham break; 15765e09c8c3SJim Ingham case 'B': 1577fe11483bSZachary Turner if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1578b9c1b51eSKate Stone error.SetErrorStringWithFormat( 15798cef4b0bSZachary Turner "unrecognized value \"%s\" for breakpoint", 1580fe11483bSZachary Turner option_arg.str().c_str()); 15815e09c8c3SJim Ingham break; 15825e09c8c3SJim Ingham case 'D': 1583fe11483bSZachary Turner if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1584b9c1b51eSKate Stone error.SetErrorStringWithFormat( 15858cef4b0bSZachary Turner "unrecognized value \"%s\" for use-dummy", 1586fe11483bSZachary Turner option_arg.str().c_str()); 15875e09c8c3SJim Ingham break; 1588e9632ebaSJim Ingham case 'H': 1589e9632ebaSJim Ingham m_help_string.SetValueFromString(option_arg); 1590e9632ebaSJim Ingham break; 15915e09c8c3SJim Ingham 15925e09c8c3SJim Ingham default: 159336162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 15945e09c8c3SJim Ingham } 15955e09c8c3SJim Ingham return error; 15965e09c8c3SJim Ingham } 15975e09c8c3SJim Ingham 1598b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 15995e09c8c3SJim Ingham m_name.Clear(); 16005e09c8c3SJim Ingham m_breakpoint.Clear(); 16015e09c8c3SJim Ingham m_use_dummy.Clear(); 16025e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 1603e9632ebaSJim Ingham m_help_string.Clear(); 16045e09c8c3SJim Ingham } 16055e09c8c3SJim Ingham 16065e09c8c3SJim Ingham OptionValueString m_name; 16075e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 16085e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 1609e9632ebaSJim Ingham OptionValueString m_help_string; 16105e09c8c3SJim Ingham }; 16115e09c8c3SJim Ingham 1612f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access 1613f94668e3SRaphael Isemann #include "CommandOptions.inc" 1614b842f2ecSJim Ingham 16158fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup { 1616b842f2ecSJim Ingham public: 16178fe53c49STatyana Krasnukha BreakpointAccessOptionGroup() : OptionGroup() {} 1618b842f2ecSJim Ingham 1619b842f2ecSJim Ingham ~BreakpointAccessOptionGroup() override = default; 1620b842f2ecSJim Ingham 1621b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1622b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_access_options); 1623b842f2ecSJim Ingham } 1624b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1625b842f2ecSJim Ingham ExecutionContext *execution_context) override { 1626b842f2ecSJim Ingham Status error; 1627a925974bSAdrian Prantl const int short_option = 1628a925974bSAdrian Prantl g_breakpoint_access_options[option_idx].short_option; 1629b842f2ecSJim Ingham 1630b842f2ecSJim Ingham switch (short_option) { 1631b842f2ecSJim Ingham case 'L': { 1632b842f2ecSJim Ingham bool value, success; 163347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1634b842f2ecSJim Ingham if (success) { 1635b842f2ecSJim Ingham m_permissions.SetAllowList(value); 1636b842f2ecSJim Ingham } else 1637b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1638b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1639b842f2ecSJim Ingham option_arg.str().c_str()); 1640b842f2ecSJim Ingham } break; 1641b842f2ecSJim Ingham case 'A': { 1642b842f2ecSJim Ingham bool value, success; 164347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1644b842f2ecSJim Ingham if (success) { 1645b842f2ecSJim Ingham m_permissions.SetAllowDisable(value); 1646b842f2ecSJim Ingham } else 1647b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1648b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1649b842f2ecSJim Ingham option_arg.str().c_str()); 1650b842f2ecSJim Ingham } break; 1651b842f2ecSJim Ingham case 'D': { 1652b842f2ecSJim Ingham bool value, success; 165347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1654b842f2ecSJim Ingham if (success) { 1655b842f2ecSJim Ingham m_permissions.SetAllowDelete(value); 1656b842f2ecSJim Ingham } else 1657b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1658b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1659b842f2ecSJim Ingham option_arg.str().c_str()); 1660b842f2ecSJim Ingham } break; 166136162014SRaphael Isemann default: 166236162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 1663b842f2ecSJim Ingham } 1664b842f2ecSJim Ingham 1665b842f2ecSJim Ingham return error; 1666b842f2ecSJim Ingham } 1667b842f2ecSJim Ingham 1668a925974bSAdrian Prantl void OptionParsingStarting(ExecutionContext *execution_context) override {} 1669b842f2ecSJim Ingham 1670a925974bSAdrian Prantl const BreakpointName::Permissions &GetPermissions() const { 1671b842f2ecSJim Ingham return m_permissions; 1672b842f2ecSJim Ingham } 1673b842f2ecSJim Ingham BreakpointName::Permissions m_permissions; 1674b842f2ecSJim Ingham }; 1675b842f2ecSJim Ingham 1676b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1677b842f2ecSJim Ingham public: 1678b842f2ecSJim Ingham CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1679b842f2ecSJim Ingham : CommandObjectParsed( 1680a925974bSAdrian Prantl interpreter, "configure", 1681a925974bSAdrian Prantl "Configure the options for the breakpoint" 1682b842f2ecSJim Ingham " name provided. " 1683b842f2ecSJim Ingham "If you provide a breakpoint id, the options will be copied from " 1684b842f2ecSJim Ingham "the breakpoint, otherwise only the options specified will be set " 1685b842f2ecSJim Ingham "on the name.", 1686b842f2ecSJim Ingham "breakpoint name configure <command-options> " 1687b842f2ecSJim Ingham "<breakpoint-name-list>"), 1688b842f2ecSJim Ingham m_bp_opts(), m_option_group() { 1689b842f2ecSJim Ingham // Create the first variant for the first (and only) argument for this 1690b842f2ecSJim Ingham // command. 1691b842f2ecSJim Ingham CommandArgumentEntry arg1; 1692b842f2ecSJim Ingham CommandArgumentData id_arg; 1693b842f2ecSJim Ingham id_arg.arg_type = eArgTypeBreakpointName; 1694b842f2ecSJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 1695b842f2ecSJim Ingham arg1.push_back(id_arg); 1696b842f2ecSJim Ingham m_arguments.push_back(arg1); 1697b842f2ecSJim Ingham 1698a925974bSAdrian Prantl m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1699a925974bSAdrian Prantl m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL, 1700b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 1701a925974bSAdrian Prantl m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4, 1702e9632ebaSJim Ingham LLDB_OPT_SET_ALL); 1703b842f2ecSJim Ingham m_option_group.Finalize(); 1704b842f2ecSJim Ingham } 1705b842f2ecSJim Ingham 1706b842f2ecSJim Ingham ~CommandObjectBreakpointNameConfigure() override = default; 1707b842f2ecSJim Ingham 1708b842f2ecSJim Ingham Options *GetOptions() override { return &m_option_group; } 1709b842f2ecSJim Ingham 1710b842f2ecSJim Ingham protected: 1711b842f2ecSJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 1712b842f2ecSJim Ingham 1713b842f2ecSJim Ingham const size_t argc = command.GetArgumentCount(); 1714b842f2ecSJim Ingham if (argc == 0) { 1715b842f2ecSJim Ingham result.AppendError("No names provided."); 1716b842f2ecSJim Ingham return false; 1717b842f2ecSJim Ingham } 1718b842f2ecSJim Ingham 1719cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(false); 1720b842f2ecSJim Ingham 1721b842f2ecSJim Ingham std::unique_lock<std::recursive_mutex> lock; 1722cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 1723b842f2ecSJim Ingham 1724b842f2ecSJim Ingham // Make a pass through first to see that all the names are legal. 1725b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1726b842f2ecSJim Ingham Status error; 1727a925974bSAdrian Prantl if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) { 1728b842f2ecSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1729b842f2ecSJim Ingham entry.c_str(), error.AsCString()); 1730b842f2ecSJim Ingham return false; 1731b842f2ecSJim Ingham } 1732b842f2ecSJim Ingham } 173305097246SAdrian Prantl // Now configure them, we already pre-checked the names so we don't need to 173405097246SAdrian Prantl // check the error: 1735b842f2ecSJim Ingham BreakpointSP bp_sp; 1736a925974bSAdrian Prantl if (m_bp_id.m_breakpoint.OptionWasSet()) { 1737b842f2ecSJim Ingham lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1738cb2380c9SRaphael Isemann bp_sp = target.GetBreakpointByID(bp_id); 1739a925974bSAdrian Prantl if (!bp_sp) { 1740b842f2ecSJim Ingham result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1741b842f2ecSJim Ingham bp_id); 1742b842f2ecSJim Ingham return false; 1743b842f2ecSJim Ingham } 1744b842f2ecSJim Ingham } 1745b842f2ecSJim Ingham 1746b842f2ecSJim Ingham Status error; 1747b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1748b842f2ecSJim Ingham ConstString name(entry.c_str()); 1749cb2380c9SRaphael Isemann BreakpointName *bp_name = target.FindBreakpointName(name, true, error); 1750b842f2ecSJim Ingham if (!bp_name) 1751b842f2ecSJim Ingham continue; 1752e9632ebaSJim Ingham if (m_bp_id.m_help_string.OptionWasSet()) 1753e9632ebaSJim Ingham bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1754e9632ebaSJim Ingham 1755b842f2ecSJim Ingham if (bp_sp) 1756cfb96d84SJim Ingham target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(), 1757b842f2ecSJim Ingham m_access_options.GetPermissions()); 1758b842f2ecSJim Ingham else 1759cb2380c9SRaphael Isemann target.ConfigureBreakpointName(*bp_name, 1760b842f2ecSJim Ingham m_bp_opts.GetBreakpointOptions(), 1761b842f2ecSJim Ingham m_access_options.GetPermissions()); 1762b842f2ecSJim Ingham } 1763b842f2ecSJim Ingham return true; 1764b842f2ecSJim Ingham } 1765b842f2ecSJim Ingham 1766b842f2ecSJim Ingham private: 1767b842f2ecSJim Ingham BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1768b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 1769b842f2ecSJim Ingham BreakpointAccessOptionGroup m_access_options; 1770b842f2ecSJim Ingham OptionGroupOptions m_option_group; 1771b842f2ecSJim Ingham }; 1772b842f2ecSJim Ingham 1773b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 17745e09c8c3SJim Ingham public: 1775b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1776b9c1b51eSKate Stone : CommandObjectParsed( 1777b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 17785e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 1779b9c1b51eSKate Stone m_name_options(), m_option_group() { 1780b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1781b9c1b51eSKate Stone // command. 17825e09c8c3SJim Ingham CommandArgumentEntry arg1; 17835e09c8c3SJim Ingham CommandArgumentData id_arg; 17845e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 17855e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 17865e09c8c3SJim Ingham arg1.push_back(id_arg); 17875e09c8c3SJim Ingham m_arguments.push_back(arg1); 17885e09c8c3SJim Ingham 17895e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 17905e09c8c3SJim Ingham m_option_group.Finalize(); 17915e09c8c3SJim Ingham } 17925e09c8c3SJim Ingham 17939e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 17945e09c8c3SJim Ingham 1795e87362e6SGongyu Deng void 1796e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 1797e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 1798e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 1799e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 1800e87362e6SGongyu Deng request, nullptr); 1801e87362e6SGongyu Deng } 1802e87362e6SGongyu Deng 1803b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 18045e09c8c3SJim Ingham 18055e09c8c3SJim Ingham protected: 1806b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1807b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 18081b1c8e4aSDavid Spickett result.AppendError("No name option provided."); 18095e09c8c3SJim Ingham return false; 18105e09c8c3SJim Ingham } 18115e09c8c3SJim Ingham 1812cb2380c9SRaphael Isemann Target &target = 1813b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 18145e09c8c3SJim Ingham 1815bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1816cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 18175e09c8c3SJim Ingham 1818cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 18195e09c8c3SJim Ingham 18205e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1821b9c1b51eSKate Stone if (num_breakpoints == 0) { 18221b1c8e4aSDavid Spickett result.AppendError("No breakpoints, cannot add names."); 18235e09c8c3SJim Ingham return false; 18245e09c8c3SJim Ingham } 18255e09c8c3SJim Ingham 18265e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 18275e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1828b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1829cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1830b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 18315e09c8c3SJim Ingham 1832b9c1b51eSKate Stone if (result.Succeeded()) { 1833b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 18341b1c8e4aSDavid Spickett result.AppendError("No breakpoints specified, cannot add names."); 18355e09c8c3SJim Ingham return false; 18365e09c8c3SJim Ingham } 18375e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1838b842f2ecSJim Ingham const char *bp_name = m_name_options.m_name.GetCurrentValue(); 1839b842f2ecSJim Ingham Status error; // This error reports illegal names, but we've already 1840b842f2ecSJim Ingham // checked that, so we don't need to check it again here. 1841b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1842b9c1b51eSKate Stone lldb::break_id_t bp_id = 1843b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 18445e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1845cb2380c9SRaphael Isemann target.AddNameToBreakpoint(bp_sp, bp_name, error); 18465e09c8c3SJim Ingham } 18475e09c8c3SJim Ingham } 18485e09c8c3SJim Ingham 18495e09c8c3SJim Ingham return true; 18505e09c8c3SJim Ingham } 18515e09c8c3SJim Ingham 18525e09c8c3SJim Ingham private: 18535e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 18545e09c8c3SJim Ingham OptionGroupOptions m_option_group; 18555e09c8c3SJim Ingham }; 18565e09c8c3SJim Ingham 1857b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 18585e09c8c3SJim Ingham public: 1859b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1860b9c1b51eSKate Stone : CommandObjectParsed( 1861b9c1b51eSKate Stone interpreter, "delete", 18625e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 18635e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 1864b9c1b51eSKate Stone m_name_options(), m_option_group() { 1865b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1866b9c1b51eSKate Stone // command. 18675e09c8c3SJim Ingham CommandArgumentEntry arg1; 18685e09c8c3SJim Ingham CommandArgumentData id_arg; 18695e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 18705e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 18715e09c8c3SJim Ingham arg1.push_back(id_arg); 18725e09c8c3SJim Ingham m_arguments.push_back(arg1); 18735e09c8c3SJim Ingham 18745e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 18755e09c8c3SJim Ingham m_option_group.Finalize(); 18765e09c8c3SJim Ingham } 18775e09c8c3SJim Ingham 18789e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 18795e09c8c3SJim Ingham 1880e87362e6SGongyu Deng void 1881e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 1882e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 1883e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 1884e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 1885e87362e6SGongyu Deng request, nullptr); 1886e87362e6SGongyu Deng } 1887e87362e6SGongyu Deng 1888b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 18895e09c8c3SJim Ingham 18905e09c8c3SJim Ingham protected: 1891b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1892b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 18931b1c8e4aSDavid Spickett result.AppendError("No name option provided."); 18945e09c8c3SJim Ingham return false; 18955e09c8c3SJim Ingham } 18965e09c8c3SJim Ingham 1897cb2380c9SRaphael Isemann Target &target = 1898b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 18995e09c8c3SJim Ingham 1900bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1901cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 19025e09c8c3SJim Ingham 1903cb2380c9SRaphael Isemann const BreakpointList &breakpoints = target.GetBreakpointList(); 19045e09c8c3SJim Ingham 19055e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1906b9c1b51eSKate Stone if (num_breakpoints == 0) { 19071b1c8e4aSDavid Spickett result.AppendError("No breakpoints, cannot delete names."); 19085e09c8c3SJim Ingham return false; 19095e09c8c3SJim Ingham } 19105e09c8c3SJim Ingham 19115e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 19125e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1913b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1914cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 1915b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 19165e09c8c3SJim Ingham 1917b9c1b51eSKate Stone if (result.Succeeded()) { 1918b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 19191b1c8e4aSDavid Spickett result.AppendError("No breakpoints specified, cannot delete names."); 19205e09c8c3SJim Ingham return false; 19215e09c8c3SJim Ingham } 1922b842f2ecSJim Ingham ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 19235e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1924b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1925b9c1b51eSKate Stone lldb::break_id_t bp_id = 1926b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 19275e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1928cb2380c9SRaphael Isemann target.RemoveNameFromBreakpoint(bp_sp, bp_name); 19295e09c8c3SJim Ingham } 19305e09c8c3SJim Ingham } 19315e09c8c3SJim Ingham 19325e09c8c3SJim Ingham return true; 19335e09c8c3SJim Ingham } 19345e09c8c3SJim Ingham 19355e09c8c3SJim Ingham private: 19365e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19375e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19385e09c8c3SJim Ingham }; 19395e09c8c3SJim Ingham 1940b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 19415e09c8c3SJim Ingham public: 1942b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 1943b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 1944b842f2ecSJim Ingham "List either the names for a breakpoint or info " 1945b842f2ecSJim Ingham "about a given name. With no arguments, lists all " 1946b842f2ecSJim Ingham "names", 19475e09c8c3SJim Ingham "breakpoint name list <command-options>"), 1948b9c1b51eSKate Stone m_name_options(), m_option_group() { 1949b842f2ecSJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 19505e09c8c3SJim Ingham m_option_group.Finalize(); 19515e09c8c3SJim Ingham } 19525e09c8c3SJim Ingham 19539e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 19545e09c8c3SJim Ingham 1955b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19565e09c8c3SJim Ingham 19575e09c8c3SJim Ingham protected: 1958b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1959cb2380c9SRaphael Isemann Target &target = 1960b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19615e09c8c3SJim Ingham 1962b842f2ecSJim Ingham std::vector<std::string> name_list; 1963b842f2ecSJim Ingham if (command.empty()) { 1964cb2380c9SRaphael Isemann target.GetBreakpointNames(name_list); 1965b842f2ecSJim Ingham } else { 1966a925974bSAdrian Prantl for (const Args::ArgEntry &arg : command) { 1967b842f2ecSJim Ingham name_list.push_back(arg.c_str()); 1968b842f2ecSJim Ingham } 1969b842f2ecSJim Ingham } 1970b842f2ecSJim Ingham 1971b842f2ecSJim Ingham if (name_list.empty()) { 1972b842f2ecSJim Ingham result.AppendMessage("No breakpoint names found."); 1973b842f2ecSJim Ingham } else { 1974b842f2ecSJim Ingham for (const std::string &name_str : name_list) { 1975b842f2ecSJim Ingham const char *name = name_str.c_str(); 1976b842f2ecSJim Ingham // First print out the options for the name: 1977b842f2ecSJim Ingham Status error; 1978cb2380c9SRaphael Isemann BreakpointName *bp_name = 1979cb2380c9SRaphael Isemann target.FindBreakpointName(ConstString(name), false, error); 1980a925974bSAdrian Prantl if (bp_name) { 1981b842f2ecSJim Ingham StreamString s; 1982b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s\n", name); 1983a925974bSAdrian Prantl if (bp_name->GetDescription(&s, eDescriptionLevelFull)) { 1984b842f2ecSJim Ingham result.AppendMessage(s.GetString()); 1985b842f2ecSJim Ingham } 1986b842f2ecSJim Ingham 1987bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1988cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 19895e09c8c3SJim Ingham 1990cb2380c9SRaphael Isemann BreakpointList &breakpoints = target.GetBreakpointList(); 1991b842f2ecSJim Ingham bool any_set = false; 1992b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 1993b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 19945e09c8c3SJim Ingham StreamString s; 1995b842f2ecSJim Ingham any_set = true; 19965e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 19975e09c8c3SJim Ingham s.EOL(); 1998c156427dSZachary Turner result.AppendMessage(s.GetString()); 19995e09c8c3SJim Ingham } 20005e09c8c3SJim Ingham } 2001b842f2ecSJim Ingham if (!any_set) 2002b842f2ecSJim Ingham result.AppendMessage("No breakpoints using this name."); 2003b9c1b51eSKate Stone } else { 2004b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s not found.\n", name); 20055e09c8c3SJim Ingham } 2006b842f2ecSJim Ingham } 20075e09c8c3SJim Ingham } 20085e09c8c3SJim Ingham return true; 20095e09c8c3SJim Ingham } 20105e09c8c3SJim Ingham 20115e09c8c3SJim Ingham private: 20125e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20135e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20145e09c8c3SJim Ingham }; 20155e09c8c3SJim Ingham 2016e14dc268SJim Ingham // CommandObjectBreakpointName 2017b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 20185e09c8c3SJim Ingham public: 20197428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2020b9c1b51eSKate Stone : CommandObjectMultiword( 2021b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2022b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2023b9c1b51eSKate Stone CommandObjectSP add_command_object( 2024b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2025b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2026b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2027b9c1b51eSKate Stone CommandObjectSP list_command_object( 2028b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 2029b842f2ecSJim Ingham CommandObjectSP configure_command_object( 2030b842f2ecSJim Ingham new CommandObjectBreakpointNameConfigure(interpreter)); 20315e09c8c3SJim Ingham 20325e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 20335e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 20345e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 2035b842f2ecSJim Ingham LoadSubCommand("configure", configure_command_object); 20365e09c8c3SJim Ingham } 20375e09c8c3SJim Ingham 20389e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 20395e09c8c3SJim Ingham }; 20405e09c8c3SJim Ingham 2041e14dc268SJim Ingham // CommandObjectBreakpointRead 20423acdf385SJim Ingham #pragma mark Read::CommandOptions 2043f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read 2044f94668e3SRaphael Isemann #include "CommandOptions.inc" 20451f0f5b5bSZachary Turner 20461f0f5b5bSZachary Turner #pragma mark Read 2047e14dc268SJim Ingham 2048e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed { 2049e14dc268SJim Ingham public: 2050e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2051e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read", 2052e14dc268SJim Ingham "Read and set the breakpoints previously saved to " 2053e14dc268SJim Ingham "a file with \"breakpoint write\". ", 2054e14dc268SJim Ingham nullptr), 20557c89297cSGongyu Deng m_options() {} 2056e14dc268SJim Ingham 2057e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default; 2058e14dc268SJim Ingham 2059e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2060e14dc268SJim Ingham 2061e14dc268SJim Ingham class CommandOptions : public Options { 2062e14dc268SJim Ingham public: 2063e14dc268SJim Ingham CommandOptions() : Options() {} 2064e14dc268SJim Ingham 2065e14dc268SJim Ingham ~CommandOptions() override = default; 2066e14dc268SJim Ingham 206797206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2068e14dc268SJim Ingham ExecutionContext *execution_context) override { 206997206d57SZachary Turner Status error; 2070e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2071e14dc268SJim Ingham 2072e14dc268SJim Ingham switch (short_option) { 2073e14dc268SJim Ingham case 'f': 2074adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 2075e14dc268SJim Ingham break; 20763acdf385SJim Ingham case 'N': { 207797206d57SZachary Turner Status name_error; 20783acdf385SJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 20793acdf385SJim Ingham name_error)) { 20803acdf385SJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 20813acdf385SJim Ingham name_error.AsCString()); 20823acdf385SJim Ingham } 2083adcd0268SBenjamin Kramer m_names.push_back(std::string(option_arg)); 20843acdf385SJim Ingham break; 20853acdf385SJim Ingham } 2086e14dc268SJim Ingham default: 208736162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 2088e14dc268SJim Ingham } 2089e14dc268SJim Ingham 2090e14dc268SJim Ingham return error; 2091e14dc268SJim Ingham } 2092e14dc268SJim Ingham 2093e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2094e14dc268SJim Ingham m_filename.clear(); 20953acdf385SJim Ingham m_names.clear(); 2096e14dc268SJim Ingham } 2097e14dc268SJim Ingham 20981f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 209970602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_read_options); 21001f0f5b5bSZachary Turner } 2101e14dc268SJim Ingham 210222e63cbaSGongyu Deng void HandleOptionArgumentCompletion( 210322e63cbaSGongyu Deng CompletionRequest &request, OptionElementVector &opt_element_vector, 210422e63cbaSGongyu Deng int opt_element_index, CommandInterpreter &interpreter) override { 210522e63cbaSGongyu Deng int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 210622e63cbaSGongyu Deng int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 210722e63cbaSGongyu Deng 210822e63cbaSGongyu Deng switch (GetDefinitions()[opt_defs_index].short_option) { 210922e63cbaSGongyu Deng case 'f': 211022e63cbaSGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 211122e63cbaSGongyu Deng interpreter, CommandCompletions::eDiskFileCompletion, request, 211222e63cbaSGongyu Deng nullptr); 211322e63cbaSGongyu Deng break; 211422e63cbaSGongyu Deng 211522e63cbaSGongyu Deng case 'N': 211622e63cbaSGongyu Deng llvm::Optional<FileSpec> file_spec; 211722e63cbaSGongyu Deng const llvm::StringRef dash_f("-f"); 211822e63cbaSGongyu Deng for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) { 211922e63cbaSGongyu Deng if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) { 212022e63cbaSGongyu Deng file_spec.emplace( 212122e63cbaSGongyu Deng request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1)); 212222e63cbaSGongyu Deng break; 212322e63cbaSGongyu Deng } 212422e63cbaSGongyu Deng } 212522e63cbaSGongyu Deng if (!file_spec) 212622e63cbaSGongyu Deng return; 212722e63cbaSGongyu Deng 212822e63cbaSGongyu Deng FileSystem::Instance().Resolve(*file_spec); 212922e63cbaSGongyu Deng Status error; 213022e63cbaSGongyu Deng StructuredData::ObjectSP input_data_sp = 213122e63cbaSGongyu Deng StructuredData::ParseJSONFromFile(*file_spec, error); 213222e63cbaSGongyu Deng if (!error.Success()) 213322e63cbaSGongyu Deng return; 213422e63cbaSGongyu Deng 213522e63cbaSGongyu Deng StructuredData::Array *bkpt_array = input_data_sp->GetAsArray(); 213622e63cbaSGongyu Deng if (!bkpt_array) 213722e63cbaSGongyu Deng return; 213822e63cbaSGongyu Deng 213922e63cbaSGongyu Deng const size_t num_bkpts = bkpt_array->GetSize(); 214022e63cbaSGongyu Deng for (size_t i = 0; i < num_bkpts; i++) { 214122e63cbaSGongyu Deng StructuredData::ObjectSP bkpt_object_sp = 214222e63cbaSGongyu Deng bkpt_array->GetItemAtIndex(i); 214322e63cbaSGongyu Deng if (!bkpt_object_sp) 214422e63cbaSGongyu Deng return; 214522e63cbaSGongyu Deng 214622e63cbaSGongyu Deng StructuredData::Dictionary *bkpt_dict = 214722e63cbaSGongyu Deng bkpt_object_sp->GetAsDictionary(); 214822e63cbaSGongyu Deng if (!bkpt_dict) 214922e63cbaSGongyu Deng return; 215022e63cbaSGongyu Deng 215122e63cbaSGongyu Deng StructuredData::ObjectSP bkpt_data_sp = 215222e63cbaSGongyu Deng bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey()); 215322e63cbaSGongyu Deng if (!bkpt_data_sp) 215422e63cbaSGongyu Deng return; 215522e63cbaSGongyu Deng 215622e63cbaSGongyu Deng bkpt_dict = bkpt_data_sp->GetAsDictionary(); 215722e63cbaSGongyu Deng if (!bkpt_dict) 215822e63cbaSGongyu Deng return; 215922e63cbaSGongyu Deng 216022e63cbaSGongyu Deng StructuredData::Array *names_array; 216122e63cbaSGongyu Deng 216222e63cbaSGongyu Deng if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array)) 216322e63cbaSGongyu Deng return; 216422e63cbaSGongyu Deng 216522e63cbaSGongyu Deng size_t num_names = names_array->GetSize(); 216622e63cbaSGongyu Deng 216722e63cbaSGongyu Deng for (size_t i = 0; i < num_names; i++) { 216822e63cbaSGongyu Deng llvm::StringRef name; 216922e63cbaSGongyu Deng if (names_array->GetItemAtIndexAsString(i, name)) 217022e63cbaSGongyu Deng request.TryCompleteCurrentArg(name); 217122e63cbaSGongyu Deng } 217222e63cbaSGongyu Deng } 217322e63cbaSGongyu Deng } 217422e63cbaSGongyu Deng } 2175e14dc268SJim Ingham 2176e14dc268SJim Ingham std::string m_filename; 21773acdf385SJim Ingham std::vector<std::string> m_names; 2178e14dc268SJim Ingham }; 2179e14dc268SJim Ingham 2180e14dc268SJim Ingham protected: 2181e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2182cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 2183e14dc268SJim Ingham 21843acdf385SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2185cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 21863acdf385SJim Ingham 21878f3be7a3SJonas Devlieghere FileSpec input_spec(m_options.m_filename); 21888f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(input_spec); 218901f16664SJim Ingham BreakpointIDList new_bps; 2190cb2380c9SRaphael Isemann Status error = target.CreateBreakpointsFromFile(input_spec, 2191cb2380c9SRaphael Isemann m_options.m_names, new_bps); 2192e14dc268SJim Ingham 2193e14dc268SJim Ingham if (!error.Success()) { 219401f16664SJim Ingham result.AppendError(error.AsCString()); 219501f16664SJim Ingham return false; 2196e14dc268SJim Ingham } 21973acdf385SJim Ingham 21983acdf385SJim Ingham Stream &output_stream = result.GetOutputStream(); 21993acdf385SJim Ingham 22003acdf385SJim Ingham size_t num_breakpoints = new_bps.GetSize(); 22013acdf385SJim Ingham if (num_breakpoints == 0) { 22023acdf385SJim Ingham result.AppendMessage("No breakpoints added."); 22033acdf385SJim Ingham } else { 22043acdf385SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 22053acdf385SJim Ingham result.AppendMessage("New breakpoints:"); 22063acdf385SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) { 22073acdf385SJim Ingham BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 2208cb2380c9SRaphael Isemann Breakpoint *bp = target.GetBreakpointList() 22093acdf385SJim Ingham .FindBreakpointByID(bp_id.GetBreakpointID()) 22103acdf385SJim Ingham .get(); 22113acdf385SJim Ingham if (bp) 22123acdf385SJim Ingham bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 22133acdf385SJim Ingham false); 22143acdf385SJim Ingham } 22153acdf385SJim Ingham } 2216e14dc268SJim Ingham return result.Succeeded(); 2217e14dc268SJim Ingham } 2218e14dc268SJim Ingham 2219e14dc268SJim Ingham private: 2220e14dc268SJim Ingham CommandOptions m_options; 2221e14dc268SJim Ingham }; 2222e14dc268SJim Ingham 2223e14dc268SJim Ingham // CommandObjectBreakpointWrite 22241f0f5b5bSZachary Turner #pragma mark Write::CommandOptions 2225f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write 2226f94668e3SRaphael Isemann #include "CommandOptions.inc" 22271f0f5b5bSZachary Turner 22281f0f5b5bSZachary Turner #pragma mark Write 2229e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed { 2230e14dc268SJim Ingham public: 2231e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2232e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write", 2233e14dc268SJim Ingham "Write the breakpoints listed to a file that can " 2234e14dc268SJim Ingham "be read in with \"breakpoint read\". " 2235e14dc268SJim Ingham "If given no arguments, writes all breakpoints.", 2236e14dc268SJim Ingham nullptr), 2237e14dc268SJim Ingham m_options() { 2238e14dc268SJim Ingham CommandArgumentEntry arg; 2239e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2240e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2241e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2242e14dc268SJim Ingham // arguments vector. 2243e14dc268SJim Ingham m_arguments.push_back(arg); 2244e14dc268SJim Ingham } 2245e14dc268SJim Ingham 2246e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default; 2247e14dc268SJim Ingham 2248e87362e6SGongyu Deng void 2249e87362e6SGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 2250e87362e6SGongyu Deng OptionElementVector &opt_element_vector) override { 2251e87362e6SGongyu Deng CommandCompletions::InvokeCommonCompletionCallbacks( 2252e87362e6SGongyu Deng GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 2253e87362e6SGongyu Deng request, nullptr); 2254e87362e6SGongyu Deng } 2255e87362e6SGongyu Deng 2256e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2257e14dc268SJim Ingham 2258e14dc268SJim Ingham class CommandOptions : public Options { 2259e14dc268SJim Ingham public: 2260e14dc268SJim Ingham CommandOptions() : Options() {} 2261e14dc268SJim Ingham 2262e14dc268SJim Ingham ~CommandOptions() override = default; 2263e14dc268SJim Ingham 226497206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2265e14dc268SJim Ingham ExecutionContext *execution_context) override { 226697206d57SZachary Turner Status error; 2267e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2268e14dc268SJim Ingham 2269e14dc268SJim Ingham switch (short_option) { 2270e14dc268SJim Ingham case 'f': 2271adcd0268SBenjamin Kramer m_filename.assign(std::string(option_arg)); 2272e14dc268SJim Ingham break; 22732d3628e1SJim Ingham case 'a': 22742d3628e1SJim Ingham m_append = true; 22752d3628e1SJim Ingham break; 2276e14dc268SJim Ingham default: 227736162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 2278e14dc268SJim Ingham } 2279e14dc268SJim Ingham 2280e14dc268SJim Ingham return error; 2281e14dc268SJim Ingham } 2282e14dc268SJim Ingham 2283e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2284e14dc268SJim Ingham m_filename.clear(); 22852d3628e1SJim Ingham m_append = false; 2286e14dc268SJim Ingham } 2287e14dc268SJim Ingham 22881f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 228970602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_write_options); 22901f0f5b5bSZachary Turner } 2291e14dc268SJim Ingham 2292e14dc268SJim Ingham // Instance variables to hold the values for command options. 2293e14dc268SJim Ingham 2294e14dc268SJim Ingham std::string m_filename; 22952d3628e1SJim Ingham bool m_append = false; 2296e14dc268SJim Ingham }; 2297e14dc268SJim Ingham 2298e14dc268SJim Ingham protected: 2299e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2300cb2380c9SRaphael Isemann Target &target = GetSelectedOrDummyTarget(); 2301e14dc268SJim Ingham 2302e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2303cb2380c9SRaphael Isemann target.GetBreakpointList().GetListMutex(lock); 2304e14dc268SJim Ingham 2305e14dc268SJim Ingham BreakpointIDList valid_bp_ids; 230611eb9c64SZachary Turner if (!command.empty()) { 2307e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2308cb2380c9SRaphael Isemann command, &target, result, &valid_bp_ids, 2309b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 2310e14dc268SJim Ingham 231101f16664SJim Ingham if (!result.Succeeded()) { 2312e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2313e14dc268SJim Ingham return false; 2314e14dc268SJim Ingham } 2315e14dc268SJim Ingham } 23168f3be7a3SJonas Devlieghere FileSpec file_spec(m_options.m_filename); 23178f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(file_spec); 2318cb2380c9SRaphael Isemann Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids, 23198f3be7a3SJonas Devlieghere m_options.m_append); 232001f16664SJim Ingham if (!error.Success()) { 232101f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.", 232201f16664SJim Ingham error.AsCString()); 2323e14dc268SJim Ingham } 2324e14dc268SJim Ingham return result.Succeeded(); 2325e14dc268SJim Ingham } 2326e14dc268SJim Ingham 2327e14dc268SJim Ingham private: 2328e14dc268SJim Ingham CommandOptions m_options; 2329e14dc268SJim Ingham }; 2330e14dc268SJim Ingham 233130fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 2332ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 233330fdc8d8SChris Lattner 2334b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2335b9c1b51eSKate Stone CommandInterpreter &interpreter) 2336b9c1b51eSKate Stone : CommandObjectMultiword( 2337b9c1b51eSKate Stone interpreter, "breakpoint", 23387428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2339b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2340b9c1b51eSKate Stone CommandObjectSP list_command_object( 2341b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2342b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2343b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2344b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2345b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2346b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2347b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2348b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2349b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2350b9c1b51eSKate Stone CommandObjectSP set_command_object( 2351b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2352b9c1b51eSKate Stone CommandObjectSP command_command_object( 2353b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2354b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2355b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2356b9c1b51eSKate Stone CommandObjectSP name_command_object( 2357b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 2358e14dc268SJim Ingham CommandObjectSP write_command_object( 2359e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter)); 2360e14dc268SJim Ingham CommandObjectSP read_command_object( 2361e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter)); 236230fdc8d8SChris Lattner 2363b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 236430fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 236530fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2366b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2367b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2368ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2369b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2370b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 23715e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 2372e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write"); 2373e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read"); 237430fdc8d8SChris Lattner 237523f59509SGreg Clayton LoadSubCommand("list", list_command_object); 237623f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 237723f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 237823f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 237923f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 238023f59509SGreg Clayton LoadSubCommand("set", set_command_object); 238123f59509SGreg Clayton LoadSubCommand("command", command_command_object); 238223f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 23835e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 2384e14dc268SJim Ingham LoadSubCommand("write", write_command_object); 2385e14dc268SJim Ingham LoadSubCommand("read", read_command_object); 238630fdc8d8SChris Lattner } 238730fdc8d8SChris Lattner 23889e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 238930fdc8d8SChris Lattner 2390a925974bSAdrian Prantl void CommandObjectMultiwordBreakpoint::VerifyIDs( 2391a925974bSAdrian Prantl Args &args, Target *target, bool allow_locations, 2392a925974bSAdrian Prantl CommandReturnObject &result, BreakpointIDList *valid_ids, 2393a925974bSAdrian Prantl BreakpointName::Permissions ::PermissionKinds purpose) { 239430fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2395b9c1b51eSKate Stone // 2). the full breakpoint & location 2396b9c1b51eSKate Stone // canonical representation 2397b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2398b9c1b51eSKate Stone // representing a range (in which case there 2399b9c1b51eSKate Stone // had *better* be an entry both before & 2400b9c1b51eSKate Stone // after of one of the first two types. 24015e09c8c3SJim Ingham // 4). A breakpoint name 2402b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2403b9c1b51eSKate Stone // one.) 240430fdc8d8SChris Lattner 240530fdc8d8SChris Lattner Args temp_args; 240630fdc8d8SChris Lattner 240711eb9c64SZachary Turner if (args.empty()) { 2408b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2409b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2410b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 241136f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2412b9c1b51eSKate Stone } else { 2413b9c1b51eSKate Stone result.AppendError( 2414b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 241536f3b369SJim Ingham } 241636f3b369SJim Ingham return; 241736f3b369SJim Ingham } 241836f3b369SJim Ingham 2419b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 242005097246SAdrian Prantl // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 242105097246SAdrian Prantl // id range strings over; instead generate a list of strings for all the 242205097246SAdrian Prantl // breakpoint ids in the range, and shove all of those breakpoint id strings 242305097246SAdrian Prantl // into TEMP_ARGS. 242430fdc8d8SChris Lattner 2425b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2426b842f2ecSJim Ingham purpose, result, temp_args); 242730fdc8d8SChris Lattner 2428b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2429b9c1b51eSKate Stone // BreakpointIDList: 243030fdc8d8SChris Lattner 243116662f3cSPavel Labath valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 243230fdc8d8SChris Lattner 243305097246SAdrian Prantl // At this point, all of the breakpoint ids that the user passed in have 243405097246SAdrian Prantl // been converted to breakpoint IDs and put into valid_ids. 243530fdc8d8SChris Lattner 2436b9c1b51eSKate Stone if (result.Succeeded()) { 2437b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 243805097246SAdrian Prantl // ids, go through our tentative list of breakpoint id's and verify that 243905097246SAdrian Prantl // they correspond to valid/currently set breakpoints. 244030fdc8d8SChris Lattner 2441c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2442b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 244330fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2444b9c1b51eSKate Stone Breakpoint *breakpoint = 2445b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2446b9c1b51eSKate Stone if (breakpoint != nullptr) { 2447c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2448b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 244930fdc8d8SChris Lattner StreamString id_str; 2450b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2451b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2452c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2453b9c1b51eSKate Stone result.AppendErrorWithFormat( 2454b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 245530fdc8d8SChris Lattner id_str.GetData()); 245630fdc8d8SChris Lattner } 2457b9c1b51eSKate Stone } else { 2458c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2459b9c1b51eSKate Stone result.AppendErrorWithFormat( 2460b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 24617428a18cSKate Stone cur_bp_id.GetBreakpointID()); 246230fdc8d8SChris Lattner } 246330fdc8d8SChris Lattner } 246430fdc8d8SChris Lattner } 246530fdc8d8SChris Lattner } 2466