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" 21b9c1b51eSKate Stone #include "lldb/Core/RegularExpression.h" 22b9c1b51eSKate Stone #include "lldb/Core/StreamString.h" 235275aaa0SVince Harron #include "lldb/Host/StringConvert.h" 24b9c1b51eSKate Stone #include "lldb/Interpreter/CommandCompletions.h" 25b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h" 26b9c1b51eSKate 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" 30b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 310e0984eeSJim Ingham #include "lldb/Target/Language.h" 32b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 33b9c1b51eSKate 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 40b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp, 41b9c1b51eSKate 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 52b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 535a988416SJim Ingham public: 54b9c1b51eSKate 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 64b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 65b9c1b51eSKate Stone : CommandObjectParsed( 66b9c1b51eSKate Stone interpreter, "breakpoint set", 675a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 685a988416SJim Ingham "breakpoint set <cmd-options>"), 69b9c1b51eSKate Stone m_options() {} 705a988416SJim Ingham 719e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 725a988416SJim Ingham 73b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 745a988416SJim Ingham 75b9c1b51eSKate Stone class CommandOptions : public Options { 765a988416SJim Ingham public: 77b9c1b51eSKate Stone CommandOptions() 78b9c1b51eSKate Stone : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0), 79b9c1b51eSKate Stone m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone), 80b9c1b51eSKate Stone m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(), 81b9c1b51eSKate Stone m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), 82b9c1b51eSKate Stone m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(), 83b9c1b51eSKate Stone m_catch_bp(false), m_throw_bp(true), m_hardware(false), 84a72b31c7SJim Ingham m_exception_language(eLanguageTypeUnknown), 8523b1decbSDawn Perchik m_language(lldb::eLanguageTypeUnknown), 86b9c1b51eSKate Stone m_skip_prologue(eLazyBoolCalculate), m_one_shot(false), 87b9c1b51eSKate Stone m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {} 8830fdc8d8SChris Lattner 899e85e5a8SEugene Zelenko ~CommandOptions() override = default; 9087df91b8SJim Ingham 91b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 92b9c1b51eSKate Stone ExecutionContext *execution_context) override { 9330fdc8d8SChris Lattner Error error; 943bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 956fa7681bSZachary Turner llvm::StringRef option_strref(option_arg ? option_arg : ""); 9630fdc8d8SChris Lattner 97b9c1b51eSKate Stone switch (short_option) { 98b9c1b51eSKate Stone case 'a': { 99b9c1b51eSKate Stone m_load_addr = Args::StringToAddress(execution_context, option_arg, 100e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 101b9c1b51eSKate Stone } break; 10230fdc8d8SChris Lattner 103e732052fSJim Ingham case 'A': 104e732052fSJim Ingham m_all_files = true; 105e732052fSJim Ingham break; 106e732052fSJim Ingham 107ca36cd16SJim Ingham case 'b': 108ca36cd16SJim Ingham m_func_names.push_back(option_arg); 109ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 110ca36cd16SJim Ingham break; 111ca36cd16SJim Ingham 112b9c1b51eSKate Stone case 'C': { 1136312991cSJim Ingham bool success; 1146312991cSJim Ingham m_column = StringConvert::ToUInt32(option_arg, 0, 0, &success); 1156312991cSJim Ingham if (!success) 116b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 117b9c1b51eSKate Stone option_arg); 11830fdc8d8SChris Lattner break; 1196312991cSJim Ingham } 1209e85e5a8SEugene Zelenko 1217d49c9c8SJohnny Chen case 'c': 1227d49c9c8SJohnny Chen m_condition.assign(option_arg); 1237d49c9c8SJohnny Chen break; 1247d49c9c8SJohnny Chen 12533df7cd3SJim Ingham case 'D': 12633df7cd3SJim Ingham m_use_dummy = true; 12733df7cd3SJim Ingham break; 12833df7cd3SJim Ingham 129b9c1b51eSKate Stone case 'E': { 1300e0984eeSJim Ingham LanguageType language = Language::GetLanguageTypeFromString(option_arg); 131fab10e89SJim Ingham 132b9c1b51eSKate Stone switch (language) { 133fab10e89SJim Ingham case eLanguageTypeC89: 134fab10e89SJim Ingham case eLanguageTypeC: 135fab10e89SJim Ingham case eLanguageTypeC99: 1361d0089faSBruce Mitchener case eLanguageTypeC11: 137a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 138fab10e89SJim Ingham break; 139fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 1401d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 1411d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 1422ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 143a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 144fab10e89SJim Ingham break; 145fab10e89SJim Ingham case eLanguageTypeObjC: 146a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 147fab10e89SJim Ingham break; 148fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 149b9c1b51eSKate Stone error.SetErrorStringWithFormat( 150b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 151fab10e89SJim Ingham break; 152fab10e89SJim Ingham case eLanguageTypeUnknown: 153b9c1b51eSKate Stone error.SetErrorStringWithFormat( 154b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 155b9c1b51eSKate Stone option_arg); 156fab10e89SJim Ingham break; 157fab10e89SJim Ingham default: 158b9c1b51eSKate Stone error.SetErrorStringWithFormat( 159b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 160b9c1b51eSKate Stone option_arg); 161fab10e89SJim Ingham } 162b9c1b51eSKate Stone } break; 163ca36cd16SJim Ingham 164ca36cd16SJim Ingham case 'f': 165ca36cd16SJim Ingham m_filenames.AppendIfUnique(FileSpec(option_arg, false)); 166fab10e89SJim Ingham break; 167ca36cd16SJim Ingham 168ca36cd16SJim Ingham case 'F': 169ca36cd16SJim Ingham m_func_names.push_back(option_arg); 170ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 171ca36cd16SJim Ingham break; 172ca36cd16SJim Ingham 173b9c1b51eSKate Stone case 'h': { 174fab10e89SJim Ingham bool success; 175ecbb0bb1SZachary Turner m_catch_bp = Args::StringToBoolean(option_strref, true, &success); 176fab10e89SJim Ingham if (!success) 177b9c1b51eSKate Stone error.SetErrorStringWithFormat( 178b9c1b51eSKate Stone "Invalid boolean value for on-catch option: '%s'", option_arg); 179b9c1b51eSKate Stone } break; 180eb023e75SGreg Clayton 181eb023e75SGreg Clayton case 'H': 182eb023e75SGreg Clayton m_hardware = true; 183eb023e75SGreg Clayton break; 184eb023e75SGreg Clayton 185ca36cd16SJim Ingham case 'i': 1865275aaa0SVince Harron m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 187ca36cd16SJim Ingham if (m_ignore_count == UINT32_MAX) 188b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid ignore count '%s'", 189b9c1b51eSKate Stone option_arg); 190ca36cd16SJim Ingham break; 191ca36cd16SJim Ingham 192b9c1b51eSKate Stone case 'K': { 193a8558b62SJim Ingham bool success; 194a8558b62SJim Ingham bool value; 195ecbb0bb1SZachary Turner value = Args::StringToBoolean(option_strref, true, &success); 196a8558b62SJim Ingham if (value) 197a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 198a8558b62SJim Ingham else 199a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 200a8558b62SJim Ingham 201a8558b62SJim Ingham if (!success) 202b9c1b51eSKate Stone error.SetErrorStringWithFormat( 203b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 204b9c1b51eSKate Stone option_arg); 205b9c1b51eSKate Stone } break; 206ca36cd16SJim Ingham 207b9c1b51eSKate Stone case 'l': { 2086312991cSJim Ingham bool success; 2096312991cSJim Ingham m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success); 2106312991cSJim Ingham if (!success) 211b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 212b9c1b51eSKate Stone option_arg); 213ca36cd16SJim Ingham break; 2146312991cSJim Ingham } 215055ad9beSIlia K 21623b1decbSDawn Perchik case 'L': 2170e0984eeSJim Ingham m_language = Language::GetLanguageTypeFromString(option_arg); 21823b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 219b9c1b51eSKate Stone error.SetErrorStringWithFormat( 220b9c1b51eSKate Stone "Unknown language type: '%s' for breakpoint", option_arg); 22123b1decbSDawn Perchik break; 22223b1decbSDawn Perchik 223b9c1b51eSKate Stone case 'm': { 224055ad9beSIlia K bool success; 225055ad9beSIlia K bool value; 226ecbb0bb1SZachary Turner value = Args::StringToBoolean(option_strref, true, &success); 227055ad9beSIlia K if (value) 228055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 229055ad9beSIlia K else 230055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 231055ad9beSIlia K 232055ad9beSIlia K if (!success) 233b9c1b51eSKate Stone error.SetErrorStringWithFormat( 234b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 235b9c1b51eSKate Stone option_arg); 236055ad9beSIlia K break; 237055ad9beSIlia K } 238055ad9beSIlia K 239ca36cd16SJim Ingham case 'M': 240ca36cd16SJim Ingham m_func_names.push_back(option_arg); 241ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 242ca36cd16SJim Ingham break; 243ca36cd16SJim Ingham 244ca36cd16SJim Ingham case 'n': 245ca36cd16SJim Ingham m_func_names.push_back(option_arg); 246ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 247ca36cd16SJim Ingham break; 248ca36cd16SJim Ingham 2496fa7681bSZachary Turner case 'N': { 2506fa7681bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_strref, error)) 2515e09c8c3SJim Ingham m_breakpoint_names.push_back(option_arg); 252*ff9a91eaSJim Ingham else 253*ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 254*ff9a91eaSJim Ingham option_arg); 2555e09c8c3SJim Ingham break; 2566fa7681bSZachary Turner } 2575e09c8c3SJim Ingham 258b9c1b51eSKate Stone case 'R': { 2592411167fSJim Ingham lldb::addr_t tmp_offset_addr; 260e1cfbc79STodd Fiala tmp_offset_addr = 261b9c1b51eSKate Stone Args::StringToAddress(execution_context, option_arg, 0, &error); 2622411167fSJim Ingham if (error.Success()) 2632411167fSJim Ingham m_offset_addr = tmp_offset_addr; 264b9c1b51eSKate Stone } break; 2652411167fSJim Ingham 266ca36cd16SJim Ingham case 'o': 267ca36cd16SJim Ingham m_one_shot = true; 268ca36cd16SJim Ingham break; 269ca36cd16SJim Ingham 270a72b31c7SJim Ingham case 'O': 271ecbb0bb1SZachary Turner m_exception_extra_args.AppendArgument(llvm::StringRef("-O")); 272ecbb0bb1SZachary Turner m_exception_extra_args.AppendArgument(option_strref); 273a72b31c7SJim Ingham break; 274a72b31c7SJim Ingham 275ca36cd16SJim Ingham case 'p': 276ca36cd16SJim Ingham m_source_text_regexp.assign(option_arg); 277ca36cd16SJim Ingham break; 278ca36cd16SJim Ingham 279ca36cd16SJim Ingham case 'q': 280ca36cd16SJim Ingham m_queue_name.assign(option_arg); 281ca36cd16SJim Ingham break; 282ca36cd16SJim Ingham 283ca36cd16SJim Ingham case 'r': 284ca36cd16SJim Ingham m_func_regexp.assign(option_arg); 285ca36cd16SJim Ingham break; 286ca36cd16SJim Ingham 287ca36cd16SJim Ingham case 's': 288ca36cd16SJim Ingham m_modules.AppendIfUnique(FileSpec(option_arg, false)); 289ca36cd16SJim Ingham break; 290ca36cd16SJim Ingham 291ca36cd16SJim Ingham case 'S': 292ca36cd16SJim Ingham m_func_names.push_back(option_arg); 293ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 294ca36cd16SJim Ingham break; 295ca36cd16SJim Ingham 296ca36cd16SJim Ingham case 't': 297b9c1b51eSKate Stone m_thread_id = 298b9c1b51eSKate Stone StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 299ca36cd16SJim Ingham if (m_thread_id == LLDB_INVALID_THREAD_ID) 300b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread id string '%s'", 301b9c1b51eSKate Stone option_arg); 302ca36cd16SJim Ingham break; 303ca36cd16SJim Ingham 304ca36cd16SJim Ingham case 'T': 305ca36cd16SJim Ingham m_thread_name.assign(option_arg); 306ca36cd16SJim Ingham break; 307ca36cd16SJim Ingham 308b9c1b51eSKate Stone case 'w': { 309ca36cd16SJim Ingham bool success; 310ecbb0bb1SZachary Turner m_throw_bp = Args::StringToBoolean(option_strref, true, &success); 311ca36cd16SJim Ingham if (!success) 312b9c1b51eSKate Stone error.SetErrorStringWithFormat( 313b9c1b51eSKate Stone "Invalid boolean value for on-throw option: '%s'", option_arg); 314b9c1b51eSKate Stone } break; 315ca36cd16SJim Ingham 316ca36cd16SJim Ingham case 'x': 3175275aaa0SVince Harron m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 318ca36cd16SJim Ingham if (m_thread_id == UINT32_MAX) 319b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread index string '%s'", 320b9c1b51eSKate Stone option_arg); 321ca36cd16SJim Ingham break; 322ca36cd16SJim Ingham 32376bb8d67SJim Ingham case 'X': 32476bb8d67SJim Ingham m_source_regex_func_names.insert(option_arg); 32576bb8d67SJim Ingham break; 32676bb8d67SJim Ingham 32730fdc8d8SChris Lattner default: 328b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 329b9c1b51eSKate Stone short_option); 33030fdc8d8SChris Lattner break; 33130fdc8d8SChris Lattner } 33230fdc8d8SChris Lattner 33330fdc8d8SChris Lattner return error; 33430fdc8d8SChris Lattner } 3359e85e5a8SEugene Zelenko 336b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 3377d49c9c8SJohnny Chen m_condition.clear(); 33887df91b8SJim Ingham m_filenames.Clear(); 33930fdc8d8SChris Lattner m_line_num = 0; 34030fdc8d8SChris Lattner m_column = 0; 341fab10e89SJim Ingham m_func_names.clear(); 3421f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 34330fdc8d8SChris Lattner m_func_regexp.clear(); 3441f746071SGreg Clayton m_source_text_regexp.clear(); 34587df91b8SJim Ingham m_modules.Clear(); 3461f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 3472411167fSJim Ingham m_offset_addr = 0; 348c982c768SGreg Clayton m_ignore_count = 0; 3491b54c88cSJim Ingham m_thread_id = LLDB_INVALID_THREAD_ID; 350c982c768SGreg Clayton m_thread_index = UINT32_MAX; 3511b54c88cSJim Ingham m_thread_name.clear(); 3521b54c88cSJim Ingham m_queue_name.clear(); 353fab10e89SJim Ingham m_catch_bp = false; 354fab10e89SJim Ingham m_throw_bp = true; 355eb023e75SGreg Clayton m_hardware = false; 356a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 35723b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 358a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 359ca36cd16SJim Ingham m_one_shot = false; 36033df7cd3SJim Ingham m_use_dummy = false; 3615e09c8c3SJim Ingham m_breakpoint_names.clear(); 362e732052fSJim Ingham m_all_files = false; 363a72b31c7SJim Ingham m_exception_extra_args.Clear(); 364055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 36576bb8d67SJim Ingham m_source_regex_func_names.clear(); 36630fdc8d8SChris Lattner } 36730fdc8d8SChris Lattner 368b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { return g_option_table; } 36930fdc8d8SChris Lattner 3705a988416SJim Ingham // Options table: Required for subclasses of Options. 37130fdc8d8SChris Lattner 3725a988416SJim Ingham static OptionDefinition g_option_table[]; 37330fdc8d8SChris Lattner 3745a988416SJim Ingham // Instance variables to hold the values for command options. 375969795f1SJim Ingham 3765a988416SJim Ingham std::string m_condition; 3775a988416SJim Ingham FileSpecList m_filenames; 3785a988416SJim Ingham uint32_t m_line_num; 3795a988416SJim Ingham uint32_t m_column; 3805a988416SJim Ingham std::vector<std::string> m_func_names; 3815e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 3825a988416SJim Ingham uint32_t m_func_name_type_mask; 3835a988416SJim Ingham std::string m_func_regexp; 3845a988416SJim Ingham std::string m_source_text_regexp; 3855a988416SJim Ingham FileSpecList m_modules; 3865a988416SJim Ingham lldb::addr_t m_load_addr; 3872411167fSJim Ingham lldb::addr_t m_offset_addr; 3885a988416SJim Ingham uint32_t m_ignore_count; 3895a988416SJim Ingham lldb::tid_t m_thread_id; 3905a988416SJim Ingham uint32_t m_thread_index; 3915a988416SJim Ingham std::string m_thread_name; 3925a988416SJim Ingham std::string m_queue_name; 3935a988416SJim Ingham bool m_catch_bp; 3945a988416SJim Ingham bool m_throw_bp; 395eb023e75SGreg Clayton bool m_hardware; // Request to use hardware breakpoints 396a72b31c7SJim Ingham lldb::LanguageType m_exception_language; 39723b1decbSDawn Perchik lldb::LanguageType m_language; 3985a988416SJim Ingham LazyBool m_skip_prologue; 399ca36cd16SJim Ingham bool m_one_shot; 40033df7cd3SJim Ingham bool m_use_dummy; 401e732052fSJim Ingham bool m_all_files; 402a72b31c7SJim Ingham Args m_exception_extra_args; 403055ad9beSIlia K LazyBool m_move_to_nearest_code; 40476bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 4055a988416SJim Ingham }; 4065a988416SJim Ingham 4075a988416SJim Ingham protected: 408b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 40933df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 41033df7cd3SJim Ingham 411b9c1b51eSKate Stone if (target == nullptr) { 412b9c1b51eSKate Stone result.AppendError("Invalid target. Must set target before setting " 413b9c1b51eSKate Stone "breakpoints (see 'target create' command)."); 41430fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 41530fdc8d8SChris Lattner return false; 41630fdc8d8SChris Lattner } 41730fdc8d8SChris Lattner 41830fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 41930fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 42030fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 42130fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 422b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 423b9c1b51eSKate Stone // expression) 424b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 425b9c1b51eSKate Stone // to source text) 426b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 427b9c1b51eSKate Stone // given language.) 42830fdc8d8SChris Lattner 42930fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 43030fdc8d8SChris Lattner 43130fdc8d8SChris Lattner if (m_options.m_line_num != 0) 43230fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 43330fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 43430fdc8d8SChris Lattner break_type = eSetTypeAddress; 435fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 43630fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 43730fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 43830fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 439969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 440969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 441a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 442fab10e89SJim Ingham break_type = eSetTypeException; 44330fdc8d8SChris Lattner 4449e85e5a8SEugene Zelenko Breakpoint *bp = nullptr; 445274060b6SGreg Clayton FileSpec module_spec; 446a8558b62SJim Ingham const bool internal = false; 447a8558b62SJim Ingham 448b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 449b9c1b51eSKate Stone // that off. 450b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 451b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 4522411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 4532411167fSJim Ingham 454b9c1b51eSKate Stone switch (break_type) { 45530fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 45630fdc8d8SChris Lattner { 45730fdc8d8SChris Lattner FileSpec file; 458c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 459b9c1b51eSKate Stone if (num_files == 0) { 460b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 46187df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 46287df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 46387df91b8SJim Ingham return false; 46487df91b8SJim Ingham } 465b9c1b51eSKate Stone } else if (num_files > 1) { 466b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 467b9c1b51eSKate Stone "line breakpoints."); 46887df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 46987df91b8SJim Ingham return false; 470b9c1b51eSKate Stone } else 47187df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 47230fdc8d8SChris Lattner 4731f746071SGreg Clayton // Only check for inline functions if 4741f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 4751f746071SGreg Clayton 476b9c1b51eSKate Stone bp = target 477b9c1b51eSKate Stone ->CreateBreakpoint(&(m_options.m_modules), file, 478b9c1b51eSKate Stone m_options.m_line_num, m_options.m_offset_addr, 479b9c1b51eSKate Stone check_inlines, m_options.m_skip_prologue, 480b9c1b51eSKate Stone internal, m_options.m_hardware, 481b9c1b51eSKate Stone m_options.m_move_to_nearest_code) 482b9c1b51eSKate Stone .get(); 483b9c1b51eSKate Stone } break; 4846eee5aa0SGreg Clayton 48530fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 486055a08a4SJim Ingham { 487b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 488b9c1b51eSKate Stone // with the library, and 489b9c1b51eSKate Stone // use that. That way the address breakpoint will track the load location 490b9c1b51eSKate Stone // of the library. 491055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 492b9c1b51eSKate Stone if (num_modules_specified == 1) { 493b9c1b51eSKate Stone const FileSpec *file_spec = 494b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 495b9c1b51eSKate Stone bp = target 496b9c1b51eSKate Stone ->CreateAddressInModuleBreakpoint(m_options.m_load_addr, 497b9c1b51eSKate Stone internal, file_spec, 498b9c1b51eSKate Stone m_options.m_hardware) 499b9c1b51eSKate Stone .get(); 500b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 501b9c1b51eSKate Stone bp = target 502b9c1b51eSKate Stone ->CreateBreakpoint(m_options.m_load_addr, internal, 503b9c1b51eSKate Stone m_options.m_hardware) 504b9c1b51eSKate Stone .get(); 505b9c1b51eSKate Stone } else { 506b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 507b9c1b51eSKate Stone "address breakpoints."); 508055a08a4SJim Ingham result.SetStatus(eReturnStatusFailed); 509055a08a4SJim Ingham return false; 510055a08a4SJim Ingham } 51130fdc8d8SChris Lattner break; 512055a08a4SJim Ingham } 51330fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 5140c5cd90dSGreg Clayton { 5150c5cd90dSGreg Clayton uint32_t name_type_mask = m_options.m_func_name_type_mask; 5160c5cd90dSGreg Clayton 5170c5cd90dSGreg Clayton if (name_type_mask == 0) 518e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 5190c5cd90dSGreg Clayton 520b9c1b51eSKate Stone bp = target 521b9c1b51eSKate Stone ->CreateBreakpoint( 522b9c1b51eSKate Stone &(m_options.m_modules), &(m_options.m_filenames), 523b9c1b51eSKate Stone m_options.m_func_names, name_type_mask, m_options.m_language, 524b9c1b51eSKate Stone m_options.m_offset_addr, m_options.m_skip_prologue, internal, 525b9c1b51eSKate Stone m_options.m_hardware) 526b9c1b51eSKate Stone .get(); 527b9c1b51eSKate Stone } break; 5280c5cd90dSGreg Clayton 529b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 530b9c1b51eSKate Stone // name 53130fdc8d8SChris Lattner { 53230fdc8d8SChris Lattner RegularExpression regexp(m_options.m_func_regexp.c_str()); 533b9c1b51eSKate Stone if (!regexp.IsValid()) { 534969795f1SJim Ingham char err_str[1024]; 535969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 536b9c1b51eSKate Stone result.AppendErrorWithFormat( 537b9c1b51eSKate Stone "Function name regular expression could not be compiled: \"%s\"", 538969795f1SJim Ingham err_str); 53930fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 540969795f1SJim Ingham return false; 54130fdc8d8SChris Lattner } 54287df91b8SJim Ingham 543b9c1b51eSKate Stone bp = target 544b9c1b51eSKate Stone ->CreateFuncRegexBreakpoint( 545b9c1b51eSKate Stone &(m_options.m_modules), &(m_options.m_filenames), regexp, 546b9c1b51eSKate Stone m_options.m_language, m_options.m_skip_prologue, internal, 547b9c1b51eSKate Stone m_options.m_hardware) 548b9c1b51eSKate Stone .get(); 549e14dc268SJim Ingham } 550e14dc268SJim Ingham break; 551969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 552969795f1SJim Ingham { 553c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 55487df91b8SJim Ingham 555b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 556969795f1SJim Ingham FileSpec file; 557b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 558b9c1b51eSKate Stone result.AppendError( 559b9c1b51eSKate Stone "No files provided and could not find default file."); 56087df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 56187df91b8SJim Ingham return false; 562b9c1b51eSKate Stone } else { 56387df91b8SJim Ingham m_options.m_filenames.Append(file); 56487df91b8SJim Ingham } 56587df91b8SJim Ingham } 5660c5cd90dSGreg Clayton 567969795f1SJim Ingham RegularExpression regexp(m_options.m_source_text_regexp.c_str()); 568b9c1b51eSKate Stone if (!regexp.IsValid()) { 569969795f1SJim Ingham char err_str[1024]; 570969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 571b9c1b51eSKate Stone result.AppendErrorWithFormat( 572b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"", 573969795f1SJim Ingham err_str); 574969795f1SJim Ingham result.SetStatus(eReturnStatusFailed); 575969795f1SJim Ingham return false; 576969795f1SJim Ingham } 577b9c1b51eSKate Stone bp = target 578b9c1b51eSKate Stone ->CreateSourceRegexBreakpoint( 579b9c1b51eSKate Stone &(m_options.m_modules), &(m_options.m_filenames), 580b9c1b51eSKate Stone m_options.m_source_regex_func_names, regexp, internal, 581b9c1b51eSKate Stone m_options.m_hardware, m_options.m_move_to_nearest_code) 582b9c1b51eSKate Stone .get(); 583b9c1b51eSKate Stone } break; 584b9c1b51eSKate Stone case eSetTypeException: { 585a72b31c7SJim Ingham Error precond_error; 586b9c1b51eSKate Stone bp = target 587b9c1b51eSKate Stone ->CreateExceptionBreakpoint( 588b9c1b51eSKate Stone m_options.m_exception_language, m_options.m_catch_bp, 589b9c1b51eSKate Stone m_options.m_throw_bp, internal, 590b9c1b51eSKate Stone &m_options.m_exception_extra_args, &precond_error) 591b9c1b51eSKate Stone .get(); 592b9c1b51eSKate Stone if (precond_error.Fail()) { 593b9c1b51eSKate Stone result.AppendErrorWithFormat( 594b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 595a72b31c7SJim Ingham precond_error.AsCString()); 596a72b31c7SJim Ingham target->RemoveBreakpointByID(bp->GetID()); 597a72b31c7SJim Ingham result.SetStatus(eReturnStatusFailed); 598a72b31c7SJim Ingham return false; 599a72b31c7SJim Ingham } 600b9c1b51eSKate Stone } break; 60130fdc8d8SChris Lattner default: 60230fdc8d8SChris Lattner break; 60330fdc8d8SChris Lattner } 60430fdc8d8SChris Lattner 6051b54c88cSJim Ingham // Now set the various options that were passed in: 606b9c1b51eSKate Stone if (bp) { 6071b54c88cSJim Ingham if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 6081b54c88cSJim Ingham bp->SetThreadID(m_options.m_thread_id); 6091b54c88cSJim Ingham 610c982c768SGreg Clayton if (m_options.m_thread_index != UINT32_MAX) 6111b54c88cSJim Ingham bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); 6121b54c88cSJim Ingham 6131b54c88cSJim Ingham if (!m_options.m_thread_name.empty()) 614b9c1b51eSKate Stone bp->GetOptions()->GetThreadSpec()->SetName( 615b9c1b51eSKate Stone m_options.m_thread_name.c_str()); 6161b54c88cSJim Ingham 6171b54c88cSJim Ingham if (!m_options.m_queue_name.empty()) 618b9c1b51eSKate Stone bp->GetOptions()->GetThreadSpec()->SetQueueName( 619b9c1b51eSKate Stone m_options.m_queue_name.c_str()); 6201b54c88cSJim Ingham 621c982c768SGreg Clayton if (m_options.m_ignore_count != 0) 6221b54c88cSJim Ingham bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); 6237d49c9c8SJohnny Chen 6247d49c9c8SJohnny Chen if (!m_options.m_condition.empty()) 6257d49c9c8SJohnny Chen bp->GetOptions()->SetCondition(m_options.m_condition.c_str()); 626ca36cd16SJim Ingham 627b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 628*ff9a91eaSJim Ingham Error name_error; 629*ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) { 630*ff9a91eaSJim Ingham bp->AddName(name.c_str(), name_error); 631*ff9a91eaSJim Ingham if (name_error.Fail()) { 632*ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s", 633*ff9a91eaSJim Ingham name.c_str()); 634*ff9a91eaSJim Ingham target->RemoveBreakpointByID(bp->GetID()); 635*ff9a91eaSJim Ingham result.SetStatus(eReturnStatusFailed); 636*ff9a91eaSJim Ingham return false; 637*ff9a91eaSJim Ingham } 638*ff9a91eaSJim Ingham } 6395e09c8c3SJim Ingham } 6405e09c8c3SJim Ingham 641ca36cd16SJim Ingham bp->SetOneShot(m_options.m_one_shot); 6421b54c88cSJim Ingham } 6431b54c88cSJim Ingham 644b9c1b51eSKate Stone if (bp) { 64585e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 6461391cc7dSJim Ingham const bool show_locations = false; 647b9c1b51eSKate Stone bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 648b9c1b51eSKate Stone show_locations); 6494aeb1989SJim Ingham if (target == m_interpreter.GetDebugger().GetDummyTarget()) 650b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 651b9c1b51eSKate Stone "into future targets.\n"); 652b9c1b51eSKate Stone else { 653b9c1b51eSKate Stone // Don't print out this warning for exception breakpoints. They can get 654b9c1b51eSKate Stone // set before the target 655b9c1b51eSKate Stone // is set, but we won't know how to actually set the breakpoint till we 656b9c1b51eSKate Stone // run. 657b9c1b51eSKate Stone if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) { 658b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 659b9c1b51eSKate Stone "actual locations.\n"); 6604aeb1989SJim Ingham } 6614aeb1989SJim Ingham } 66230fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 663b9c1b51eSKate Stone } else if (!bp) { 66430fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 66530fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 66630fdc8d8SChris Lattner } 66730fdc8d8SChris Lattner 66830fdc8d8SChris Lattner return result.Succeeded(); 66930fdc8d8SChris Lattner } 67030fdc8d8SChris Lattner 6715a988416SJim Ingham private: 672b9c1b51eSKate Stone bool GetDefaultFile(Target *target, FileSpec &file, 673b9c1b51eSKate Stone CommandReturnObject &result) { 6745a988416SJim Ingham uint32_t default_line; 6755a988416SJim Ingham // First use the Source Manager's default file. 6765a988416SJim Ingham // Then use the current stack frame's file. 677b9c1b51eSKate Stone if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 678b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 679b9c1b51eSKate Stone if (cur_frame == nullptr) { 680b9c1b51eSKate Stone result.AppendError( 681b9c1b51eSKate Stone "No selected frame to use to find the default file."); 6825a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 6835a988416SJim Ingham return false; 684b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 685b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 686b9c1b51eSKate Stone "file, it has no debug info."); 6875a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 6885a988416SJim Ingham return false; 689b9c1b51eSKate Stone } else { 690b9c1b51eSKate Stone const SymbolContext &sc = 691b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 692b9c1b51eSKate Stone if (sc.line_entry.file) { 6935a988416SJim Ingham file = sc.line_entry.file; 694b9c1b51eSKate Stone } else { 695b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 696b9c1b51eSKate Stone "use as the default file."); 6975a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 6985a988416SJim Ingham return false; 6995a988416SJim Ingham } 7005a988416SJim Ingham } 7015a988416SJim Ingham } 7025a988416SJim Ingham return true; 7035a988416SJim Ingham } 7045a988416SJim Ingham 7055a988416SJim Ingham CommandOptions m_options; 7065a988416SJim Ingham }; 7079e85e5a8SEugene Zelenko 7085a988416SJim Ingham // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to 7095a988416SJim Ingham // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. 7105a988416SJim Ingham #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2) 7115a988416SJim Ingham #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10) 7125a988416SJim Ingham #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 7132411167fSJim Ingham #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 714055ad9beSIlia K #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) 7150fcdac36SJim Ingham #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) 7165a988416SJim Ingham 717b9c1b51eSKate Stone OptionDefinition CommandObjectBreakpointSet::CommandOptions::g_option_table[] = 7185a988416SJim Ingham { 719ac9c3a62SKate Stone // clang-format off 720ac9c3a62SKate 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 " 721ac9c3a62SKate Stone "multiple times to specify multiple shared libraries."}, 722ac9c3a62SKate 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." }, 723ac9c3a62SKate 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." }, 724ac9c3a62SKate 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."}, 725ac9c3a62SKate 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."}, 726ac9c3a62SKate 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."}, 727ac9c3a62SKate 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 " 728ac9c3a62SKate Stone "argument."}, 729ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints."}, 730ac9c3a62SKate 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 " 731ac9c3a62SKate Stone "this argument."}, 732ac9c3a62SKate 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 " 733ac9c3a62SKate Stone "lldb only looks for files that are #included if they use the standard include " 734ac9c3a62SKate Stone "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " 735ac9c3a62SKate Stone "#included, set target.inline-breakpoint-strategy to \"always\"."}, 736ac9c3a62SKate Stone {LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint."}, 7375a988416SJim Ingham 7385a988416SJim Ingham // Comment out this option for the moment, as we don't actually use it, but will in the future. 7395a988416SJim Ingham // This way users won't see it, but the infrastructure is left in place. 7409e85e5a8SEugene Zelenko // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>", 7415a988416SJim Ingham // "Set the breakpoint by source location at this particular column."}, 7425a988416SJim Ingham 743ac9c3a62SKate 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 " 744ac9c3a62SKate Stone "a particular binary, then the address will be converted to a \"file\" " 745ac9c3a62SKate Stone "address, so that the breakpoint will track that binary+offset no matter where " 746ac9c3a62SKate Stone "the binary eventually loads. Alternately, if you also specify the module - " 747ac9c3a62SKate Stone "with the -s option - then the address will be treated as a file address in " 748ac9c3a62SKate Stone "that module, and resolved accordingly. Again, this will allow lldb to track " 749ac9c3a62SKate Stone "that offset on subsequent reloads. The module need not have been loaded at " 750ac9c3a62SKate Stone "the time you specify this breakpoint, and will get resolved when the module " 751ac9c3a62SKate Stone "is loaded."}, 752ac9c3a62SKate 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 " 753ac9c3a62SKate Stone "one breakpoint for multiple names"}, 754ac9c3a62SKate 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 " 755ac9c3a62SKate Stone "functions. Can be repeated multiple times."}, 756ac9c3a62SKate 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 " 757ac9c3a62SKate Stone "namespaces and all arguments, and for Objective C this means a full function " 758ac9c3a62SKate Stone "prototype with class and selector. Can be repeated multiple times to make " 759ac9c3a62SKate Stone "one breakpoint for multiple names."}, 760ac9c3a62SKate 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 " 761ac9c3a62SKate Stone "make one breakpoint for multiple Selectors."}, 762ac9c3a62SKate 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 " 763ac9c3a62SKate Stone "make one breakpoint for multiple methods."}, 764ac9c3a62SKate 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 " 765ac9c3a62SKate Stone "the function name(s)."}, 766ac9c3a62SKate 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 " 767ac9c3a62SKate Stone "ignored). Can be repeated multiple times to make one breakpoint for multiple " 768ac9c3a62SKate Stone "symbols."}, 769ac9c3a62SKate 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 " 770ac9c3a62SKate Stone "against the source text in a source file or files specified with the -f " 771ac9c3a62SKate Stone "option. The -f option can be specified more than once. If no source files " 772ac9c3a62SKate Stone "are specified, uses the current \"default source file\". If you want to " 773ac9c3a62SKate Stone "match against all source files, pass the \"--all-files\" option."}, 774ac9c3a62SKate Stone {LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches."}, 775ac9c3a62SKate 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 " 776ac9c3a62SKate Stone "options, on throw but not catch.)"}, 777ac9c3a62SKate Stone {LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW."}, 778ac9c3a62SKate Stone {LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH."}, 7795a988416SJim Ingham 780a72b31c7SJim Ingham // Don't add this option till it actually does something useful... 7819e85e5a8SEugene Zelenko // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, 782a72b31c7SJim 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" }, 783a72b31c7SJim Ingham 784ac9c3a62SKate 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 " 785ac9c3a62SKate Stone "(note: currently only implemented for setting breakpoints on identifiers). " 786ac9c3a62SKate Stone "If not set the target.language setting is used."}, 787ac9c3a62SKate 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. " 788ac9c3a62SKate Stone "If not set the target.skip-prologue setting is used."}, 789ac9c3a62SKate 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, " 790ac9c3a62SKate Stone "which prime new targets."}, 791ac9c3a62SKate 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."}, 792ac9c3a62SKate 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. " 7932411167fSJim Ingham "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries."}, 794ac9c3a62SKate 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 " 795ac9c3a62SKate Stone "setting is used."}, 7969e85e5a8SEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 797ac9c3a62SKate Stone // clang-format on 7985a988416SJim Ingham }; 7995a988416SJim Ingham 8005a988416SJim Ingham //------------------------------------------------------------------------- 8015a988416SJim Ingham // CommandObjectBreakpointModify 8025a988416SJim Ingham //------------------------------------------------------------------------- 8035a988416SJim Ingham #pragma mark Modify 8045a988416SJim Ingham 805b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 8065a988416SJim Ingham public: 807b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 808b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 809b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 810b9c1b51eSKate Stone "breakpoints in the executable. " 811b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 812b9c1b51eSKate Stone "created breakpoint. " 813b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 814b9c1b51eSKate Stone "empty argument clears the modification.", 8159e85e5a8SEugene Zelenko nullptr), 816b9c1b51eSKate Stone m_options() { 8175a988416SJim Ingham CommandArgumentEntry arg; 818b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 819b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 820b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 821b9c1b51eSKate Stone // arguments vector. 8225a988416SJim Ingham m_arguments.push_back(arg); 8235a988416SJim Ingham } 8245a988416SJim Ingham 8259e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 8265a988416SJim Ingham 827b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 8285a988416SJim Ingham 829b9c1b51eSKate Stone class CommandOptions : public Options { 8305a988416SJim Ingham public: 831b9c1b51eSKate Stone CommandOptions() 832b9c1b51eSKate Stone : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), 833b9c1b51eSKate Stone m_thread_id_passed(false), m_thread_index(UINT32_MAX), 834b9c1b51eSKate Stone m_thread_index_passed(false), m_thread_name(), m_queue_name(), 835b9c1b51eSKate Stone m_condition(), m_one_shot(false), m_enable_passed(false), 836b9c1b51eSKate Stone m_enable_value(false), m_name_passed(false), m_queue_passed(false), 837b9c1b51eSKate Stone m_condition_passed(false), m_one_shot_passed(false), 838b9c1b51eSKate Stone m_use_dummy(false) {} 8395a988416SJim Ingham 8409e85e5a8SEugene Zelenko ~CommandOptions() override = default; 8415a988416SJim Ingham 842b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 843b9c1b51eSKate Stone ExecutionContext *execution_context) override { 8445a988416SJim Ingham Error error; 8453bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 8465a988416SJim Ingham 847b9c1b51eSKate Stone switch (short_option) { 8485a988416SJim Ingham case 'c': 8499e85e5a8SEugene Zelenko if (option_arg != nullptr) 8505a988416SJim Ingham m_condition.assign(option_arg); 8515a988416SJim Ingham else 8525a988416SJim Ingham m_condition.clear(); 8535a988416SJim Ingham m_condition_passed = true; 8545a988416SJim Ingham break; 8555a988416SJim Ingham case 'd': 8565a988416SJim Ingham m_enable_passed = true; 8575a988416SJim Ingham m_enable_value = false; 8585a988416SJim Ingham break; 85933df7cd3SJim Ingham case 'D': 86033df7cd3SJim Ingham m_use_dummy = true; 86133df7cd3SJim Ingham break; 8625a988416SJim Ingham case 'e': 8635a988416SJim Ingham m_enable_passed = true; 8645a988416SJim Ingham m_enable_value = true; 8655a988416SJim Ingham break; 8665a988416SJim Ingham case 'i': 8675275aaa0SVince Harron m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 8685a988416SJim Ingham if (m_ignore_count == UINT32_MAX) 869b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid ignore count '%s'", 870b9c1b51eSKate Stone option_arg); 8715a988416SJim Ingham break; 872b9c1b51eSKate Stone case 'o': { 873ca36cd16SJim Ingham bool value, success; 874ecbb0bb1SZachary Turner value = Args::StringToBoolean( 875ecbb0bb1SZachary Turner llvm::StringRef::withNullAsEmpty(option_arg), false, &success); 876b9c1b51eSKate Stone if (success) { 877ca36cd16SJim Ingham m_one_shot_passed = true; 878ca36cd16SJim Ingham m_one_shot = value; 879b9c1b51eSKate Stone } else 880b9c1b51eSKate Stone error.SetErrorStringWithFormat( 881b9c1b51eSKate Stone "invalid boolean value '%s' passed for -o option", option_arg); 882b9c1b51eSKate Stone } break; 8835a988416SJim Ingham case 't': 884b9c1b51eSKate Stone if (option_arg[0] == '\0') { 8855a988416SJim Ingham m_thread_id = LLDB_INVALID_THREAD_ID; 8865a988416SJim Ingham m_thread_id_passed = true; 887b9c1b51eSKate Stone } else { 888b9c1b51eSKate Stone m_thread_id = 889b9c1b51eSKate Stone StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 8905a988416SJim Ingham if (m_thread_id == LLDB_INVALID_THREAD_ID) 891b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread id string '%s'", 892b9c1b51eSKate Stone option_arg); 8935a988416SJim Ingham else 8945a988416SJim Ingham m_thread_id_passed = true; 8955a988416SJim Ingham } 8965a988416SJim Ingham break; 8975a988416SJim Ingham case 'T': 8989e85e5a8SEugene Zelenko if (option_arg != nullptr) 8995a988416SJim Ingham m_thread_name.assign(option_arg); 9005a988416SJim Ingham else 9015a988416SJim Ingham m_thread_name.clear(); 9025a988416SJim Ingham m_name_passed = true; 9035a988416SJim Ingham break; 9045a988416SJim Ingham case 'q': 9059e85e5a8SEugene Zelenko if (option_arg != nullptr) 9065a988416SJim Ingham m_queue_name.assign(option_arg); 9075a988416SJim Ingham else 9085a988416SJim Ingham m_queue_name.clear(); 9095a988416SJim Ingham m_queue_passed = true; 9105a988416SJim Ingham break; 9115a988416SJim Ingham case 'x': 912b9c1b51eSKate Stone if (option_arg[0] == '\n') { 9135a988416SJim Ingham m_thread_index = UINT32_MAX; 9145a988416SJim Ingham m_thread_index_passed = true; 915b9c1b51eSKate Stone } else { 9165275aaa0SVince Harron m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 9175a988416SJim Ingham if (m_thread_id == UINT32_MAX) 918b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread index string '%s'", 919b9c1b51eSKate Stone option_arg); 9205a988416SJim Ingham else 9215a988416SJim Ingham m_thread_index_passed = true; 9225a988416SJim Ingham } 9235a988416SJim Ingham break; 9245a988416SJim Ingham default: 925b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 926b9c1b51eSKate Stone short_option); 9275a988416SJim Ingham break; 9285a988416SJim Ingham } 9295a988416SJim Ingham 9305a988416SJim Ingham return error; 9315a988416SJim Ingham } 9329e85e5a8SEugene Zelenko 933b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 9345a988416SJim Ingham m_ignore_count = 0; 9355a988416SJim Ingham m_thread_id = LLDB_INVALID_THREAD_ID; 9365a988416SJim Ingham m_thread_id_passed = false; 9375a988416SJim Ingham m_thread_index = UINT32_MAX; 9385a988416SJim Ingham m_thread_index_passed = false; 9395a988416SJim Ingham m_thread_name.clear(); 9405a988416SJim Ingham m_queue_name.clear(); 9415a988416SJim Ingham m_condition.clear(); 942ca36cd16SJim Ingham m_one_shot = false; 9435a988416SJim Ingham m_enable_passed = false; 9445a988416SJim Ingham m_queue_passed = false; 9455a988416SJim Ingham m_name_passed = false; 9465a988416SJim Ingham m_condition_passed = false; 947ca36cd16SJim Ingham m_one_shot_passed = false; 94833df7cd3SJim Ingham m_use_dummy = false; 9495a988416SJim Ingham } 9505a988416SJim Ingham 951b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { return g_option_table; } 9525a988416SJim Ingham 9535a988416SJim Ingham // Options table: Required for subclasses of Options. 9545a988416SJim Ingham 9555a988416SJim Ingham static OptionDefinition g_option_table[]; 9565a988416SJim Ingham 9575a988416SJim Ingham // Instance variables to hold the values for command options. 9585a988416SJim Ingham 9595a988416SJim Ingham uint32_t m_ignore_count; 9605a988416SJim Ingham lldb::tid_t m_thread_id; 9615a988416SJim Ingham bool m_thread_id_passed; 9625a988416SJim Ingham uint32_t m_thread_index; 9635a988416SJim Ingham bool m_thread_index_passed; 9645a988416SJim Ingham std::string m_thread_name; 9655a988416SJim Ingham std::string m_queue_name; 9665a988416SJim Ingham std::string m_condition; 967ca36cd16SJim Ingham bool m_one_shot; 9685a988416SJim Ingham bool m_enable_passed; 9695a988416SJim Ingham bool m_enable_value; 9705a988416SJim Ingham bool m_name_passed; 9715a988416SJim Ingham bool m_queue_passed; 9725a988416SJim Ingham bool m_condition_passed; 973ca36cd16SJim Ingham bool m_one_shot_passed; 97433df7cd3SJim Ingham bool m_use_dummy; 9755a988416SJim Ingham }; 9765a988416SJim Ingham 9775a988416SJim Ingham protected: 978b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 97933df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 980b9c1b51eSKate Stone if (target == nullptr) { 9815a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 9825a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9835a988416SJim Ingham return false; 9845a988416SJim Ingham } 9855a988416SJim Ingham 986bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 987bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 9885a988416SJim Ingham 9895a988416SJim Ingham BreakpointIDList valid_bp_ids; 9905a988416SJim Ingham 991b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 992b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 9935a988416SJim Ingham 994b9c1b51eSKate Stone if (result.Succeeded()) { 9955a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 996b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 9975a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 9985a988416SJim Ingham 999b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1000b9c1b51eSKate Stone Breakpoint *bp = 1001b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1002b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1003b9c1b51eSKate Stone BreakpointLocation *location = 1004b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1005b9c1b51eSKate Stone if (location) { 10065a988416SJim Ingham if (m_options.m_thread_id_passed) 10075a988416SJim Ingham location->SetThreadID(m_options.m_thread_id); 10085a988416SJim Ingham 10095a988416SJim Ingham if (m_options.m_thread_index_passed) 10105a988416SJim Ingham location->SetThreadIndex(m_options.m_thread_index); 10115a988416SJim Ingham 10125a988416SJim Ingham if (m_options.m_name_passed) 10135a988416SJim Ingham location->SetThreadName(m_options.m_thread_name.c_str()); 10145a988416SJim Ingham 10155a988416SJim Ingham if (m_options.m_queue_passed) 10165a988416SJim Ingham location->SetQueueName(m_options.m_queue_name.c_str()); 10175a988416SJim Ingham 10185a988416SJim Ingham if (m_options.m_ignore_count != 0) 10195a988416SJim Ingham location->SetIgnoreCount(m_options.m_ignore_count); 10205a988416SJim Ingham 10215a988416SJim Ingham if (m_options.m_enable_passed) 10225a988416SJim Ingham location->SetEnabled(m_options.m_enable_value); 10235a988416SJim Ingham 10245a988416SJim Ingham if (m_options.m_condition_passed) 10255a988416SJim Ingham location->SetCondition(m_options.m_condition.c_str()); 10265a988416SJim Ingham } 1027b9c1b51eSKate Stone } else { 10285a988416SJim Ingham if (m_options.m_thread_id_passed) 10295a988416SJim Ingham bp->SetThreadID(m_options.m_thread_id); 10305a988416SJim Ingham 10315a988416SJim Ingham if (m_options.m_thread_index_passed) 10325a988416SJim Ingham bp->SetThreadIndex(m_options.m_thread_index); 10335a988416SJim Ingham 10345a988416SJim Ingham if (m_options.m_name_passed) 10355a988416SJim Ingham bp->SetThreadName(m_options.m_thread_name.c_str()); 10365a988416SJim Ingham 10375a988416SJim Ingham if (m_options.m_queue_passed) 10385a988416SJim Ingham bp->SetQueueName(m_options.m_queue_name.c_str()); 10395a988416SJim Ingham 10405a988416SJim Ingham if (m_options.m_ignore_count != 0) 10415a988416SJim Ingham bp->SetIgnoreCount(m_options.m_ignore_count); 10425a988416SJim Ingham 10435a988416SJim Ingham if (m_options.m_enable_passed) 10445a988416SJim Ingham bp->SetEnabled(m_options.m_enable_value); 10455a988416SJim Ingham 10465a988416SJim Ingham if (m_options.m_condition_passed) 10475a988416SJim Ingham bp->SetCondition(m_options.m_condition.c_str()); 10485a988416SJim Ingham } 10495a988416SJim Ingham } 10505a988416SJim Ingham } 10515a988416SJim Ingham } 10525a988416SJim Ingham 10535a988416SJim Ingham return result.Succeeded(); 10545a988416SJim Ingham } 10555a988416SJim Ingham 10565a988416SJim Ingham private: 10575a988416SJim Ingham CommandOptions m_options; 10585a988416SJim Ingham }; 10595a988416SJim Ingham 10605a988416SJim Ingham #pragma mark Modify::CommandOptions 10615a988416SJim Ingham OptionDefinition 1062b9c1b51eSKate Stone CommandObjectBreakpointModify::CommandOptions::g_option_table[] = { 1063ac9c3a62SKate Stone // clang-format off 10649e85e5a8SEugene 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."}, 10659e85e5a8SEugene 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."}, 10669e85e5a8SEugene 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."}, 10679e85e5a8SEugene 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."}, 10689e85e5a8SEugene 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."}, 10699e85e5a8SEugene 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."}, 10709e85e5a8SEugene 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."}, 10719e85e5a8SEugene Zelenko {LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint."}, 10729e85e5a8SEugene Zelenko {LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint."}, 10739e85e5a8SEugene 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."}, 10749e85e5a8SEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 1075ac9c3a62SKate Stone // clang-format on 10765a988416SJim Ingham }; 10775a988416SJim Ingham 10785a988416SJim Ingham //------------------------------------------------------------------------- 10795a988416SJim Ingham // CommandObjectBreakpointEnable 10805a988416SJim Ingham //------------------------------------------------------------------------- 10815a988416SJim Ingham #pragma mark Enable 10825a988416SJim Ingham 1083b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 10845a988416SJim Ingham public: 1085b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 1086b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 1087b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 1088b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 1089b9c1b51eSKate Stone nullptr) { 10905a988416SJim Ingham CommandArgumentEntry arg; 1091b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1092b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1093b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1094b9c1b51eSKate Stone // arguments vector. 10955a988416SJim Ingham m_arguments.push_back(arg); 10965a988416SJim Ingham } 10975a988416SJim Ingham 10989e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 10995a988416SJim Ingham 11005a988416SJim Ingham protected: 1101b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1102893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1103b9c1b51eSKate Stone if (target == nullptr) { 11045a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 11055a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11065a988416SJim Ingham return false; 11075a988416SJim Ingham } 11085a988416SJim Ingham 1109bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1110bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 11115a988416SJim Ingham 11125a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 11135a988416SJim Ingham 11145a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 11155a988416SJim Ingham 1116b9c1b51eSKate Stone if (num_breakpoints == 0) { 11175a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 11185a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11195a988416SJim Ingham return false; 11205a988416SJim Ingham } 11215a988416SJim Ingham 1122b9c1b51eSKate Stone if (command.GetArgumentCount() == 0) { 11235a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 11245a988416SJim Ingham target->EnableAllBreakpoints(); 1125b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 1126b9c1b51eSKate Stone " breakpoints)\n", 1127b9c1b51eSKate Stone (uint64_t)num_breakpoints); 11285a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1129b9c1b51eSKate Stone } else { 11305a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 11315a988416SJim Ingham BreakpointIDList valid_bp_ids; 1132b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1133b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 11345a988416SJim Ingham 1135b9c1b51eSKate Stone if (result.Succeeded()) { 11365a988416SJim Ingham int enable_count = 0; 11375a988416SJim Ingham int loc_count = 0; 11385a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1139b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 11405a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 11415a988416SJim Ingham 1142b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1143b9c1b51eSKate Stone Breakpoint *breakpoint = 1144b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1145b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1146b9c1b51eSKate Stone BreakpointLocation *location = 1147b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1148b9c1b51eSKate Stone if (location) { 11495a988416SJim Ingham location->SetEnabled(true); 11505a988416SJim Ingham ++loc_count; 11515a988416SJim Ingham } 1152b9c1b51eSKate Stone } else { 11535a988416SJim Ingham breakpoint->SetEnabled(true); 11545a988416SJim Ingham ++enable_count; 11555a988416SJim Ingham } 11565a988416SJim Ingham } 11575a988416SJim Ingham } 1158b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 1159b9c1b51eSKate Stone enable_count + loc_count); 11605a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 11615a988416SJim Ingham } 11625a988416SJim Ingham } 11635a988416SJim Ingham 11645a988416SJim Ingham return result.Succeeded(); 11655a988416SJim Ingham } 11665a988416SJim Ingham }; 11675a988416SJim Ingham 11685a988416SJim Ingham //------------------------------------------------------------------------- 11695a988416SJim Ingham // CommandObjectBreakpointDisable 11705a988416SJim Ingham //------------------------------------------------------------------------- 11715a988416SJim Ingham #pragma mark Disable 11725a988416SJim Ingham 1173b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 11745a988416SJim Ingham public: 11757428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 1176b9c1b51eSKate Stone : CommandObjectParsed( 1177b9c1b51eSKate Stone interpreter, "breakpoint disable", 1178b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 11797428a18cSKate Stone "them. If none are specified, disable all " 11807428a18cSKate Stone "breakpoints.", 1181b9c1b51eSKate Stone nullptr) { 1182b9c1b51eSKate Stone SetHelpLong( 1183b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 11847428a18cSKate Stone If none are specified, disable all breakpoints." 11857428a18cSKate Stone R"( 1186ea671fbdSKate Stone 11877428a18cSKate Stone )" 11887428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 11897428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 11907428a18cSKate Stone R"( 1191ea671fbdSKate Stone 1192ea671fbdSKate Stone (lldb) break disable 1 1193ea671fbdSKate Stone (lldb) break enable 1.1 1194ea671fbdSKate Stone 1195ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 1196ea671fbdSKate Stone 1197ea671fbdSKate Stone (lldb) break disable 1.* 1198ea671fbdSKate Stone (lldb) break enable 1.1 1199ea671fbdSKate Stone 12007428a18cSKate Stone )" 12017428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 12027428a18cSKate Stone the second re-enables the first location."); 1203b0fac509SJim Ingham 12045a988416SJim Ingham CommandArgumentEntry arg; 1205b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1206b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1207b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1208b9c1b51eSKate Stone // arguments vector. 12095a988416SJim Ingham m_arguments.push_back(arg); 12105a988416SJim Ingham } 12115a988416SJim Ingham 12129e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 12135a988416SJim Ingham 12145a988416SJim Ingham protected: 1215b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1216893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1217b9c1b51eSKate Stone if (target == nullptr) { 12185a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 12195a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 12205a988416SJim Ingham return false; 12215a988416SJim Ingham } 12225a988416SJim Ingham 1223bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1224bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 12255a988416SJim Ingham 12265a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 12275a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 12285a988416SJim Ingham 1229b9c1b51eSKate Stone if (num_breakpoints == 0) { 12305a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 12315a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 12325a988416SJim Ingham return false; 12335a988416SJim Ingham } 12345a988416SJim Ingham 1235b9c1b51eSKate Stone if (command.GetArgumentCount() == 0) { 12365a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 12375a988416SJim Ingham target->DisableAllBreakpoints(); 1238b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1239b9c1b51eSKate Stone " breakpoints)\n", 1240b9c1b51eSKate Stone (uint64_t)num_breakpoints); 12415a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1242b9c1b51eSKate Stone } else { 12435a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 12445a988416SJim Ingham BreakpointIDList valid_bp_ids; 12455a988416SJim Ingham 1246b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1247b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 12485a988416SJim Ingham 1249b9c1b51eSKate Stone if (result.Succeeded()) { 12505a988416SJim Ingham int disable_count = 0; 12515a988416SJim Ingham int loc_count = 0; 12525a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1253b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 12545a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 12555a988416SJim Ingham 1256b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1257b9c1b51eSKate Stone Breakpoint *breakpoint = 1258b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1259b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1260b9c1b51eSKate Stone BreakpointLocation *location = 1261b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1262b9c1b51eSKate Stone if (location) { 12635a988416SJim Ingham location->SetEnabled(false); 12645a988416SJim Ingham ++loc_count; 12655a988416SJim Ingham } 1266b9c1b51eSKate Stone } else { 12675a988416SJim Ingham breakpoint->SetEnabled(false); 12685a988416SJim Ingham ++disable_count; 12695a988416SJim Ingham } 12705a988416SJim Ingham } 12715a988416SJim Ingham } 1272b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1273b9c1b51eSKate Stone disable_count + loc_count); 12745a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 12755a988416SJim Ingham } 12765a988416SJim Ingham } 12775a988416SJim Ingham 12785a988416SJim Ingham return result.Succeeded(); 12795a988416SJim Ingham } 12805a988416SJim Ingham }; 12815a988416SJim Ingham 12825a988416SJim Ingham //------------------------------------------------------------------------- 12835a988416SJim Ingham // CommandObjectBreakpointList 12845a988416SJim Ingham //------------------------------------------------------------------------- 12855a988416SJim Ingham #pragma mark List 12865a988416SJim Ingham 1287b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 12885a988416SJim Ingham public: 1289b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1290b9c1b51eSKate Stone : CommandObjectParsed( 1291b9c1b51eSKate Stone interpreter, "breakpoint list", 12925a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 12939e85e5a8SEugene Zelenko nullptr), 1294b9c1b51eSKate Stone m_options() { 12955a988416SJim Ingham CommandArgumentEntry arg; 12965a988416SJim Ingham CommandArgumentData bp_id_arg; 12975a988416SJim Ingham 12985a988416SJim Ingham // Define the first (and only) variant of this arg. 12995a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 13005a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 13015a988416SJim Ingham 1302b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1303b9c1b51eSKate Stone // argument entry. 13045a988416SJim Ingham arg.push_back(bp_id_arg); 13055a988416SJim Ingham 13065a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 13075a988416SJim Ingham m_arguments.push_back(arg); 13085a988416SJim Ingham } 13095a988416SJim Ingham 13109e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 13115a988416SJim Ingham 1312b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 13135a988416SJim Ingham 1314b9c1b51eSKate Stone class CommandOptions : public Options { 13155a988416SJim Ingham public: 1316b9c1b51eSKate Stone CommandOptions() 1317b9c1b51eSKate Stone : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 13185a988416SJim Ingham } 13195a988416SJim Ingham 13209e85e5a8SEugene Zelenko ~CommandOptions() override = default; 13215a988416SJim Ingham 1322b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1323b9c1b51eSKate Stone ExecutionContext *execution_context) override { 13245a988416SJim Ingham Error error; 13253bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 13265a988416SJim Ingham 1327b9c1b51eSKate Stone switch (short_option) { 13285a988416SJim Ingham case 'b': 13295a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 13305a988416SJim Ingham break; 133133df7cd3SJim Ingham case 'D': 133233df7cd3SJim Ingham m_use_dummy = true; 133333df7cd3SJim Ingham break; 13345a988416SJim Ingham case 'f': 13355a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 13365a988416SJim Ingham break; 13375a988416SJim Ingham case 'v': 13385a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 13395a988416SJim Ingham break; 13405a988416SJim Ingham case 'i': 13415a988416SJim Ingham m_internal = true; 13425a988416SJim Ingham break; 13435a988416SJim Ingham default: 1344b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1345b9c1b51eSKate Stone short_option); 13465a988416SJim Ingham break; 13475a988416SJim Ingham } 13485a988416SJim Ingham 13495a988416SJim Ingham return error; 13505a988416SJim Ingham } 13515a988416SJim Ingham 1352b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 13535a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 13545a988416SJim Ingham m_internal = false; 135533df7cd3SJim Ingham m_use_dummy = false; 13565a988416SJim Ingham } 13575a988416SJim Ingham 1358b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { return g_option_table; } 13595a988416SJim Ingham 13605a988416SJim Ingham // Options table: Required for subclasses of Options. 13615a988416SJim Ingham 13625a988416SJim Ingham static OptionDefinition g_option_table[]; 13635a988416SJim Ingham 13645a988416SJim Ingham // Instance variables to hold the values for command options. 13655a988416SJim Ingham 13665a988416SJim Ingham lldb::DescriptionLevel m_level; 13675a988416SJim Ingham 13685a988416SJim Ingham bool m_internal; 136933df7cd3SJim Ingham bool m_use_dummy; 13705a988416SJim Ingham }; 13715a988416SJim Ingham 13725a988416SJim Ingham protected: 1373b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 137433df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 137533df7cd3SJim Ingham 1376b9c1b51eSKate Stone if (target == nullptr) { 13775a988416SJim Ingham result.AppendError("Invalid target. No current target or breakpoints."); 13785a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13795a988416SJim Ingham return true; 13805a988416SJim Ingham } 13815a988416SJim Ingham 1382b9c1b51eSKate Stone const BreakpointList &breakpoints = 1383b9c1b51eSKate Stone target->GetBreakpointList(m_options.m_internal); 1384bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1385bb19a13cSSaleem Abdulrasool target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); 13865a988416SJim Ingham 13875a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 13885a988416SJim Ingham 1389b9c1b51eSKate Stone if (num_breakpoints == 0) { 13905a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 13915a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13925a988416SJim Ingham return true; 13935a988416SJim Ingham } 13945a988416SJim Ingham 13955a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 13965a988416SJim Ingham 1397b9c1b51eSKate Stone if (command.GetArgumentCount() == 0) { 13985a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 13995a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1400b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 14015a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 14025a988416SJim Ingham AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level); 14035a988416SJim Ingham } 14045a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1405b9c1b51eSKate Stone } else { 14065a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 14075a988416SJim Ingham BreakpointIDList valid_bp_ids; 1408b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1409b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 14105a988416SJim Ingham 1411b9c1b51eSKate Stone if (result.Succeeded()) { 1412b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 14135a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1414b9c1b51eSKate Stone Breakpoint *breakpoint = 1415b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1416b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1417b9c1b51eSKate Stone m_options.m_level); 14185a988416SJim Ingham } 14195a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1420b9c1b51eSKate Stone } else { 14217428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 14225a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14235a988416SJim Ingham } 14245a988416SJim Ingham } 14255a988416SJim Ingham 14265a988416SJim Ingham return result.Succeeded(); 14275a988416SJim Ingham } 14285a988416SJim Ingham 14295a988416SJim Ingham private: 14305a988416SJim Ingham CommandOptions m_options; 14315a988416SJim Ingham }; 14325a988416SJim Ingham 14335a988416SJim Ingham #pragma mark List::CommandOptions 1434b9c1b51eSKate Stone OptionDefinition CommandObjectBreakpointList::CommandOptions::g_option_table[] = 14355a988416SJim Ingham { 1436ac9c3a62SKate Stone // clang-format off 1437ac9c3a62SKate Stone {LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" }, 1438ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)."}, 14395a988416SJim Ingham // FIXME: We need to add an "internal" command, and then add this sort of thing to it. 14405a988416SJim Ingham // But I need to see it for now, and don't want to wait. 1441ac9c3a62SKate Stone {LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations."}, 1442ac9c3a62SKate 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)."}, 1443ac9c3a62SKate 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."}, 14449e85e5a8SEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 1445ac9c3a62SKate Stone // clang-format on 14465a988416SJim Ingham }; 14475a988416SJim Ingham 14485a988416SJim Ingham //------------------------------------------------------------------------- 14495a988416SJim Ingham // CommandObjectBreakpointClear 14505a988416SJim Ingham //------------------------------------------------------------------------- 14515a988416SJim Ingham #pragma mark Clear 14525a988416SJim Ingham 1453b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed { 14545a988416SJim Ingham public: 1455b9c1b51eSKate Stone typedef enum BreakpointClearType { 14565a988416SJim Ingham eClearTypeInvalid, 14575a988416SJim Ingham eClearTypeFileAndLine 14585a988416SJim Ingham } BreakpointClearType; 14595a988416SJim Ingham 14607428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter) 14617428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear", 1462b9c1b51eSKate Stone "Delete or disable breakpoints matching the " 1463b9c1b51eSKate Stone "specified source file and line.", 14645a988416SJim Ingham "breakpoint clear <cmd-options>"), 1465b9c1b51eSKate Stone m_options() {} 14665a988416SJim Ingham 14679e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default; 14685a988416SJim Ingham 1469b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 14705a988416SJim Ingham 1471b9c1b51eSKate Stone class CommandOptions : public Options { 14725a988416SJim Ingham public: 1473b9c1b51eSKate Stone CommandOptions() : Options(), m_filename(), m_line_num(0) {} 14745a988416SJim Ingham 14759e85e5a8SEugene Zelenko ~CommandOptions() override = default; 14765a988416SJim Ingham 1477b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1478b9c1b51eSKate Stone ExecutionContext *execution_context) override { 14795a988416SJim Ingham Error error; 14803bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 14815a988416SJim Ingham 1482b9c1b51eSKate Stone switch (short_option) { 14835a988416SJim Ingham case 'f': 14845a988416SJim Ingham m_filename.assign(option_arg); 14855a988416SJim Ingham break; 14865a988416SJim Ingham 14875a988416SJim Ingham case 'l': 14885275aaa0SVince Harron m_line_num = StringConvert::ToUInt32(option_arg, 0); 14895a988416SJim Ingham break; 14905a988416SJim Ingham 14915a988416SJim Ingham default: 1492b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1493b9c1b51eSKate Stone short_option); 14945a988416SJim Ingham break; 14955a988416SJim Ingham } 14965a988416SJim Ingham 14975a988416SJim Ingham return error; 14985a988416SJim Ingham } 14995a988416SJim Ingham 1500b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 15015a988416SJim Ingham m_filename.clear(); 15025a988416SJim Ingham m_line_num = 0; 15035a988416SJim Ingham } 15045a988416SJim Ingham 1505b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { return g_option_table; } 15065a988416SJim Ingham 15075a988416SJim Ingham // Options table: Required for subclasses of Options. 15085a988416SJim Ingham 15095a988416SJim Ingham static OptionDefinition g_option_table[]; 15105a988416SJim Ingham 15115a988416SJim Ingham // Instance variables to hold the values for command options. 15125a988416SJim Ingham 15135a988416SJim Ingham std::string m_filename; 15145a988416SJim Ingham uint32_t m_line_num; 15155a988416SJim Ingham }; 15165a988416SJim Ingham 15175a988416SJim Ingham protected: 1518b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1519893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1520b9c1b51eSKate Stone if (target == nullptr) { 15215a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 15225a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15235a988416SJim Ingham return false; 15245a988416SJim Ingham } 15255a988416SJim Ingham 15265a988416SJim Ingham // The following are the various types of breakpoints that could be cleared: 15275a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 15285a988416SJim Ingham 15295a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 15305a988416SJim Ingham 15315a988416SJim Ingham if (m_options.m_line_num != 0) 15325a988416SJim Ingham break_type = eClearTypeFileAndLine; 15335a988416SJim Ingham 1534bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1535bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 15365a988416SJim Ingham 15375a988416SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 15385a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 15395a988416SJim Ingham 15405a988416SJim Ingham // Early return if there's no breakpoint at all. 1541b9c1b51eSKate Stone if (num_breakpoints == 0) { 15425a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15435a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15445a988416SJim Ingham return result.Succeeded(); 15455a988416SJim Ingham } 15465a988416SJim Ingham 15475a988416SJim Ingham // Find matching breakpoints and delete them. 15485a988416SJim Ingham 15495a988416SJim Ingham // First create a copy of all the IDs. 15505a988416SJim Ingham std::vector<break_id_t> BreakIDs; 15515a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 15529e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 15535a988416SJim Ingham 15545a988416SJim Ingham int num_cleared = 0; 15555a988416SJim Ingham StreamString ss; 1556b9c1b51eSKate Stone switch (break_type) { 15575a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 15585a988416SJim Ingham { 15595a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 15605a988416SJim Ingham BreakpointLocationCollection loc_coll; 15615a988416SJim Ingham 1562b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 15635a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 15645a988416SJim Ingham 1565b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1566b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1567b9c1b51eSKate Stone // remove the breakpoint. 1568b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 15695a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 15705a988416SJim Ingham ss.EOL(); 15715a988416SJim Ingham target->RemoveBreakpointByID(bp->GetID()); 15725a988416SJim Ingham ++num_cleared; 15735a988416SJim Ingham } 15745a988416SJim Ingham } 15755a988416SJim Ingham } 1576b9c1b51eSKate Stone } break; 15775a988416SJim Ingham 15785a988416SJim Ingham default: 15795a988416SJim Ingham break; 15805a988416SJim Ingham } 15815a988416SJim Ingham 1582b9c1b51eSKate Stone if (num_cleared > 0) { 15835a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 15845a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 15855a988416SJim Ingham output_stream << ss.GetData(); 15865a988416SJim Ingham output_stream.EOL(); 15875a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1588b9c1b51eSKate Stone } else { 15895a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15905a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15915a988416SJim Ingham } 15925a988416SJim Ingham 15935a988416SJim Ingham return result.Succeeded(); 15945a988416SJim Ingham } 15955a988416SJim Ingham 15965a988416SJim Ingham private: 15975a988416SJim Ingham CommandOptions m_options; 15985a988416SJim Ingham }; 15995a988416SJim Ingham 16005a988416SJim Ingham #pragma mark Clear::CommandOptions 16015a988416SJim Ingham 16025a988416SJim Ingham OptionDefinition 1603b9c1b51eSKate Stone CommandObjectBreakpointClear::CommandOptions::g_option_table[] = { 1604ac9c3a62SKate Stone // clang-format off 1605ac9c3a62SKate 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."}, 1606ac9c3a62SKate Stone {LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line."}, 16079e85e5a8SEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 1608ac9c3a62SKate Stone // clang-format on 16095a988416SJim Ingham }; 16105a988416SJim Ingham 16115a988416SJim Ingham //------------------------------------------------------------------------- 16125a988416SJim Ingham // CommandObjectBreakpointDelete 16135a988416SJim Ingham //------------------------------------------------------------------------- 16145a988416SJim Ingham #pragma mark Delete 16155a988416SJim Ingham 1616b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 16175a988416SJim Ingham public: 1618b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1619b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1620b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1621b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 16229e85e5a8SEugene Zelenko nullptr), 1623b9c1b51eSKate Stone m_options() { 16245a988416SJim Ingham CommandArgumentEntry arg; 1625b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1626b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1627b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1628b9c1b51eSKate Stone // arguments vector. 16295a988416SJim Ingham m_arguments.push_back(arg); 16305a988416SJim Ingham } 16315a988416SJim Ingham 16329e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 16335a988416SJim Ingham 1634b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 163533df7cd3SJim Ingham 1636b9c1b51eSKate Stone class CommandOptions : public Options { 163733df7cd3SJim Ingham public: 1638b9c1b51eSKate Stone CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 163933df7cd3SJim Ingham 16409e85e5a8SEugene Zelenko ~CommandOptions() override = default; 164133df7cd3SJim Ingham 1642b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1643b9c1b51eSKate Stone ExecutionContext *execution_context) override { 164433df7cd3SJim Ingham Error error; 164533df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 164633df7cd3SJim Ingham 1647b9c1b51eSKate Stone switch (short_option) { 164833df7cd3SJim Ingham case 'f': 164933df7cd3SJim Ingham m_force = true; 165033df7cd3SJim Ingham break; 165133df7cd3SJim Ingham 165233df7cd3SJim Ingham case 'D': 165333df7cd3SJim Ingham m_use_dummy = true; 165433df7cd3SJim Ingham break; 165533df7cd3SJim Ingham 165633df7cd3SJim Ingham default: 1657b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1658b9c1b51eSKate Stone short_option); 165933df7cd3SJim Ingham break; 166033df7cd3SJim Ingham } 166133df7cd3SJim Ingham 166233df7cd3SJim Ingham return error; 166333df7cd3SJim Ingham } 166433df7cd3SJim Ingham 1665b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 166633df7cd3SJim Ingham m_use_dummy = false; 166733df7cd3SJim Ingham m_force = false; 166833df7cd3SJim Ingham } 166933df7cd3SJim Ingham 1670b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { return g_option_table; } 167133df7cd3SJim Ingham 167233df7cd3SJim Ingham // Options table: Required for subclasses of Options. 167333df7cd3SJim Ingham 167433df7cd3SJim Ingham static OptionDefinition g_option_table[]; 167533df7cd3SJim Ingham 167633df7cd3SJim Ingham // Instance variables to hold the values for command options. 167733df7cd3SJim Ingham bool m_use_dummy; 167833df7cd3SJim Ingham bool m_force; 167933df7cd3SJim Ingham }; 168033df7cd3SJim Ingham 16815a988416SJim Ingham protected: 1682b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 168333df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 168433df7cd3SJim Ingham 1685b9c1b51eSKate Stone if (target == nullptr) { 16865a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 16875a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16885a988416SJim Ingham return false; 16895a988416SJim Ingham } 16905a988416SJim Ingham 1691bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1692bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 16935a988416SJim Ingham 16945a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 16955a988416SJim Ingham 16965a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 16975a988416SJim Ingham 1698b9c1b51eSKate Stone if (num_breakpoints == 0) { 16995a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 17005a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 17015a988416SJim Ingham return false; 17025a988416SJim Ingham } 17035a988416SJim Ingham 1704b9c1b51eSKate Stone if (command.GetArgumentCount() == 0) { 1705b9c1b51eSKate Stone if (!m_options.m_force && 1706b9c1b51eSKate Stone !m_interpreter.Confirm( 1707b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1708b9c1b51eSKate Stone true)) { 17095a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1710b9c1b51eSKate Stone } else { 17115a988416SJim Ingham target->RemoveAllBreakpoints(); 1712b9c1b51eSKate Stone result.AppendMessageWithFormat( 1713b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1714b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 17155a988416SJim Ingham } 17165a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1717b9c1b51eSKate Stone } else { 17185a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 17195a988416SJim Ingham BreakpointIDList valid_bp_ids; 1720b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1721b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 17225a988416SJim Ingham 1723b9c1b51eSKate Stone if (result.Succeeded()) { 17245a988416SJim Ingham int delete_count = 0; 17255a988416SJim Ingham int disable_count = 0; 17265a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1727b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 17285a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 17295a988416SJim Ingham 1730b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1731b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1732b9c1b51eSKate Stone Breakpoint *breakpoint = 1733b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1734b9c1b51eSKate Stone BreakpointLocation *location = 1735b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1736b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1737b9c1b51eSKate Stone // disable them instead. 1738b9c1b51eSKate Stone if (location) { 17395a988416SJim Ingham location->SetEnabled(false); 17405a988416SJim Ingham ++disable_count; 17415a988416SJim Ingham } 1742b9c1b51eSKate Stone } else { 17435a988416SJim Ingham target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 17445a988416SJim Ingham ++delete_count; 17455a988416SJim Ingham } 17465a988416SJim Ingham } 17475a988416SJim Ingham } 1748b9c1b51eSKate Stone result.AppendMessageWithFormat( 1749b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 17505a988416SJim Ingham delete_count, disable_count); 17515a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 17525a988416SJim Ingham } 17535a988416SJim Ingham } 17545a988416SJim Ingham return result.Succeeded(); 17555a988416SJim Ingham } 17569e85e5a8SEugene Zelenko 175733df7cd3SJim Ingham private: 175833df7cd3SJim Ingham CommandOptions m_options; 175933df7cd3SJim Ingham }; 176033df7cd3SJim Ingham 176133df7cd3SJim Ingham OptionDefinition 1762b9c1b51eSKate Stone CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = { 1763ac9c3a62SKate Stone // clang-format off 1764ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation."}, 1765ac9c3a62SKate 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."}, 17669e85e5a8SEugene Zelenko {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 1767ac9c3a62SKate Stone // clang-format on 17685a988416SJim Ingham }; 17695a988416SJim Ingham 177030fdc8d8SChris Lattner //------------------------------------------------------------------------- 17715e09c8c3SJim Ingham // CommandObjectBreakpointName 17725e09c8c3SJim Ingham //------------------------------------------------------------------------- 17735e09c8c3SJim Ingham 17747428a18cSKate Stone static OptionDefinition g_breakpoint_name_options[] = { 1775ac9c3a62SKate Stone // clang-format off 1776ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, 1777ac9c3a62SKate Stone {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, 1778ac9c3a62SKate 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."}, 1779ac9c3a62SKate Stone // clang-format on 17805e09c8c3SJim Ingham }; 1781b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 17825e09c8c3SJim Ingham public: 1783b9c1b51eSKate Stone BreakpointNameOptionGroup() 1784b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 17855e09c8c3SJim Ingham } 17865e09c8c3SJim Ingham 17879e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 17885e09c8c3SJim Ingham 1789b9c1b51eSKate Stone uint32_t GetNumDefinitions() override { 17905e09c8c3SJim Ingham return sizeof(g_breakpoint_name_options) / sizeof(OptionDefinition); 17915e09c8c3SJim Ingham } 17925e09c8c3SJim Ingham 1793b9c1b51eSKate Stone const OptionDefinition *GetDefinitions() override { 17945e09c8c3SJim Ingham return g_breakpoint_name_options; 17955e09c8c3SJim Ingham } 17965e09c8c3SJim Ingham 1797b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_value, 1798b9c1b51eSKate Stone ExecutionContext *execution_context) override { 17995e09c8c3SJim Ingham Error error; 18005e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 18016fa7681bSZachary Turner llvm::StringRef option_strref(option_value ? option_value : ""); 18025e09c8c3SJim Ingham 1803b9c1b51eSKate Stone switch (short_option) { 18045e09c8c3SJim Ingham case 'N': 18056fa7681bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_strref, error) && 1806b9c1b51eSKate Stone error.Success()) 18076fa7681bSZachary Turner m_name.SetValueFromString(option_strref); 18085e09c8c3SJim Ingham break; 18095e09c8c3SJim Ingham 18105e09c8c3SJim Ingham case 'B': 1811c95f7e2aSPavel Labath if (m_breakpoint.SetValueFromString(option_value).Fail()) 1812b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1813b9c1b51eSKate Stone "unrecognized value \"%s\" for breakpoint", option_value); 18145e09c8c3SJim Ingham break; 18155e09c8c3SJim Ingham case 'D': 1816c95f7e2aSPavel Labath if (m_use_dummy.SetValueFromString(option_value).Fail()) 1817b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1818b9c1b51eSKate Stone "unrecognized value \"%s\" for use-dummy", option_value); 18195e09c8c3SJim Ingham break; 18205e09c8c3SJim Ingham 18215e09c8c3SJim Ingham default: 1822b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized short option '%c'", 1823b9c1b51eSKate Stone short_option); 18245e09c8c3SJim Ingham break; 18255e09c8c3SJim Ingham } 18265e09c8c3SJim Ingham return error; 18275e09c8c3SJim Ingham } 18285e09c8c3SJim Ingham 1829b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 18305e09c8c3SJim Ingham m_name.Clear(); 18315e09c8c3SJim Ingham m_breakpoint.Clear(); 18325e09c8c3SJim Ingham m_use_dummy.Clear(); 18335e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 18345e09c8c3SJim Ingham } 18355e09c8c3SJim Ingham 18365e09c8c3SJim Ingham OptionValueString m_name; 18375e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 18385e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 18395e09c8c3SJim Ingham }; 18405e09c8c3SJim Ingham 1841b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 18425e09c8c3SJim Ingham public: 1843b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1844b9c1b51eSKate Stone : CommandObjectParsed( 1845b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 18465e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 1847b9c1b51eSKate Stone m_name_options(), m_option_group() { 1848b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1849b9c1b51eSKate Stone // command. 18505e09c8c3SJim Ingham CommandArgumentEntry arg1; 18515e09c8c3SJim Ingham CommandArgumentData id_arg; 18525e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 18535e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 18545e09c8c3SJim Ingham arg1.push_back(id_arg); 18555e09c8c3SJim Ingham m_arguments.push_back(arg1); 18565e09c8c3SJim Ingham 18575e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 18585e09c8c3SJim Ingham m_option_group.Finalize(); 18595e09c8c3SJim Ingham } 18605e09c8c3SJim Ingham 18619e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 18625e09c8c3SJim Ingham 1863b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 18645e09c8c3SJim Ingham 18655e09c8c3SJim Ingham protected: 1866b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1867b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 18685e09c8c3SJim Ingham result.SetError("No name option provided."); 18695e09c8c3SJim Ingham return false; 18705e09c8c3SJim Ingham } 18715e09c8c3SJim Ingham 1872b9c1b51eSKate Stone Target *target = 1873b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 18745e09c8c3SJim Ingham 1875b9c1b51eSKate Stone if (target == nullptr) { 18765e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 18775e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18785e09c8c3SJim Ingham return false; 18795e09c8c3SJim Ingham } 18805e09c8c3SJim Ingham 1881bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1882bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 18835e09c8c3SJim Ingham 18845e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 18855e09c8c3SJim Ingham 18865e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1887b9c1b51eSKate Stone if (num_breakpoints == 0) { 18885e09c8c3SJim Ingham result.SetError("No breakpoints, cannot add names."); 18895e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18905e09c8c3SJim Ingham return false; 18915e09c8c3SJim Ingham } 18925e09c8c3SJim Ingham 18935e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 18945e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1895b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1896b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 18975e09c8c3SJim Ingham 1898b9c1b51eSKate Stone if (result.Succeeded()) { 1899b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 19005e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot add names."); 19015e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19025e09c8c3SJim Ingham return false; 19035e09c8c3SJim Ingham } 19045e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1905b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1906b9c1b51eSKate Stone lldb::break_id_t bp_id = 1907b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 19085e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1909b9c1b51eSKate Stone Error error; // We don't need to check the error here, since the option 1910b9c1b51eSKate Stone // parser checked it... 19115e09c8c3SJim Ingham bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error); 19125e09c8c3SJim Ingham } 19135e09c8c3SJim Ingham } 19145e09c8c3SJim Ingham 19155e09c8c3SJim Ingham return true; 19165e09c8c3SJim Ingham } 19175e09c8c3SJim Ingham 19185e09c8c3SJim Ingham private: 19195e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19205e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19215e09c8c3SJim Ingham }; 19225e09c8c3SJim Ingham 1923b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 19245e09c8c3SJim Ingham public: 1925b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1926b9c1b51eSKate Stone : CommandObjectParsed( 1927b9c1b51eSKate Stone interpreter, "delete", 19285e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 19295e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 1930b9c1b51eSKate Stone m_name_options(), m_option_group() { 1931b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1932b9c1b51eSKate Stone // command. 19335e09c8c3SJim Ingham CommandArgumentEntry arg1; 19345e09c8c3SJim Ingham CommandArgumentData id_arg; 19355e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 19365e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 19375e09c8c3SJim Ingham arg1.push_back(id_arg); 19385e09c8c3SJim Ingham m_arguments.push_back(arg1); 19395e09c8c3SJim Ingham 19405e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 19415e09c8c3SJim Ingham m_option_group.Finalize(); 19425e09c8c3SJim Ingham } 19435e09c8c3SJim Ingham 19449e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 19455e09c8c3SJim Ingham 1946b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19475e09c8c3SJim Ingham 19485e09c8c3SJim Ingham protected: 1949b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1950b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 19515e09c8c3SJim Ingham result.SetError("No name option provided."); 19525e09c8c3SJim Ingham return false; 19535e09c8c3SJim Ingham } 19545e09c8c3SJim Ingham 1955b9c1b51eSKate Stone Target *target = 1956b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19575e09c8c3SJim Ingham 1958b9c1b51eSKate Stone if (target == nullptr) { 19595e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 19605e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19615e09c8c3SJim Ingham return false; 19625e09c8c3SJim Ingham } 19635e09c8c3SJim Ingham 1964bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1965bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 19665e09c8c3SJim Ingham 19675e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 19685e09c8c3SJim Ingham 19695e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1970b9c1b51eSKate Stone if (num_breakpoints == 0) { 19715e09c8c3SJim Ingham result.SetError("No breakpoints, cannot delete names."); 19725e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19735e09c8c3SJim Ingham return false; 19745e09c8c3SJim Ingham } 19755e09c8c3SJim Ingham 19765e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 19775e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1978b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1979b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 19805e09c8c3SJim Ingham 1981b9c1b51eSKate Stone if (result.Succeeded()) { 1982b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 19835e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot delete names."); 19845e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19855e09c8c3SJim Ingham return false; 19865e09c8c3SJim Ingham } 19875e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1988b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1989b9c1b51eSKate Stone lldb::break_id_t bp_id = 1990b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 19915e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 19925e09c8c3SJim Ingham bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue()); 19935e09c8c3SJim Ingham } 19945e09c8c3SJim Ingham } 19955e09c8c3SJim Ingham 19965e09c8c3SJim Ingham return true; 19975e09c8c3SJim Ingham } 19985e09c8c3SJim Ingham 19995e09c8c3SJim Ingham private: 20005e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20015e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20025e09c8c3SJim Ingham }; 20035e09c8c3SJim Ingham 2004b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 20055e09c8c3SJim Ingham public: 2006b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 2007b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 2008b9c1b51eSKate Stone "List either the names for a breakpoint or the " 2009b9c1b51eSKate Stone "breakpoints for a given name.", 20105e09c8c3SJim Ingham "breakpoint name list <command-options>"), 2011b9c1b51eSKate Stone m_name_options(), m_option_group() { 20125e09c8c3SJim Ingham m_option_group.Append(&m_name_options); 20135e09c8c3SJim Ingham m_option_group.Finalize(); 20145e09c8c3SJim Ingham } 20155e09c8c3SJim Ingham 20169e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 20175e09c8c3SJim Ingham 2018b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 20195e09c8c3SJim Ingham 20205e09c8c3SJim Ingham protected: 2021b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2022b9c1b51eSKate Stone Target *target = 2023b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 20245e09c8c3SJim Ingham 2025b9c1b51eSKate Stone if (target == nullptr) { 20265e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 20275e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20285e09c8c3SJim Ingham return false; 20295e09c8c3SJim Ingham } 20305e09c8c3SJim Ingham 2031b9c1b51eSKate Stone if (m_name_options.m_name.OptionWasSet()) { 20325e09c8c3SJim Ingham const char *name = m_name_options.m_name.GetCurrentValue(); 2033bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2034bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 20355e09c8c3SJim Ingham 20365e09c8c3SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 2037b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2038b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 20395e09c8c3SJim Ingham StreamString s; 20405e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 20415e09c8c3SJim Ingham s.EOL(); 20425e09c8c3SJim Ingham result.AppendMessage(s.GetData()); 20435e09c8c3SJim Ingham } 20445e09c8c3SJim Ingham } 20455e09c8c3SJim Ingham 2046b9c1b51eSKate Stone } else if (m_name_options.m_breakpoint.OptionWasSet()) { 2047b9c1b51eSKate Stone BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID( 2048b9c1b51eSKate Stone m_name_options.m_breakpoint.GetCurrentValue()); 2049b9c1b51eSKate Stone if (bp_sp) { 20505e09c8c3SJim Ingham std::vector<std::string> names; 20515e09c8c3SJim Ingham bp_sp->GetNames(names); 20525e09c8c3SJim Ingham result.AppendMessage("Names:"); 20535e09c8c3SJim Ingham for (auto name : names) 20545e09c8c3SJim Ingham result.AppendMessageWithFormat(" %s\n", name.c_str()); 2055b9c1b51eSKate Stone } else { 2056b9c1b51eSKate Stone result.AppendErrorWithFormat( 2057b9c1b51eSKate Stone "Could not find breakpoint %" PRId64 ".\n", 20585e09c8c3SJim Ingham m_name_options.m_breakpoint.GetCurrentValue()); 20595e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20605e09c8c3SJim Ingham return false; 20615e09c8c3SJim Ingham } 2062b9c1b51eSKate Stone } else { 20635e09c8c3SJim Ingham result.SetError("Must specify -N or -B option to list."); 20645e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20655e09c8c3SJim Ingham return false; 20665e09c8c3SJim Ingham } 20675e09c8c3SJim Ingham return true; 20685e09c8c3SJim Ingham } 20695e09c8c3SJim Ingham 20705e09c8c3SJim Ingham private: 20715e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20725e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20735e09c8c3SJim Ingham }; 20745e09c8c3SJim Ingham 20755e09c8c3SJim Ingham //------------------------------------------------------------------------- 2076e14dc268SJim Ingham // CommandObjectBreakpointName 20775e09c8c3SJim Ingham //------------------------------------------------------------------------- 2078b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 20795e09c8c3SJim Ingham public: 20807428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2081b9c1b51eSKate Stone : CommandObjectMultiword( 2082b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2083b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2084b9c1b51eSKate Stone CommandObjectSP add_command_object( 2085b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2086b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2087b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2088b9c1b51eSKate Stone CommandObjectSP list_command_object( 2089b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 20905e09c8c3SJim Ingham 20915e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 20925e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 20935e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 20945e09c8c3SJim Ingham } 20955e09c8c3SJim Ingham 20969e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 20975e09c8c3SJim Ingham }; 20985e09c8c3SJim Ingham 20995e09c8c3SJim Ingham //------------------------------------------------------------------------- 2100e14dc268SJim Ingham // CommandObjectBreakpointRead 2101e14dc268SJim Ingham //------------------------------------------------------------------------- 2102e14dc268SJim Ingham #pragma mark Restore 2103e14dc268SJim Ingham 2104e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed { 2105e14dc268SJim Ingham public: 2106e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2107e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read", 2108e14dc268SJim Ingham "Read and set the breakpoints previously saved to " 2109e14dc268SJim Ingham "a file with \"breakpoint write\". ", 2110e14dc268SJim Ingham nullptr), 2111e14dc268SJim Ingham m_options() { 2112e14dc268SJim Ingham CommandArgumentEntry arg; 2113e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2114e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2115e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2116e14dc268SJim Ingham // arguments vector. 2117e14dc268SJim Ingham m_arguments.push_back(arg); 2118e14dc268SJim Ingham } 2119e14dc268SJim Ingham 2120e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default; 2121e14dc268SJim Ingham 2122e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2123e14dc268SJim Ingham 2124e14dc268SJim Ingham class CommandOptions : public Options { 2125e14dc268SJim Ingham public: 2126e14dc268SJim Ingham CommandOptions() : Options() {} 2127e14dc268SJim Ingham 2128e14dc268SJim Ingham ~CommandOptions() override = default; 2129e14dc268SJim Ingham 2130e14dc268SJim Ingham Error SetOptionValue(uint32_t option_idx, const char *option_arg, 2131e14dc268SJim Ingham ExecutionContext *execution_context) override { 2132e14dc268SJim Ingham Error error; 2133e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2134e14dc268SJim Ingham 2135e14dc268SJim Ingham switch (short_option) { 2136e14dc268SJim Ingham case 'f': 2137e14dc268SJim Ingham m_filename.assign(option_arg); 2138e14dc268SJim Ingham break; 2139e14dc268SJim Ingham default: 2140e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2141e14dc268SJim Ingham short_option); 2142e14dc268SJim Ingham break; 2143e14dc268SJim Ingham } 2144e14dc268SJim Ingham 2145e14dc268SJim Ingham return error; 2146e14dc268SJim Ingham } 2147e14dc268SJim Ingham 2148e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2149e14dc268SJim Ingham m_filename.clear(); 2150e14dc268SJim Ingham } 2151e14dc268SJim Ingham 2152e14dc268SJim Ingham const OptionDefinition *GetDefinitions() override { return g_option_table; } 2153e14dc268SJim Ingham 2154e14dc268SJim Ingham // Options table: Required for subclasses of Options. 2155e14dc268SJim Ingham 2156e14dc268SJim Ingham static OptionDefinition g_option_table[]; 2157e14dc268SJim Ingham 2158e14dc268SJim Ingham // Instance variables to hold the values for command options. 2159e14dc268SJim Ingham 2160e14dc268SJim Ingham std::string m_filename; 2161e14dc268SJim Ingham }; 2162e14dc268SJim Ingham 2163e14dc268SJim Ingham protected: 2164e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2165e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2166e14dc268SJim Ingham if (target == nullptr) { 2167e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2168e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2169e14dc268SJim Ingham return false; 2170e14dc268SJim Ingham } 2171e14dc268SJim Ingham 2172e14dc268SJim Ingham FileSpec input_spec(m_options.m_filename, true); 217301f16664SJim Ingham BreakpointIDList new_bps; 217401f16664SJim Ingham Error error = target->CreateBreakpointsFromFile(input_spec, new_bps); 2175e14dc268SJim Ingham 2176e14dc268SJim Ingham if (!error.Success()) { 217701f16664SJim Ingham result.AppendError(error.AsCString()); 2178e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 217901f16664SJim Ingham return false; 2180e14dc268SJim Ingham } 218101f16664SJim Ingham // FIXME: Report the newly created breakpoints. 2182e14dc268SJim Ingham return result.Succeeded(); 2183e14dc268SJim Ingham } 2184e14dc268SJim Ingham 2185e14dc268SJim Ingham private: 2186e14dc268SJim Ingham CommandOptions m_options; 2187e14dc268SJim Ingham }; 2188e14dc268SJim Ingham 2189e14dc268SJim Ingham #pragma mark Modify::CommandOptions 2190e14dc268SJim Ingham OptionDefinition CommandObjectBreakpointRead::CommandOptions::g_option_table[] = 2191e14dc268SJim Ingham { 2192e14dc268SJim Ingham // clang-format off 2193e14dc268SJim Ingham {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints."}, 2194e14dc268SJim Ingham {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 2195e14dc268SJim Ingham // clang-format on 2196e14dc268SJim Ingham }; 2197e14dc268SJim Ingham 2198e14dc268SJim Ingham //------------------------------------------------------------------------- 2199e14dc268SJim Ingham // CommandObjectBreakpointWrite 2200e14dc268SJim Ingham //------------------------------------------------------------------------- 2201e14dc268SJim Ingham #pragma mark Save 2202e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed { 2203e14dc268SJim Ingham public: 2204e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2205e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write", 2206e14dc268SJim Ingham "Write the breakpoints listed to a file that can " 2207e14dc268SJim Ingham "be read in with \"breakpoint read\". " 2208e14dc268SJim Ingham "If given no arguments, writes all breakpoints.", 2209e14dc268SJim Ingham nullptr), 2210e14dc268SJim Ingham m_options() { 2211e14dc268SJim Ingham CommandArgumentEntry arg; 2212e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2213e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2214e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2215e14dc268SJim Ingham // arguments vector. 2216e14dc268SJim Ingham m_arguments.push_back(arg); 2217e14dc268SJim Ingham } 2218e14dc268SJim Ingham 2219e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default; 2220e14dc268SJim Ingham 2221e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2222e14dc268SJim Ingham 2223e14dc268SJim Ingham class CommandOptions : public Options { 2224e14dc268SJim Ingham public: 2225e14dc268SJim Ingham CommandOptions() : Options() {} 2226e14dc268SJim Ingham 2227e14dc268SJim Ingham ~CommandOptions() override = default; 2228e14dc268SJim Ingham 2229e14dc268SJim Ingham Error SetOptionValue(uint32_t option_idx, const char *option_arg, 2230e14dc268SJim Ingham ExecutionContext *execution_context) override { 2231e14dc268SJim Ingham Error error; 2232e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2233e14dc268SJim Ingham 2234e14dc268SJim Ingham switch (short_option) { 2235e14dc268SJim Ingham case 'f': 2236e14dc268SJim Ingham m_filename.assign(option_arg); 2237e14dc268SJim Ingham break; 2238e14dc268SJim Ingham default: 2239e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2240e14dc268SJim Ingham short_option); 2241e14dc268SJim Ingham break; 2242e14dc268SJim Ingham } 2243e14dc268SJim Ingham 2244e14dc268SJim Ingham return error; 2245e14dc268SJim Ingham } 2246e14dc268SJim Ingham 2247e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2248e14dc268SJim Ingham m_filename.clear(); 2249e14dc268SJim Ingham } 2250e14dc268SJim Ingham 2251e14dc268SJim Ingham const OptionDefinition *GetDefinitions() override { return g_option_table; } 2252e14dc268SJim Ingham 2253e14dc268SJim Ingham // Options table: Required for subclasses of Options. 2254e14dc268SJim Ingham 2255e14dc268SJim Ingham static OptionDefinition g_option_table[]; 2256e14dc268SJim Ingham 2257e14dc268SJim Ingham // Instance variables to hold the values for command options. 2258e14dc268SJim Ingham 2259e14dc268SJim Ingham std::string m_filename; 2260e14dc268SJim Ingham }; 2261e14dc268SJim Ingham 2262e14dc268SJim Ingham protected: 2263e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2264e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2265e14dc268SJim Ingham if (target == nullptr) { 2266e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2267e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2268e14dc268SJim Ingham return false; 2269e14dc268SJim Ingham } 2270e14dc268SJim Ingham 2271e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2272e14dc268SJim Ingham target->GetBreakpointList().GetListMutex(lock); 2273e14dc268SJim Ingham 2274e14dc268SJim Ingham BreakpointIDList valid_bp_ids; 227501f16664SJim Ingham if (command.GetArgumentCount() > 0) { 2276e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2277e14dc268SJim Ingham command, target, result, &valid_bp_ids); 2278e14dc268SJim Ingham 227901f16664SJim Ingham if (!result.Succeeded()) { 2280e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2281e14dc268SJim Ingham return false; 2282e14dc268SJim Ingham } 2283e14dc268SJim Ingham } 228401f16664SJim Ingham Error error = target->SerializeBreakpointsToFile( 228501f16664SJim Ingham FileSpec(m_options.m_filename.c_str(), true), valid_bp_ids); 228601f16664SJim Ingham if (!error.Success()) { 228701f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.", 228801f16664SJim Ingham error.AsCString()); 228901f16664SJim Ingham result.SetStatus(eReturnStatusFailed); 2290e14dc268SJim Ingham } 2291e14dc268SJim Ingham return result.Succeeded(); 2292e14dc268SJim Ingham } 2293e14dc268SJim Ingham 2294e14dc268SJim Ingham private: 2295e14dc268SJim Ingham CommandOptions m_options; 2296e14dc268SJim Ingham }; 2297e14dc268SJim Ingham 2298e14dc268SJim Ingham #pragma mark Modify::CommandOptions 2299e14dc268SJim Ingham OptionDefinition 2300e14dc268SJim Ingham CommandObjectBreakpointWrite::CommandOptions::g_option_table[] = { 2301e14dc268SJim Ingham // clang-format off 2302e14dc268SJim Ingham {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints."}, 2303e14dc268SJim Ingham {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr} 2304e14dc268SJim Ingham // clang-format on 2305e14dc268SJim Ingham }; 2306e14dc268SJim Ingham 2307e14dc268SJim Ingham //------------------------------------------------------------------------- 230830fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 230930fdc8d8SChris Lattner //------------------------------------------------------------------------- 2310ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 231130fdc8d8SChris Lattner 2312b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2313b9c1b51eSKate Stone CommandInterpreter &interpreter) 2314b9c1b51eSKate Stone : CommandObjectMultiword( 2315b9c1b51eSKate Stone interpreter, "breakpoint", 23167428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2317b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2318b9c1b51eSKate Stone CommandObjectSP list_command_object( 2319b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2320b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2321b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2322b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2323b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2324b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2325b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2326b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2327b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2328b9c1b51eSKate Stone CommandObjectSP set_command_object( 2329b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2330b9c1b51eSKate Stone CommandObjectSP command_command_object( 2331b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2332b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2333b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2334b9c1b51eSKate Stone CommandObjectSP name_command_object( 2335b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 2336e14dc268SJim Ingham CommandObjectSP write_command_object( 2337e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter)); 2338e14dc268SJim Ingham CommandObjectSP read_command_object( 2339e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter)); 234030fdc8d8SChris Lattner 2341b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 234230fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 234330fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2344b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2345b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2346ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2347b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2348b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 23495e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 2350e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write"); 2351e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read"); 235230fdc8d8SChris Lattner 235323f59509SGreg Clayton LoadSubCommand("list", list_command_object); 235423f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 235523f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 235623f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 235723f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 235823f59509SGreg Clayton LoadSubCommand("set", set_command_object); 235923f59509SGreg Clayton LoadSubCommand("command", command_command_object); 236023f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 23615e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 2362e14dc268SJim Ingham LoadSubCommand("write", write_command_object); 2363e14dc268SJim Ingham LoadSubCommand("read", read_command_object); 236430fdc8d8SChris Lattner } 236530fdc8d8SChris Lattner 23669e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 236730fdc8d8SChris Lattner 2368b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, 23695e09c8c3SJim Ingham bool allow_locations, 23705e09c8c3SJim Ingham CommandReturnObject &result, 2371b9c1b51eSKate Stone BreakpointIDList *valid_ids) { 237230fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2373b9c1b51eSKate Stone // 2). the full breakpoint & location 2374b9c1b51eSKate Stone // canonical representation 2375b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2376b9c1b51eSKate Stone // representing a range (in which case there 2377b9c1b51eSKate Stone // had *better* be an entry both before & 2378b9c1b51eSKate Stone // after of one of the first two types. 23795e09c8c3SJim Ingham // 4). A breakpoint name 2380b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2381b9c1b51eSKate Stone // one.) 238230fdc8d8SChris Lattner 238330fdc8d8SChris Lattner Args temp_args; 238430fdc8d8SChris Lattner 2385b9c1b51eSKate Stone if (args.GetArgumentCount() == 0) { 2386b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2387b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2388b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 238936f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2390b9c1b51eSKate Stone } else { 2391b9c1b51eSKate Stone result.AppendError( 2392b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 239336f3b369SJim Ingham result.SetStatus(eReturnStatusFailed); 239436f3b369SJim Ingham } 239536f3b369SJim Ingham return; 239636f3b369SJim Ingham } 239736f3b369SJim Ingham 2398b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 2399b9c1b51eSKate Stone // directly from the old ARGS to 2400b9c1b51eSKate Stone // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead 2401b9c1b51eSKate Stone // generate a list of strings for 2402b9c1b51eSKate Stone // all the breakpoint ids in the range, and shove all of those breakpoint id 2403b9c1b51eSKate Stone // strings into TEMP_ARGS. 240430fdc8d8SChris Lattner 2405b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2406b9c1b51eSKate Stone result, temp_args); 240730fdc8d8SChris Lattner 2408b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2409b9c1b51eSKate Stone // BreakpointIDList: 241030fdc8d8SChris Lattner 2411b9c1b51eSKate Stone valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(), 2412b9c1b51eSKate Stone temp_args.GetArgumentCount(), result); 241330fdc8d8SChris Lattner 2414b9c1b51eSKate Stone // At this point, all of the breakpoint ids that the user passed in have been 2415b9c1b51eSKate Stone // converted to breakpoint IDs 241630fdc8d8SChris Lattner // and put into valid_ids. 241730fdc8d8SChris Lattner 2418b9c1b51eSKate Stone if (result.Succeeded()) { 2419b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 2420b9c1b51eSKate Stone // ids, go through our tentative list 2421b9c1b51eSKate Stone // of breakpoint id's and verify that they correspond to valid/currently set 2422b9c1b51eSKate Stone // breakpoints. 242330fdc8d8SChris Lattner 2424c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2425b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 242630fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2427b9c1b51eSKate Stone Breakpoint *breakpoint = 2428b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2429b9c1b51eSKate Stone if (breakpoint != nullptr) { 2430c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2431b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 243230fdc8d8SChris Lattner StreamString id_str; 2433b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2434b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2435c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2436b9c1b51eSKate Stone result.AppendErrorWithFormat( 2437b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 243830fdc8d8SChris Lattner id_str.GetData()); 243930fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 244030fdc8d8SChris Lattner } 2441b9c1b51eSKate Stone } else { 2442c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2443b9c1b51eSKate Stone result.AppendErrorWithFormat( 2444b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 24457428a18cSKate Stone cur_bp_id.GetBreakpointID()); 244630fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 244730fdc8d8SChris Lattner } 244830fdc8d8SChris Lattner } 244930fdc8d8SChris Lattner } 245030fdc8d8SChris Lattner } 2451