130fdc8d8SChris Lattner //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===// 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/CommandCompletions.h" 16b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h" 17b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h" 1847cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h" 1932abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h" 205e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h" 215e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h" 22b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 230e0984eeSJim Ingham #include "lldb/Target/Language.h" 24b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 25b9c1b51eSKate Stone #include "lldb/Target/Target.h" 261b54c88cSJim Ingham #include "lldb/Target/Thread.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 478fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_modify_options[] = { 48*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify 49*f94668e3SRaphael Isemann #include "CommandOptions.inc" 50b842f2ecSJim Ingham }; 51b842f2ecSJim Ingham class lldb_private::BreakpointOptionGroup : public OptionGroup 52b842f2ecSJim Ingham { 53b842f2ecSJim Ingham public: 54b842f2ecSJim Ingham BreakpointOptionGroup() : 55b842f2ecSJim Ingham OptionGroup(), 56b842f2ecSJim Ingham m_bp_opts(false) {} 57b842f2ecSJim Ingham 58b842f2ecSJim Ingham ~BreakpointOptionGroup() override = default; 59b842f2ecSJim Ingham 60b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 61b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_modify_options); 62b842f2ecSJim Ingham } 63b842f2ecSJim Ingham 64b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 65b842f2ecSJim Ingham ExecutionContext *execution_context) override { 66b842f2ecSJim Ingham Status error; 67b842f2ecSJim Ingham const int short_option = g_breakpoint_modify_options[option_idx].short_option; 68b842f2ecSJim Ingham 69b842f2ecSJim Ingham switch (short_option) { 70b842f2ecSJim Ingham case 'c': 7105097246SAdrian Prantl // Normally an empty breakpoint condition marks is as unset. But we need 7205097246SAdrian Prantl // to say it was passed in. 73b842f2ecSJim Ingham m_bp_opts.SetCondition(option_arg.str().c_str()); 74b842f2ecSJim Ingham m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition); 75b842f2ecSJim Ingham break; 76b842f2ecSJim Ingham case 'C': 77b842f2ecSJim Ingham m_commands.push_back(option_arg); 78b842f2ecSJim Ingham break; 79b842f2ecSJim Ingham case 'd': 80b842f2ecSJim Ingham m_bp_opts.SetEnabled(false); 81b842f2ecSJim Ingham break; 82b842f2ecSJim Ingham case 'e': 83b842f2ecSJim Ingham m_bp_opts.SetEnabled(true); 84b842f2ecSJim Ingham break; 85b842f2ecSJim Ingham case 'G': { 86b842f2ecSJim Ingham bool value, success; 8747cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 88b842f2ecSJim Ingham if (success) { 89b842f2ecSJim Ingham m_bp_opts.SetAutoContinue(value); 90b842f2ecSJim Ingham } else 91b842f2ecSJim Ingham error.SetErrorStringWithFormat( 92b842f2ecSJim Ingham "invalid boolean value '%s' passed for -G option", 93b842f2ecSJim Ingham option_arg.str().c_str()); 94b842f2ecSJim Ingham } 95b842f2ecSJim Ingham break; 96b842f2ecSJim Ingham case 'i': 97b842f2ecSJim Ingham { 98b842f2ecSJim Ingham uint32_t ignore_count; 99b842f2ecSJim Ingham if (option_arg.getAsInteger(0, ignore_count)) 100b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid ignore count '%s'", 101b842f2ecSJim Ingham option_arg.str().c_str()); 102b842f2ecSJim Ingham else 103b842f2ecSJim Ingham m_bp_opts.SetIgnoreCount(ignore_count); 104b842f2ecSJim Ingham } 105b842f2ecSJim Ingham break; 106b842f2ecSJim Ingham case 'o': { 107b842f2ecSJim Ingham bool value, success; 10847cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 109b842f2ecSJim Ingham if (success) { 110b842f2ecSJim Ingham m_bp_opts.SetOneShot(value); 111b842f2ecSJim Ingham } else 112b842f2ecSJim Ingham error.SetErrorStringWithFormat( 113b842f2ecSJim Ingham "invalid boolean value '%s' passed for -o option", 114b842f2ecSJim Ingham option_arg.str().c_str()); 115b842f2ecSJim Ingham } break; 116b842f2ecSJim Ingham case 't': 117b842f2ecSJim Ingham { 118b842f2ecSJim Ingham lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID; 119b842f2ecSJim Ingham if (option_arg[0] != '\0') { 120b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_id)) 121b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread id string '%s'", 122b842f2ecSJim Ingham option_arg.str().c_str()); 123b842f2ecSJim Ingham } 124b842f2ecSJim Ingham m_bp_opts.SetThreadID(thread_id); 125b842f2ecSJim Ingham } 126b842f2ecSJim Ingham break; 127b842f2ecSJim Ingham case 'T': 128b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); 129b842f2ecSJim Ingham break; 130b842f2ecSJim Ingham case 'q': 131b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str()); 132b842f2ecSJim Ingham break; 133b842f2ecSJim Ingham case 'x': 134b842f2ecSJim Ingham { 135b842f2ecSJim Ingham uint32_t thread_index = UINT32_MAX; 136b842f2ecSJim Ingham if (option_arg[0] != '\n') { 137b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_index)) 138b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread index string '%s'", 139b842f2ecSJim Ingham option_arg.str().c_str()); 140b842f2ecSJim Ingham } 141b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetIndex(thread_index); 142b842f2ecSJim Ingham } 143b842f2ecSJim Ingham break; 144b842f2ecSJim Ingham default: 145b842f2ecSJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 146b842f2ecSJim Ingham short_option); 147b842f2ecSJim Ingham break; 148b842f2ecSJim Ingham } 149b842f2ecSJim Ingham 150b842f2ecSJim Ingham return error; 151b842f2ecSJim Ingham } 152b842f2ecSJim Ingham 153b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 154b842f2ecSJim Ingham m_bp_opts.Clear(); 155b842f2ecSJim Ingham m_commands.clear(); 156b842f2ecSJim Ingham } 157b842f2ecSJim Ingham 158b842f2ecSJim Ingham Status OptionParsingFinished(ExecutionContext *execution_context) override { 159b842f2ecSJim Ingham if (!m_commands.empty()) 160b842f2ecSJim Ingham { 161b842f2ecSJim Ingham if (!m_commands.empty()) 162b842f2ecSJim Ingham { 163b842f2ecSJim Ingham auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); 164b842f2ecSJim Ingham 165b842f2ecSJim Ingham for (std::string &str : m_commands) 166b842f2ecSJim Ingham cmd_data->user_source.AppendString(str); 167b842f2ecSJim Ingham 168b842f2ecSJim Ingham cmd_data->stop_on_error = true; 169b842f2ecSJim Ingham m_bp_opts.SetCommandDataCallback(cmd_data); 170b842f2ecSJim Ingham } 171b842f2ecSJim Ingham } 172b842f2ecSJim Ingham return Status(); 173b842f2ecSJim Ingham } 174b842f2ecSJim Ingham 175b842f2ecSJim Ingham const BreakpointOptions &GetBreakpointOptions() 176b842f2ecSJim Ingham { 177b842f2ecSJim Ingham return m_bp_opts; 178b842f2ecSJim Ingham } 179b842f2ecSJim Ingham 180b842f2ecSJim Ingham std::vector<std::string> m_commands; 181b842f2ecSJim Ingham BreakpointOptions m_bp_opts; 182b842f2ecSJim Ingham 183b842f2ecSJim Ingham }; 1848fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_dummy_options[] = { 185*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy 186*f94668e3SRaphael Isemann #include "CommandOptions.inc" 187b842f2ecSJim Ingham }; 188b842f2ecSJim Ingham 189b842f2ecSJim Ingham class BreakpointDummyOptionGroup : public OptionGroup 190b842f2ecSJim Ingham { 191b842f2ecSJim Ingham public: 192b842f2ecSJim Ingham BreakpointDummyOptionGroup() : 193b842f2ecSJim Ingham OptionGroup() {} 194b842f2ecSJim Ingham 195b842f2ecSJim Ingham ~BreakpointDummyOptionGroup() override = default; 196b842f2ecSJim Ingham 197b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 198b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_dummy_options); 199b842f2ecSJim Ingham } 200b842f2ecSJim Ingham 201b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 202b842f2ecSJim Ingham ExecutionContext *execution_context) override { 203b842f2ecSJim Ingham Status error; 204b842f2ecSJim Ingham const int short_option = g_breakpoint_modify_options[option_idx].short_option; 205b842f2ecSJim Ingham 206b842f2ecSJim Ingham switch (short_option) { 207b842f2ecSJim Ingham case 'D': 208b842f2ecSJim Ingham m_use_dummy = true; 209b842f2ecSJim Ingham break; 210b842f2ecSJim Ingham default: 211b842f2ecSJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 212b842f2ecSJim Ingham short_option); 213b842f2ecSJim Ingham break; 214b842f2ecSJim Ingham } 215b842f2ecSJim Ingham 216b842f2ecSJim Ingham return error; 217b842f2ecSJim Ingham } 218b842f2ecSJim Ingham 219b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 220b842f2ecSJim Ingham m_use_dummy = false; 221b842f2ecSJim Ingham } 222b842f2ecSJim Ingham 223b842f2ecSJim Ingham bool m_use_dummy; 224b842f2ecSJim Ingham 225b842f2ecSJim Ingham }; 226b842f2ecSJim Ingham 2278fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_set_options[] = { 228*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set 229*f94668e3SRaphael Isemann #include "CommandOptions.inc" 2301f0f5b5bSZachary Turner }; 2311f0f5b5bSZachary Turner 2325a988416SJim Ingham // CommandObjectBreakpointSet 23330fdc8d8SChris Lattner 234b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 2355a988416SJim Ingham public: 236efe8e7e3SFangrui Song enum BreakpointSetType { 2375a988416SJim Ingham eSetTypeInvalid, 2385a988416SJim Ingham eSetTypeFileAndLine, 2395a988416SJim Ingham eSetTypeAddress, 2405a988416SJim Ingham eSetTypeFunctionName, 2415a988416SJim Ingham eSetTypeFunctionRegexp, 2425a988416SJim Ingham eSetTypeSourceRegexp, 2433815e702SJim Ingham eSetTypeException, 2443815e702SJim Ingham eSetTypeScripted, 245efe8e7e3SFangrui Song }; 2465a988416SJim Ingham 247b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 248b9c1b51eSKate Stone : CommandObjectParsed( 249b9c1b51eSKate Stone interpreter, "breakpoint set", 2505a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 2515a988416SJim Ingham "breakpoint set <cmd-options>"), 252b842f2ecSJim Ingham m_bp_opts(), m_options() { 253b842f2ecSJim Ingham // We're picking up all the normal options, commands and disable. 254b842f2ecSJim Ingham m_all_options.Append(&m_bp_opts, 255b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, 256b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 257b842f2ecSJim Ingham m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 258b842f2ecSJim Ingham m_all_options.Append(&m_options); 259b842f2ecSJim Ingham m_all_options.Finalize(); 260b842f2ecSJim Ingham } 2615a988416SJim Ingham 2629e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 2635a988416SJim Ingham 264b842f2ecSJim Ingham Options *GetOptions() override { return &m_all_options; } 2655a988416SJim Ingham 266b842f2ecSJim Ingham class CommandOptions : public OptionGroup { 2675a988416SJim Ingham public: 268b9c1b51eSKate Stone CommandOptions() 269b842f2ecSJim Ingham : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0), 270b9c1b51eSKate Stone m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone), 271b9c1b51eSKate Stone m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(), 272b9c1b51eSKate Stone m_catch_bp(false), m_throw_bp(true), m_hardware(false), 273a72b31c7SJim Ingham m_exception_language(eLanguageTypeUnknown), 27423b1decbSDawn Perchik m_language(lldb::eLanguageTypeUnknown), 275b842f2ecSJim Ingham m_skip_prologue(eLazyBoolCalculate), 276b9c1b51eSKate Stone m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {} 27730fdc8d8SChris Lattner 2789e85e5a8SEugene Zelenko ~CommandOptions() override = default; 27987df91b8SJim Ingham 28097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 281b9c1b51eSKate Stone ExecutionContext *execution_context) override { 28297206d57SZachary Turner Status error; 283b842f2ecSJim Ingham const int short_option = g_breakpoint_set_options[option_idx].short_option; 28430fdc8d8SChris Lattner 285b9c1b51eSKate Stone switch (short_option) { 286b9c1b51eSKate Stone case 'a': { 28747cbf4a0SPavel Labath m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 288e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 289b9c1b51eSKate Stone } break; 29030fdc8d8SChris Lattner 291e732052fSJim Ingham case 'A': 292e732052fSJim Ingham m_all_files = true; 293e732052fSJim Ingham break; 294e732052fSJim Ingham 295ca36cd16SJim Ingham case 'b': 296ca36cd16SJim Ingham m_func_names.push_back(option_arg); 297ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 298ca36cd16SJim Ingham break; 299ca36cd16SJim Ingham 300fe11483bSZachary Turner case 'C': 301fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_column)) 302b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 303fe11483bSZachary Turner option_arg.str().c_str()); 30430fdc8d8SChris Lattner break; 3059e85e5a8SEugene Zelenko 306b9c1b51eSKate Stone case 'E': { 307fe11483bSZachary Turner LanguageType language = Language::GetLanguageTypeFromString(option_arg); 308fab10e89SJim Ingham 309b9c1b51eSKate Stone switch (language) { 310fab10e89SJim Ingham case eLanguageTypeC89: 311fab10e89SJim Ingham case eLanguageTypeC: 312fab10e89SJim Ingham case eLanguageTypeC99: 3131d0089faSBruce Mitchener case eLanguageTypeC11: 314a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 315fab10e89SJim Ingham break; 316fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 3171d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 3181d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 3192ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 320a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 321fab10e89SJim Ingham break; 322fab10e89SJim Ingham case eLanguageTypeObjC: 323a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 324fab10e89SJim Ingham break; 325fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 326b9c1b51eSKate Stone error.SetErrorStringWithFormat( 327b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 328fab10e89SJim Ingham break; 329fab10e89SJim Ingham case eLanguageTypeUnknown: 330b9c1b51eSKate Stone error.SetErrorStringWithFormat( 331b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 332fe11483bSZachary Turner option_arg.str().c_str()); 333fab10e89SJim Ingham break; 334fab10e89SJim Ingham default: 335b9c1b51eSKate Stone error.SetErrorStringWithFormat( 336b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 337fe11483bSZachary Turner option_arg.str().c_str()); 338fab10e89SJim Ingham } 339b9c1b51eSKate Stone } break; 340ca36cd16SJim Ingham 341ca36cd16SJim Ingham case 'f': 3428f3be7a3SJonas Devlieghere m_filenames.AppendIfUnique(FileSpec(option_arg)); 343fab10e89SJim Ingham break; 344ca36cd16SJim Ingham 345ca36cd16SJim Ingham case 'F': 346ca36cd16SJim Ingham m_func_names.push_back(option_arg); 347ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 348ca36cd16SJim Ingham break; 349ca36cd16SJim Ingham 350b9c1b51eSKate Stone case 'h': { 351fab10e89SJim Ingham bool success; 35247cbf4a0SPavel Labath m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 353fab10e89SJim Ingham if (!success) 354b9c1b51eSKate Stone error.SetErrorStringWithFormat( 355fe11483bSZachary Turner "Invalid boolean value for on-catch option: '%s'", 356fe11483bSZachary Turner option_arg.str().c_str()); 357b9c1b51eSKate Stone } break; 358eb023e75SGreg Clayton 359eb023e75SGreg Clayton case 'H': 360eb023e75SGreg Clayton m_hardware = true; 361eb023e75SGreg Clayton break; 362eb023e75SGreg Clayton 3633815e702SJim Ingham case 'k': { 3643815e702SJim Ingham if (m_current_key.empty()) 3653815e702SJim Ingham m_current_key.assign(option_arg); 3663815e702SJim Ingham else 3673815e702SJim Ingham error.SetErrorStringWithFormat("Key: %s missing value.", 3683815e702SJim Ingham m_current_key.c_str()); 3693815e702SJim Ingham 3703815e702SJim Ingham } break; 371b9c1b51eSKate Stone case 'K': { 372a8558b62SJim Ingham bool success; 373a8558b62SJim Ingham bool value; 37447cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 375a8558b62SJim Ingham if (value) 376a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 377a8558b62SJim Ingham else 378a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 379a8558b62SJim Ingham 380a8558b62SJim Ingham if (!success) 381b9c1b51eSKate Stone error.SetErrorStringWithFormat( 382b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 383fe11483bSZachary Turner option_arg.str().c_str()); 384b9c1b51eSKate Stone } break; 385ca36cd16SJim Ingham 386fe11483bSZachary Turner case 'l': 387fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_line_num)) 388b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 389fe11483bSZachary Turner option_arg.str().c_str()); 390ca36cd16SJim Ingham break; 391055ad9beSIlia K 39223b1decbSDawn Perchik case 'L': 393fe11483bSZachary Turner m_language = Language::GetLanguageTypeFromString(option_arg); 39423b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 395b9c1b51eSKate Stone error.SetErrorStringWithFormat( 396fe11483bSZachary Turner "Unknown language type: '%s' for breakpoint", 397fe11483bSZachary Turner option_arg.str().c_str()); 39823b1decbSDawn Perchik break; 39923b1decbSDawn Perchik 400b9c1b51eSKate Stone case 'm': { 401055ad9beSIlia K bool success; 402055ad9beSIlia K bool value; 40347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 404055ad9beSIlia K if (value) 405055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 406055ad9beSIlia K else 407055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 408055ad9beSIlia K 409055ad9beSIlia K if (!success) 410b9c1b51eSKate Stone error.SetErrorStringWithFormat( 411b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 412fe11483bSZachary Turner option_arg.str().c_str()); 413055ad9beSIlia K break; 414055ad9beSIlia K } 415055ad9beSIlia K 416ca36cd16SJim Ingham case 'M': 417ca36cd16SJim Ingham m_func_names.push_back(option_arg); 418ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 419ca36cd16SJim Ingham break; 420ca36cd16SJim Ingham 421ca36cd16SJim Ingham case 'n': 422ca36cd16SJim Ingham m_func_names.push_back(option_arg); 423ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 424ca36cd16SJim Ingham break; 425ca36cd16SJim Ingham 4266fa7681bSZachary Turner case 'N': { 427fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error)) 4285e09c8c3SJim Ingham m_breakpoint_names.push_back(option_arg); 429ff9a91eaSJim Ingham else 430ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 431fe11483bSZachary Turner option_arg.str().c_str()); 4325e09c8c3SJim Ingham break; 4336fa7681bSZachary Turner } 4345e09c8c3SJim Ingham 435b9c1b51eSKate Stone case 'R': { 4362411167fSJim Ingham lldb::addr_t tmp_offset_addr; 43747cbf4a0SPavel Labath tmp_offset_addr = OptionArgParser::ToAddress(execution_context, 43847cbf4a0SPavel Labath option_arg, 0, &error); 4392411167fSJim Ingham if (error.Success()) 4402411167fSJim Ingham m_offset_addr = tmp_offset_addr; 441b9c1b51eSKate Stone } break; 4422411167fSJim Ingham 443a72b31c7SJim Ingham case 'O': 444fe11483bSZachary Turner m_exception_extra_args.AppendArgument("-O"); 445fe11483bSZachary Turner m_exception_extra_args.AppendArgument(option_arg); 446a72b31c7SJim Ingham break; 447a72b31c7SJim Ingham 448ca36cd16SJim Ingham case 'p': 449ca36cd16SJim Ingham m_source_text_regexp.assign(option_arg); 450ca36cd16SJim Ingham break; 451ca36cd16SJim Ingham 4523815e702SJim Ingham case 'P': 4533815e702SJim Ingham m_python_class.assign(option_arg); 4543815e702SJim Ingham break; 4553815e702SJim Ingham 456ca36cd16SJim Ingham case 'r': 457ca36cd16SJim Ingham m_func_regexp.assign(option_arg); 458ca36cd16SJim Ingham break; 459ca36cd16SJim Ingham 460ca36cd16SJim Ingham case 's': 4618f3be7a3SJonas Devlieghere m_modules.AppendIfUnique(FileSpec(option_arg)); 462ca36cd16SJim Ingham break; 463ca36cd16SJim Ingham 464ca36cd16SJim Ingham case 'S': 465ca36cd16SJim Ingham m_func_names.push_back(option_arg); 466ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 467ca36cd16SJim Ingham break; 468ca36cd16SJim Ingham 4693815e702SJim Ingham case 'v': { 4703815e702SJim Ingham if (!m_current_key.empty()) { 4713815e702SJim Ingham m_extra_args_sp->AddStringItem(m_current_key, option_arg); 4723815e702SJim Ingham m_current_key.clear(); 4733815e702SJim Ingham } 4743815e702SJim Ingham else 4753815e702SJim Ingham error.SetErrorStringWithFormat("Value \"%s\" missing matching key.", 4763815e702SJim Ingham option_arg.str().c_str()); 4773815e702SJim Ingham } break; 4783815e702SJim Ingham 479b9c1b51eSKate Stone case 'w': { 480ca36cd16SJim Ingham bool success; 48147cbf4a0SPavel Labath m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 482ca36cd16SJim Ingham if (!success) 483b9c1b51eSKate Stone error.SetErrorStringWithFormat( 484fe11483bSZachary Turner "Invalid boolean value for on-throw option: '%s'", 485fe11483bSZachary Turner option_arg.str().c_str()); 486b9c1b51eSKate Stone } break; 487ca36cd16SJim Ingham 48876bb8d67SJim Ingham case 'X': 48976bb8d67SJim Ingham m_source_regex_func_names.insert(option_arg); 49076bb8d67SJim Ingham break; 49176bb8d67SJim Ingham 49230fdc8d8SChris Lattner default: 493b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 494b9c1b51eSKate Stone short_option); 49530fdc8d8SChris Lattner break; 49630fdc8d8SChris Lattner } 49730fdc8d8SChris Lattner 49830fdc8d8SChris Lattner return error; 49930fdc8d8SChris Lattner } 5009e85e5a8SEugene Zelenko 501b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 50287df91b8SJim Ingham m_filenames.Clear(); 50330fdc8d8SChris Lattner m_line_num = 0; 50430fdc8d8SChris Lattner m_column = 0; 505fab10e89SJim Ingham m_func_names.clear(); 5061f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 50730fdc8d8SChris Lattner m_func_regexp.clear(); 5081f746071SGreg Clayton m_source_text_regexp.clear(); 50987df91b8SJim Ingham m_modules.Clear(); 5101f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 5112411167fSJim Ingham m_offset_addr = 0; 512fab10e89SJim Ingham m_catch_bp = false; 513fab10e89SJim Ingham m_throw_bp = true; 514eb023e75SGreg Clayton m_hardware = false; 515a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 51623b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 517a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 5185e09c8c3SJim Ingham m_breakpoint_names.clear(); 519e732052fSJim Ingham m_all_files = false; 520a72b31c7SJim Ingham m_exception_extra_args.Clear(); 521055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 52276bb8d67SJim Ingham m_source_regex_func_names.clear(); 5233815e702SJim Ingham m_python_class.clear(); 524796ac80bSJonas Devlieghere m_extra_args_sp = std::make_shared<StructuredData::Dictionary>(); 5253815e702SJim Ingham m_current_key.clear(); 52630fdc8d8SChris Lattner } 52730fdc8d8SChris Lattner 5281f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 52970602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_set_options); 5301f0f5b5bSZachary Turner } 53130fdc8d8SChris Lattner 5325a988416SJim Ingham // Instance variables to hold the values for command options. 533969795f1SJim Ingham 5345a988416SJim Ingham std::string m_condition; 5355a988416SJim Ingham FileSpecList m_filenames; 5365a988416SJim Ingham uint32_t m_line_num; 5375a988416SJim Ingham uint32_t m_column; 5385a988416SJim Ingham std::vector<std::string> m_func_names; 5395e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 540117b1fa1SZachary Turner lldb::FunctionNameType m_func_name_type_mask; 5415a988416SJim Ingham std::string m_func_regexp; 5425a988416SJim Ingham std::string m_source_text_regexp; 5435a988416SJim Ingham FileSpecList m_modules; 5445a988416SJim Ingham lldb::addr_t m_load_addr; 5452411167fSJim Ingham lldb::addr_t m_offset_addr; 5465a988416SJim Ingham bool m_catch_bp; 5475a988416SJim Ingham bool m_throw_bp; 548eb023e75SGreg Clayton bool m_hardware; // Request to use hardware breakpoints 549a72b31c7SJim Ingham lldb::LanguageType m_exception_language; 55023b1decbSDawn Perchik lldb::LanguageType m_language; 5515a988416SJim Ingham LazyBool m_skip_prologue; 552e732052fSJim Ingham bool m_all_files; 553a72b31c7SJim Ingham Args m_exception_extra_args; 554055ad9beSIlia K LazyBool m_move_to_nearest_code; 55576bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 5563815e702SJim Ingham std::string m_python_class; 5573815e702SJim Ingham StructuredData::DictionarySP m_extra_args_sp; 5583815e702SJim Ingham std::string m_current_key; 5595a988416SJim Ingham }; 5605a988416SJim Ingham 5615a988416SJim Ingham protected: 562b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 563b842f2ecSJim Ingham Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); 56433df7cd3SJim Ingham 565b9c1b51eSKate Stone if (target == nullptr) { 566b9c1b51eSKate Stone result.AppendError("Invalid target. Must set target before setting " 567b9c1b51eSKate Stone "breakpoints (see 'target create' command)."); 56830fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 56930fdc8d8SChris Lattner return false; 57030fdc8d8SChris Lattner } 57130fdc8d8SChris Lattner 57230fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 57330fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 57430fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 57530fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 576b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 577b9c1b51eSKate Stone // expression) 578b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 579b9c1b51eSKate Stone // to source text) 580b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 581b9c1b51eSKate Stone // given language.) 58230fdc8d8SChris Lattner 58330fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 58430fdc8d8SChris Lattner 5853815e702SJim Ingham if (!m_options.m_python_class.empty()) 5863815e702SJim Ingham break_type = eSetTypeScripted; 5873815e702SJim Ingham else if (m_options.m_line_num != 0) 58830fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 58930fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 59030fdc8d8SChris Lattner break_type = eSetTypeAddress; 591fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 59230fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 59330fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 59430fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 595969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 596969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 597a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 598fab10e89SJim Ingham break_type = eSetTypeException; 59930fdc8d8SChris Lattner 600b842f2ecSJim Ingham BreakpointSP bp_sp = nullptr; 601274060b6SGreg Clayton FileSpec module_spec; 602a8558b62SJim Ingham const bool internal = false; 603a8558b62SJim Ingham 604b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 605b9c1b51eSKate Stone // that off. 606b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 607b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 6082411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 6092411167fSJim Ingham 610b9c1b51eSKate Stone switch (break_type) { 61130fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 61230fdc8d8SChris Lattner { 61330fdc8d8SChris Lattner FileSpec file; 614c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 615b9c1b51eSKate Stone if (num_files == 0) { 616b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 61787df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 61887df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 61987df91b8SJim Ingham return false; 62087df91b8SJim Ingham } 621b9c1b51eSKate Stone } else if (num_files > 1) { 622b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 623b9c1b51eSKate Stone "line breakpoints."); 62487df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 62587df91b8SJim Ingham return false; 626b9c1b51eSKate Stone } else 62787df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 62830fdc8d8SChris Lattner 6291f746071SGreg Clayton // Only check for inline functions if 6301f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 6311f746071SGreg Clayton 632b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(&(m_options.m_modules), 633b842f2ecSJim Ingham file, 634b842f2ecSJim Ingham m_options.m_line_num, 635431b1584SAdrian Prantl m_options.m_column, 636b842f2ecSJim Ingham m_options.m_offset_addr, 637b842f2ecSJim Ingham check_inlines, 638b842f2ecSJim Ingham m_options.m_skip_prologue, 639b842f2ecSJim Ingham internal, 640b842f2ecSJim Ingham m_options.m_hardware, 641b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 642b9c1b51eSKate Stone } break; 6436eee5aa0SGreg Clayton 64430fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 645055a08a4SJim Ingham { 646b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 647b842f2ecSJim Ingham // with the library, and use that. That way the address breakpoint 648b842f2ecSJim Ingham // will track the load location of the library. 649055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 650b9c1b51eSKate Stone if (num_modules_specified == 1) { 651b9c1b51eSKate Stone const FileSpec *file_spec = 652b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 653b842f2ecSJim Ingham bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr, 654b9c1b51eSKate Stone internal, file_spec, 655b842f2ecSJim Ingham m_options.m_hardware); 656b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 657b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal, 658b842f2ecSJim Ingham m_options.m_hardware); 659b9c1b51eSKate Stone } else { 660b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 661b9c1b51eSKate Stone "address breakpoints."); 662055a08a4SJim Ingham result.SetStatus(eReturnStatusFailed); 663055a08a4SJim Ingham return false; 664055a08a4SJim Ingham } 66530fdc8d8SChris Lattner break; 666055a08a4SJim Ingham } 66730fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 6680c5cd90dSGreg Clayton { 669117b1fa1SZachary Turner FunctionNameType name_type_mask = m_options.m_func_name_type_mask; 6700c5cd90dSGreg Clayton 6710c5cd90dSGreg Clayton if (name_type_mask == 0) 672e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 6730c5cd90dSGreg Clayton 674b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(&(m_options.m_modules), 675b842f2ecSJim Ingham &(m_options.m_filenames), 676b842f2ecSJim Ingham m_options.m_func_names, 677b842f2ecSJim Ingham name_type_mask, 678b842f2ecSJim Ingham m_options.m_language, 679b842f2ecSJim Ingham m_options.m_offset_addr, 680b842f2ecSJim Ingham m_options.m_skip_prologue, 681b842f2ecSJim Ingham internal, 682b842f2ecSJim Ingham m_options.m_hardware); 683b9c1b51eSKate Stone } break; 6840c5cd90dSGreg Clayton 685b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 686b9c1b51eSKate Stone // name 68730fdc8d8SChris Lattner { 68895eae423SZachary Turner RegularExpression regexp(m_options.m_func_regexp); 689b9c1b51eSKate Stone if (!regexp.IsValid()) { 690969795f1SJim Ingham char err_str[1024]; 691969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 692b9c1b51eSKate Stone result.AppendErrorWithFormat( 693b9c1b51eSKate Stone "Function name regular expression could not be compiled: \"%s\"", 694969795f1SJim Ingham err_str); 69530fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 696969795f1SJim Ingham return false; 69730fdc8d8SChris Lattner } 69887df91b8SJim Ingham 699b842f2ecSJim Ingham bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules), 700b842f2ecSJim Ingham &(m_options.m_filenames), 701b842f2ecSJim Ingham regexp, 702b842f2ecSJim Ingham m_options.m_language, 703b842f2ecSJim Ingham m_options.m_skip_prologue, 704b842f2ecSJim Ingham internal, 705b842f2ecSJim Ingham m_options.m_hardware); 706e14dc268SJim Ingham } 707e14dc268SJim Ingham break; 708969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 709969795f1SJim Ingham { 710c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 71187df91b8SJim Ingham 712b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 713969795f1SJim Ingham FileSpec file; 714b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 715b9c1b51eSKate Stone result.AppendError( 716b9c1b51eSKate Stone "No files provided and could not find default file."); 71787df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 71887df91b8SJim Ingham return false; 719b9c1b51eSKate Stone } else { 72087df91b8SJim Ingham m_options.m_filenames.Append(file); 72187df91b8SJim Ingham } 72287df91b8SJim Ingham } 7230c5cd90dSGreg Clayton 72495eae423SZachary Turner RegularExpression regexp(m_options.m_source_text_regexp); 725b9c1b51eSKate Stone if (!regexp.IsValid()) { 726969795f1SJim Ingham char err_str[1024]; 727969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 728b9c1b51eSKate Stone result.AppendErrorWithFormat( 729b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"", 730969795f1SJim Ingham err_str); 731969795f1SJim Ingham result.SetStatus(eReturnStatusFailed); 732969795f1SJim Ingham return false; 733969795f1SJim Ingham } 734b842f2ecSJim Ingham bp_sp = 735b842f2ecSJim Ingham target->CreateSourceRegexBreakpoint(&(m_options.m_modules), 736b842f2ecSJim Ingham &(m_options.m_filenames), 737b842f2ecSJim Ingham m_options 738b842f2ecSJim Ingham .m_source_regex_func_names, 739b842f2ecSJim Ingham regexp, 740b842f2ecSJim Ingham internal, 741b842f2ecSJim Ingham m_options.m_hardware, 742b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 743b9c1b51eSKate Stone } break; 744b9c1b51eSKate Stone case eSetTypeException: { 74597206d57SZachary Turner Status precond_error; 746b842f2ecSJim Ingham bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language, 747b842f2ecSJim Ingham m_options.m_catch_bp, 748b842f2ecSJim Ingham m_options.m_throw_bp, 749b842f2ecSJim Ingham internal, 750b842f2ecSJim Ingham &m_options 751b842f2ecSJim Ingham .m_exception_extra_args, 752b842f2ecSJim Ingham &precond_error); 753b9c1b51eSKate Stone if (precond_error.Fail()) { 754b9c1b51eSKate Stone result.AppendErrorWithFormat( 755b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 756a72b31c7SJim Ingham precond_error.AsCString()); 757b842f2ecSJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 758a72b31c7SJim Ingham result.SetStatus(eReturnStatusFailed); 759a72b31c7SJim Ingham return false; 760a72b31c7SJim Ingham } 761b9c1b51eSKate Stone } break; 7623815e702SJim Ingham case eSetTypeScripted: { 7633815e702SJim Ingham 7643815e702SJim Ingham Status error; 7653815e702SJim Ingham bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class, 7663815e702SJim Ingham &(m_options.m_modules), 7673815e702SJim Ingham &(m_options.m_filenames), 7683815e702SJim Ingham false, 7693815e702SJim Ingham m_options.m_hardware, 7703815e702SJim Ingham m_options.m_extra_args_sp, 7713815e702SJim Ingham &error); 7723815e702SJim Ingham if (error.Fail()) { 7733815e702SJim Ingham result.AppendErrorWithFormat( 7743815e702SJim Ingham "Error setting extra exception arguments: %s", 7753815e702SJim Ingham error.AsCString()); 7763815e702SJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 7773815e702SJim Ingham result.SetStatus(eReturnStatusFailed); 7783815e702SJim Ingham return false; 7793815e702SJim Ingham } 7803815e702SJim Ingham } break; 78130fdc8d8SChris Lattner default: 78230fdc8d8SChris Lattner break; 78330fdc8d8SChris Lattner } 78430fdc8d8SChris Lattner 7851b54c88cSJim Ingham // Now set the various options that were passed in: 786b842f2ecSJim Ingham if (bp_sp) { 787b842f2ecSJim Ingham bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 788ca36cd16SJim Ingham 789b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 79097206d57SZachary Turner Status name_error; 791ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) { 792b842f2ecSJim Ingham target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error); 793ff9a91eaSJim Ingham if (name_error.Fail()) { 794ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s", 795ff9a91eaSJim Ingham name.c_str()); 796b842f2ecSJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 797ff9a91eaSJim Ingham result.SetStatus(eReturnStatusFailed); 798ff9a91eaSJim Ingham return false; 799ff9a91eaSJim Ingham } 800ff9a91eaSJim Ingham } 8015e09c8c3SJim Ingham } 8021b54c88cSJim Ingham } 8031b54c88cSJim Ingham 804b842f2ecSJim Ingham if (bp_sp) { 80585e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 8061391cc7dSJim Ingham const bool show_locations = false; 807b842f2ecSJim Ingham bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 808b9c1b51eSKate Stone show_locations); 80957179860SJonas Devlieghere if (target == GetDebugger().GetDummyTarget()) 810b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 811b9c1b51eSKate Stone "into future targets.\n"); 812b9c1b51eSKate Stone else { 81305097246SAdrian Prantl // Don't print out this warning for exception breakpoints. They can 81405097246SAdrian Prantl // get set before the target is set, but we won't know how to actually 81505097246SAdrian Prantl // set the breakpoint till we run. 816b842f2ecSJim Ingham if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { 817b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 818b9c1b51eSKate Stone "actual locations.\n"); 8194aeb1989SJim Ingham } 8204aeb1989SJim Ingham } 82130fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 822b842f2ecSJim Ingham } else if (!bp_sp) { 82330fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 82430fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 82530fdc8d8SChris Lattner } 82630fdc8d8SChris Lattner 82730fdc8d8SChris Lattner return result.Succeeded(); 82830fdc8d8SChris Lattner } 82930fdc8d8SChris Lattner 8305a988416SJim Ingham private: 831b9c1b51eSKate Stone bool GetDefaultFile(Target *target, FileSpec &file, 832b9c1b51eSKate Stone CommandReturnObject &result) { 8335a988416SJim Ingham uint32_t default_line; 83405097246SAdrian Prantl // First use the Source Manager's default file. Then use the current stack 83505097246SAdrian Prantl // frame's file. 836b9c1b51eSKate Stone if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 837b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 838b9c1b51eSKate Stone if (cur_frame == nullptr) { 839b9c1b51eSKate Stone result.AppendError( 840b9c1b51eSKate Stone "No selected frame to use to find the default file."); 8415a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 8425a988416SJim Ingham return false; 843b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 844b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 845b9c1b51eSKate Stone "file, it has no debug info."); 8465a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 8475a988416SJim Ingham return false; 848b9c1b51eSKate Stone } else { 849b9c1b51eSKate Stone const SymbolContext &sc = 850b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 851b9c1b51eSKate Stone if (sc.line_entry.file) { 8525a988416SJim Ingham file = sc.line_entry.file; 853b9c1b51eSKate Stone } else { 854b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 855b9c1b51eSKate Stone "use as the default file."); 8565a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 8575a988416SJim Ingham return false; 8585a988416SJim Ingham } 8595a988416SJim Ingham } 8605a988416SJim Ingham } 8615a988416SJim Ingham return true; 8625a988416SJim Ingham } 8635a988416SJim Ingham 864b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 865b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_options; 8665a988416SJim Ingham CommandOptions m_options; 867b842f2ecSJim Ingham OptionGroupOptions m_all_options; 8685a988416SJim Ingham }; 8699e85e5a8SEugene Zelenko 8705a988416SJim Ingham // CommandObjectBreakpointModify 8715a988416SJim Ingham #pragma mark Modify 8725a988416SJim Ingham 873b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 8745a988416SJim Ingham public: 875b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 876b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 877b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 878b9c1b51eSKate Stone "breakpoints in the executable. " 879b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 880b9c1b51eSKate Stone "created breakpoint. " 881b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 882b9c1b51eSKate Stone "empty argument clears the modification.", 8839e85e5a8SEugene Zelenko nullptr), 884b9c1b51eSKate Stone m_options() { 8855a988416SJim Ingham CommandArgumentEntry arg; 886b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 887b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 888b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 889b9c1b51eSKate Stone // arguments vector. 8905a988416SJim Ingham m_arguments.push_back(arg); 891b842f2ecSJim Ingham 892b842f2ecSJim Ingham m_options.Append(&m_bp_opts, 893b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, 894b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 895b842f2ecSJim Ingham m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 896b842f2ecSJim Ingham m_options.Finalize(); 8975a988416SJim Ingham } 8985a988416SJim Ingham 8999e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 9005a988416SJim Ingham 901b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 9025a988416SJim Ingham 9035a988416SJim Ingham protected: 904b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 905b842f2ecSJim Ingham Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 906b9c1b51eSKate Stone if (target == nullptr) { 9075a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 9085a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9095a988416SJim Ingham return false; 9105a988416SJim Ingham } 9115a988416SJim Ingham 912bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 913bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 9145a988416SJim Ingham 9155a988416SJim Ingham BreakpointIDList valid_bp_ids; 9165a988416SJim Ingham 917b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 918b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 919b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 9205a988416SJim Ingham 921b9c1b51eSKate Stone if (result.Succeeded()) { 9225a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 923b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 9245a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 9255a988416SJim Ingham 926b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 927b9c1b51eSKate Stone Breakpoint *bp = 928b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 929b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 930b9c1b51eSKate Stone BreakpointLocation *location = 931b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 932b842f2ecSJim Ingham if (location) 933b842f2ecSJim Ingham location->GetLocationOptions() 934b842f2ecSJim Ingham ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 935b9c1b51eSKate Stone } else { 936b842f2ecSJim Ingham bp->GetOptions() 937b842f2ecSJim Ingham ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 9385a988416SJim Ingham } 9395a988416SJim Ingham } 9405a988416SJim Ingham } 9415a988416SJim Ingham } 9425a988416SJim Ingham 9435a988416SJim Ingham return result.Succeeded(); 9445a988416SJim Ingham } 9455a988416SJim Ingham 9465a988416SJim Ingham private: 947b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 948b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_opts; 949b842f2ecSJim Ingham OptionGroupOptions m_options; 9505a988416SJim Ingham }; 9515a988416SJim Ingham 9525a988416SJim Ingham // CommandObjectBreakpointEnable 9535a988416SJim Ingham #pragma mark Enable 9545a988416SJim Ingham 955b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 9565a988416SJim Ingham public: 957b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 958b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 959b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 960b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 961b9c1b51eSKate Stone nullptr) { 9625a988416SJim Ingham CommandArgumentEntry arg; 963b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 964b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 965b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 966b9c1b51eSKate Stone // arguments vector. 9675a988416SJim Ingham m_arguments.push_back(arg); 9685a988416SJim Ingham } 9695a988416SJim Ingham 9709e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 9715a988416SJim Ingham 9725a988416SJim Ingham protected: 973b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 974893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 975b9c1b51eSKate Stone if (target == nullptr) { 9765a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 9775a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9785a988416SJim Ingham return false; 9795a988416SJim Ingham } 9805a988416SJim Ingham 981bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 982bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 9835a988416SJim Ingham 9845a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 9855a988416SJim Ingham 9865a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 9875a988416SJim Ingham 988b9c1b51eSKate Stone if (num_breakpoints == 0) { 9895a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 9905a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9915a988416SJim Ingham return false; 9925a988416SJim Ingham } 9935a988416SJim Ingham 99411eb9c64SZachary Turner if (command.empty()) { 9955a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 996b842f2ecSJim Ingham target->EnableAllowedBreakpoints(); 997b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 998b9c1b51eSKate Stone " breakpoints)\n", 999b9c1b51eSKate Stone (uint64_t)num_breakpoints); 10005a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1001b9c1b51eSKate Stone } else { 10025a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 10035a988416SJim Ingham BreakpointIDList valid_bp_ids; 1004b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1005b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1006b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 10075a988416SJim Ingham 1008b9c1b51eSKate Stone if (result.Succeeded()) { 10095a988416SJim Ingham int enable_count = 0; 10105a988416SJim Ingham int loc_count = 0; 10115a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1012b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 10135a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 10145a988416SJim Ingham 1015b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1016b9c1b51eSKate Stone Breakpoint *breakpoint = 1017b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1018b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1019b9c1b51eSKate Stone BreakpointLocation *location = 1020b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1021b9c1b51eSKate Stone if (location) { 10225a988416SJim Ingham location->SetEnabled(true); 10235a988416SJim Ingham ++loc_count; 10245a988416SJim Ingham } 1025b9c1b51eSKate Stone } else { 10265a988416SJim Ingham breakpoint->SetEnabled(true); 10275a988416SJim Ingham ++enable_count; 10285a988416SJim Ingham } 10295a988416SJim Ingham } 10305a988416SJim Ingham } 1031b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 1032b9c1b51eSKate Stone enable_count + loc_count); 10335a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 10345a988416SJim Ingham } 10355a988416SJim Ingham } 10365a988416SJim Ingham 10375a988416SJim Ingham return result.Succeeded(); 10385a988416SJim Ingham } 10395a988416SJim Ingham }; 10405a988416SJim Ingham 10415a988416SJim Ingham // CommandObjectBreakpointDisable 10425a988416SJim Ingham #pragma mark Disable 10435a988416SJim Ingham 1044b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 10455a988416SJim Ingham public: 10467428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 1047b9c1b51eSKate Stone : CommandObjectParsed( 1048b9c1b51eSKate Stone interpreter, "breakpoint disable", 1049b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 10507428a18cSKate Stone "them. If none are specified, disable all " 10517428a18cSKate Stone "breakpoints.", 1052b9c1b51eSKate Stone nullptr) { 1053b9c1b51eSKate Stone SetHelpLong( 1054b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 10557428a18cSKate Stone If none are specified, disable all breakpoints." 10567428a18cSKate Stone R"( 1057ea671fbdSKate Stone 10587428a18cSKate Stone )" 10597428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 10607428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 10617428a18cSKate Stone R"( 1062ea671fbdSKate Stone 1063ea671fbdSKate Stone (lldb) break disable 1 1064ea671fbdSKate Stone (lldb) break enable 1.1 1065ea671fbdSKate Stone 1066ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 1067ea671fbdSKate Stone 1068ea671fbdSKate Stone (lldb) break disable 1.* 1069ea671fbdSKate Stone (lldb) break enable 1.1 1070ea671fbdSKate Stone 10717428a18cSKate Stone )" 10727428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 10737428a18cSKate Stone the second re-enables the first location."); 1074b0fac509SJim Ingham 10755a988416SJim Ingham CommandArgumentEntry arg; 1076b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1077b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1078b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1079b9c1b51eSKate Stone // arguments vector. 10805a988416SJim Ingham m_arguments.push_back(arg); 10815a988416SJim Ingham } 10825a988416SJim Ingham 10839e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 10845a988416SJim Ingham 10855a988416SJim Ingham protected: 1086b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1087893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1088b9c1b51eSKate Stone if (target == nullptr) { 10895a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 10905a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10915a988416SJim Ingham return false; 10925a988416SJim Ingham } 10935a988416SJim Ingham 1094bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1095bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 10965a988416SJim Ingham 10975a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 10985a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 10995a988416SJim Ingham 1100b9c1b51eSKate Stone if (num_breakpoints == 0) { 11015a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 11025a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11035a988416SJim Ingham return false; 11045a988416SJim Ingham } 11055a988416SJim Ingham 110611eb9c64SZachary Turner if (command.empty()) { 11075a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 1108b842f2ecSJim Ingham target->DisableAllowedBreakpoints(); 1109b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1110b9c1b51eSKate Stone " breakpoints)\n", 1111b9c1b51eSKate Stone (uint64_t)num_breakpoints); 11125a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1113b9c1b51eSKate Stone } else { 11145a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 11155a988416SJim Ingham BreakpointIDList valid_bp_ids; 11165a988416SJim Ingham 1117b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1118b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1119b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 11205a988416SJim Ingham 1121b9c1b51eSKate Stone if (result.Succeeded()) { 11225a988416SJim Ingham int disable_count = 0; 11235a988416SJim Ingham int loc_count = 0; 11245a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1125b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 11265a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 11275a988416SJim Ingham 1128b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1129b9c1b51eSKate Stone Breakpoint *breakpoint = 1130b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1131b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1132b9c1b51eSKate Stone BreakpointLocation *location = 1133b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1134b9c1b51eSKate Stone if (location) { 11355a988416SJim Ingham location->SetEnabled(false); 11365a988416SJim Ingham ++loc_count; 11375a988416SJim Ingham } 1138b9c1b51eSKate Stone } else { 11395a988416SJim Ingham breakpoint->SetEnabled(false); 11405a988416SJim Ingham ++disable_count; 11415a988416SJim Ingham } 11425a988416SJim Ingham } 11435a988416SJim Ingham } 1144b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1145b9c1b51eSKate Stone disable_count + loc_count); 11465a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 11475a988416SJim Ingham } 11485a988416SJim Ingham } 11495a988416SJim Ingham 11505a988416SJim Ingham return result.Succeeded(); 11515a988416SJim Ingham } 11525a988416SJim Ingham }; 11535a988416SJim Ingham 11545a988416SJim Ingham // CommandObjectBreakpointList 11551f0f5b5bSZachary Turner 11561f0f5b5bSZachary Turner #pragma mark List::CommandOptions 11578fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_list_options[] = { 11586f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list 1159c5a2d747SRaphael Isemann #include "CommandOptions.inc" 11601f0f5b5bSZachary Turner }; 11611f0f5b5bSZachary Turner 11625a988416SJim Ingham #pragma mark List 11635a988416SJim Ingham 1164b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 11655a988416SJim Ingham public: 1166b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1167b9c1b51eSKate Stone : CommandObjectParsed( 1168b9c1b51eSKate Stone interpreter, "breakpoint list", 11695a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 11709e85e5a8SEugene Zelenko nullptr), 1171b9c1b51eSKate Stone m_options() { 11725a988416SJim Ingham CommandArgumentEntry arg; 11735a988416SJim Ingham CommandArgumentData bp_id_arg; 11745a988416SJim Ingham 11755a988416SJim Ingham // Define the first (and only) variant of this arg. 11765a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 11775a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 11785a988416SJim Ingham 1179b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1180b9c1b51eSKate Stone // argument entry. 11815a988416SJim Ingham arg.push_back(bp_id_arg); 11825a988416SJim Ingham 11835a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 11845a988416SJim Ingham m_arguments.push_back(arg); 11855a988416SJim Ingham } 11865a988416SJim Ingham 11879e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 11885a988416SJim Ingham 1189b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 11905a988416SJim Ingham 1191b9c1b51eSKate Stone class CommandOptions : public Options { 11925a988416SJim Ingham public: 1193b9c1b51eSKate Stone CommandOptions() 1194b9c1b51eSKate Stone : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 11955a988416SJim Ingham } 11965a988416SJim Ingham 11979e85e5a8SEugene Zelenko ~CommandOptions() override = default; 11985a988416SJim Ingham 119997206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1200b9c1b51eSKate Stone ExecutionContext *execution_context) override { 120197206d57SZachary Turner Status error; 12023bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 12035a988416SJim Ingham 1204b9c1b51eSKate Stone switch (short_option) { 12055a988416SJim Ingham case 'b': 12065a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 12075a988416SJim Ingham break; 120833df7cd3SJim Ingham case 'D': 120933df7cd3SJim Ingham m_use_dummy = true; 121033df7cd3SJim Ingham break; 12115a988416SJim Ingham case 'f': 12125a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 12135a988416SJim Ingham break; 12145a988416SJim Ingham case 'v': 12155a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 12165a988416SJim Ingham break; 12175a988416SJim Ingham case 'i': 12185a988416SJim Ingham m_internal = true; 12195a988416SJim Ingham break; 12205a988416SJim Ingham default: 1221b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1222b9c1b51eSKate Stone short_option); 12235a988416SJim Ingham break; 12245a988416SJim Ingham } 12255a988416SJim Ingham 12265a988416SJim Ingham return error; 12275a988416SJim Ingham } 12285a988416SJim Ingham 1229b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 12305a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 12315a988416SJim Ingham m_internal = false; 123233df7cd3SJim Ingham m_use_dummy = false; 12335a988416SJim Ingham } 12345a988416SJim Ingham 12351f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 123670602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_list_options); 12371f0f5b5bSZachary Turner } 12385a988416SJim Ingham 12395a988416SJim Ingham // Instance variables to hold the values for command options. 12405a988416SJim Ingham 12415a988416SJim Ingham lldb::DescriptionLevel m_level; 12425a988416SJim Ingham 12435a988416SJim Ingham bool m_internal; 124433df7cd3SJim Ingham bool m_use_dummy; 12455a988416SJim Ingham }; 12465a988416SJim Ingham 12475a988416SJim Ingham protected: 1248b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 124933df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 125033df7cd3SJim Ingham 1251b9c1b51eSKate Stone if (target == nullptr) { 12525a988416SJim Ingham result.AppendError("Invalid target. No current target or breakpoints."); 12535a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 12545a988416SJim Ingham return true; 12555a988416SJim Ingham } 12565a988416SJim Ingham 1257b9c1b51eSKate Stone const BreakpointList &breakpoints = 1258b9c1b51eSKate Stone target->GetBreakpointList(m_options.m_internal); 1259bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1260bb19a13cSSaleem Abdulrasool target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); 12615a988416SJim Ingham 12625a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 12635a988416SJim Ingham 1264b9c1b51eSKate Stone if (num_breakpoints == 0) { 12655a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 12665a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 12675a988416SJim Ingham return true; 12685a988416SJim Ingham } 12695a988416SJim Ingham 12705a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 12715a988416SJim Ingham 127211eb9c64SZachary Turner if (command.empty()) { 12735a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 12745a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1275b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 12765a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1277b842f2ecSJim Ingham if (breakpoint->AllowList()) 1278b842f2ecSJim Ingham AddBreakpointDescription(&output_stream, breakpoint, 1279b842f2ecSJim Ingham m_options.m_level); 12805a988416SJim Ingham } 12815a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1282b9c1b51eSKate Stone } else { 12835a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 12845a988416SJim Ingham BreakpointIDList valid_bp_ids; 1285b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1286b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1287b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 12885a988416SJim Ingham 1289b9c1b51eSKate Stone if (result.Succeeded()) { 1290b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 12915a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1292b9c1b51eSKate Stone Breakpoint *breakpoint = 1293b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1294b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1295b9c1b51eSKate Stone m_options.m_level); 12965a988416SJim Ingham } 12975a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1298b9c1b51eSKate Stone } else { 12997428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 13005a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 13015a988416SJim Ingham } 13025a988416SJim Ingham } 13035a988416SJim Ingham 13045a988416SJim Ingham return result.Succeeded(); 13055a988416SJim Ingham } 13065a988416SJim Ingham 13075a988416SJim Ingham private: 13085a988416SJim Ingham CommandOptions m_options; 13095a988416SJim Ingham }; 13105a988416SJim Ingham 13115a988416SJim Ingham // CommandObjectBreakpointClear 13121f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions 13131f0f5b5bSZachary Turner 13148fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_clear_options[] = { 1315*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear 1316*f94668e3SRaphael Isemann #include "CommandOptions.inc" 13171f0f5b5bSZachary Turner }; 13181f0f5b5bSZachary Turner 13195a988416SJim Ingham #pragma mark Clear 13205a988416SJim Ingham 1321b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed { 13225a988416SJim Ingham public: 1323efe8e7e3SFangrui Song enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine }; 13245a988416SJim Ingham 13257428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter) 13267428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear", 1327b9c1b51eSKate Stone "Delete or disable breakpoints matching the " 1328b9c1b51eSKate Stone "specified source file and line.", 13295a988416SJim Ingham "breakpoint clear <cmd-options>"), 1330b9c1b51eSKate Stone m_options() {} 13315a988416SJim Ingham 13329e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default; 13335a988416SJim Ingham 1334b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 13355a988416SJim Ingham 1336b9c1b51eSKate Stone class CommandOptions : public Options { 13375a988416SJim Ingham public: 1338b9c1b51eSKate Stone CommandOptions() : Options(), m_filename(), m_line_num(0) {} 13395a988416SJim Ingham 13409e85e5a8SEugene Zelenko ~CommandOptions() override = default; 13415a988416SJim Ingham 134297206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1343b9c1b51eSKate Stone ExecutionContext *execution_context) override { 134497206d57SZachary Turner Status error; 13453bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 13465a988416SJim Ingham 1347b9c1b51eSKate Stone switch (short_option) { 13485a988416SJim Ingham case 'f': 13495a988416SJim Ingham m_filename.assign(option_arg); 13505a988416SJim Ingham break; 13515a988416SJim Ingham 13525a988416SJim Ingham case 'l': 1353fe11483bSZachary Turner option_arg.getAsInteger(0, m_line_num); 13545a988416SJim Ingham break; 13555a988416SJim Ingham 13565a988416SJim Ingham default: 1357b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1358b9c1b51eSKate Stone short_option); 13595a988416SJim Ingham break; 13605a988416SJim Ingham } 13615a988416SJim Ingham 13625a988416SJim Ingham return error; 13635a988416SJim Ingham } 13645a988416SJim Ingham 1365b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 13665a988416SJim Ingham m_filename.clear(); 13675a988416SJim Ingham m_line_num = 0; 13685a988416SJim Ingham } 13695a988416SJim Ingham 13701f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 137170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_clear_options); 13721f0f5b5bSZachary Turner } 13735a988416SJim Ingham 13745a988416SJim Ingham // Instance variables to hold the values for command options. 13755a988416SJim Ingham 13765a988416SJim Ingham std::string m_filename; 13775a988416SJim Ingham uint32_t m_line_num; 13785a988416SJim Ingham }; 13795a988416SJim Ingham 13805a988416SJim Ingham protected: 1381b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1382893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1383b9c1b51eSKate Stone if (target == nullptr) { 13845a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 13855a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 13865a988416SJim Ingham return false; 13875a988416SJim Ingham } 13885a988416SJim Ingham 138905097246SAdrian Prantl // The following are the various types of breakpoints that could be 139005097246SAdrian Prantl // cleared: 13915a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 13925a988416SJim Ingham 13935a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 13945a988416SJim Ingham 13955a988416SJim Ingham if (m_options.m_line_num != 0) 13965a988416SJim Ingham break_type = eClearTypeFileAndLine; 13975a988416SJim Ingham 1398bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1399bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 14005a988416SJim Ingham 14015a988416SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 14025a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 14035a988416SJim Ingham 14045a988416SJim Ingham // Early return if there's no breakpoint at all. 1405b9c1b51eSKate Stone if (num_breakpoints == 0) { 14065a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 14075a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14085a988416SJim Ingham return result.Succeeded(); 14095a988416SJim Ingham } 14105a988416SJim Ingham 14115a988416SJim Ingham // Find matching breakpoints and delete them. 14125a988416SJim Ingham 14135a988416SJim Ingham // First create a copy of all the IDs. 14145a988416SJim Ingham std::vector<break_id_t> BreakIDs; 14155a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 14169e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 14175a988416SJim Ingham 14185a988416SJim Ingham int num_cleared = 0; 14195a988416SJim Ingham StreamString ss; 1420b9c1b51eSKate Stone switch (break_type) { 14215a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 14225a988416SJim Ingham { 14235a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 14245a988416SJim Ingham BreakpointLocationCollection loc_coll; 14255a988416SJim Ingham 1426b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 14275a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 14285a988416SJim Ingham 1429b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1430b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1431b9c1b51eSKate Stone // remove the breakpoint. 1432b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 14335a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 14345a988416SJim Ingham ss.EOL(); 14355a988416SJim Ingham target->RemoveBreakpointByID(bp->GetID()); 14365a988416SJim Ingham ++num_cleared; 14375a988416SJim Ingham } 14385a988416SJim Ingham } 14395a988416SJim Ingham } 1440b9c1b51eSKate Stone } break; 14415a988416SJim Ingham 14425a988416SJim Ingham default: 14435a988416SJim Ingham break; 14445a988416SJim Ingham } 14455a988416SJim Ingham 1446b9c1b51eSKate Stone if (num_cleared > 0) { 14475a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 14485a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1449c156427dSZachary Turner output_stream << ss.GetString(); 14505a988416SJim Ingham output_stream.EOL(); 14515a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1452b9c1b51eSKate Stone } else { 14535a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 14545a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14555a988416SJim Ingham } 14565a988416SJim Ingham 14575a988416SJim Ingham return result.Succeeded(); 14585a988416SJim Ingham } 14595a988416SJim Ingham 14605a988416SJim Ingham private: 14615a988416SJim Ingham CommandOptions m_options; 14625a988416SJim Ingham }; 14635a988416SJim Ingham 14645a988416SJim Ingham // CommandObjectBreakpointDelete 14658fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_delete_options[] = { 1466*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete 1467*f94668e3SRaphael Isemann #include "CommandOptions.inc" 14681f0f5b5bSZachary Turner }; 14691f0f5b5bSZachary Turner 14705a988416SJim Ingham #pragma mark Delete 14715a988416SJim Ingham 1472b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 14735a988416SJim Ingham public: 1474b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1475b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1476b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1477b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 14789e85e5a8SEugene Zelenko nullptr), 1479b9c1b51eSKate Stone m_options() { 14805a988416SJim Ingham CommandArgumentEntry arg; 1481b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1482b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1483b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1484b9c1b51eSKate Stone // arguments vector. 14855a988416SJim Ingham m_arguments.push_back(arg); 14865a988416SJim Ingham } 14875a988416SJim Ingham 14889e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 14895a988416SJim Ingham 1490b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 149133df7cd3SJim Ingham 1492b9c1b51eSKate Stone class CommandOptions : public Options { 149333df7cd3SJim Ingham public: 1494b9c1b51eSKate Stone CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 149533df7cd3SJim Ingham 14969e85e5a8SEugene Zelenko ~CommandOptions() override = default; 149733df7cd3SJim Ingham 149897206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1499b9c1b51eSKate Stone ExecutionContext *execution_context) override { 150097206d57SZachary Turner Status error; 150133df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 150233df7cd3SJim Ingham 1503b9c1b51eSKate Stone switch (short_option) { 150433df7cd3SJim Ingham case 'f': 150533df7cd3SJim Ingham m_force = true; 150633df7cd3SJim Ingham break; 150733df7cd3SJim Ingham 150833df7cd3SJim Ingham case 'D': 150933df7cd3SJim Ingham m_use_dummy = true; 151033df7cd3SJim Ingham break; 151133df7cd3SJim Ingham 151233df7cd3SJim Ingham default: 1513b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1514b9c1b51eSKate Stone short_option); 151533df7cd3SJim Ingham break; 151633df7cd3SJim Ingham } 151733df7cd3SJim Ingham 151833df7cd3SJim Ingham return error; 151933df7cd3SJim Ingham } 152033df7cd3SJim Ingham 1521b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 152233df7cd3SJim Ingham m_use_dummy = false; 152333df7cd3SJim Ingham m_force = false; 152433df7cd3SJim Ingham } 152533df7cd3SJim Ingham 15261f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 152770602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_delete_options); 15281f0f5b5bSZachary Turner } 152933df7cd3SJim Ingham 153033df7cd3SJim Ingham // Instance variables to hold the values for command options. 153133df7cd3SJim Ingham bool m_use_dummy; 153233df7cd3SJim Ingham bool m_force; 153333df7cd3SJim Ingham }; 153433df7cd3SJim Ingham 15355a988416SJim Ingham protected: 1536b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 153733df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 153833df7cd3SJim Ingham 1539b9c1b51eSKate Stone if (target == nullptr) { 15405a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 15415a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15425a988416SJim Ingham return false; 15435a988416SJim Ingham } 15445a988416SJim Ingham 1545bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1546bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 15475a988416SJim Ingham 15485a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 15495a988416SJim Ingham 15505a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 15515a988416SJim Ingham 1552b9c1b51eSKate Stone if (num_breakpoints == 0) { 15535a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 15545a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15555a988416SJim Ingham return false; 15565a988416SJim Ingham } 15575a988416SJim Ingham 155811eb9c64SZachary Turner if (command.empty()) { 1559b9c1b51eSKate Stone if (!m_options.m_force && 1560b9c1b51eSKate Stone !m_interpreter.Confirm( 1561b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1562b9c1b51eSKate Stone true)) { 15635a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1564b9c1b51eSKate Stone } else { 1565b842f2ecSJim Ingham target->RemoveAllowedBreakpoints(); 1566b9c1b51eSKate Stone result.AppendMessageWithFormat( 1567b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1568b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 15695a988416SJim Ingham } 15705a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1571b9c1b51eSKate Stone } else { 15725a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 15735a988416SJim Ingham BreakpointIDList valid_bp_ids; 1574b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1575b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1576b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 15775a988416SJim Ingham 1578b9c1b51eSKate Stone if (result.Succeeded()) { 15795a988416SJim Ingham int delete_count = 0; 15805a988416SJim Ingham int disable_count = 0; 15815a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1582b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 15835a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 15845a988416SJim Ingham 1585b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1586b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1587b9c1b51eSKate Stone Breakpoint *breakpoint = 1588b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1589b9c1b51eSKate Stone BreakpointLocation *location = 1590b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1591b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1592b9c1b51eSKate Stone // disable them instead. 1593b9c1b51eSKate Stone if (location) { 15945a988416SJim Ingham location->SetEnabled(false); 15955a988416SJim Ingham ++disable_count; 15965a988416SJim Ingham } 1597b9c1b51eSKate Stone } else { 15985a988416SJim Ingham target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 15995a988416SJim Ingham ++delete_count; 16005a988416SJim Ingham } 16015a988416SJim Ingham } 16025a988416SJim Ingham } 1603b9c1b51eSKate Stone result.AppendMessageWithFormat( 1604b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 16055a988416SJim Ingham delete_count, disable_count); 16065a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 16075a988416SJim Ingham } 16085a988416SJim Ingham } 16095a988416SJim Ingham return result.Succeeded(); 16105a988416SJim Ingham } 16119e85e5a8SEugene Zelenko 161233df7cd3SJim Ingham private: 161333df7cd3SJim Ingham CommandOptions m_options; 161433df7cd3SJim Ingham }; 161533df7cd3SJim Ingham 16165e09c8c3SJim Ingham // CommandObjectBreakpointName 16175e09c8c3SJim Ingham 16188fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_name_options[] = { 1619*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name 1620*f94668e3SRaphael Isemann #include "CommandOptions.inc" 16215e09c8c3SJim Ingham }; 1622b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 16235e09c8c3SJim Ingham public: 1624b9c1b51eSKate Stone BreakpointNameOptionGroup() 1625b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 16265e09c8c3SJim Ingham } 16275e09c8c3SJim Ingham 16289e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 16295e09c8c3SJim Ingham 16301f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 163170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_name_options); 16325e09c8c3SJim Ingham } 16335e09c8c3SJim Ingham 163497206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1635b9c1b51eSKate Stone ExecutionContext *execution_context) override { 163697206d57SZachary Turner Status error; 16375e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 16385e09c8c3SJim Ingham 1639b9c1b51eSKate Stone switch (short_option) { 16405e09c8c3SJim Ingham case 'N': 1641fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1642b9c1b51eSKate Stone error.Success()) 1643fe11483bSZachary Turner m_name.SetValueFromString(option_arg); 16445e09c8c3SJim Ingham break; 16455e09c8c3SJim Ingham case 'B': 1646fe11483bSZachary Turner if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1647b9c1b51eSKate Stone error.SetErrorStringWithFormat( 16488cef4b0bSZachary Turner "unrecognized value \"%s\" for breakpoint", 1649fe11483bSZachary Turner option_arg.str().c_str()); 16505e09c8c3SJim Ingham break; 16515e09c8c3SJim Ingham case 'D': 1652fe11483bSZachary Turner if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1653b9c1b51eSKate Stone error.SetErrorStringWithFormat( 16548cef4b0bSZachary Turner "unrecognized value \"%s\" for use-dummy", 1655fe11483bSZachary Turner option_arg.str().c_str()); 16565e09c8c3SJim Ingham break; 1657e9632ebaSJim Ingham case 'H': 1658e9632ebaSJim Ingham m_help_string.SetValueFromString(option_arg); 1659e9632ebaSJim Ingham break; 16605e09c8c3SJim Ingham 16615e09c8c3SJim Ingham default: 1662b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized short option '%c'", 1663b9c1b51eSKate Stone short_option); 16645e09c8c3SJim Ingham break; 16655e09c8c3SJim Ingham } 16665e09c8c3SJim Ingham return error; 16675e09c8c3SJim Ingham } 16685e09c8c3SJim Ingham 1669b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 16705e09c8c3SJim Ingham m_name.Clear(); 16715e09c8c3SJim Ingham m_breakpoint.Clear(); 16725e09c8c3SJim Ingham m_use_dummy.Clear(); 16735e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 1674e9632ebaSJim Ingham m_help_string.Clear(); 16755e09c8c3SJim Ingham } 16765e09c8c3SJim Ingham 16775e09c8c3SJim Ingham OptionValueString m_name; 16785e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 16795e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 1680e9632ebaSJim Ingham OptionValueString m_help_string; 16815e09c8c3SJim Ingham }; 16825e09c8c3SJim Ingham 16838fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_access_options[] = { 1684*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access 1685*f94668e3SRaphael Isemann #include "CommandOptions.inc" 1686b842f2ecSJim Ingham }; 1687b842f2ecSJim Ingham 16888fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup { 1689b842f2ecSJim Ingham public: 16908fe53c49STatyana Krasnukha BreakpointAccessOptionGroup() : OptionGroup() {} 1691b842f2ecSJim Ingham 1692b842f2ecSJim Ingham ~BreakpointAccessOptionGroup() override = default; 1693b842f2ecSJim Ingham 1694b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1695b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_access_options); 1696b842f2ecSJim Ingham } 1697b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1698b842f2ecSJim Ingham ExecutionContext *execution_context) override { 1699b842f2ecSJim Ingham Status error; 1700b842f2ecSJim Ingham const int short_option 1701b842f2ecSJim Ingham = g_breakpoint_access_options[option_idx].short_option; 1702b842f2ecSJim Ingham 1703b842f2ecSJim Ingham switch (short_option) { 1704b842f2ecSJim Ingham case 'L': { 1705b842f2ecSJim Ingham bool value, success; 170647cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1707b842f2ecSJim Ingham if (success) { 1708b842f2ecSJim Ingham m_permissions.SetAllowList(value); 1709b842f2ecSJim Ingham } else 1710b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1711b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1712b842f2ecSJim Ingham option_arg.str().c_str()); 1713b842f2ecSJim Ingham } break; 1714b842f2ecSJim Ingham case 'A': { 1715b842f2ecSJim Ingham bool value, success; 171647cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1717b842f2ecSJim Ingham if (success) { 1718b842f2ecSJim Ingham m_permissions.SetAllowDisable(value); 1719b842f2ecSJim Ingham } else 1720b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1721b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1722b842f2ecSJim Ingham option_arg.str().c_str()); 1723b842f2ecSJim Ingham } break; 1724b842f2ecSJim Ingham case 'D': { 1725b842f2ecSJim Ingham bool value, success; 172647cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1727b842f2ecSJim Ingham if (success) { 1728b842f2ecSJim Ingham m_permissions.SetAllowDelete(value); 1729b842f2ecSJim Ingham } else 1730b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1731b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1732b842f2ecSJim Ingham option_arg.str().c_str()); 1733b842f2ecSJim Ingham } break; 1734b842f2ecSJim Ingham 1735b842f2ecSJim Ingham } 1736b842f2ecSJim Ingham 1737b842f2ecSJim Ingham return error; 1738b842f2ecSJim Ingham } 1739b842f2ecSJim Ingham 1740b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 1741b842f2ecSJim Ingham } 1742b842f2ecSJim Ingham 1743b842f2ecSJim Ingham const BreakpointName::Permissions &GetPermissions() const 1744b842f2ecSJim Ingham { 1745b842f2ecSJim Ingham return m_permissions; 1746b842f2ecSJim Ingham } 1747b842f2ecSJim Ingham BreakpointName::Permissions m_permissions; 1748b842f2ecSJim Ingham }; 1749b842f2ecSJim Ingham 1750b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1751b842f2ecSJim Ingham public: 1752b842f2ecSJim Ingham CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1753b842f2ecSJim Ingham : CommandObjectParsed( 1754b842f2ecSJim Ingham interpreter, "configure", "Configure the options for the breakpoint" 1755b842f2ecSJim Ingham " name provided. " 1756b842f2ecSJim Ingham "If you provide a breakpoint id, the options will be copied from " 1757b842f2ecSJim Ingham "the breakpoint, otherwise only the options specified will be set " 1758b842f2ecSJim Ingham "on the name.", 1759b842f2ecSJim Ingham "breakpoint name configure <command-options> " 1760b842f2ecSJim Ingham "<breakpoint-name-list>"), 1761b842f2ecSJim Ingham m_bp_opts(), m_option_group() { 1762b842f2ecSJim Ingham // Create the first variant for the first (and only) argument for this 1763b842f2ecSJim Ingham // command. 1764b842f2ecSJim Ingham CommandArgumentEntry arg1; 1765b842f2ecSJim Ingham CommandArgumentData id_arg; 1766b842f2ecSJim Ingham id_arg.arg_type = eArgTypeBreakpointName; 1767b842f2ecSJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 1768b842f2ecSJim Ingham arg1.push_back(id_arg); 1769b842f2ecSJim Ingham m_arguments.push_back(arg1); 1770b842f2ecSJim Ingham 1771b842f2ecSJim Ingham m_option_group.Append(&m_bp_opts, 1772b842f2ecSJim Ingham LLDB_OPT_SET_ALL, 1773b842f2ecSJim Ingham LLDB_OPT_SET_1); 1774b842f2ecSJim Ingham m_option_group.Append(&m_access_options, 1775b842f2ecSJim Ingham LLDB_OPT_SET_ALL, 1776b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 1777e9632ebaSJim Ingham m_option_group.Append(&m_bp_id, 1778e9632ebaSJim Ingham LLDB_OPT_SET_2|LLDB_OPT_SET_4, 1779e9632ebaSJim Ingham LLDB_OPT_SET_ALL); 1780b842f2ecSJim Ingham m_option_group.Finalize(); 1781b842f2ecSJim Ingham } 1782b842f2ecSJim Ingham 1783b842f2ecSJim Ingham ~CommandObjectBreakpointNameConfigure() override = default; 1784b842f2ecSJim Ingham 1785b842f2ecSJim Ingham Options *GetOptions() override { return &m_option_group; } 1786b842f2ecSJim Ingham 1787b842f2ecSJim Ingham protected: 1788b842f2ecSJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 1789b842f2ecSJim Ingham 1790b842f2ecSJim Ingham const size_t argc = command.GetArgumentCount(); 1791b842f2ecSJim Ingham if (argc == 0) { 1792b842f2ecSJim Ingham result.AppendError("No names provided."); 1793b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1794b842f2ecSJim Ingham return false; 1795b842f2ecSJim Ingham } 1796b842f2ecSJim Ingham 1797b842f2ecSJim Ingham Target *target = 1798b842f2ecSJim Ingham GetSelectedOrDummyTarget(false); 1799b842f2ecSJim Ingham 1800b842f2ecSJim Ingham if (target == nullptr) { 1801b842f2ecSJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 1802b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1803b842f2ecSJim Ingham return false; 1804b842f2ecSJim Ingham } 1805b842f2ecSJim Ingham 1806b842f2ecSJim Ingham std::unique_lock<std::recursive_mutex> lock; 1807b842f2ecSJim Ingham target->GetBreakpointList().GetListMutex(lock); 1808b842f2ecSJim Ingham 1809b842f2ecSJim Ingham // Make a pass through first to see that all the names are legal. 1810b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1811b842f2ecSJim Ingham Status error; 1812b842f2ecSJim Ingham if (!BreakpointID::StringIsBreakpointName(entry.ref, error)) 1813b842f2ecSJim Ingham { 1814b842f2ecSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1815b842f2ecSJim Ingham entry.c_str(), error.AsCString()); 1816b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1817b842f2ecSJim Ingham return false; 1818b842f2ecSJim Ingham } 1819b842f2ecSJim Ingham } 182005097246SAdrian Prantl // Now configure them, we already pre-checked the names so we don't need to 182105097246SAdrian Prantl // check the error: 1822b842f2ecSJim Ingham BreakpointSP bp_sp; 1823b842f2ecSJim Ingham if (m_bp_id.m_breakpoint.OptionWasSet()) 1824b842f2ecSJim Ingham { 1825b842f2ecSJim Ingham lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1826b842f2ecSJim Ingham bp_sp = target->GetBreakpointByID(bp_id); 1827b842f2ecSJim Ingham if (!bp_sp) 1828b842f2ecSJim Ingham { 1829b842f2ecSJim Ingham result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1830b842f2ecSJim Ingham bp_id); 1831b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1832b842f2ecSJim Ingham return false; 1833b842f2ecSJim Ingham } 1834b842f2ecSJim Ingham } 1835b842f2ecSJim Ingham 1836b842f2ecSJim Ingham Status error; 1837b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1838b842f2ecSJim Ingham ConstString name(entry.c_str()); 1839b842f2ecSJim Ingham BreakpointName *bp_name = target->FindBreakpointName(name, true, error); 1840b842f2ecSJim Ingham if (!bp_name) 1841b842f2ecSJim Ingham continue; 1842e9632ebaSJim Ingham if (m_bp_id.m_help_string.OptionWasSet()) 1843e9632ebaSJim Ingham bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1844e9632ebaSJim Ingham 1845b842f2ecSJim Ingham if (bp_sp) 1846b842f2ecSJim Ingham target->ConfigureBreakpointName(*bp_name, 1847b842f2ecSJim Ingham *bp_sp->GetOptions(), 1848b842f2ecSJim Ingham m_access_options.GetPermissions()); 1849b842f2ecSJim Ingham else 1850b842f2ecSJim Ingham target->ConfigureBreakpointName(*bp_name, 1851b842f2ecSJim Ingham m_bp_opts.GetBreakpointOptions(), 1852b842f2ecSJim Ingham m_access_options.GetPermissions()); 1853b842f2ecSJim Ingham } 1854b842f2ecSJim Ingham return true; 1855b842f2ecSJim Ingham } 1856b842f2ecSJim Ingham 1857b842f2ecSJim Ingham private: 1858b842f2ecSJim Ingham BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1859b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 1860b842f2ecSJim Ingham BreakpointAccessOptionGroup m_access_options; 1861b842f2ecSJim Ingham OptionGroupOptions m_option_group; 1862b842f2ecSJim Ingham }; 1863b842f2ecSJim Ingham 1864b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 18655e09c8c3SJim Ingham public: 1866b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1867b9c1b51eSKate Stone : CommandObjectParsed( 1868b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 18695e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 1870b9c1b51eSKate Stone m_name_options(), m_option_group() { 1871b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1872b9c1b51eSKate Stone // command. 18735e09c8c3SJim Ingham CommandArgumentEntry arg1; 18745e09c8c3SJim Ingham CommandArgumentData id_arg; 18755e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 18765e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 18775e09c8c3SJim Ingham arg1.push_back(id_arg); 18785e09c8c3SJim Ingham m_arguments.push_back(arg1); 18795e09c8c3SJim Ingham 18805e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 18815e09c8c3SJim Ingham m_option_group.Finalize(); 18825e09c8c3SJim Ingham } 18835e09c8c3SJim Ingham 18849e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 18855e09c8c3SJim Ingham 1886b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 18875e09c8c3SJim Ingham 18885e09c8c3SJim Ingham protected: 1889b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1890b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 18915e09c8c3SJim Ingham result.SetError("No name option provided."); 18925e09c8c3SJim Ingham return false; 18935e09c8c3SJim Ingham } 18945e09c8c3SJim Ingham 1895b9c1b51eSKate Stone Target *target = 1896b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 18975e09c8c3SJim Ingham 1898b9c1b51eSKate Stone if (target == nullptr) { 18995e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 19005e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19015e09c8c3SJim Ingham return false; 19025e09c8c3SJim Ingham } 19035e09c8c3SJim Ingham 1904bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1905bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 19065e09c8c3SJim Ingham 19075e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 19085e09c8c3SJim Ingham 19095e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1910b9c1b51eSKate Stone if (num_breakpoints == 0) { 19115e09c8c3SJim Ingham result.SetError("No breakpoints, cannot add names."); 19125e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19135e09c8c3SJim Ingham return false; 19145e09c8c3SJim Ingham } 19155e09c8c3SJim Ingham 19165e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 19175e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1918b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1919b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1920b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 19215e09c8c3SJim Ingham 1922b9c1b51eSKate Stone if (result.Succeeded()) { 1923b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 19245e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot add names."); 19255e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19265e09c8c3SJim Ingham return false; 19275e09c8c3SJim Ingham } 19285e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1929b842f2ecSJim Ingham const char *bp_name = m_name_options.m_name.GetCurrentValue(); 1930b842f2ecSJim Ingham Status error; // This error reports illegal names, but we've already 1931b842f2ecSJim Ingham // checked that, so we don't need to check it again here. 1932b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1933b9c1b51eSKate Stone lldb::break_id_t bp_id = 1934b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 19355e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1936b842f2ecSJim Ingham target->AddNameToBreakpoint(bp_sp, bp_name, error); 19375e09c8c3SJim Ingham } 19385e09c8c3SJim Ingham } 19395e09c8c3SJim Ingham 19405e09c8c3SJim Ingham return true; 19415e09c8c3SJim Ingham } 19425e09c8c3SJim Ingham 19435e09c8c3SJim Ingham private: 19445e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19455e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19465e09c8c3SJim Ingham }; 19475e09c8c3SJim Ingham 1948b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 19495e09c8c3SJim Ingham public: 1950b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1951b9c1b51eSKate Stone : CommandObjectParsed( 1952b9c1b51eSKate Stone interpreter, "delete", 19535e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 19545e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 1955b9c1b51eSKate Stone m_name_options(), m_option_group() { 1956b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1957b9c1b51eSKate Stone // command. 19585e09c8c3SJim Ingham CommandArgumentEntry arg1; 19595e09c8c3SJim Ingham CommandArgumentData id_arg; 19605e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 19615e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 19625e09c8c3SJim Ingham arg1.push_back(id_arg); 19635e09c8c3SJim Ingham m_arguments.push_back(arg1); 19645e09c8c3SJim Ingham 19655e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 19665e09c8c3SJim Ingham m_option_group.Finalize(); 19675e09c8c3SJim Ingham } 19685e09c8c3SJim Ingham 19699e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 19705e09c8c3SJim Ingham 1971b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19725e09c8c3SJim Ingham 19735e09c8c3SJim Ingham protected: 1974b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1975b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 19765e09c8c3SJim Ingham result.SetError("No name option provided."); 19775e09c8c3SJim Ingham return false; 19785e09c8c3SJim Ingham } 19795e09c8c3SJim Ingham 1980b9c1b51eSKate Stone Target *target = 1981b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19825e09c8c3SJim Ingham 1983b9c1b51eSKate Stone if (target == nullptr) { 19845e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 19855e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19865e09c8c3SJim Ingham return false; 19875e09c8c3SJim Ingham } 19885e09c8c3SJim Ingham 1989bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1990bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 19915e09c8c3SJim Ingham 19925e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 19935e09c8c3SJim Ingham 19945e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1995b9c1b51eSKate Stone if (num_breakpoints == 0) { 19965e09c8c3SJim Ingham result.SetError("No breakpoints, cannot delete names."); 19975e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19985e09c8c3SJim Ingham return false; 19995e09c8c3SJim Ingham } 20005e09c8c3SJim Ingham 20015e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 20025e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 2003b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2004b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2005b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 20065e09c8c3SJim Ingham 2007b9c1b51eSKate Stone if (result.Succeeded()) { 2008b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 20095e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot delete names."); 20105e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20115e09c8c3SJim Ingham return false; 20125e09c8c3SJim Ingham } 2013b842f2ecSJim Ingham ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 20145e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 2015b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 2016b9c1b51eSKate Stone lldb::break_id_t bp_id = 2017b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 20185e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 2019b842f2ecSJim Ingham target->RemoveNameFromBreakpoint(bp_sp, bp_name); 20205e09c8c3SJim Ingham } 20215e09c8c3SJim Ingham } 20225e09c8c3SJim Ingham 20235e09c8c3SJim Ingham return true; 20245e09c8c3SJim Ingham } 20255e09c8c3SJim Ingham 20265e09c8c3SJim Ingham private: 20275e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20285e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20295e09c8c3SJim Ingham }; 20305e09c8c3SJim Ingham 2031b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 20325e09c8c3SJim Ingham public: 2033b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 2034b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 2035b842f2ecSJim Ingham "List either the names for a breakpoint or info " 2036b842f2ecSJim Ingham "about a given name. With no arguments, lists all " 2037b842f2ecSJim Ingham "names", 20385e09c8c3SJim Ingham "breakpoint name list <command-options>"), 2039b9c1b51eSKate Stone m_name_options(), m_option_group() { 2040b842f2ecSJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 20415e09c8c3SJim Ingham m_option_group.Finalize(); 20425e09c8c3SJim Ingham } 20435e09c8c3SJim Ingham 20449e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 20455e09c8c3SJim Ingham 2046b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 20475e09c8c3SJim Ingham 20485e09c8c3SJim Ingham protected: 2049b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2050b9c1b51eSKate Stone Target *target = 2051b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 20525e09c8c3SJim Ingham 2053b9c1b51eSKate Stone if (target == nullptr) { 20545e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 20555e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20565e09c8c3SJim Ingham return false; 20575e09c8c3SJim Ingham } 20585e09c8c3SJim Ingham 2059b842f2ecSJim Ingham 2060b842f2ecSJim Ingham std::vector<std::string> name_list; 2061b842f2ecSJim Ingham if (command.empty()) { 2062b842f2ecSJim Ingham target->GetBreakpointNames(name_list); 2063b842f2ecSJim Ingham } else { 2064b842f2ecSJim Ingham for (const Args::ArgEntry &arg : command) 2065b842f2ecSJim Ingham { 2066b842f2ecSJim Ingham name_list.push_back(arg.c_str()); 2067b842f2ecSJim Ingham } 2068b842f2ecSJim Ingham } 2069b842f2ecSJim Ingham 2070b842f2ecSJim Ingham if (name_list.empty()) { 2071b842f2ecSJim Ingham result.AppendMessage("No breakpoint names found."); 2072b842f2ecSJim Ingham } else { 2073b842f2ecSJim Ingham for (const std::string &name_str : name_list) { 2074b842f2ecSJim Ingham const char *name = name_str.c_str(); 2075b842f2ecSJim Ingham // First print out the options for the name: 2076b842f2ecSJim Ingham Status error; 2077b842f2ecSJim Ingham BreakpointName *bp_name = target->FindBreakpointName(ConstString(name), 2078b842f2ecSJim Ingham false, 2079b842f2ecSJim Ingham error); 2080b842f2ecSJim Ingham if (bp_name) 2081b842f2ecSJim Ingham { 2082b842f2ecSJim Ingham StreamString s; 2083b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s\n", name); 2084b842f2ecSJim Ingham if (bp_name->GetDescription(&s, eDescriptionLevelFull)) 2085b842f2ecSJim Ingham { 2086b842f2ecSJim Ingham result.AppendMessage(s.GetString()); 2087b842f2ecSJim Ingham } 2088b842f2ecSJim Ingham 2089bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2090bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 20915e09c8c3SJim Ingham 20925e09c8c3SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 2093b842f2ecSJim Ingham bool any_set = false; 2094b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2095b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 20965e09c8c3SJim Ingham StreamString s; 2097b842f2ecSJim Ingham any_set = true; 20985e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 20995e09c8c3SJim Ingham s.EOL(); 2100c156427dSZachary Turner result.AppendMessage(s.GetString()); 21015e09c8c3SJim Ingham } 21025e09c8c3SJim Ingham } 2103b842f2ecSJim Ingham if (!any_set) 2104b842f2ecSJim Ingham result.AppendMessage("No breakpoints using this name."); 2105b9c1b51eSKate Stone } else { 2106b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s not found.\n", name); 21075e09c8c3SJim Ingham } 2108b842f2ecSJim Ingham } 21095e09c8c3SJim Ingham } 21105e09c8c3SJim Ingham return true; 21115e09c8c3SJim Ingham } 21125e09c8c3SJim Ingham 21135e09c8c3SJim Ingham private: 21145e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 21155e09c8c3SJim Ingham OptionGroupOptions m_option_group; 21165e09c8c3SJim Ingham }; 21175e09c8c3SJim Ingham 2118e14dc268SJim Ingham // CommandObjectBreakpointName 2119b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 21205e09c8c3SJim Ingham public: 21217428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2122b9c1b51eSKate Stone : CommandObjectMultiword( 2123b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2124b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2125b9c1b51eSKate Stone CommandObjectSP add_command_object( 2126b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2127b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2128b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2129b9c1b51eSKate Stone CommandObjectSP list_command_object( 2130b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 2131b842f2ecSJim Ingham CommandObjectSP configure_command_object( 2132b842f2ecSJim Ingham new CommandObjectBreakpointNameConfigure(interpreter)); 21335e09c8c3SJim Ingham 21345e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 21355e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 21365e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 2137b842f2ecSJim Ingham LoadSubCommand("configure", configure_command_object); 21385e09c8c3SJim Ingham } 21395e09c8c3SJim Ingham 21409e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 21415e09c8c3SJim Ingham }; 21425e09c8c3SJim Ingham 2143e14dc268SJim Ingham // CommandObjectBreakpointRead 21443acdf385SJim Ingham #pragma mark Read::CommandOptions 21458fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_read_options[] = { 2146*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read 2147*f94668e3SRaphael Isemann #include "CommandOptions.inc" 21481f0f5b5bSZachary Turner }; 21491f0f5b5bSZachary Turner 21501f0f5b5bSZachary Turner #pragma mark Read 2151e14dc268SJim Ingham 2152e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed { 2153e14dc268SJim Ingham public: 2154e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2155e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read", 2156e14dc268SJim Ingham "Read and set the breakpoints previously saved to " 2157e14dc268SJim Ingham "a file with \"breakpoint write\". ", 2158e14dc268SJim Ingham nullptr), 2159e14dc268SJim Ingham m_options() { 2160e14dc268SJim Ingham CommandArgumentEntry arg; 2161e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2162e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2163e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2164e14dc268SJim Ingham // arguments vector. 2165e14dc268SJim Ingham m_arguments.push_back(arg); 2166e14dc268SJim Ingham } 2167e14dc268SJim Ingham 2168e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default; 2169e14dc268SJim Ingham 2170e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2171e14dc268SJim Ingham 2172e14dc268SJim Ingham class CommandOptions : public Options { 2173e14dc268SJim Ingham public: 2174e14dc268SJim Ingham CommandOptions() : Options() {} 2175e14dc268SJim Ingham 2176e14dc268SJim Ingham ~CommandOptions() override = default; 2177e14dc268SJim Ingham 217897206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2179e14dc268SJim Ingham ExecutionContext *execution_context) override { 218097206d57SZachary Turner Status error; 2181e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2182e14dc268SJim Ingham 2183e14dc268SJim Ingham switch (short_option) { 2184e14dc268SJim Ingham case 'f': 2185e14dc268SJim Ingham m_filename.assign(option_arg); 2186e14dc268SJim Ingham break; 21873acdf385SJim Ingham case 'N': { 218897206d57SZachary Turner Status name_error; 21893acdf385SJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 21903acdf385SJim Ingham name_error)) { 21913acdf385SJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 21923acdf385SJim Ingham name_error.AsCString()); 21933acdf385SJim Ingham } 21943acdf385SJim Ingham m_names.push_back(option_arg); 21953acdf385SJim Ingham break; 21963acdf385SJim Ingham } 2197e14dc268SJim Ingham default: 2198e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2199e14dc268SJim Ingham short_option); 2200e14dc268SJim Ingham break; 2201e14dc268SJim Ingham } 2202e14dc268SJim Ingham 2203e14dc268SJim Ingham return error; 2204e14dc268SJim Ingham } 2205e14dc268SJim Ingham 2206e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2207e14dc268SJim Ingham m_filename.clear(); 22083acdf385SJim Ingham m_names.clear(); 2209e14dc268SJim Ingham } 2210e14dc268SJim Ingham 22111f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 221270602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_read_options); 22131f0f5b5bSZachary Turner } 2214e14dc268SJim Ingham 2215e14dc268SJim Ingham // Instance variables to hold the values for command options. 2216e14dc268SJim Ingham 2217e14dc268SJim Ingham std::string m_filename; 22183acdf385SJim Ingham std::vector<std::string> m_names; 2219e14dc268SJim Ingham }; 2220e14dc268SJim Ingham 2221e14dc268SJim Ingham protected: 2222e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2223e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2224e14dc268SJim Ingham if (target == nullptr) { 2225e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2226e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2227e14dc268SJim Ingham return false; 2228e14dc268SJim Ingham } 2229e14dc268SJim Ingham 22303acdf385SJim Ingham std::unique_lock<std::recursive_mutex> lock; 22313acdf385SJim Ingham target->GetBreakpointList().GetListMutex(lock); 22323acdf385SJim Ingham 22338f3be7a3SJonas Devlieghere FileSpec input_spec(m_options.m_filename); 22348f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(input_spec); 223501f16664SJim Ingham BreakpointIDList new_bps; 223697206d57SZachary Turner Status error = target->CreateBreakpointsFromFile( 223797206d57SZachary Turner input_spec, m_options.m_names, new_bps); 2238e14dc268SJim Ingham 2239e14dc268SJim Ingham if (!error.Success()) { 224001f16664SJim Ingham result.AppendError(error.AsCString()); 2241e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 224201f16664SJim Ingham return false; 2243e14dc268SJim Ingham } 22443acdf385SJim Ingham 22453acdf385SJim Ingham Stream &output_stream = result.GetOutputStream(); 22463acdf385SJim Ingham 22473acdf385SJim Ingham size_t num_breakpoints = new_bps.GetSize(); 22483acdf385SJim Ingham if (num_breakpoints == 0) { 22493acdf385SJim Ingham result.AppendMessage("No breakpoints added."); 22503acdf385SJim Ingham } else { 22513acdf385SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 22523acdf385SJim Ingham result.AppendMessage("New breakpoints:"); 22533acdf385SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) { 22543acdf385SJim Ingham BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 22553acdf385SJim Ingham Breakpoint *bp = target->GetBreakpointList() 22563acdf385SJim Ingham .FindBreakpointByID(bp_id.GetBreakpointID()) 22573acdf385SJim Ingham .get(); 22583acdf385SJim Ingham if (bp) 22593acdf385SJim Ingham bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 22603acdf385SJim Ingham false); 22613acdf385SJim Ingham } 22623acdf385SJim Ingham } 2263e14dc268SJim Ingham return result.Succeeded(); 2264e14dc268SJim Ingham } 2265e14dc268SJim Ingham 2266e14dc268SJim Ingham private: 2267e14dc268SJim Ingham CommandOptions m_options; 2268e14dc268SJim Ingham }; 2269e14dc268SJim Ingham 2270e14dc268SJim Ingham // CommandObjectBreakpointWrite 22711f0f5b5bSZachary Turner #pragma mark Write::CommandOptions 22728fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_write_options[] = { 2273*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write 2274*f94668e3SRaphael Isemann #include "CommandOptions.inc" 22751f0f5b5bSZachary Turner }; 22761f0f5b5bSZachary Turner 22771f0f5b5bSZachary Turner #pragma mark Write 2278e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed { 2279e14dc268SJim Ingham public: 2280e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2281e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write", 2282e14dc268SJim Ingham "Write the breakpoints listed to a file that can " 2283e14dc268SJim Ingham "be read in with \"breakpoint read\". " 2284e14dc268SJim Ingham "If given no arguments, writes all breakpoints.", 2285e14dc268SJim Ingham nullptr), 2286e14dc268SJim Ingham m_options() { 2287e14dc268SJim Ingham CommandArgumentEntry arg; 2288e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2289e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2290e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2291e14dc268SJim Ingham // arguments vector. 2292e14dc268SJim Ingham m_arguments.push_back(arg); 2293e14dc268SJim Ingham } 2294e14dc268SJim Ingham 2295e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default; 2296e14dc268SJim Ingham 2297e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2298e14dc268SJim Ingham 2299e14dc268SJim Ingham class CommandOptions : public Options { 2300e14dc268SJim Ingham public: 2301e14dc268SJim Ingham CommandOptions() : Options() {} 2302e14dc268SJim Ingham 2303e14dc268SJim Ingham ~CommandOptions() override = default; 2304e14dc268SJim Ingham 230597206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2306e14dc268SJim Ingham ExecutionContext *execution_context) override { 230797206d57SZachary Turner Status error; 2308e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2309e14dc268SJim Ingham 2310e14dc268SJim Ingham switch (short_option) { 2311e14dc268SJim Ingham case 'f': 2312e14dc268SJim Ingham m_filename.assign(option_arg); 2313e14dc268SJim Ingham break; 23142d3628e1SJim Ingham case 'a': 23152d3628e1SJim Ingham m_append = true; 23162d3628e1SJim Ingham break; 2317e14dc268SJim Ingham default: 2318e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2319e14dc268SJim Ingham short_option); 2320e14dc268SJim Ingham break; 2321e14dc268SJim Ingham } 2322e14dc268SJim Ingham 2323e14dc268SJim Ingham return error; 2324e14dc268SJim Ingham } 2325e14dc268SJim Ingham 2326e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2327e14dc268SJim Ingham m_filename.clear(); 23282d3628e1SJim Ingham m_append = false; 2329e14dc268SJim Ingham } 2330e14dc268SJim Ingham 23311f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 233270602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_write_options); 23331f0f5b5bSZachary Turner } 2334e14dc268SJim Ingham 2335e14dc268SJim Ingham // Instance variables to hold the values for command options. 2336e14dc268SJim Ingham 2337e14dc268SJim Ingham std::string m_filename; 23382d3628e1SJim Ingham bool m_append = false; 2339e14dc268SJim Ingham }; 2340e14dc268SJim Ingham 2341e14dc268SJim Ingham protected: 2342e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2343e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2344e14dc268SJim Ingham if (target == nullptr) { 2345e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2346e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2347e14dc268SJim Ingham return false; 2348e14dc268SJim Ingham } 2349e14dc268SJim Ingham 2350e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2351e14dc268SJim Ingham target->GetBreakpointList().GetListMutex(lock); 2352e14dc268SJim Ingham 2353e14dc268SJim Ingham BreakpointIDList valid_bp_ids; 235411eb9c64SZachary Turner if (!command.empty()) { 2355e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2356b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2357b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 2358e14dc268SJim Ingham 235901f16664SJim Ingham if (!result.Succeeded()) { 2360e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2361e14dc268SJim Ingham return false; 2362e14dc268SJim Ingham } 2363e14dc268SJim Ingham } 23648f3be7a3SJonas Devlieghere FileSpec file_spec(m_options.m_filename); 23658f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(file_spec); 23668f3be7a3SJonas Devlieghere Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids, 23678f3be7a3SJonas Devlieghere m_options.m_append); 236801f16664SJim Ingham if (!error.Success()) { 236901f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.", 237001f16664SJim Ingham error.AsCString()); 237101f16664SJim Ingham result.SetStatus(eReturnStatusFailed); 2372e14dc268SJim Ingham } 2373e14dc268SJim Ingham return result.Succeeded(); 2374e14dc268SJim Ingham } 2375e14dc268SJim Ingham 2376e14dc268SJim Ingham private: 2377e14dc268SJim Ingham CommandOptions m_options; 2378e14dc268SJim Ingham }; 2379e14dc268SJim Ingham 238030fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 2381ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 238230fdc8d8SChris Lattner 2383b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2384b9c1b51eSKate Stone CommandInterpreter &interpreter) 2385b9c1b51eSKate Stone : CommandObjectMultiword( 2386b9c1b51eSKate Stone interpreter, "breakpoint", 23877428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2388b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2389b9c1b51eSKate Stone CommandObjectSP list_command_object( 2390b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2391b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2392b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2393b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2394b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2395b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2396b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2397b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2398b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2399b9c1b51eSKate Stone CommandObjectSP set_command_object( 2400b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2401b9c1b51eSKate Stone CommandObjectSP command_command_object( 2402b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2403b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2404b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2405b9c1b51eSKate Stone CommandObjectSP name_command_object( 2406b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 2407e14dc268SJim Ingham CommandObjectSP write_command_object( 2408e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter)); 2409e14dc268SJim Ingham CommandObjectSP read_command_object( 2410e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter)); 241130fdc8d8SChris Lattner 2412b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 241330fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 241430fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2415b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2416b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2417ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2418b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2419b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 24205e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 2421e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write"); 2422e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read"); 242330fdc8d8SChris Lattner 242423f59509SGreg Clayton LoadSubCommand("list", list_command_object); 242523f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 242623f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 242723f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 242823f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 242923f59509SGreg Clayton LoadSubCommand("set", set_command_object); 243023f59509SGreg Clayton LoadSubCommand("command", command_command_object); 243123f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 24325e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 2433e14dc268SJim Ingham LoadSubCommand("write", write_command_object); 2434e14dc268SJim Ingham LoadSubCommand("read", read_command_object); 243530fdc8d8SChris Lattner } 243630fdc8d8SChris Lattner 24379e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 243830fdc8d8SChris Lattner 2439b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, 24405e09c8c3SJim Ingham bool allow_locations, 24415e09c8c3SJim Ingham CommandReturnObject &result, 2442b842f2ecSJim Ingham BreakpointIDList *valid_ids, 2443b842f2ecSJim Ingham BreakpointName::Permissions 2444b842f2ecSJim Ingham ::PermissionKinds 2445b842f2ecSJim Ingham purpose) { 244630fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2447b9c1b51eSKate Stone // 2). the full breakpoint & location 2448b9c1b51eSKate Stone // canonical representation 2449b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2450b9c1b51eSKate Stone // representing a range (in which case there 2451b9c1b51eSKate Stone // had *better* be an entry both before & 2452b9c1b51eSKate Stone // after of one of the first two types. 24535e09c8c3SJim Ingham // 4). A breakpoint name 2454b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2455b9c1b51eSKate Stone // one.) 245630fdc8d8SChris Lattner 245730fdc8d8SChris Lattner Args temp_args; 245830fdc8d8SChris Lattner 245911eb9c64SZachary Turner if (args.empty()) { 2460b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2461b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2462b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 246336f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2464b9c1b51eSKate Stone } else { 2465b9c1b51eSKate Stone result.AppendError( 2466b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 246736f3b369SJim Ingham result.SetStatus(eReturnStatusFailed); 246836f3b369SJim Ingham } 246936f3b369SJim Ingham return; 247036f3b369SJim Ingham } 247136f3b369SJim Ingham 2472b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 247305097246SAdrian Prantl // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 247405097246SAdrian Prantl // id range strings over; instead generate a list of strings for all the 247505097246SAdrian Prantl // breakpoint ids in the range, and shove all of those breakpoint id strings 247605097246SAdrian Prantl // into TEMP_ARGS. 247730fdc8d8SChris Lattner 2478b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2479b842f2ecSJim Ingham purpose, result, temp_args); 248030fdc8d8SChris Lattner 2481b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2482b9c1b51eSKate Stone // BreakpointIDList: 248330fdc8d8SChris Lattner 248416662f3cSPavel Labath valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 248530fdc8d8SChris Lattner 248605097246SAdrian Prantl // At this point, all of the breakpoint ids that the user passed in have 248705097246SAdrian Prantl // been converted to breakpoint IDs and put into valid_ids. 248830fdc8d8SChris Lattner 2489b9c1b51eSKate Stone if (result.Succeeded()) { 2490b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 249105097246SAdrian Prantl // ids, go through our tentative list of breakpoint id's and verify that 249205097246SAdrian Prantl // they correspond to valid/currently set breakpoints. 249330fdc8d8SChris Lattner 2494c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2495b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 249630fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2497b9c1b51eSKate Stone Breakpoint *breakpoint = 2498b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2499b9c1b51eSKate Stone if (breakpoint != nullptr) { 2500c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2501b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 250230fdc8d8SChris Lattner StreamString id_str; 2503b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2504b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2505c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2506b9c1b51eSKate Stone result.AppendErrorWithFormat( 2507b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 250830fdc8d8SChris Lattner id_str.GetData()); 250930fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 251030fdc8d8SChris Lattner } 2511b9c1b51eSKate Stone } else { 2512c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2513b9c1b51eSKate Stone result.AppendErrorWithFormat( 2514b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 25157428a18cSKate Stone cur_bp_id.GetBreakpointID()); 251630fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 251730fdc8d8SChris Lattner } 251830fdc8d8SChris Lattner } 251930fdc8d8SChris Lattner } 252030fdc8d8SChris Lattner } 2521