130fdc8d8SChris Lattner //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner // C Includes 1130fdc8d8SChris Lattner // C++ Includes 129e85e5a8SEugene Zelenko #include <vector> 139e85e5a8SEugene Zelenko 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 169e85e5a8SEugene Zelenko #include "CommandObjectBreakpoint.h" 179e85e5a8SEugene Zelenko #include "CommandObjectBreakpointCommand.h" 1830fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h" 1930fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h" 2030fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h" 21*b9c1b51eSKate Stone #include "lldb/Core/RegularExpression.h" 22*b9c1b51eSKate Stone #include "lldb/Core/StreamString.h" 235275aaa0SVince Harron #include "lldb/Host/StringConvert.h" 24*b9c1b51eSKate Stone #include "lldb/Interpreter/CommandCompletions.h" 25*b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h" 26*b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h" 2732abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h" 285e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h" 295e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h" 30*b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 310e0984eeSJim Ingham #include "lldb/Target/Language.h" 32b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 33*b9c1b51eSKate Stone #include "lldb/Target/Target.h" 341b54c88cSJim Ingham #include "lldb/Target/Thread.h" 351b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h" 3630fdc8d8SChris Lattner 3730fdc8d8SChris Lattner using namespace lldb; 3830fdc8d8SChris Lattner using namespace lldb_private; 3930fdc8d8SChris Lattner 40*b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp, 41*b9c1b51eSKate Stone lldb::DescriptionLevel level) { 4230fdc8d8SChris Lattner s->IndentMore(); 4330fdc8d8SChris Lattner bp->GetDescription(s, level, true); 4430fdc8d8SChris Lattner s->IndentLess(); 4530fdc8d8SChris Lattner s->EOL(); 4630fdc8d8SChris Lattner } 4730fdc8d8SChris Lattner 4830fdc8d8SChris Lattner //------------------------------------------------------------------------- 495a988416SJim Ingham // CommandObjectBreakpointSet 5030fdc8d8SChris Lattner //------------------------------------------------------------------------- 5130fdc8d8SChris Lattner 52*b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 535a988416SJim Ingham public: 54*b9c1b51eSKate Stone typedef enum BreakpointSetType { 555a988416SJim Ingham eSetTypeInvalid, 565a988416SJim Ingham eSetTypeFileAndLine, 575a988416SJim Ingham eSetTypeAddress, 585a988416SJim Ingham eSetTypeFunctionName, 595a988416SJim Ingham eSetTypeFunctionRegexp, 605a988416SJim Ingham eSetTypeSourceRegexp, 615a988416SJim Ingham eSetTypeException 625a988416SJim Ingham } BreakpointSetType; 635a988416SJim Ingham 64*b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 65*b9c1b51eSKate Stone : CommandObjectParsed( 66*b9c1b51eSKate Stone interpreter, "breakpoint set", 675a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 685a988416SJim Ingham "breakpoint set <cmd-options>"), 69*b9c1b51eSKate Stone m_options() {} 705a988416SJim Ingham 719e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 725a988416SJim Ingham 73*b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 745a988416SJim Ingham 75*b9c1b51eSKate Stone class CommandOptions : public Options { 765a988416SJim Ingham public: 77*b9c1b51eSKate Stone CommandOptions() 78*b9c1b51eSKate Stone : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0), 79*b9c1b51eSKate Stone m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone), 80*b9c1b51eSKate Stone m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(), 81*b9c1b51eSKate Stone m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), 82*b9c1b51eSKate Stone m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(), 83*b9c1b51eSKate Stone m_catch_bp(false), m_throw_bp(true), m_hardware(false), 84a72b31c7SJim Ingham m_exception_language(eLanguageTypeUnknown), 8523b1decbSDawn Perchik m_language(lldb::eLanguageTypeUnknown), 86*b9c1b51eSKate Stone m_skip_prologue(eLazyBoolCalculate), m_one_shot(false), 87*b9c1b51eSKate Stone m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {} 8830fdc8d8SChris Lattner 899e85e5a8SEugene Zelenko ~CommandOptions() override = default; 9087df91b8SJim Ingham 91*b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 92*b9c1b51eSKate Stone ExecutionContext *execution_context) override { 9330fdc8d8SChris Lattner Error error; 943bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 9530fdc8d8SChris Lattner 96*b9c1b51eSKate Stone switch (short_option) { 97*b9c1b51eSKate Stone case 'a': { 98*b9c1b51eSKate Stone m_load_addr = Args::StringToAddress(execution_context, option_arg, 99e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 100*b9c1b51eSKate Stone } break; 10130fdc8d8SChris Lattner 102e732052fSJim Ingham case 'A': 103e732052fSJim Ingham m_all_files = true; 104e732052fSJim Ingham break; 105e732052fSJim Ingham 106ca36cd16SJim Ingham case 'b': 107ca36cd16SJim Ingham m_func_names.push_back(option_arg); 108ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 109ca36cd16SJim Ingham break; 110ca36cd16SJim Ingham 111*b9c1b51eSKate Stone case 'C': { 1126312991cSJim Ingham bool success; 1136312991cSJim Ingham m_column = StringConvert::ToUInt32(option_arg, 0, 0, &success); 1146312991cSJim Ingham if (!success) 115*b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 116*b9c1b51eSKate Stone option_arg); 11730fdc8d8SChris Lattner break; 1186312991cSJim Ingham } 1199e85e5a8SEugene Zelenko 1207d49c9c8SJohnny Chen case 'c': 1217d49c9c8SJohnny Chen m_condition.assign(option_arg); 1227d49c9c8SJohnny Chen break; 1237d49c9c8SJohnny Chen 12433df7cd3SJim Ingham case 'D': 12533df7cd3SJim Ingham m_use_dummy = true; 12633df7cd3SJim Ingham break; 12733df7cd3SJim Ingham 128*b9c1b51eSKate Stone case 'E': { 1290e0984eeSJim Ingham LanguageType language = Language::GetLanguageTypeFromString(option_arg); 130fab10e89SJim Ingham 131*b9c1b51eSKate Stone switch (language) { 132fab10e89SJim Ingham case eLanguageTypeC89: 133fab10e89SJim Ingham case eLanguageTypeC: 134fab10e89SJim Ingham case eLanguageTypeC99: 1351d0089faSBruce Mitchener case eLanguageTypeC11: 136a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 137fab10e89SJim Ingham break; 138fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 1391d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 1401d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 1412ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 142a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 143fab10e89SJim Ingham break; 144fab10e89SJim Ingham case eLanguageTypeObjC: 145a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 146fab10e89SJim Ingham break; 147fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 148*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 149*b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 150fab10e89SJim Ingham break; 151fab10e89SJim Ingham case eLanguageTypeUnknown: 152*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 153*b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 154*b9c1b51eSKate Stone option_arg); 155fab10e89SJim Ingham break; 156fab10e89SJim Ingham default: 157*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 158*b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 159*b9c1b51eSKate Stone option_arg); 160fab10e89SJim Ingham } 161*b9c1b51eSKate Stone } break; 162ca36cd16SJim Ingham 163ca36cd16SJim Ingham case 'f': 164ca36cd16SJim Ingham m_filenames.AppendIfUnique(FileSpec(option_arg, false)); 165fab10e89SJim Ingham break; 166ca36cd16SJim Ingham 167ca36cd16SJim Ingham case 'F': 168ca36cd16SJim Ingham m_func_names.push_back(option_arg); 169ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 170ca36cd16SJim Ingham break; 171ca36cd16SJim Ingham 172*b9c1b51eSKate Stone case 'h': { 173fab10e89SJim Ingham bool success; 174fab10e89SJim Ingham m_catch_bp = Args::StringToBoolean(option_arg, true, &success); 175fab10e89SJim Ingham if (!success) 176*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 177*b9c1b51eSKate Stone "Invalid boolean value for on-catch option: '%s'", option_arg); 178*b9c1b51eSKate Stone } break; 179eb023e75SGreg Clayton 180eb023e75SGreg Clayton case 'H': 181eb023e75SGreg Clayton m_hardware = true; 182eb023e75SGreg Clayton break; 183eb023e75SGreg Clayton 184ca36cd16SJim Ingham case 'i': 1855275aaa0SVince Harron m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 186ca36cd16SJim Ingham if (m_ignore_count == UINT32_MAX) 187*b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid ignore count '%s'", 188*b9c1b51eSKate Stone option_arg); 189ca36cd16SJim Ingham break; 190ca36cd16SJim Ingham 191*b9c1b51eSKate Stone case 'K': { 192a8558b62SJim Ingham bool success; 193a8558b62SJim Ingham bool value; 194a8558b62SJim Ingham value = Args::StringToBoolean(option_arg, true, &success); 195a8558b62SJim Ingham if (value) 196a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 197a8558b62SJim Ingham else 198a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 199a8558b62SJim Ingham 200a8558b62SJim Ingham if (!success) 201*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 202*b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 203*b9c1b51eSKate Stone option_arg); 204*b9c1b51eSKate Stone } break; 205ca36cd16SJim Ingham 206*b9c1b51eSKate Stone case 'l': { 2076312991cSJim Ingham bool success; 2086312991cSJim Ingham m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success); 2096312991cSJim Ingham if (!success) 210*b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 211*b9c1b51eSKate Stone option_arg); 212ca36cd16SJim Ingham break; 2136312991cSJim Ingham } 214055ad9beSIlia K 21523b1decbSDawn Perchik case 'L': 2160e0984eeSJim Ingham m_language = Language::GetLanguageTypeFromString(option_arg); 21723b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 218*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 219*b9c1b51eSKate Stone "Unknown language type: '%s' for breakpoint", option_arg); 22023b1decbSDawn Perchik break; 22123b1decbSDawn Perchik 222*b9c1b51eSKate Stone case 'm': { 223055ad9beSIlia K bool success; 224055ad9beSIlia K bool value; 225055ad9beSIlia K value = Args::StringToBoolean(option_arg, true, &success); 226055ad9beSIlia K if (value) 227055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 228055ad9beSIlia K else 229055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 230055ad9beSIlia K 231055ad9beSIlia K if (!success) 232*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 233*b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 234*b9c1b51eSKate Stone option_arg); 235055ad9beSIlia K break; 236055ad9beSIlia K } 237055ad9beSIlia K 238ca36cd16SJim Ingham case 'M': 239ca36cd16SJim Ingham m_func_names.push_back(option_arg); 240ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 241ca36cd16SJim Ingham break; 242ca36cd16SJim Ingham 243ca36cd16SJim Ingham case 'n': 244ca36cd16SJim Ingham m_func_names.push_back(option_arg); 245ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 246ca36cd16SJim Ingham break; 247ca36cd16SJim Ingham 2485e09c8c3SJim Ingham case 'N': 2495e09c8c3SJim Ingham if (BreakpointID::StringIsBreakpointName(option_arg, error)) 2505e09c8c3SJim Ingham m_breakpoint_names.push_back(option_arg); 2515e09c8c3SJim Ingham break; 2525e09c8c3SJim Ingham 253*b9c1b51eSKate Stone case 'R': { 2542411167fSJim Ingham lldb::addr_t tmp_offset_addr; 255e1cfbc79STodd Fiala tmp_offset_addr = 256*b9c1b51eSKate Stone Args::StringToAddress(execution_context, option_arg, 0, &error); 2572411167fSJim Ingham if (error.Success()) 2582411167fSJim Ingham m_offset_addr = tmp_offset_addr; 259*b9c1b51eSKate Stone } break; 2602411167fSJim Ingham 261ca36cd16SJim Ingham case 'o': 262ca36cd16SJim Ingham m_one_shot = true; 263ca36cd16SJim Ingham break; 264ca36cd16SJim Ingham 265a72b31c7SJim Ingham case 'O': 266a72b31c7SJim Ingham m_exception_extra_args.AppendArgument("-O"); 267a72b31c7SJim Ingham m_exception_extra_args.AppendArgument(option_arg); 268a72b31c7SJim Ingham break; 269a72b31c7SJim Ingham 270ca36cd16SJim Ingham case 'p': 271ca36cd16SJim Ingham m_source_text_regexp.assign(option_arg); 272ca36cd16SJim Ingham break; 273ca36cd16SJim Ingham 274ca36cd16SJim Ingham case 'q': 275ca36cd16SJim Ingham m_queue_name.assign(option_arg); 276ca36cd16SJim Ingham break; 277ca36cd16SJim Ingham 278ca36cd16SJim Ingham case 'r': 279ca36cd16SJim Ingham m_func_regexp.assign(option_arg); 280ca36cd16SJim Ingham break; 281ca36cd16SJim Ingham 282ca36cd16SJim Ingham case 's': 283ca36cd16SJim Ingham m_modules.AppendIfUnique(FileSpec(option_arg, false)); 284ca36cd16SJim Ingham break; 285ca36cd16SJim Ingham 286ca36cd16SJim Ingham case 'S': 287ca36cd16SJim Ingham m_func_names.push_back(option_arg); 288ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 289ca36cd16SJim Ingham break; 290ca36cd16SJim Ingham 291ca36cd16SJim Ingham case 't': 292*b9c1b51eSKate Stone m_thread_id = 293*b9c1b51eSKate Stone StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 294ca36cd16SJim Ingham if (m_thread_id == LLDB_INVALID_THREAD_ID) 295*b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread id string '%s'", 296*b9c1b51eSKate Stone option_arg); 297ca36cd16SJim Ingham break; 298ca36cd16SJim Ingham 299ca36cd16SJim Ingham case 'T': 300ca36cd16SJim Ingham m_thread_name.assign(option_arg); 301ca36cd16SJim Ingham break; 302ca36cd16SJim Ingham 303*b9c1b51eSKate Stone case 'w': { 304ca36cd16SJim Ingham bool success; 305ca36cd16SJim Ingham m_throw_bp = Args::StringToBoolean(option_arg, true, &success); 306ca36cd16SJim Ingham if (!success) 307*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 308*b9c1b51eSKate Stone "Invalid boolean value for on-throw option: '%s'", option_arg); 309*b9c1b51eSKate Stone } break; 310ca36cd16SJim Ingham 311ca36cd16SJim Ingham case 'x': 3125275aaa0SVince Harron m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 313ca36cd16SJim Ingham if (m_thread_id == UINT32_MAX) 314*b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread index string '%s'", 315*b9c1b51eSKate Stone option_arg); 316ca36cd16SJim Ingham break; 317ca36cd16SJim Ingham 31876bb8d67SJim Ingham case 'X': 31976bb8d67SJim Ingham m_source_regex_func_names.insert(option_arg); 32076bb8d67SJim Ingham break; 32176bb8d67SJim Ingham 32230fdc8d8SChris Lattner default: 323*b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 324*b9c1b51eSKate Stone short_option); 32530fdc8d8SChris Lattner break; 32630fdc8d8SChris Lattner } 32730fdc8d8SChris Lattner 32830fdc8d8SChris Lattner return error; 32930fdc8d8SChris Lattner } 3309e85e5a8SEugene Zelenko 331*b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 3327d49c9c8SJohnny Chen m_condition.clear(); 33387df91b8SJim Ingham m_filenames.Clear(); 33430fdc8d8SChris Lattner m_line_num = 0; 33530fdc8d8SChris Lattner m_column = 0; 336fab10e89SJim Ingham m_func_names.clear(); 3371f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 33830fdc8d8SChris Lattner m_func_regexp.clear(); 3391f746071SGreg Clayton m_source_text_regexp.clear(); 34087df91b8SJim Ingham m_modules.Clear(); 3411f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 3422411167fSJim Ingham m_offset_addr = 0; 343c982c768SGreg Clayton m_ignore_count = 0; 3441b54c88cSJim Ingham m_thread_id = LLDB_INVALID_THREAD_ID; 345c982c768SGreg Clayton m_thread_index = UINT32_MAX; 3461b54c88cSJim Ingham m_thread_name.clear(); 3471b54c88cSJim Ingham m_queue_name.clear(); 348fab10e89SJim Ingham m_catch_bp = false; 349fab10e89SJim Ingham m_throw_bp = true; 350eb023e75SGreg Clayton m_hardware = false; 351a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 35223b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 353a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 354ca36cd16SJim Ingham m_one_shot = false; 35533df7cd3SJim Ingham m_use_dummy = false; 3565e09c8c3SJim Ingham m_breakpoint_names.clear(); 357e732052fSJim Ingham m_all_files = false; 358a72b31c7SJim Ingham m_exception_extra_args.Clear(); 359055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 36076bb8d67SJim Ingham m_source_regex_func_names.clear(); 36130fdc8d8SChris Lattner } 36230fdc8d8SChris Lattner 363*b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { return g_option_table; } 36430fdc8d8SChris Lattner 3655a988416SJim Ingham // Options table: Required for subclasses of Options. 36630fdc8d8SChris Lattner 3675a988416SJim Ingham static OptionDefinition g_option_table[]; 36830fdc8d8SChris Lattner 3695a988416SJim Ingham // Instance variables to hold the values for command options. 370969795f1SJim Ingham 3715a988416SJim Ingham std::string m_condition; 3725a988416SJim Ingham FileSpecList m_filenames; 3735a988416SJim Ingham uint32_t m_line_num; 3745a988416SJim Ingham uint32_t m_column; 3755a988416SJim Ingham std::vector<std::string> m_func_names; 3765e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 3775a988416SJim Ingham uint32_t m_func_name_type_mask; 3785a988416SJim Ingham std::string m_func_regexp; 3795a988416SJim Ingham std::string m_source_text_regexp; 3805a988416SJim Ingham FileSpecList m_modules; 3815a988416SJim Ingham lldb::addr_t m_load_addr; 3822411167fSJim Ingham lldb::addr_t m_offset_addr; 3835a988416SJim Ingham uint32_t m_ignore_count; 3845a988416SJim Ingham lldb::tid_t m_thread_id; 3855a988416SJim Ingham uint32_t m_thread_index; 3865a988416SJim Ingham std::string m_thread_name; 3875a988416SJim Ingham std::string m_queue_name; 3885a988416SJim Ingham bool m_catch_bp; 3895a988416SJim Ingham bool m_throw_bp; 390eb023e75SGreg Clayton bool m_hardware; // Request to use hardware breakpoints 391a72b31c7SJim Ingham lldb::LanguageType m_exception_language; 39223b1decbSDawn Perchik lldb::LanguageType m_language; 3935a988416SJim Ingham LazyBool m_skip_prologue; 394ca36cd16SJim Ingham bool m_one_shot; 39533df7cd3SJim Ingham bool m_use_dummy; 396e732052fSJim Ingham bool m_all_files; 397a72b31c7SJim Ingham Args m_exception_extra_args; 398055ad9beSIlia K LazyBool m_move_to_nearest_code; 39976bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 4005a988416SJim Ingham }; 4015a988416SJim Ingham 4025a988416SJim Ingham protected: 403*b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 40433df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 40533df7cd3SJim Ingham 406*b9c1b51eSKate Stone if (target == nullptr) { 407*b9c1b51eSKate Stone result.AppendError("Invalid target. Must set target before setting " 408*b9c1b51eSKate Stone "breakpoints (see 'target create' command)."); 40930fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 41030fdc8d8SChris Lattner return false; 41130fdc8d8SChris Lattner } 41230fdc8d8SChris Lattner 41330fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 41430fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 41530fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 41630fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 417*b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 418*b9c1b51eSKate Stone // expression) 419*b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 420*b9c1b51eSKate Stone // to source text) 421*b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 422*b9c1b51eSKate Stone // given language.) 42330fdc8d8SChris Lattner 42430fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 42530fdc8d8SChris Lattner 42630fdc8d8SChris Lattner if (m_options.m_line_num != 0) 42730fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 42830fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 42930fdc8d8SChris Lattner break_type = eSetTypeAddress; 430fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 43130fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 43230fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 43330fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 434969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 435969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 436a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 437fab10e89SJim Ingham break_type = eSetTypeException; 43830fdc8d8SChris Lattner 4399e85e5a8SEugene Zelenko Breakpoint *bp = nullptr; 440274060b6SGreg Clayton FileSpec module_spec; 441a8558b62SJim Ingham const bool internal = false; 442a8558b62SJim Ingham 443*b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 444*b9c1b51eSKate Stone // that off. 445*b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 446*b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 4472411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 4482411167fSJim Ingham 449*b9c1b51eSKate Stone switch (break_type) { 45030fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 45130fdc8d8SChris Lattner { 45230fdc8d8SChris Lattner FileSpec file; 453c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 454*b9c1b51eSKate Stone if (num_files == 0) { 455*b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 45687df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 45787df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 45887df91b8SJim Ingham return false; 45987df91b8SJim Ingham } 460*b9c1b51eSKate Stone } else if (num_files > 1) { 461*b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 462*b9c1b51eSKate Stone "line breakpoints."); 46387df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 46487df91b8SJim Ingham return false; 465*b9c1b51eSKate Stone } else 46687df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 46730fdc8d8SChris Lattner 4681f746071SGreg Clayton // Only check for inline functions if 4691f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 4701f746071SGreg Clayton 471*b9c1b51eSKate Stone bp = target 472*b9c1b51eSKate Stone ->CreateBreakpoint(&(m_options.m_modules), file, 473*b9c1b51eSKate Stone m_options.m_line_num, m_options.m_offset_addr, 474*b9c1b51eSKate Stone check_inlines, m_options.m_skip_prologue, 475*b9c1b51eSKate Stone internal, m_options.m_hardware, 476*b9c1b51eSKate Stone m_options.m_move_to_nearest_code) 477*b9c1b51eSKate Stone .get(); 478*b9c1b51eSKate Stone } break; 4796eee5aa0SGreg Clayton 48030fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 481055a08a4SJim Ingham { 482*b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 483*b9c1b51eSKate Stone // with the library, and 484*b9c1b51eSKate Stone // use that. That way the address breakpoint will track the load location 485*b9c1b51eSKate Stone // of the library. 486055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 487*b9c1b51eSKate Stone if (num_modules_specified == 1) { 488*b9c1b51eSKate Stone const FileSpec *file_spec = 489*b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 490*b9c1b51eSKate Stone bp = target 491*b9c1b51eSKate Stone ->CreateAddressInModuleBreakpoint(m_options.m_load_addr, 492*b9c1b51eSKate Stone internal, file_spec, 493*b9c1b51eSKate Stone m_options.m_hardware) 494*b9c1b51eSKate Stone .get(); 495*b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 496*b9c1b51eSKate Stone bp = target 497*b9c1b51eSKate Stone ->CreateBreakpoint(m_options.m_load_addr, internal, 498*b9c1b51eSKate Stone m_options.m_hardware) 499*b9c1b51eSKate Stone .get(); 500*b9c1b51eSKate Stone } else { 501*b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 502*b9c1b51eSKate Stone "address breakpoints."); 503055a08a4SJim Ingham result.SetStatus(eReturnStatusFailed); 504055a08a4SJim Ingham return false; 505055a08a4SJim Ingham } 50630fdc8d8SChris Lattner break; 507055a08a4SJim Ingham } 50830fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 5090c5cd90dSGreg Clayton { 5100c5cd90dSGreg Clayton uint32_t name_type_mask = m_options.m_func_name_type_mask; 5110c5cd90dSGreg Clayton 5120c5cd90dSGreg Clayton if (name_type_mask == 0) 513e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 5140c5cd90dSGreg Clayton 515*b9c1b51eSKate Stone bp = target 516*b9c1b51eSKate Stone ->CreateBreakpoint( 517*b9c1b51eSKate Stone &(m_options.m_modules), &(m_options.m_filenames), 518*b9c1b51eSKate Stone m_options.m_func_names, name_type_mask, m_options.m_language, 519*b9c1b51eSKate Stone m_options.m_offset_addr, m_options.m_skip_prologue, internal, 520*b9c1b51eSKate Stone m_options.m_hardware) 521*b9c1b51eSKate Stone .get(); 522*b9c1b51eSKate Stone } break; 5230c5cd90dSGreg Clayton 524*b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 525*b9c1b51eSKate Stone // name 52630fdc8d8SChris Lattner { 52730fdc8d8SChris Lattner RegularExpression regexp(m_options.m_func_regexp.c_str()); 528*b9c1b51eSKate Stone if (!regexp.IsValid()) { 529969795f1SJim Ingham char err_str[1024]; 530969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 531*b9c1b51eSKate Stone result.AppendErrorWithFormat( 532*b9c1b51eSKate Stone "Function name regular expression could not be compiled: \"%s\"", 533969795f1SJim Ingham err_str); 53430fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 535969795f1SJim Ingham return false; 53630fdc8d8SChris Lattner } 53787df91b8SJim Ingham 538*b9c1b51eSKate Stone bp = target 539*b9c1b51eSKate Stone ->CreateFuncRegexBreakpoint( 540*b9c1b51eSKate Stone &(m_options.m_modules), &(m_options.m_filenames), regexp, 541*b9c1b51eSKate Stone m_options.m_language, m_options.m_skip_prologue, internal, 542*b9c1b51eSKate Stone m_options.m_hardware) 543*b9c1b51eSKate Stone .get(); 544*b9c1b51eSKate Stone } break; 545969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 546969795f1SJim Ingham { 547c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 54887df91b8SJim Ingham 549*b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 550969795f1SJim Ingham FileSpec file; 551*b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 552*b9c1b51eSKate Stone result.AppendError( 553*b9c1b51eSKate Stone "No files provided and could not find default file."); 55487df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 55587df91b8SJim Ingham return false; 556*b9c1b51eSKate Stone } else { 55787df91b8SJim Ingham m_options.m_filenames.Append(file); 55887df91b8SJim Ingham } 55987df91b8SJim Ingham } 5600c5cd90dSGreg Clayton 561969795f1SJim Ingham RegularExpression regexp(m_options.m_source_text_regexp.c_str()); 562*b9c1b51eSKate Stone if (!regexp.IsValid()) { 563969795f1SJim Ingham char err_str[1024]; 564969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 565*b9c1b51eSKate Stone result.AppendErrorWithFormat( 566*b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"", 567969795f1SJim Ingham err_str); 568969795f1SJim Ingham result.SetStatus(eReturnStatusFailed); 569969795f1SJim Ingham return false; 570969795f1SJim Ingham } 571*b9c1b51eSKate Stone bp = target 572*b9c1b51eSKate Stone ->CreateSourceRegexBreakpoint( 573*b9c1b51eSKate Stone &(m_options.m_modules), &(m_options.m_filenames), 574*b9c1b51eSKate Stone m_options.m_source_regex_func_names, regexp, internal, 575*b9c1b51eSKate Stone m_options.m_hardware, m_options.m_move_to_nearest_code) 576*b9c1b51eSKate Stone .get(); 577*b9c1b51eSKate Stone } break; 578*b9c1b51eSKate Stone case eSetTypeException: { 579a72b31c7SJim Ingham Error precond_error; 580*b9c1b51eSKate Stone bp = target 581*b9c1b51eSKate Stone ->CreateExceptionBreakpoint( 582*b9c1b51eSKate Stone m_options.m_exception_language, m_options.m_catch_bp, 583*b9c1b51eSKate Stone m_options.m_throw_bp, internal, 584*b9c1b51eSKate Stone &m_options.m_exception_extra_args, &precond_error) 585*b9c1b51eSKate Stone .get(); 586*b9c1b51eSKate Stone if (precond_error.Fail()) { 587*b9c1b51eSKate Stone result.AppendErrorWithFormat( 588*b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 589a72b31c7SJim Ingham precond_error.AsCString()); 590a72b31c7SJim Ingham target->RemoveBreakpointByID(bp->GetID()); 591a72b31c7SJim Ingham result.SetStatus(eReturnStatusFailed); 592a72b31c7SJim Ingham return false; 593a72b31c7SJim Ingham } 594*b9c1b51eSKate Stone } break; 59530fdc8d8SChris Lattner default: 59630fdc8d8SChris Lattner break; 59730fdc8d8SChris Lattner } 59830fdc8d8SChris Lattner 5991b54c88cSJim Ingham // Now set the various options that were passed in: 600*b9c1b51eSKate Stone if (bp) { 6011b54c88cSJim Ingham if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 6021b54c88cSJim Ingham bp->SetThreadID(m_options.m_thread_id); 6031b54c88cSJim Ingham 604c982c768SGreg Clayton if (m_options.m_thread_index != UINT32_MAX) 6051b54c88cSJim Ingham bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); 6061b54c88cSJim Ingham 6071b54c88cSJim Ingham if (!m_options.m_thread_name.empty()) 608*b9c1b51eSKate Stone bp->GetOptions()->GetThreadSpec()->SetName( 609*b9c1b51eSKate Stone m_options.m_thread_name.c_str()); 6101b54c88cSJim Ingham 6111b54c88cSJim Ingham if (!m_options.m_queue_name.empty()) 612*b9c1b51eSKate Stone bp->GetOptions()->GetThreadSpec()->SetQueueName( 613*b9c1b51eSKate Stone m_options.m_queue_name.c_str()); 6141b54c88cSJim Ingham 615c982c768SGreg Clayton if (m_options.m_ignore_count != 0) 6161b54c88cSJim Ingham bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); 6177d49c9c8SJohnny Chen 6187d49c9c8SJohnny Chen if (!m_options.m_condition.empty()) 6197d49c9c8SJohnny Chen bp->GetOptions()->SetCondition(m_options.m_condition.c_str()); 620ca36cd16SJim Ingham 621*b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 622*b9c1b51eSKate Stone Error error; // We don't need to check the error here, since the option 623*b9c1b51eSKate Stone // parser checked it... 6245e09c8c3SJim Ingham for (auto name : m_options.m_breakpoint_names) 6255e09c8c3SJim Ingham bp->AddName(name.c_str(), error); 6265e09c8c3SJim Ingham } 6275e09c8c3SJim Ingham 628ca36cd16SJim Ingham bp->SetOneShot(m_options.m_one_shot); 6291b54c88cSJim Ingham } 6301b54c88cSJim Ingham 631*b9c1b51eSKate Stone if (bp) { 63285e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 6331391cc7dSJim Ingham const bool show_locations = false; 634*b9c1b51eSKate Stone bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 635*b9c1b51eSKate Stone show_locations); 6364aeb1989SJim Ingham if (target == m_interpreter.GetDebugger().GetDummyTarget()) 637*b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 638*b9c1b51eSKate Stone "into future targets.\n"); 639*b9c1b51eSKate Stone else { 640*b9c1b51eSKate Stone // Don't print out this warning for exception breakpoints. They can get 641*b9c1b51eSKate Stone // set before the target 642*b9c1b51eSKate Stone // is set, but we won't know how to actually set the breakpoint till we 643*b9c1b51eSKate Stone // run. 644*b9c1b51eSKate Stone if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) { 645*b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 646*b9c1b51eSKate Stone "actual locations.\n"); 6474aeb1989SJim Ingham } 6484aeb1989SJim Ingham } 64930fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 650*b9c1b51eSKate Stone } else if (!bp) { 65130fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 65230fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 65330fdc8d8SChris Lattner } 65430fdc8d8SChris Lattner 65530fdc8d8SChris Lattner return result.Succeeded(); 65630fdc8d8SChris Lattner } 65730fdc8d8SChris Lattner 6585a988416SJim Ingham private: 659*b9c1b51eSKate Stone bool GetDefaultFile(Target *target, FileSpec &file, 660*b9c1b51eSKate Stone CommandReturnObject &result) { 6615a988416SJim Ingham uint32_t default_line; 6625a988416SJim Ingham // First use the Source Manager's default file. 6635a988416SJim Ingham // Then use the current stack frame's file. 664*b9c1b51eSKate Stone if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 665b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 666*b9c1b51eSKate Stone if (cur_frame == nullptr) { 667*b9c1b51eSKate Stone result.AppendError( 668*b9c1b51eSKate Stone "No selected frame to use to find the default file."); 6695a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 6705a988416SJim Ingham return false; 671*b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 672*b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 673*b9c1b51eSKate Stone "file, it has no debug info."); 6745a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 6755a988416SJim Ingham return false; 676*b9c1b51eSKate Stone } else { 677*b9c1b51eSKate Stone const SymbolContext &sc = 678*b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 679*b9c1b51eSKate Stone if (sc.line_entry.file) { 6805a988416SJim Ingham file = sc.line_entry.file; 681*b9c1b51eSKate Stone } else { 682*b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 683*b9c1b51eSKate Stone "use as the default file."); 6845a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 6855a988416SJim Ingham return false; 6865a988416SJim Ingham } 6875a988416SJim Ingham } 6885a988416SJim Ingham } 6895a988416SJim Ingham return true; 6905a988416SJim Ingham } 6915a988416SJim Ingham 6925a988416SJim Ingham CommandOptions m_options; 6935a988416SJim Ingham }; 6949e85e5a8SEugene Zelenko 6955a988416SJim Ingham // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to 6965a988416SJim Ingham // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. 6975a988416SJim Ingham #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2) 6985a988416SJim Ingham #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10) 6995a988416SJim Ingham #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 7002411167fSJim Ingham #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 701055ad9beSIlia K #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) 7020fcdac36SJim Ingham #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) 7035a988416SJim Ingham 704*b9c1b51eSKate Stone OptionDefinition CommandObjectBreakpointSet::CommandOptions::g_option_table[] = 7055a988416SJim Ingham { 706ac9c3a62SKate Stone // clang-format off 707ac9c3a62SKate Stone {LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option " 708ac9c3a62SKate Stone "multiple times to specify multiple shared libraries."}, 709ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, 710ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "The breakpoint is deleted the first time it causes a stop." }, 711ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."}, 712ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose indeX matches this argument."}, 713ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."}, 714ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this " 715ac9c3a62SKate Stone "argument."}, 716ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints."}, 717ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by " 718ac9c3a62SKate Stone "this argument."}, 719ac9c3a62SKate Stone {LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default " 720ac9c3a62SKate Stone "lldb only looks for files that are #included if they use the standard include " 721ac9c3a62SKate Stone "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " 722ac9c3a62SKate Stone "#included, set target.inline-breakpoint-strategy to \"always\"."}, 723ac9c3a62SKate Stone {LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint."}, 7245a988416SJim Ingham 7255a988416SJim Ingham // Comment out this option for the moment, as we don't actually use it, but will in the future. 7265a988416SJim Ingham // This way users won't see it, but the infrastructure is left in place. 7279e85e5a8SEugene Zelenko // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>", 7285a988416SJim Ingham // "Set the breakpoint by source location at this particular column."}, 7295a988416SJim Ingham 730ac9c3a62SKate Stone {LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to " 731ac9c3a62SKate Stone "a particular binary, then the address will be converted to a \"file\" " 732ac9c3a62SKate Stone "address, so that the breakpoint will track that binary+offset no matter where " 733ac9c3a62SKate Stone "the binary eventually loads. Alternately, if you also specify the module - " 734ac9c3a62SKate Stone "with the -s option - then the address will be treated as a file address in " 735ac9c3a62SKate Stone "that module, and resolved accordingly. Again, this will allow lldb to track " 736ac9c3a62SKate Stone "that offset on subsequent reloads. The module need not have been loaded at " 737ac9c3a62SKate Stone "the time you specify this breakpoint, and will get resolved when the module " 738ac9c3a62SKate Stone "is loaded."}, 739ac9c3a62SKate Stone {LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make " 740ac9c3a62SKate Stone "one breakpoint for multiple names"}, 741ac9c3a62SKate Stone {LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named " 742ac9c3a62SKate Stone "functions. Can be repeated multiple times."}, 743ac9c3a62SKate Stone {LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means " 744ac9c3a62SKate Stone "namespaces and all arguments, and for Objective C this means a full function " 745ac9c3a62SKate Stone "prototype with class and selector. Can be repeated multiple times to make " 746ac9c3a62SKate Stone "one breakpoint for multiple names."}, 747ac9c3a62SKate Stone {LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to " 748ac9c3a62SKate Stone "make one breakpoint for multiple Selectors."}, 749ac9c3a62SKate Stone {LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to " 750ac9c3a62SKate Stone "make one breakpoint for multiple methods."}, 751ac9c3a62SKate Stone {LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find " 752ac9c3a62SKate Stone "the function name(s)."}, 753ac9c3a62SKate Stone {LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be " 754ac9c3a62SKate Stone "ignored). Can be repeated multiple times to make one breakpoint for multiple " 755ac9c3a62SKate Stone "symbols."}, 756ac9c3a62SKate Stone {LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched " 757ac9c3a62SKate Stone "against the source text in a source file or files specified with the -f " 758ac9c3a62SKate Stone "option. The -f option can be specified more than once. If no source files " 759ac9c3a62SKate Stone "are specified, uses the current \"default source file\". If you want to " 760ac9c3a62SKate Stone "match against all source files, pass the \"--all-files\" option."}, 761ac9c3a62SKate Stone {LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches."}, 762ac9c3a62SKate Stone {LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without " 763ac9c3a62SKate Stone "options, on throw but not catch.)"}, 764ac9c3a62SKate Stone {LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW."}, 765ac9c3a62SKate Stone {LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH."}, 7665a988416SJim Ingham 767a72b31c7SJim Ingham // Don't add this option till it actually does something useful... 7689e85e5a8SEugene Zelenko // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, 769a72b31c7SJim Ingham // "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" }, 770a72b31c7SJim Ingham 771ac9c3a62SKate Stone {LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression " 772ac9c3a62SKate Stone "(note: currently only implemented for setting breakpoints on identifiers). " 773ac9c3a62SKate Stone "If not set the target.language setting is used."}, 774ac9c3a62SKate Stone {LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. " 775ac9c3a62SKate Stone "If not set the target.skip-prologue setting is used."}, 776ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, " 777ac9c3a62SKate Stone "which prime new targets."}, 778ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint."}, 779ac9c3a62SKate Stone {LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. " 7802411167fSJim Ingham "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries."}, 781ac9c3a62SKate Stone {LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code " 782ac9c3a62SKate Stone "setting is used."}, 7839e85e5a8SEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 784ac9c3a62SKate Stone // clang-format on 7855a988416SJim Ingham }; 7865a988416SJim Ingham 7875a988416SJim Ingham //------------------------------------------------------------------------- 7885a988416SJim Ingham // CommandObjectBreakpointModify 7895a988416SJim Ingham //------------------------------------------------------------------------- 7905a988416SJim Ingham #pragma mark Modify 7915a988416SJim Ingham 792*b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 7935a988416SJim Ingham public: 794*b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 795*b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 796*b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 797*b9c1b51eSKate Stone "breakpoints in the executable. " 798*b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 799*b9c1b51eSKate Stone "created breakpoint. " 800*b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 801*b9c1b51eSKate Stone "empty argument clears the modification.", 8029e85e5a8SEugene Zelenko nullptr), 803*b9c1b51eSKate Stone m_options() { 8045a988416SJim Ingham CommandArgumentEntry arg; 805*b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 806*b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 807*b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 808*b9c1b51eSKate Stone // arguments vector. 8095a988416SJim Ingham m_arguments.push_back(arg); 8105a988416SJim Ingham } 8115a988416SJim Ingham 8129e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 8135a988416SJim Ingham 814*b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 8155a988416SJim Ingham 816*b9c1b51eSKate Stone class CommandOptions : public Options { 8175a988416SJim Ingham public: 818*b9c1b51eSKate Stone CommandOptions() 819*b9c1b51eSKate Stone : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), 820*b9c1b51eSKate Stone m_thread_id_passed(false), m_thread_index(UINT32_MAX), 821*b9c1b51eSKate Stone m_thread_index_passed(false), m_thread_name(), m_queue_name(), 822*b9c1b51eSKate Stone m_condition(), m_one_shot(false), m_enable_passed(false), 823*b9c1b51eSKate Stone m_enable_value(false), m_name_passed(false), m_queue_passed(false), 824*b9c1b51eSKate Stone m_condition_passed(false), m_one_shot_passed(false), 825*b9c1b51eSKate Stone m_use_dummy(false) {} 8265a988416SJim Ingham 8279e85e5a8SEugene Zelenko ~CommandOptions() override = default; 8285a988416SJim Ingham 829*b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 830*b9c1b51eSKate Stone ExecutionContext *execution_context) override { 8315a988416SJim Ingham Error error; 8323bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 8335a988416SJim Ingham 834*b9c1b51eSKate Stone switch (short_option) { 8355a988416SJim Ingham case 'c': 8369e85e5a8SEugene Zelenko if (option_arg != nullptr) 8375a988416SJim Ingham m_condition.assign(option_arg); 8385a988416SJim Ingham else 8395a988416SJim Ingham m_condition.clear(); 8405a988416SJim Ingham m_condition_passed = true; 8415a988416SJim Ingham break; 8425a988416SJim Ingham case 'd': 8435a988416SJim Ingham m_enable_passed = true; 8445a988416SJim Ingham m_enable_value = false; 8455a988416SJim Ingham break; 84633df7cd3SJim Ingham case 'D': 84733df7cd3SJim Ingham m_use_dummy = true; 84833df7cd3SJim Ingham break; 8495a988416SJim Ingham case 'e': 8505a988416SJim Ingham m_enable_passed = true; 8515a988416SJim Ingham m_enable_value = true; 8525a988416SJim Ingham break; 8535a988416SJim Ingham case 'i': 8545275aaa0SVince Harron m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 8555a988416SJim Ingham if (m_ignore_count == UINT32_MAX) 856*b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid ignore count '%s'", 857*b9c1b51eSKate Stone option_arg); 8585a988416SJim Ingham break; 859*b9c1b51eSKate Stone case 'o': { 860ca36cd16SJim Ingham bool value, success; 861ca36cd16SJim Ingham value = Args::StringToBoolean(option_arg, false, &success); 862*b9c1b51eSKate Stone if (success) { 863ca36cd16SJim Ingham m_one_shot_passed = true; 864ca36cd16SJim Ingham m_one_shot = value; 865*b9c1b51eSKate Stone } else 866*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 867*b9c1b51eSKate Stone "invalid boolean value '%s' passed for -o option", option_arg); 868*b9c1b51eSKate Stone } break; 8695a988416SJim Ingham case 't': 870*b9c1b51eSKate Stone if (option_arg[0] == '\0') { 8715a988416SJim Ingham m_thread_id = LLDB_INVALID_THREAD_ID; 8725a988416SJim Ingham m_thread_id_passed = true; 873*b9c1b51eSKate Stone } else { 874*b9c1b51eSKate Stone m_thread_id = 875*b9c1b51eSKate Stone StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 8765a988416SJim Ingham if (m_thread_id == LLDB_INVALID_THREAD_ID) 877*b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread id string '%s'", 878*b9c1b51eSKate Stone option_arg); 8795a988416SJim Ingham else 8805a988416SJim Ingham m_thread_id_passed = true; 8815a988416SJim Ingham } 8825a988416SJim Ingham break; 8835a988416SJim Ingham case 'T': 8849e85e5a8SEugene Zelenko if (option_arg != nullptr) 8855a988416SJim Ingham m_thread_name.assign(option_arg); 8865a988416SJim Ingham else 8875a988416SJim Ingham m_thread_name.clear(); 8885a988416SJim Ingham m_name_passed = true; 8895a988416SJim Ingham break; 8905a988416SJim Ingham case 'q': 8919e85e5a8SEugene Zelenko if (option_arg != nullptr) 8925a988416SJim Ingham m_queue_name.assign(option_arg); 8935a988416SJim Ingham else 8945a988416SJim Ingham m_queue_name.clear(); 8955a988416SJim Ingham m_queue_passed = true; 8965a988416SJim Ingham break; 8975a988416SJim Ingham case 'x': 898*b9c1b51eSKate Stone if (option_arg[0] == '\n') { 8995a988416SJim Ingham m_thread_index = UINT32_MAX; 9005a988416SJim Ingham m_thread_index_passed = true; 901*b9c1b51eSKate Stone } else { 9025275aaa0SVince Harron m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 9035a988416SJim Ingham if (m_thread_id == UINT32_MAX) 904*b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread index string '%s'", 905*b9c1b51eSKate Stone option_arg); 9065a988416SJim Ingham else 9075a988416SJim Ingham m_thread_index_passed = true; 9085a988416SJim Ingham } 9095a988416SJim Ingham break; 9105a988416SJim Ingham default: 911*b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 912*b9c1b51eSKate Stone short_option); 9135a988416SJim Ingham break; 9145a988416SJim Ingham } 9155a988416SJim Ingham 9165a988416SJim Ingham return error; 9175a988416SJim Ingham } 9189e85e5a8SEugene Zelenko 919*b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 9205a988416SJim Ingham m_ignore_count = 0; 9215a988416SJim Ingham m_thread_id = LLDB_INVALID_THREAD_ID; 9225a988416SJim Ingham m_thread_id_passed = false; 9235a988416SJim Ingham m_thread_index = UINT32_MAX; 9245a988416SJim Ingham m_thread_index_passed = false; 9255a988416SJim Ingham m_thread_name.clear(); 9265a988416SJim Ingham m_queue_name.clear(); 9275a988416SJim Ingham m_condition.clear(); 928ca36cd16SJim Ingham m_one_shot = false; 9295a988416SJim Ingham m_enable_passed = false; 9305a988416SJim Ingham m_queue_passed = false; 9315a988416SJim Ingham m_name_passed = false; 9325a988416SJim Ingham m_condition_passed = false; 933ca36cd16SJim Ingham m_one_shot_passed = false; 93433df7cd3SJim Ingham m_use_dummy = false; 9355a988416SJim Ingham } 9365a988416SJim Ingham 937*b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { return g_option_table; } 9385a988416SJim Ingham 9395a988416SJim Ingham // Options table: Required for subclasses of Options. 9405a988416SJim Ingham 9415a988416SJim Ingham static OptionDefinition g_option_table[]; 9425a988416SJim Ingham 9435a988416SJim Ingham // Instance variables to hold the values for command options. 9445a988416SJim Ingham 9455a988416SJim Ingham uint32_t m_ignore_count; 9465a988416SJim Ingham lldb::tid_t m_thread_id; 9475a988416SJim Ingham bool m_thread_id_passed; 9485a988416SJim Ingham uint32_t m_thread_index; 9495a988416SJim Ingham bool m_thread_index_passed; 9505a988416SJim Ingham std::string m_thread_name; 9515a988416SJim Ingham std::string m_queue_name; 9525a988416SJim Ingham std::string m_condition; 953ca36cd16SJim Ingham bool m_one_shot; 9545a988416SJim Ingham bool m_enable_passed; 9555a988416SJim Ingham bool m_enable_value; 9565a988416SJim Ingham bool m_name_passed; 9575a988416SJim Ingham bool m_queue_passed; 9585a988416SJim Ingham bool m_condition_passed; 959ca36cd16SJim Ingham bool m_one_shot_passed; 96033df7cd3SJim Ingham bool m_use_dummy; 9615a988416SJim Ingham }; 9625a988416SJim Ingham 9635a988416SJim Ingham protected: 964*b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 96533df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 966*b9c1b51eSKate Stone if (target == nullptr) { 9675a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 9685a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9695a988416SJim Ingham return false; 9705a988416SJim Ingham } 9715a988416SJim Ingham 972bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 973bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 9745a988416SJim Ingham 9755a988416SJim Ingham BreakpointIDList valid_bp_ids; 9765a988416SJim Ingham 977*b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 978*b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 9795a988416SJim Ingham 980*b9c1b51eSKate Stone if (result.Succeeded()) { 9815a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 982*b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 9835a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 9845a988416SJim Ingham 985*b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 986*b9c1b51eSKate Stone Breakpoint *bp = 987*b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 988*b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 989*b9c1b51eSKate Stone BreakpointLocation *location = 990*b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 991*b9c1b51eSKate Stone if (location) { 9925a988416SJim Ingham if (m_options.m_thread_id_passed) 9935a988416SJim Ingham location->SetThreadID(m_options.m_thread_id); 9945a988416SJim Ingham 9955a988416SJim Ingham if (m_options.m_thread_index_passed) 9965a988416SJim Ingham location->SetThreadIndex(m_options.m_thread_index); 9975a988416SJim Ingham 9985a988416SJim Ingham if (m_options.m_name_passed) 9995a988416SJim Ingham location->SetThreadName(m_options.m_thread_name.c_str()); 10005a988416SJim Ingham 10015a988416SJim Ingham if (m_options.m_queue_passed) 10025a988416SJim Ingham location->SetQueueName(m_options.m_queue_name.c_str()); 10035a988416SJim Ingham 10045a988416SJim Ingham if (m_options.m_ignore_count != 0) 10055a988416SJim Ingham location->SetIgnoreCount(m_options.m_ignore_count); 10065a988416SJim Ingham 10075a988416SJim Ingham if (m_options.m_enable_passed) 10085a988416SJim Ingham location->SetEnabled(m_options.m_enable_value); 10095a988416SJim Ingham 10105a988416SJim Ingham if (m_options.m_condition_passed) 10115a988416SJim Ingham location->SetCondition(m_options.m_condition.c_str()); 10125a988416SJim Ingham } 1013*b9c1b51eSKate Stone } else { 10145a988416SJim Ingham if (m_options.m_thread_id_passed) 10155a988416SJim Ingham bp->SetThreadID(m_options.m_thread_id); 10165a988416SJim Ingham 10175a988416SJim Ingham if (m_options.m_thread_index_passed) 10185a988416SJim Ingham bp->SetThreadIndex(m_options.m_thread_index); 10195a988416SJim Ingham 10205a988416SJim Ingham if (m_options.m_name_passed) 10215a988416SJim Ingham bp->SetThreadName(m_options.m_thread_name.c_str()); 10225a988416SJim Ingham 10235a988416SJim Ingham if (m_options.m_queue_passed) 10245a988416SJim Ingham bp->SetQueueName(m_options.m_queue_name.c_str()); 10255a988416SJim Ingham 10265a988416SJim Ingham if (m_options.m_ignore_count != 0) 10275a988416SJim Ingham bp->SetIgnoreCount(m_options.m_ignore_count); 10285a988416SJim Ingham 10295a988416SJim Ingham if (m_options.m_enable_passed) 10305a988416SJim Ingham bp->SetEnabled(m_options.m_enable_value); 10315a988416SJim Ingham 10325a988416SJim Ingham if (m_options.m_condition_passed) 10335a988416SJim Ingham bp->SetCondition(m_options.m_condition.c_str()); 10345a988416SJim Ingham } 10355a988416SJim Ingham } 10365a988416SJim Ingham } 10375a988416SJim Ingham } 10385a988416SJim Ingham 10395a988416SJim Ingham return result.Succeeded(); 10405a988416SJim Ingham } 10415a988416SJim Ingham 10425a988416SJim Ingham private: 10435a988416SJim Ingham CommandOptions m_options; 10445a988416SJim Ingham }; 10455a988416SJim Ingham 10465a988416SJim Ingham #pragma mark Modify::CommandOptions 10475a988416SJim Ingham OptionDefinition 1048*b9c1b51eSKate Stone CommandObjectBreakpointModify::CommandOptions::g_option_table[] = { 1049ac9c3a62SKate Stone // clang-format off 10509e85e5a8SEugene Zelenko {LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping."}, 10519e85e5a8SEugene Zelenko {LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop."}, 10529e85e5a8SEugene Zelenko {LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."}, 10539e85e5a8SEugene Zelenko {LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."}, 10549e85e5a8SEugene Zelenko {LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."}, 10559e85e5a8SEugene Zelenko {LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."}, 10569e85e5a8SEugene Zelenko {LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."}, 10579e85e5a8SEugene Zelenko {LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint."}, 10589e85e5a8SEugene Zelenko {LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint."}, 10599e85e5a8SEugene Zelenko {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 10609e85e5a8SEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 1061ac9c3a62SKate Stone // clang-format on 10625a988416SJim Ingham }; 10635a988416SJim Ingham 10645a988416SJim Ingham //------------------------------------------------------------------------- 10655a988416SJim Ingham // CommandObjectBreakpointEnable 10665a988416SJim Ingham //------------------------------------------------------------------------- 10675a988416SJim Ingham #pragma mark Enable 10685a988416SJim Ingham 1069*b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 10705a988416SJim Ingham public: 1071*b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 1072*b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 1073*b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 1074*b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 1075*b9c1b51eSKate Stone nullptr) { 10765a988416SJim Ingham CommandArgumentEntry arg; 1077*b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1078*b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1079*b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1080*b9c1b51eSKate Stone // arguments vector. 10815a988416SJim Ingham m_arguments.push_back(arg); 10825a988416SJim Ingham } 10835a988416SJim Ingham 10849e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 10855a988416SJim Ingham 10865a988416SJim Ingham protected: 1087*b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1088893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1089*b9c1b51eSKate Stone if (target == nullptr) { 10905a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 10915a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10925a988416SJim Ingham return false; 10935a988416SJim Ingham } 10945a988416SJim Ingham 1095bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1096bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 10975a988416SJim Ingham 10985a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 10995a988416SJim Ingham 11005a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 11015a988416SJim Ingham 1102*b9c1b51eSKate Stone if (num_breakpoints == 0) { 11035a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 11045a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11055a988416SJim Ingham return false; 11065a988416SJim Ingham } 11075a988416SJim Ingham 1108*b9c1b51eSKate Stone if (command.GetArgumentCount() == 0) { 11095a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 11105a988416SJim Ingham target->EnableAllBreakpoints(); 1111*b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 1112*b9c1b51eSKate Stone " breakpoints)\n", 1113*b9c1b51eSKate Stone (uint64_t)num_breakpoints); 11145a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1115*b9c1b51eSKate Stone } else { 11165a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 11175a988416SJim Ingham BreakpointIDList valid_bp_ids; 1118*b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1119*b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 11205a988416SJim Ingham 1121*b9c1b51eSKate Stone if (result.Succeeded()) { 11225a988416SJim Ingham int enable_count = 0; 11235a988416SJim Ingham int loc_count = 0; 11245a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1125*b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 11265a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 11275a988416SJim Ingham 1128*b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1129*b9c1b51eSKate Stone Breakpoint *breakpoint = 1130*b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1131*b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1132*b9c1b51eSKate Stone BreakpointLocation *location = 1133*b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1134*b9c1b51eSKate Stone if (location) { 11355a988416SJim Ingham location->SetEnabled(true); 11365a988416SJim Ingham ++loc_count; 11375a988416SJim Ingham } 1138*b9c1b51eSKate Stone } else { 11395a988416SJim Ingham breakpoint->SetEnabled(true); 11405a988416SJim Ingham ++enable_count; 11415a988416SJim Ingham } 11425a988416SJim Ingham } 11435a988416SJim Ingham } 1144*b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 1145*b9c1b51eSKate Stone enable_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 //------------------------------------------------------------------------- 11555a988416SJim Ingham // CommandObjectBreakpointDisable 11565a988416SJim Ingham //------------------------------------------------------------------------- 11575a988416SJim Ingham #pragma mark Disable 11585a988416SJim Ingham 1159*b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 11605a988416SJim Ingham public: 11617428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 1162*b9c1b51eSKate Stone : CommandObjectParsed( 1163*b9c1b51eSKate Stone interpreter, "breakpoint disable", 1164*b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 11657428a18cSKate Stone "them. If none are specified, disable all " 11667428a18cSKate Stone "breakpoints.", 1167*b9c1b51eSKate Stone nullptr) { 1168*b9c1b51eSKate Stone SetHelpLong( 1169*b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 11707428a18cSKate Stone If none are specified, disable all breakpoints." 11717428a18cSKate Stone R"( 1172ea671fbdSKate Stone 11737428a18cSKate Stone )" 11747428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 11757428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 11767428a18cSKate Stone R"( 1177ea671fbdSKate Stone 1178ea671fbdSKate Stone (lldb) break disable 1 1179ea671fbdSKate Stone (lldb) break enable 1.1 1180ea671fbdSKate Stone 1181ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 1182ea671fbdSKate Stone 1183ea671fbdSKate Stone (lldb) break disable 1.* 1184ea671fbdSKate Stone (lldb) break enable 1.1 1185ea671fbdSKate Stone 11867428a18cSKate Stone )" 11877428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 11887428a18cSKate Stone the second re-enables the first location."); 1189b0fac509SJim Ingham 11905a988416SJim Ingham CommandArgumentEntry arg; 1191*b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1192*b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1193*b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1194*b9c1b51eSKate Stone // arguments vector. 11955a988416SJim Ingham m_arguments.push_back(arg); 11965a988416SJim Ingham } 11975a988416SJim Ingham 11989e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 11995a988416SJim Ingham 12005a988416SJim Ingham protected: 1201*b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1202893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1203*b9c1b51eSKate Stone if (target == nullptr) { 12045a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 12055a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 12065a988416SJim Ingham return false; 12075a988416SJim Ingham } 12085a988416SJim Ingham 1209bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1210bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 12115a988416SJim Ingham 12125a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 12135a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 12145a988416SJim Ingham 1215*b9c1b51eSKate Stone if (num_breakpoints == 0) { 12165a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 12175a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 12185a988416SJim Ingham return false; 12195a988416SJim Ingham } 12205a988416SJim Ingham 1221*b9c1b51eSKate Stone if (command.GetArgumentCount() == 0) { 12225a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 12235a988416SJim Ingham target->DisableAllBreakpoints(); 1224*b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1225*b9c1b51eSKate Stone " breakpoints)\n", 1226*b9c1b51eSKate Stone (uint64_t)num_breakpoints); 12275a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1228*b9c1b51eSKate Stone } else { 12295a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 12305a988416SJim Ingham BreakpointIDList valid_bp_ids; 12315a988416SJim Ingham 1232*b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1233*b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 12345a988416SJim Ingham 1235*b9c1b51eSKate Stone if (result.Succeeded()) { 12365a988416SJim Ingham int disable_count = 0; 12375a988416SJim Ingham int loc_count = 0; 12385a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1239*b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 12405a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 12415a988416SJim Ingham 1242*b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1243*b9c1b51eSKate Stone Breakpoint *breakpoint = 1244*b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1245*b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1246*b9c1b51eSKate Stone BreakpointLocation *location = 1247*b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1248*b9c1b51eSKate Stone if (location) { 12495a988416SJim Ingham location->SetEnabled(false); 12505a988416SJim Ingham ++loc_count; 12515a988416SJim Ingham } 1252*b9c1b51eSKate Stone } else { 12535a988416SJim Ingham breakpoint->SetEnabled(false); 12545a988416SJim Ingham ++disable_count; 12555a988416SJim Ingham } 12565a988416SJim Ingham } 12575a988416SJim Ingham } 1258*b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1259*b9c1b51eSKate Stone disable_count + loc_count); 12605a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 12615a988416SJim Ingham } 12625a988416SJim Ingham } 12635a988416SJim Ingham 12645a988416SJim Ingham return result.Succeeded(); 12655a988416SJim Ingham } 12665a988416SJim Ingham }; 12675a988416SJim Ingham 12685a988416SJim Ingham //------------------------------------------------------------------------- 12695a988416SJim Ingham // CommandObjectBreakpointList 12705a988416SJim Ingham //------------------------------------------------------------------------- 12715a988416SJim Ingham #pragma mark List 12725a988416SJim Ingham 1273*b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 12745a988416SJim Ingham public: 1275*b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1276*b9c1b51eSKate Stone : CommandObjectParsed( 1277*b9c1b51eSKate Stone interpreter, "breakpoint list", 12785a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 12799e85e5a8SEugene Zelenko nullptr), 1280*b9c1b51eSKate Stone m_options() { 12815a988416SJim Ingham CommandArgumentEntry arg; 12825a988416SJim Ingham CommandArgumentData bp_id_arg; 12835a988416SJim Ingham 12845a988416SJim Ingham // Define the first (and only) variant of this arg. 12855a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 12865a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 12875a988416SJim Ingham 1288*b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1289*b9c1b51eSKate Stone // argument entry. 12905a988416SJim Ingham arg.push_back(bp_id_arg); 12915a988416SJim Ingham 12925a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 12935a988416SJim Ingham m_arguments.push_back(arg); 12945a988416SJim Ingham } 12955a988416SJim Ingham 12969e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 12975a988416SJim Ingham 1298*b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 12995a988416SJim Ingham 1300*b9c1b51eSKate Stone class CommandOptions : public Options { 13015a988416SJim Ingham public: 1302*b9c1b51eSKate Stone CommandOptions() 1303*b9c1b51eSKate Stone : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 13045a988416SJim Ingham } 13055a988416SJim Ingham 13069e85e5a8SEugene Zelenko ~CommandOptions() override = default; 13075a988416SJim Ingham 1308*b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1309*b9c1b51eSKate Stone ExecutionContext *execution_context) override { 13105a988416SJim Ingham Error error; 13113bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 13125a988416SJim Ingham 1313*b9c1b51eSKate Stone switch (short_option) { 13145a988416SJim Ingham case 'b': 13155a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 13165a988416SJim Ingham break; 131733df7cd3SJim Ingham case 'D': 131833df7cd3SJim Ingham m_use_dummy = true; 131933df7cd3SJim Ingham break; 13205a988416SJim Ingham case 'f': 13215a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 13225a988416SJim Ingham break; 13235a988416SJim Ingham case 'v': 13245a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 13255a988416SJim Ingham break; 13265a988416SJim Ingham case 'i': 13275a988416SJim Ingham m_internal = true; 13285a988416SJim Ingham break; 13295a988416SJim Ingham default: 1330*b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1331*b9c1b51eSKate Stone short_option); 13325a988416SJim Ingham break; 13335a988416SJim Ingham } 13345a988416SJim Ingham 13355a988416SJim Ingham return error; 13365a988416SJim Ingham } 13375a988416SJim Ingham 1338*b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 13395a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 13405a988416SJim Ingham m_internal = false; 134133df7cd3SJim Ingham m_use_dummy = false; 13425a988416SJim Ingham } 13435a988416SJim Ingham 1344*b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { return g_option_table; } 13455a988416SJim Ingham 13465a988416SJim Ingham // Options table: Required for subclasses of Options. 13475a988416SJim Ingham 13485a988416SJim Ingham static OptionDefinition g_option_table[]; 13495a988416SJim Ingham 13505a988416SJim Ingham // Instance variables to hold the values for command options. 13515a988416SJim Ingham 13525a988416SJim Ingham lldb::DescriptionLevel m_level; 13535a988416SJim Ingham 13545a988416SJim Ingham bool m_internal; 135533df7cd3SJim Ingham bool m_use_dummy; 13565a988416SJim Ingham }; 13575a988416SJim Ingham 13585a988416SJim Ingham protected: 1359*b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 136033df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 136133df7cd3SJim Ingham 1362*b9c1b51eSKate Stone if (target == nullptr) { 13635a988416SJim Ingham result.AppendError("Invalid target. No current target or breakpoints."); 13645a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13655a988416SJim Ingham return true; 13665a988416SJim Ingham } 13675a988416SJim Ingham 1368*b9c1b51eSKate Stone const BreakpointList &breakpoints = 1369*b9c1b51eSKate Stone target->GetBreakpointList(m_options.m_internal); 1370bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1371bb19a13cSSaleem Abdulrasool target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); 13725a988416SJim Ingham 13735a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 13745a988416SJim Ingham 1375*b9c1b51eSKate Stone if (num_breakpoints == 0) { 13765a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 13775a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13785a988416SJim Ingham return true; 13795a988416SJim Ingham } 13805a988416SJim Ingham 13815a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 13825a988416SJim Ingham 1383*b9c1b51eSKate Stone if (command.GetArgumentCount() == 0) { 13845a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 13855a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1386*b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 13875a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 13885a988416SJim Ingham AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level); 13895a988416SJim Ingham } 13905a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1391*b9c1b51eSKate Stone } else { 13925a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 13935a988416SJim Ingham BreakpointIDList valid_bp_ids; 1394*b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1395*b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 13965a988416SJim Ingham 1397*b9c1b51eSKate Stone if (result.Succeeded()) { 1398*b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 13995a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1400*b9c1b51eSKate Stone Breakpoint *breakpoint = 1401*b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1402*b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1403*b9c1b51eSKate Stone m_options.m_level); 14045a988416SJim Ingham } 14055a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1406*b9c1b51eSKate Stone } else { 14077428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 14085a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14095a988416SJim Ingham } 14105a988416SJim Ingham } 14115a988416SJim Ingham 14125a988416SJim Ingham return result.Succeeded(); 14135a988416SJim Ingham } 14145a988416SJim Ingham 14155a988416SJim Ingham private: 14165a988416SJim Ingham CommandOptions m_options; 14175a988416SJim Ingham }; 14185a988416SJim Ingham 14195a988416SJim Ingham #pragma mark List::CommandOptions 1420*b9c1b51eSKate Stone OptionDefinition CommandObjectBreakpointList::CommandOptions::g_option_table[] = 14215a988416SJim Ingham { 1422ac9c3a62SKate Stone // clang-format off 1423ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" }, 1424ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)."}, 14255a988416SJim Ingham // FIXME: We need to add an "internal" command, and then add this sort of thing to it. 14265a988416SJim Ingham // But I need to see it for now, and don't want to wait. 1427ac9c3a62SKate Stone {LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations."}, 1428ac9c3a62SKate Stone {LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)."}, 1429ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 14309e85e5a8SEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 1431ac9c3a62SKate Stone // clang-format on 14325a988416SJim Ingham }; 14335a988416SJim Ingham 14345a988416SJim Ingham //------------------------------------------------------------------------- 14355a988416SJim Ingham // CommandObjectBreakpointClear 14365a988416SJim Ingham //------------------------------------------------------------------------- 14375a988416SJim Ingham #pragma mark Clear 14385a988416SJim Ingham 1439*b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed { 14405a988416SJim Ingham public: 1441*b9c1b51eSKate Stone typedef enum BreakpointClearType { 14425a988416SJim Ingham eClearTypeInvalid, 14435a988416SJim Ingham eClearTypeFileAndLine 14445a988416SJim Ingham } BreakpointClearType; 14455a988416SJim Ingham 14467428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter) 14477428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear", 1448*b9c1b51eSKate Stone "Delete or disable breakpoints matching the " 1449*b9c1b51eSKate Stone "specified source file and line.", 14505a988416SJim Ingham "breakpoint clear <cmd-options>"), 1451*b9c1b51eSKate Stone m_options() {} 14525a988416SJim Ingham 14539e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default; 14545a988416SJim Ingham 1455*b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 14565a988416SJim Ingham 1457*b9c1b51eSKate Stone class CommandOptions : public Options { 14585a988416SJim Ingham public: 1459*b9c1b51eSKate Stone CommandOptions() : Options(), m_filename(), m_line_num(0) {} 14605a988416SJim Ingham 14619e85e5a8SEugene Zelenko ~CommandOptions() override = default; 14625a988416SJim Ingham 1463*b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1464*b9c1b51eSKate Stone ExecutionContext *execution_context) override { 14655a988416SJim Ingham Error error; 14663bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 14675a988416SJim Ingham 1468*b9c1b51eSKate Stone switch (short_option) { 14695a988416SJim Ingham case 'f': 14705a988416SJim Ingham m_filename.assign(option_arg); 14715a988416SJim Ingham break; 14725a988416SJim Ingham 14735a988416SJim Ingham case 'l': 14745275aaa0SVince Harron m_line_num = StringConvert::ToUInt32(option_arg, 0); 14755a988416SJim Ingham break; 14765a988416SJim Ingham 14775a988416SJim Ingham default: 1478*b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1479*b9c1b51eSKate Stone short_option); 14805a988416SJim Ingham break; 14815a988416SJim Ingham } 14825a988416SJim Ingham 14835a988416SJim Ingham return error; 14845a988416SJim Ingham } 14855a988416SJim Ingham 1486*b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 14875a988416SJim Ingham m_filename.clear(); 14885a988416SJim Ingham m_line_num = 0; 14895a988416SJim Ingham } 14905a988416SJim Ingham 1491*b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { return g_option_table; } 14925a988416SJim Ingham 14935a988416SJim Ingham // Options table: Required for subclasses of Options. 14945a988416SJim Ingham 14955a988416SJim Ingham static OptionDefinition g_option_table[]; 14965a988416SJim Ingham 14975a988416SJim Ingham // Instance variables to hold the values for command options. 14985a988416SJim Ingham 14995a988416SJim Ingham std::string m_filename; 15005a988416SJim Ingham uint32_t m_line_num; 15015a988416SJim Ingham }; 15025a988416SJim Ingham 15035a988416SJim Ingham protected: 1504*b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1505893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1506*b9c1b51eSKate Stone if (target == nullptr) { 15075a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 15085a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15095a988416SJim Ingham return false; 15105a988416SJim Ingham } 15115a988416SJim Ingham 15125a988416SJim Ingham // The following are the various types of breakpoints that could be cleared: 15135a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 15145a988416SJim Ingham 15155a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 15165a988416SJim Ingham 15175a988416SJim Ingham if (m_options.m_line_num != 0) 15185a988416SJim Ingham break_type = eClearTypeFileAndLine; 15195a988416SJim Ingham 1520bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1521bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 15225a988416SJim Ingham 15235a988416SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 15245a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 15255a988416SJim Ingham 15265a988416SJim Ingham // Early return if there's no breakpoint at all. 1527*b9c1b51eSKate Stone if (num_breakpoints == 0) { 15285a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15295a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15305a988416SJim Ingham return result.Succeeded(); 15315a988416SJim Ingham } 15325a988416SJim Ingham 15335a988416SJim Ingham // Find matching breakpoints and delete them. 15345a988416SJim Ingham 15355a988416SJim Ingham // First create a copy of all the IDs. 15365a988416SJim Ingham std::vector<break_id_t> BreakIDs; 15375a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 15389e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 15395a988416SJim Ingham 15405a988416SJim Ingham int num_cleared = 0; 15415a988416SJim Ingham StreamString ss; 1542*b9c1b51eSKate Stone switch (break_type) { 15435a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 15445a988416SJim Ingham { 15455a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 15465a988416SJim Ingham BreakpointLocationCollection loc_coll; 15475a988416SJim Ingham 1548*b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 15495a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 15505a988416SJim Ingham 1551*b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1552*b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1553*b9c1b51eSKate Stone // remove the breakpoint. 1554*b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 15555a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 15565a988416SJim Ingham ss.EOL(); 15575a988416SJim Ingham target->RemoveBreakpointByID(bp->GetID()); 15585a988416SJim Ingham ++num_cleared; 15595a988416SJim Ingham } 15605a988416SJim Ingham } 15615a988416SJim Ingham } 1562*b9c1b51eSKate Stone } break; 15635a988416SJim Ingham 15645a988416SJim Ingham default: 15655a988416SJim Ingham break; 15665a988416SJim Ingham } 15675a988416SJim Ingham 1568*b9c1b51eSKate Stone if (num_cleared > 0) { 15695a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 15705a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 15715a988416SJim Ingham output_stream << ss.GetData(); 15725a988416SJim Ingham output_stream.EOL(); 15735a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1574*b9c1b51eSKate Stone } else { 15755a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15765a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15775a988416SJim Ingham } 15785a988416SJim Ingham 15795a988416SJim Ingham return result.Succeeded(); 15805a988416SJim Ingham } 15815a988416SJim Ingham 15825a988416SJim Ingham private: 15835a988416SJim Ingham CommandOptions m_options; 15845a988416SJim Ingham }; 15855a988416SJim Ingham 15865a988416SJim Ingham #pragma mark Clear::CommandOptions 15875a988416SJim Ingham 15885a988416SJim Ingham OptionDefinition 1589*b9c1b51eSKate Stone CommandObjectBreakpointClear::CommandOptions::g_option_table[] = { 1590ac9c3a62SKate Stone // clang-format off 1591ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file."}, 1592ac9c3a62SKate Stone {LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line."}, 15939e85e5a8SEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 1594ac9c3a62SKate Stone // clang-format on 15955a988416SJim Ingham }; 15965a988416SJim Ingham 15975a988416SJim Ingham //------------------------------------------------------------------------- 15985a988416SJim Ingham // CommandObjectBreakpointDelete 15995a988416SJim Ingham //------------------------------------------------------------------------- 16005a988416SJim Ingham #pragma mark Delete 16015a988416SJim Ingham 1602*b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 16035a988416SJim Ingham public: 1604*b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1605*b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1606*b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1607*b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 16089e85e5a8SEugene Zelenko nullptr), 1609*b9c1b51eSKate Stone m_options() { 16105a988416SJim Ingham CommandArgumentEntry arg; 1611*b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1612*b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1613*b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1614*b9c1b51eSKate Stone // arguments vector. 16155a988416SJim Ingham m_arguments.push_back(arg); 16165a988416SJim Ingham } 16175a988416SJim Ingham 16189e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 16195a988416SJim Ingham 1620*b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 162133df7cd3SJim Ingham 1622*b9c1b51eSKate Stone class CommandOptions : public Options { 162333df7cd3SJim Ingham public: 1624*b9c1b51eSKate Stone CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 162533df7cd3SJim Ingham 16269e85e5a8SEugene Zelenko ~CommandOptions() override = default; 162733df7cd3SJim Ingham 1628*b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1629*b9c1b51eSKate Stone ExecutionContext *execution_context) override { 163033df7cd3SJim Ingham Error error; 163133df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 163233df7cd3SJim Ingham 1633*b9c1b51eSKate Stone switch (short_option) { 163433df7cd3SJim Ingham case 'f': 163533df7cd3SJim Ingham m_force = true; 163633df7cd3SJim Ingham break; 163733df7cd3SJim Ingham 163833df7cd3SJim Ingham case 'D': 163933df7cd3SJim Ingham m_use_dummy = true; 164033df7cd3SJim Ingham break; 164133df7cd3SJim Ingham 164233df7cd3SJim Ingham default: 1643*b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1644*b9c1b51eSKate Stone short_option); 164533df7cd3SJim Ingham break; 164633df7cd3SJim Ingham } 164733df7cd3SJim Ingham 164833df7cd3SJim Ingham return error; 164933df7cd3SJim Ingham } 165033df7cd3SJim Ingham 1651*b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 165233df7cd3SJim Ingham m_use_dummy = false; 165333df7cd3SJim Ingham m_force = false; 165433df7cd3SJim Ingham } 165533df7cd3SJim Ingham 1656*b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { return g_option_table; } 165733df7cd3SJim Ingham 165833df7cd3SJim Ingham // Options table: Required for subclasses of Options. 165933df7cd3SJim Ingham 166033df7cd3SJim Ingham static OptionDefinition g_option_table[]; 166133df7cd3SJim Ingham 166233df7cd3SJim Ingham // Instance variables to hold the values for command options. 166333df7cd3SJim Ingham bool m_use_dummy; 166433df7cd3SJim Ingham bool m_force; 166533df7cd3SJim Ingham }; 166633df7cd3SJim Ingham 16675a988416SJim Ingham protected: 1668*b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 166933df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 167033df7cd3SJim Ingham 1671*b9c1b51eSKate Stone if (target == nullptr) { 16725a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 16735a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16745a988416SJim Ingham return false; 16755a988416SJim Ingham } 16765a988416SJim Ingham 1677bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1678bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 16795a988416SJim Ingham 16805a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 16815a988416SJim Ingham 16825a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 16835a988416SJim Ingham 1684*b9c1b51eSKate Stone if (num_breakpoints == 0) { 16855a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 16865a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16875a988416SJim Ingham return false; 16885a988416SJim Ingham } 16895a988416SJim Ingham 1690*b9c1b51eSKate Stone if (command.GetArgumentCount() == 0) { 1691*b9c1b51eSKate Stone if (!m_options.m_force && 1692*b9c1b51eSKate Stone !m_interpreter.Confirm( 1693*b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1694*b9c1b51eSKate Stone true)) { 16955a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1696*b9c1b51eSKate Stone } else { 16975a988416SJim Ingham target->RemoveAllBreakpoints(); 1698*b9c1b51eSKate Stone result.AppendMessageWithFormat( 1699*b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1700*b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 17015a988416SJim Ingham } 17025a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1703*b9c1b51eSKate Stone } else { 17045a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 17055a988416SJim Ingham BreakpointIDList valid_bp_ids; 1706*b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1707*b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 17085a988416SJim Ingham 1709*b9c1b51eSKate Stone if (result.Succeeded()) { 17105a988416SJim Ingham int delete_count = 0; 17115a988416SJim Ingham int disable_count = 0; 17125a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1713*b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 17145a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 17155a988416SJim Ingham 1716*b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1717*b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1718*b9c1b51eSKate Stone Breakpoint *breakpoint = 1719*b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1720*b9c1b51eSKate Stone BreakpointLocation *location = 1721*b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1722*b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1723*b9c1b51eSKate Stone // disable them instead. 1724*b9c1b51eSKate Stone if (location) { 17255a988416SJim Ingham location->SetEnabled(false); 17265a988416SJim Ingham ++disable_count; 17275a988416SJim Ingham } 1728*b9c1b51eSKate Stone } else { 17295a988416SJim Ingham target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 17305a988416SJim Ingham ++delete_count; 17315a988416SJim Ingham } 17325a988416SJim Ingham } 17335a988416SJim Ingham } 1734*b9c1b51eSKate Stone result.AppendMessageWithFormat( 1735*b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 17365a988416SJim Ingham delete_count, disable_count); 17375a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 17385a988416SJim Ingham } 17395a988416SJim Ingham } 17405a988416SJim Ingham return result.Succeeded(); 17415a988416SJim Ingham } 17429e85e5a8SEugene Zelenko 174333df7cd3SJim Ingham private: 174433df7cd3SJim Ingham CommandOptions m_options; 174533df7cd3SJim Ingham }; 174633df7cd3SJim Ingham 174733df7cd3SJim Ingham OptionDefinition 1748*b9c1b51eSKate Stone CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = { 1749ac9c3a62SKate Stone // clang-format off 1750ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation."}, 1751ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 17529e85e5a8SEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 1753ac9c3a62SKate Stone // clang-format on 17545a988416SJim Ingham }; 17555a988416SJim Ingham 175630fdc8d8SChris Lattner //------------------------------------------------------------------------- 17575e09c8c3SJim Ingham // CommandObjectBreakpointName 17585e09c8c3SJim Ingham //------------------------------------------------------------------------- 17595e09c8c3SJim Ingham 17607428a18cSKate Stone static OptionDefinition g_breakpoint_name_options[] = { 1761ac9c3a62SKate Stone // clang-format off 1762ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, 1763ac9c3a62SKate Stone {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, 1764ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 1765ac9c3a62SKate Stone // clang-format on 17665e09c8c3SJim Ingham }; 1767*b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 17685e09c8c3SJim Ingham public: 1769*b9c1b51eSKate Stone BreakpointNameOptionGroup() 1770*b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 17715e09c8c3SJim Ingham } 17725e09c8c3SJim Ingham 17739e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 17745e09c8c3SJim Ingham 1775*b9c1b51eSKate Stone uint32_t GetNumDefinitions() override { 17765e09c8c3SJim Ingham return sizeof(g_breakpoint_name_options) / sizeof(OptionDefinition); 17775e09c8c3SJim Ingham } 17785e09c8c3SJim Ingham 1779*b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { 17805e09c8c3SJim Ingham return g_breakpoint_name_options; 17815e09c8c3SJim Ingham } 17825e09c8c3SJim Ingham 1783*b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_value, 1784*b9c1b51eSKate Stone ExecutionContext *execution_context) override { 17855e09c8c3SJim Ingham Error error; 17865e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 17875e09c8c3SJim Ingham 1788*b9c1b51eSKate Stone switch (short_option) { 17895e09c8c3SJim Ingham case 'N': 1790*b9c1b51eSKate Stone if (BreakpointID::StringIsBreakpointName(option_value, error) && 1791*b9c1b51eSKate Stone error.Success()) 1792c95f7e2aSPavel Labath m_name.SetValueFromString(option_value); 17935e09c8c3SJim Ingham break; 17945e09c8c3SJim Ingham 17955e09c8c3SJim Ingham case 'B': 1796c95f7e2aSPavel Labath if (m_breakpoint.SetValueFromString(option_value).Fail()) 1797*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1798*b9c1b51eSKate Stone "unrecognized value \"%s\" for breakpoint", option_value); 17995e09c8c3SJim Ingham break; 18005e09c8c3SJim Ingham case 'D': 1801c95f7e2aSPavel Labath if (m_use_dummy.SetValueFromString(option_value).Fail()) 1802*b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1803*b9c1b51eSKate Stone "unrecognized value \"%s\" for use-dummy", option_value); 18045e09c8c3SJim Ingham break; 18055e09c8c3SJim Ingham 18065e09c8c3SJim Ingham default: 1807*b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized short option '%c'", 1808*b9c1b51eSKate Stone short_option); 18095e09c8c3SJim Ingham break; 18105e09c8c3SJim Ingham } 18115e09c8c3SJim Ingham return error; 18125e09c8c3SJim Ingham } 18135e09c8c3SJim Ingham 1814*b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 18155e09c8c3SJim Ingham m_name.Clear(); 18165e09c8c3SJim Ingham m_breakpoint.Clear(); 18175e09c8c3SJim Ingham m_use_dummy.Clear(); 18185e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 18195e09c8c3SJim Ingham } 18205e09c8c3SJim Ingham 18215e09c8c3SJim Ingham OptionValueString m_name; 18225e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 18235e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 18245e09c8c3SJim Ingham }; 18255e09c8c3SJim Ingham 1826*b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 18275e09c8c3SJim Ingham public: 1828*b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1829*b9c1b51eSKate Stone : CommandObjectParsed( 1830*b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 18315e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 1832*b9c1b51eSKate Stone m_name_options(), m_option_group() { 1833*b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1834*b9c1b51eSKate Stone // command. 18355e09c8c3SJim Ingham CommandArgumentEntry arg1; 18365e09c8c3SJim Ingham CommandArgumentData id_arg; 18375e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 18385e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 18395e09c8c3SJim Ingham arg1.push_back(id_arg); 18405e09c8c3SJim Ingham m_arguments.push_back(arg1); 18415e09c8c3SJim Ingham 18425e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 18435e09c8c3SJim Ingham m_option_group.Finalize(); 18445e09c8c3SJim Ingham } 18455e09c8c3SJim Ingham 18469e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 18475e09c8c3SJim Ingham 1848*b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 18495e09c8c3SJim Ingham 18505e09c8c3SJim Ingham protected: 1851*b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1852*b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 18535e09c8c3SJim Ingham result.SetError("No name option provided."); 18545e09c8c3SJim Ingham return false; 18555e09c8c3SJim Ingham } 18565e09c8c3SJim Ingham 1857*b9c1b51eSKate Stone Target *target = 1858*b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 18595e09c8c3SJim Ingham 1860*b9c1b51eSKate Stone if (target == nullptr) { 18615e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 18625e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18635e09c8c3SJim Ingham return false; 18645e09c8c3SJim Ingham } 18655e09c8c3SJim Ingham 1866bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1867bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 18685e09c8c3SJim Ingham 18695e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 18705e09c8c3SJim Ingham 18715e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1872*b9c1b51eSKate Stone if (num_breakpoints == 0) { 18735e09c8c3SJim Ingham result.SetError("No breakpoints, cannot add names."); 18745e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18755e09c8c3SJim Ingham return false; 18765e09c8c3SJim Ingham } 18775e09c8c3SJim Ingham 18785e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 18795e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1880*b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1881*b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 18825e09c8c3SJim Ingham 1883*b9c1b51eSKate Stone if (result.Succeeded()) { 1884*b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 18855e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot add names."); 18865e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18875e09c8c3SJim Ingham return false; 18885e09c8c3SJim Ingham } 18895e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1890*b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1891*b9c1b51eSKate Stone lldb::break_id_t bp_id = 1892*b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 18935e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1894*b9c1b51eSKate Stone Error error; // We don't need to check the error here, since the option 1895*b9c1b51eSKate Stone // parser checked it... 18965e09c8c3SJim Ingham bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error); 18975e09c8c3SJim Ingham } 18985e09c8c3SJim Ingham } 18995e09c8c3SJim Ingham 19005e09c8c3SJim Ingham return true; 19015e09c8c3SJim Ingham } 19025e09c8c3SJim Ingham 19035e09c8c3SJim Ingham private: 19045e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19055e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19065e09c8c3SJim Ingham }; 19075e09c8c3SJim Ingham 1908*b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 19095e09c8c3SJim Ingham public: 1910*b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1911*b9c1b51eSKate Stone : CommandObjectParsed( 1912*b9c1b51eSKate Stone interpreter, "delete", 19135e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 19145e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 1915*b9c1b51eSKate Stone m_name_options(), m_option_group() { 1916*b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1917*b9c1b51eSKate Stone // command. 19185e09c8c3SJim Ingham CommandArgumentEntry arg1; 19195e09c8c3SJim Ingham CommandArgumentData id_arg; 19205e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 19215e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 19225e09c8c3SJim Ingham arg1.push_back(id_arg); 19235e09c8c3SJim Ingham m_arguments.push_back(arg1); 19245e09c8c3SJim Ingham 19255e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 19265e09c8c3SJim Ingham m_option_group.Finalize(); 19275e09c8c3SJim Ingham } 19285e09c8c3SJim Ingham 19299e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 19305e09c8c3SJim Ingham 1931*b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19325e09c8c3SJim Ingham 19335e09c8c3SJim Ingham protected: 1934*b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1935*b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 19365e09c8c3SJim Ingham result.SetError("No name option provided."); 19375e09c8c3SJim Ingham return false; 19385e09c8c3SJim Ingham } 19395e09c8c3SJim Ingham 1940*b9c1b51eSKate Stone Target *target = 1941*b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19425e09c8c3SJim Ingham 1943*b9c1b51eSKate Stone if (target == nullptr) { 19445e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 19455e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19465e09c8c3SJim Ingham return false; 19475e09c8c3SJim Ingham } 19485e09c8c3SJim Ingham 1949bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1950bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 19515e09c8c3SJim Ingham 19525e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 19535e09c8c3SJim Ingham 19545e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1955*b9c1b51eSKate Stone if (num_breakpoints == 0) { 19565e09c8c3SJim Ingham result.SetError("No breakpoints, cannot delete names."); 19575e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19585e09c8c3SJim Ingham return false; 19595e09c8c3SJim Ingham } 19605e09c8c3SJim Ingham 19615e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 19625e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1963*b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1964*b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 19655e09c8c3SJim Ingham 1966*b9c1b51eSKate Stone if (result.Succeeded()) { 1967*b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 19685e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot delete names."); 19695e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19705e09c8c3SJim Ingham return false; 19715e09c8c3SJim Ingham } 19725e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1973*b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1974*b9c1b51eSKate Stone lldb::break_id_t bp_id = 1975*b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 19765e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 19775e09c8c3SJim Ingham bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue()); 19785e09c8c3SJim Ingham } 19795e09c8c3SJim Ingham } 19805e09c8c3SJim Ingham 19815e09c8c3SJim Ingham return true; 19825e09c8c3SJim Ingham } 19835e09c8c3SJim Ingham 19845e09c8c3SJim Ingham private: 19855e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19865e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19875e09c8c3SJim Ingham }; 19885e09c8c3SJim Ingham 1989*b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 19905e09c8c3SJim Ingham public: 1991*b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 1992*b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 1993*b9c1b51eSKate Stone "List either the names for a breakpoint or the " 1994*b9c1b51eSKate Stone "breakpoints for a given name.", 19955e09c8c3SJim Ingham "breakpoint name list <command-options>"), 1996*b9c1b51eSKate Stone m_name_options(), m_option_group() { 19975e09c8c3SJim Ingham m_option_group.Append(&m_name_options); 19985e09c8c3SJim Ingham m_option_group.Finalize(); 19995e09c8c3SJim Ingham } 20005e09c8c3SJim Ingham 20019e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 20025e09c8c3SJim Ingham 2003*b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 20045e09c8c3SJim Ingham 20055e09c8c3SJim Ingham protected: 2006*b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2007*b9c1b51eSKate Stone Target *target = 2008*b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 20095e09c8c3SJim Ingham 2010*b9c1b51eSKate Stone if (target == nullptr) { 20115e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 20125e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20135e09c8c3SJim Ingham return false; 20145e09c8c3SJim Ingham } 20155e09c8c3SJim Ingham 2016*b9c1b51eSKate Stone if (m_name_options.m_name.OptionWasSet()) { 20175e09c8c3SJim Ingham const char *name = m_name_options.m_name.GetCurrentValue(); 2018bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2019bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 20205e09c8c3SJim Ingham 20215e09c8c3SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 2022*b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2023*b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 20245e09c8c3SJim Ingham StreamString s; 20255e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 20265e09c8c3SJim Ingham s.EOL(); 20275e09c8c3SJim Ingham result.AppendMessage(s.GetData()); 20285e09c8c3SJim Ingham } 20295e09c8c3SJim Ingham } 20305e09c8c3SJim Ingham 2031*b9c1b51eSKate Stone } else if (m_name_options.m_breakpoint.OptionWasSet()) { 2032*b9c1b51eSKate Stone BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID( 2033*b9c1b51eSKate Stone m_name_options.m_breakpoint.GetCurrentValue()); 2034*b9c1b51eSKate Stone if (bp_sp) { 20355e09c8c3SJim Ingham std::vector<std::string> names; 20365e09c8c3SJim Ingham bp_sp->GetNames(names); 20375e09c8c3SJim Ingham result.AppendMessage("Names:"); 20385e09c8c3SJim Ingham for (auto name : names) 20395e09c8c3SJim Ingham result.AppendMessageWithFormat(" %s\n", name.c_str()); 2040*b9c1b51eSKate Stone } else { 2041*b9c1b51eSKate Stone result.AppendErrorWithFormat( 2042*b9c1b51eSKate Stone "Could not find breakpoint %" PRId64 ".\n", 20435e09c8c3SJim Ingham m_name_options.m_breakpoint.GetCurrentValue()); 20445e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20455e09c8c3SJim Ingham return false; 20465e09c8c3SJim Ingham } 2047*b9c1b51eSKate Stone } else { 20485e09c8c3SJim Ingham result.SetError("Must specify -N or -B option to list."); 20495e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20505e09c8c3SJim Ingham return false; 20515e09c8c3SJim Ingham } 20525e09c8c3SJim Ingham return true; 20535e09c8c3SJim Ingham } 20545e09c8c3SJim Ingham 20555e09c8c3SJim Ingham private: 20565e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20575e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20585e09c8c3SJim Ingham }; 20595e09c8c3SJim Ingham 20605e09c8c3SJim Ingham //------------------------------------------------------------------------- 20615e09c8c3SJim Ingham // CommandObjectMultiwordBreakpoint 20625e09c8c3SJim Ingham //------------------------------------------------------------------------- 2063*b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 20645e09c8c3SJim Ingham public: 20657428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2066*b9c1b51eSKate Stone : CommandObjectMultiword( 2067*b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2068*b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2069*b9c1b51eSKate Stone CommandObjectSP add_command_object( 2070*b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2071*b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2072*b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2073*b9c1b51eSKate Stone CommandObjectSP list_command_object( 2074*b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 20755e09c8c3SJim Ingham 20765e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 20775e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 20785e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 20795e09c8c3SJim Ingham } 20805e09c8c3SJim Ingham 20819e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 20825e09c8c3SJim Ingham }; 20835e09c8c3SJim Ingham 20845e09c8c3SJim Ingham //------------------------------------------------------------------------- 208530fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 208630fdc8d8SChris Lattner //------------------------------------------------------------------------- 2087ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 208830fdc8d8SChris Lattner 2089*b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2090*b9c1b51eSKate Stone CommandInterpreter &interpreter) 2091*b9c1b51eSKate Stone : CommandObjectMultiword( 2092*b9c1b51eSKate Stone interpreter, "breakpoint", 20937428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2094*b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2095*b9c1b51eSKate Stone CommandObjectSP list_command_object( 2096*b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2097*b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2098*b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2099*b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2100*b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2101*b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2102*b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2103*b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2104*b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2105*b9c1b51eSKate Stone CommandObjectSP set_command_object( 2106*b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2107*b9c1b51eSKate Stone CommandObjectSP command_command_object( 2108*b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2109*b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2110*b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2111*b9c1b51eSKate Stone CommandObjectSP name_command_object( 2112*b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 211330fdc8d8SChris Lattner 2114b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 211530fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 211630fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2117b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2118b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2119ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2120b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2121b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 21225e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 212330fdc8d8SChris Lattner 212423f59509SGreg Clayton LoadSubCommand("list", list_command_object); 212523f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 212623f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 212723f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 212823f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 212923f59509SGreg Clayton LoadSubCommand("set", set_command_object); 213023f59509SGreg Clayton LoadSubCommand("command", command_command_object); 213123f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 21325e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 213330fdc8d8SChris Lattner } 213430fdc8d8SChris Lattner 21359e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 213630fdc8d8SChris Lattner 2137*b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, 21385e09c8c3SJim Ingham bool allow_locations, 21395e09c8c3SJim Ingham CommandReturnObject &result, 2140*b9c1b51eSKate Stone BreakpointIDList *valid_ids) { 214130fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2142*b9c1b51eSKate Stone // 2). the full breakpoint & location 2143*b9c1b51eSKate Stone // canonical representation 2144*b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2145*b9c1b51eSKate Stone // representing a range (in which case there 2146*b9c1b51eSKate Stone // had *better* be an entry both before & 2147*b9c1b51eSKate Stone // after of one of the first two types. 21485e09c8c3SJim Ingham // 4). A breakpoint name 2149*b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2150*b9c1b51eSKate Stone // one.) 215130fdc8d8SChris Lattner 215230fdc8d8SChris Lattner Args temp_args; 215330fdc8d8SChris Lattner 2154*b9c1b51eSKate Stone if (args.GetArgumentCount() == 0) { 2155*b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2156*b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2157*b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 215836f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2159*b9c1b51eSKate Stone } else { 2160*b9c1b51eSKate Stone result.AppendError( 2161*b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 216236f3b369SJim Ingham result.SetStatus(eReturnStatusFailed); 216336f3b369SJim Ingham } 216436f3b369SJim Ingham return; 216536f3b369SJim Ingham } 216636f3b369SJim Ingham 2167*b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 2168*b9c1b51eSKate Stone // directly from the old ARGS to 2169*b9c1b51eSKate Stone // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead 2170*b9c1b51eSKate Stone // generate a list of strings for 2171*b9c1b51eSKate Stone // all the breakpoint ids in the range, and shove all of those breakpoint id 2172*b9c1b51eSKate Stone // strings into TEMP_ARGS. 217330fdc8d8SChris Lattner 2174*b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2175*b9c1b51eSKate Stone result, temp_args); 217630fdc8d8SChris Lattner 2177*b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2178*b9c1b51eSKate Stone // BreakpointIDList: 217930fdc8d8SChris Lattner 2180*b9c1b51eSKate Stone valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(), 2181*b9c1b51eSKate Stone temp_args.GetArgumentCount(), result); 218230fdc8d8SChris Lattner 2183*b9c1b51eSKate Stone // At this point, all of the breakpoint ids that the user passed in have been 2184*b9c1b51eSKate Stone // converted to breakpoint IDs 218530fdc8d8SChris Lattner // and put into valid_ids. 218630fdc8d8SChris Lattner 2187*b9c1b51eSKate Stone if (result.Succeeded()) { 2188*b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 2189*b9c1b51eSKate Stone // ids, go through our tentative list 2190*b9c1b51eSKate Stone // of breakpoint id's and verify that they correspond to valid/currently set 2191*b9c1b51eSKate Stone // breakpoints. 219230fdc8d8SChris Lattner 2193c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2194*b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 219530fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2196*b9c1b51eSKate Stone Breakpoint *breakpoint = 2197*b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2198*b9c1b51eSKate Stone if (breakpoint != nullptr) { 2199c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2200*b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 220130fdc8d8SChris Lattner StreamString id_str; 2202*b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2203*b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2204c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2205*b9c1b51eSKate Stone result.AppendErrorWithFormat( 2206*b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 220730fdc8d8SChris Lattner id_str.GetData()); 220830fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 220930fdc8d8SChris Lattner } 2210*b9c1b51eSKate Stone } else { 2211c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2212*b9c1b51eSKate Stone result.AppendErrorWithFormat( 2213*b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 22147428a18cSKate Stone cur_bp_id.GetBreakpointID()); 221530fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 221630fdc8d8SChris Lattner } 221730fdc8d8SChris Lattner } 221830fdc8d8SChris Lattner } 221930fdc8d8SChris Lattner } 2220