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 481f0f5b5bSZachary Turner // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to 491f0f5b5bSZachary Turner // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. 501f0f5b5bSZachary Turner #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2) 511f0f5b5bSZachary Turner #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10) 521f0f5b5bSZachary Turner #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 531f0f5b5bSZachary Turner #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 541f0f5b5bSZachary Turner #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) 551f0f5b5bSZachary Turner #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) 561f0f5b5bSZachary Turner 571f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_set_options[] = { 581f0f5b5bSZachary Turner // clang-format off 591f0f5b5bSZachary Turner { 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 " 601f0f5b5bSZachary Turner "multiple times to specify multiple shared libraries." }, 611f0f5b5bSZachary Turner { 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." }, 621f0f5b5bSZachary Turner { 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." }, 631f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, 641f0f5b5bSZachary Turner { 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." }, 651f0f5b5bSZachary Turner { 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." }, 661f0f5b5bSZachary Turner { 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 " 671f0f5b5bSZachary Turner "argument." }, 681f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." }, 691f0f5b5bSZachary Turner { 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 " 701f0f5b5bSZachary Turner "this argument." }, 711f0f5b5bSZachary Turner { 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 " 721f0f5b5bSZachary Turner "lldb only looks for files that are #included if they use the standard include " 731f0f5b5bSZachary Turner "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " 741f0f5b5bSZachary Turner "#included, set target.inline-breakpoint-strategy to \"always\"." }, 751f0f5b5bSZachary Turner { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." }, 761f0f5b5bSZachary Turner 771f0f5b5bSZachary Turner // Comment out this option for the moment, as we don't actually use it, but will in the future. 781f0f5b5bSZachary Turner // This way users won't see it, but the infrastructure is left in place. 791f0f5b5bSZachary Turner // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>", 801f0f5b5bSZachary Turner // "Set the breakpoint by source location at this particular column."}, 811f0f5b5bSZachary Turner 821f0f5b5bSZachary Turner { 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 " 831f0f5b5bSZachary Turner "a particular binary, then the address will be converted to a \"file\" " 841f0f5b5bSZachary Turner "address, so that the breakpoint will track that binary+offset no matter where " 851f0f5b5bSZachary Turner "the binary eventually loads. Alternately, if you also specify the module - " 861f0f5b5bSZachary Turner "with the -s option - then the address will be treated as a file address in " 871f0f5b5bSZachary Turner "that module, and resolved accordingly. Again, this will allow lldb to track " 881f0f5b5bSZachary Turner "that offset on subsequent reloads. The module need not have been loaded at " 891f0f5b5bSZachary Turner "the time you specify this breakpoint, and will get resolved when the module " 901f0f5b5bSZachary Turner "is loaded." }, 911f0f5b5bSZachary Turner { 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 " 921f0f5b5bSZachary Turner "one breakpoint for multiple names" }, 931f0f5b5bSZachary Turner { 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 " 941f0f5b5bSZachary Turner "functions. Can be repeated multiple times." }, 951f0f5b5bSZachary Turner { 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 " 961f0f5b5bSZachary Turner "namespaces and all arguments, and for Objective C this means a full function " 971f0f5b5bSZachary Turner "prototype with class and selector. Can be repeated multiple times to make " 981f0f5b5bSZachary Turner "one breakpoint for multiple names." }, 991f0f5b5bSZachary Turner { 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 " 1001f0f5b5bSZachary Turner "make one breakpoint for multiple Selectors." }, 1011f0f5b5bSZachary Turner { 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 " 1021f0f5b5bSZachary Turner "make one breakpoint for multiple methods." }, 1031f0f5b5bSZachary Turner { 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 " 1041f0f5b5bSZachary Turner "the function name(s)." }, 1051f0f5b5bSZachary Turner { 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 " 1061f0f5b5bSZachary Turner "ignored). Can be repeated multiple times to make one breakpoint for multiple " 1071f0f5b5bSZachary Turner "symbols." }, 1081f0f5b5bSZachary Turner { 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 " 1091f0f5b5bSZachary Turner "against the source text in a source file or files specified with the -f " 1101f0f5b5bSZachary Turner "option. The -f option can be specified more than once. If no source files " 1111f0f5b5bSZachary Turner "are specified, uses the current \"default source file\". If you want to " 1121f0f5b5bSZachary Turner "match against all source files, pass the \"--all-files\" option." }, 1131f0f5b5bSZachary Turner { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches." }, 1141f0f5b5bSZachary Turner { 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 " 1151f0f5b5bSZachary Turner "options, on throw but not catch.)" }, 1161f0f5b5bSZachary Turner { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." }, 1171f0f5b5bSZachary Turner { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, 1181f0f5b5bSZachary Turner 1191f0f5b5bSZachary Turner // Don't add this option till it actually does something useful... 1201f0f5b5bSZachary Turner // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, 1211f0f5b5bSZachary Turner // "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" }, 1221f0f5b5bSZachary Turner 1231f0f5b5bSZachary Turner { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression " 1241f0f5b5bSZachary Turner "(note: currently only implemented for setting breakpoints on identifiers). " 1251f0f5b5bSZachary Turner "If not set the target.language setting is used." }, 1261f0f5b5bSZachary Turner { 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. " 1271f0f5b5bSZachary Turner "If not set the target.skip-prologue setting is used." }, 1281f0f5b5bSZachary Turner { 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, " 1291f0f5b5bSZachary Turner "which prime new targets." }, 1301f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." }, 1311f0f5b5bSZachary Turner { 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. " 1321f0f5b5bSZachary Turner "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." }, 1331f0f5b5bSZachary Turner { 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 " 1341f0f5b5bSZachary Turner "setting is used." }, 1351f0f5b5bSZachary Turner // clang-format on 1361f0f5b5bSZachary Turner }; 1371f0f5b5bSZachary Turner 13830fdc8d8SChris Lattner //------------------------------------------------------------------------- 1395a988416SJim Ingham // CommandObjectBreakpointSet 14030fdc8d8SChris Lattner //------------------------------------------------------------------------- 14130fdc8d8SChris Lattner 142b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 1435a988416SJim Ingham public: 144b9c1b51eSKate Stone typedef enum BreakpointSetType { 1455a988416SJim Ingham eSetTypeInvalid, 1465a988416SJim Ingham eSetTypeFileAndLine, 1475a988416SJim Ingham eSetTypeAddress, 1485a988416SJim Ingham eSetTypeFunctionName, 1495a988416SJim Ingham eSetTypeFunctionRegexp, 1505a988416SJim Ingham eSetTypeSourceRegexp, 1515a988416SJim Ingham eSetTypeException 1525a988416SJim Ingham } BreakpointSetType; 1535a988416SJim Ingham 154b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 155b9c1b51eSKate Stone : CommandObjectParsed( 156b9c1b51eSKate Stone interpreter, "breakpoint set", 1575a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 1585a988416SJim Ingham "breakpoint set <cmd-options>"), 159b9c1b51eSKate Stone m_options() {} 1605a988416SJim Ingham 1619e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 1625a988416SJim Ingham 163b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 1645a988416SJim Ingham 165b9c1b51eSKate Stone class CommandOptions : public Options { 1665a988416SJim Ingham public: 167b9c1b51eSKate Stone CommandOptions() 168b9c1b51eSKate Stone : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0), 169b9c1b51eSKate Stone m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone), 170b9c1b51eSKate Stone m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(), 171b9c1b51eSKate Stone m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), 172b9c1b51eSKate Stone m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(), 173b9c1b51eSKate Stone m_catch_bp(false), m_throw_bp(true), m_hardware(false), 174a72b31c7SJim Ingham m_exception_language(eLanguageTypeUnknown), 17523b1decbSDawn Perchik m_language(lldb::eLanguageTypeUnknown), 176b9c1b51eSKate Stone m_skip_prologue(eLazyBoolCalculate), m_one_shot(false), 177b9c1b51eSKate Stone m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {} 17830fdc8d8SChris Lattner 1799e85e5a8SEugene Zelenko ~CommandOptions() override = default; 18087df91b8SJim Ingham 181b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 182b9c1b51eSKate Stone ExecutionContext *execution_context) override { 18330fdc8d8SChris Lattner Error error; 1843bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1856fa7681bSZachary Turner llvm::StringRef option_strref(option_arg ? option_arg : ""); 18630fdc8d8SChris Lattner 187b9c1b51eSKate Stone switch (short_option) { 188b9c1b51eSKate Stone case 'a': { 189b9c1b51eSKate Stone m_load_addr = Args::StringToAddress(execution_context, option_arg, 190e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 191b9c1b51eSKate Stone } break; 19230fdc8d8SChris Lattner 193e732052fSJim Ingham case 'A': 194e732052fSJim Ingham m_all_files = true; 195e732052fSJim Ingham break; 196e732052fSJim Ingham 197ca36cd16SJim Ingham case 'b': 198ca36cd16SJim Ingham m_func_names.push_back(option_arg); 199ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 200ca36cd16SJim Ingham break; 201ca36cd16SJim Ingham 202b9c1b51eSKate Stone case 'C': { 2036312991cSJim Ingham bool success; 2046312991cSJim Ingham m_column = StringConvert::ToUInt32(option_arg, 0, 0, &success); 2056312991cSJim Ingham if (!success) 206b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 207b9c1b51eSKate Stone option_arg); 20830fdc8d8SChris Lattner break; 2096312991cSJim Ingham } 2109e85e5a8SEugene Zelenko 2117d49c9c8SJohnny Chen case 'c': 2127d49c9c8SJohnny Chen m_condition.assign(option_arg); 2137d49c9c8SJohnny Chen break; 2147d49c9c8SJohnny Chen 21533df7cd3SJim Ingham case 'D': 21633df7cd3SJim Ingham m_use_dummy = true; 21733df7cd3SJim Ingham break; 21833df7cd3SJim Ingham 219b9c1b51eSKate Stone case 'E': { 2208cef4b0bSZachary Turner LanguageType language = 2218cef4b0bSZachary Turner Language::GetLanguageTypeFromString(option_strref); 222fab10e89SJim Ingham 223b9c1b51eSKate Stone switch (language) { 224fab10e89SJim Ingham case eLanguageTypeC89: 225fab10e89SJim Ingham case eLanguageTypeC: 226fab10e89SJim Ingham case eLanguageTypeC99: 2271d0089faSBruce Mitchener case eLanguageTypeC11: 228a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 229fab10e89SJim Ingham break; 230fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 2311d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 2321d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 2332ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 234a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 235fab10e89SJim Ingham break; 236fab10e89SJim Ingham case eLanguageTypeObjC: 237a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 238fab10e89SJim Ingham break; 239fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 240b9c1b51eSKate Stone error.SetErrorStringWithFormat( 241b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 242fab10e89SJim Ingham break; 243fab10e89SJim Ingham case eLanguageTypeUnknown: 244b9c1b51eSKate Stone error.SetErrorStringWithFormat( 245b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 246b9c1b51eSKate Stone option_arg); 247fab10e89SJim Ingham break; 248fab10e89SJim Ingham default: 249b9c1b51eSKate Stone error.SetErrorStringWithFormat( 250b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 251b9c1b51eSKate Stone option_arg); 252fab10e89SJim Ingham } 253b9c1b51eSKate Stone } break; 254ca36cd16SJim Ingham 255ca36cd16SJim Ingham case 'f': 256ca36cd16SJim Ingham m_filenames.AppendIfUnique(FileSpec(option_arg, false)); 257fab10e89SJim Ingham break; 258ca36cd16SJim Ingham 259ca36cd16SJim Ingham case 'F': 260ca36cd16SJim Ingham m_func_names.push_back(option_arg); 261ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 262ca36cd16SJim Ingham break; 263ca36cd16SJim Ingham 264b9c1b51eSKate Stone case 'h': { 265fab10e89SJim Ingham bool success; 266ecbb0bb1SZachary Turner m_catch_bp = Args::StringToBoolean(option_strref, true, &success); 267fab10e89SJim Ingham if (!success) 268b9c1b51eSKate Stone error.SetErrorStringWithFormat( 269b9c1b51eSKate Stone "Invalid boolean value for on-catch option: '%s'", option_arg); 270b9c1b51eSKate Stone } break; 271eb023e75SGreg Clayton 272eb023e75SGreg Clayton case 'H': 273eb023e75SGreg Clayton m_hardware = true; 274eb023e75SGreg Clayton break; 275eb023e75SGreg Clayton 276ca36cd16SJim Ingham case 'i': 2775275aaa0SVince Harron m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 278ca36cd16SJim Ingham if (m_ignore_count == UINT32_MAX) 279b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid ignore count '%s'", 280b9c1b51eSKate Stone option_arg); 281ca36cd16SJim Ingham break; 282ca36cd16SJim Ingham 283b9c1b51eSKate Stone case 'K': { 284a8558b62SJim Ingham bool success; 285a8558b62SJim Ingham bool value; 286ecbb0bb1SZachary Turner value = Args::StringToBoolean(option_strref, true, &success); 287a8558b62SJim Ingham if (value) 288a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 289a8558b62SJim Ingham else 290a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 291a8558b62SJim Ingham 292a8558b62SJim Ingham if (!success) 293b9c1b51eSKate Stone error.SetErrorStringWithFormat( 294b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 295b9c1b51eSKate Stone option_arg); 296b9c1b51eSKate Stone } break; 297ca36cd16SJim Ingham 298b9c1b51eSKate Stone case 'l': { 2996312991cSJim Ingham bool success; 3006312991cSJim Ingham m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success); 3016312991cSJim Ingham if (!success) 302b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 303b9c1b51eSKate Stone option_arg); 304ca36cd16SJim Ingham break; 3056312991cSJim Ingham } 306055ad9beSIlia K 30723b1decbSDawn Perchik case 'L': 3088cef4b0bSZachary Turner m_language = Language::GetLanguageTypeFromString(option_strref); 30923b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 310b9c1b51eSKate Stone error.SetErrorStringWithFormat( 311b9c1b51eSKate Stone "Unknown language type: '%s' for breakpoint", option_arg); 31223b1decbSDawn Perchik break; 31323b1decbSDawn Perchik 314b9c1b51eSKate Stone case 'm': { 315055ad9beSIlia K bool success; 316055ad9beSIlia K bool value; 317ecbb0bb1SZachary Turner value = Args::StringToBoolean(option_strref, true, &success); 318055ad9beSIlia K if (value) 319055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 320055ad9beSIlia K else 321055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 322055ad9beSIlia K 323055ad9beSIlia K if (!success) 324b9c1b51eSKate Stone error.SetErrorStringWithFormat( 325b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 326b9c1b51eSKate Stone option_arg); 327055ad9beSIlia K break; 328055ad9beSIlia K } 329055ad9beSIlia K 330ca36cd16SJim Ingham case 'M': 331ca36cd16SJim Ingham m_func_names.push_back(option_arg); 332ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 333ca36cd16SJim Ingham break; 334ca36cd16SJim Ingham 335ca36cd16SJim Ingham case 'n': 336ca36cd16SJim Ingham m_func_names.push_back(option_arg); 337ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 338ca36cd16SJim Ingham break; 339ca36cd16SJim Ingham 3406fa7681bSZachary Turner case 'N': { 3416fa7681bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_strref, error)) 3425e09c8c3SJim Ingham m_breakpoint_names.push_back(option_arg); 343ff9a91eaSJim Ingham else 344ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 345ff9a91eaSJim Ingham option_arg); 3465e09c8c3SJim Ingham break; 3476fa7681bSZachary Turner } 3485e09c8c3SJim Ingham 349b9c1b51eSKate Stone case 'R': { 3502411167fSJim Ingham lldb::addr_t tmp_offset_addr; 351e1cfbc79STodd Fiala tmp_offset_addr = 352b9c1b51eSKate Stone Args::StringToAddress(execution_context, option_arg, 0, &error); 3532411167fSJim Ingham if (error.Success()) 3542411167fSJim Ingham m_offset_addr = tmp_offset_addr; 355b9c1b51eSKate Stone } break; 3562411167fSJim Ingham 357ca36cd16SJim Ingham case 'o': 358ca36cd16SJim Ingham m_one_shot = true; 359ca36cd16SJim Ingham break; 360ca36cd16SJim Ingham 361a72b31c7SJim Ingham case 'O': 362ecbb0bb1SZachary Turner m_exception_extra_args.AppendArgument(llvm::StringRef("-O")); 363ecbb0bb1SZachary Turner m_exception_extra_args.AppendArgument(option_strref); 364a72b31c7SJim Ingham break; 365a72b31c7SJim Ingham 366ca36cd16SJim Ingham case 'p': 367ca36cd16SJim Ingham m_source_text_regexp.assign(option_arg); 368ca36cd16SJim Ingham break; 369ca36cd16SJim Ingham 370ca36cd16SJim Ingham case 'q': 371ca36cd16SJim Ingham m_queue_name.assign(option_arg); 372ca36cd16SJim Ingham break; 373ca36cd16SJim Ingham 374ca36cd16SJim Ingham case 'r': 375ca36cd16SJim Ingham m_func_regexp.assign(option_arg); 376ca36cd16SJim Ingham break; 377ca36cd16SJim Ingham 378ca36cd16SJim Ingham case 's': 379ca36cd16SJim Ingham m_modules.AppendIfUnique(FileSpec(option_arg, false)); 380ca36cd16SJim Ingham break; 381ca36cd16SJim Ingham 382ca36cd16SJim Ingham case 'S': 383ca36cd16SJim Ingham m_func_names.push_back(option_arg); 384ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 385ca36cd16SJim Ingham break; 386ca36cd16SJim Ingham 387ca36cd16SJim Ingham case 't': 388b9c1b51eSKate Stone m_thread_id = 389b9c1b51eSKate Stone StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 390ca36cd16SJim Ingham if (m_thread_id == LLDB_INVALID_THREAD_ID) 391b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread id string '%s'", 392b9c1b51eSKate Stone option_arg); 393ca36cd16SJim Ingham break; 394ca36cd16SJim Ingham 395ca36cd16SJim Ingham case 'T': 396ca36cd16SJim Ingham m_thread_name.assign(option_arg); 397ca36cd16SJim Ingham break; 398ca36cd16SJim Ingham 399b9c1b51eSKate Stone case 'w': { 400ca36cd16SJim Ingham bool success; 401ecbb0bb1SZachary Turner m_throw_bp = Args::StringToBoolean(option_strref, true, &success); 402ca36cd16SJim Ingham if (!success) 403b9c1b51eSKate Stone error.SetErrorStringWithFormat( 404b9c1b51eSKate Stone "Invalid boolean value for on-throw option: '%s'", option_arg); 405b9c1b51eSKate Stone } break; 406ca36cd16SJim Ingham 407ca36cd16SJim Ingham case 'x': 4085275aaa0SVince Harron m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 409ca36cd16SJim Ingham if (m_thread_id == UINT32_MAX) 410b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread index string '%s'", 411b9c1b51eSKate Stone option_arg); 412ca36cd16SJim Ingham break; 413ca36cd16SJim Ingham 41476bb8d67SJim Ingham case 'X': 41576bb8d67SJim Ingham m_source_regex_func_names.insert(option_arg); 41676bb8d67SJim Ingham break; 41776bb8d67SJim Ingham 41830fdc8d8SChris Lattner default: 419b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 420b9c1b51eSKate Stone short_option); 42130fdc8d8SChris Lattner break; 42230fdc8d8SChris Lattner } 42330fdc8d8SChris Lattner 42430fdc8d8SChris Lattner return error; 42530fdc8d8SChris Lattner } 4269e85e5a8SEugene Zelenko 427b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 4287d49c9c8SJohnny Chen m_condition.clear(); 42987df91b8SJim Ingham m_filenames.Clear(); 43030fdc8d8SChris Lattner m_line_num = 0; 43130fdc8d8SChris Lattner m_column = 0; 432fab10e89SJim Ingham m_func_names.clear(); 4331f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 43430fdc8d8SChris Lattner m_func_regexp.clear(); 4351f746071SGreg Clayton m_source_text_regexp.clear(); 43687df91b8SJim Ingham m_modules.Clear(); 4371f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 4382411167fSJim Ingham m_offset_addr = 0; 439c982c768SGreg Clayton m_ignore_count = 0; 4401b54c88cSJim Ingham m_thread_id = LLDB_INVALID_THREAD_ID; 441c982c768SGreg Clayton m_thread_index = UINT32_MAX; 4421b54c88cSJim Ingham m_thread_name.clear(); 4431b54c88cSJim Ingham m_queue_name.clear(); 444fab10e89SJim Ingham m_catch_bp = false; 445fab10e89SJim Ingham m_throw_bp = true; 446eb023e75SGreg Clayton m_hardware = false; 447a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 44823b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 449a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 450ca36cd16SJim Ingham m_one_shot = false; 45133df7cd3SJim Ingham m_use_dummy = false; 4525e09c8c3SJim Ingham m_breakpoint_names.clear(); 453e732052fSJim Ingham m_all_files = false; 454a72b31c7SJim Ingham m_exception_extra_args.Clear(); 455055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 45676bb8d67SJim Ingham m_source_regex_func_names.clear(); 45730fdc8d8SChris Lattner } 45830fdc8d8SChris Lattner 4591f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 46070602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_set_options); 4611f0f5b5bSZachary Turner } 46230fdc8d8SChris Lattner 4635a988416SJim Ingham // Instance variables to hold the values for command options. 464969795f1SJim Ingham 4655a988416SJim Ingham std::string m_condition; 4665a988416SJim Ingham FileSpecList m_filenames; 4675a988416SJim Ingham uint32_t m_line_num; 4685a988416SJim Ingham uint32_t m_column; 4695a988416SJim Ingham std::vector<std::string> m_func_names; 4705e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 4715a988416SJim Ingham uint32_t m_func_name_type_mask; 4725a988416SJim Ingham std::string m_func_regexp; 4735a988416SJim Ingham std::string m_source_text_regexp; 4745a988416SJim Ingham FileSpecList m_modules; 4755a988416SJim Ingham lldb::addr_t m_load_addr; 4762411167fSJim Ingham lldb::addr_t m_offset_addr; 4775a988416SJim Ingham uint32_t m_ignore_count; 4785a988416SJim Ingham lldb::tid_t m_thread_id; 4795a988416SJim Ingham uint32_t m_thread_index; 4805a988416SJim Ingham std::string m_thread_name; 4815a988416SJim Ingham std::string m_queue_name; 4825a988416SJim Ingham bool m_catch_bp; 4835a988416SJim Ingham bool m_throw_bp; 484eb023e75SGreg Clayton bool m_hardware; // Request to use hardware breakpoints 485a72b31c7SJim Ingham lldb::LanguageType m_exception_language; 48623b1decbSDawn Perchik lldb::LanguageType m_language; 4875a988416SJim Ingham LazyBool m_skip_prologue; 488ca36cd16SJim Ingham bool m_one_shot; 48933df7cd3SJim Ingham bool m_use_dummy; 490e732052fSJim Ingham bool m_all_files; 491a72b31c7SJim Ingham Args m_exception_extra_args; 492055ad9beSIlia K LazyBool m_move_to_nearest_code; 49376bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 4945a988416SJim Ingham }; 4955a988416SJim Ingham 4965a988416SJim Ingham protected: 497b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 49833df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 49933df7cd3SJim Ingham 500b9c1b51eSKate Stone if (target == nullptr) { 501b9c1b51eSKate Stone result.AppendError("Invalid target. Must set target before setting " 502b9c1b51eSKate Stone "breakpoints (see 'target create' command)."); 50330fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 50430fdc8d8SChris Lattner return false; 50530fdc8d8SChris Lattner } 50630fdc8d8SChris Lattner 50730fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 50830fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 50930fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 51030fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 511b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 512b9c1b51eSKate Stone // expression) 513b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 514b9c1b51eSKate Stone // to source text) 515b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 516b9c1b51eSKate Stone // given language.) 51730fdc8d8SChris Lattner 51830fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 51930fdc8d8SChris Lattner 52030fdc8d8SChris Lattner if (m_options.m_line_num != 0) 52130fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 52230fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 52330fdc8d8SChris Lattner break_type = eSetTypeAddress; 524fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 52530fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 52630fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 52730fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 528969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 529969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 530a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 531fab10e89SJim Ingham break_type = eSetTypeException; 53230fdc8d8SChris Lattner 5339e85e5a8SEugene Zelenko Breakpoint *bp = nullptr; 534274060b6SGreg Clayton FileSpec module_spec; 535a8558b62SJim Ingham const bool internal = false; 536a8558b62SJim Ingham 537b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 538b9c1b51eSKate Stone // that off. 539b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 540b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 5412411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 5422411167fSJim Ingham 543b9c1b51eSKate Stone switch (break_type) { 54430fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 54530fdc8d8SChris Lattner { 54630fdc8d8SChris Lattner FileSpec file; 547c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 548b9c1b51eSKate Stone if (num_files == 0) { 549b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 55087df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 55187df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 55287df91b8SJim Ingham return false; 55387df91b8SJim Ingham } 554b9c1b51eSKate Stone } else if (num_files > 1) { 555b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 556b9c1b51eSKate Stone "line breakpoints."); 55787df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 55887df91b8SJim Ingham return false; 559b9c1b51eSKate Stone } else 56087df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 56130fdc8d8SChris Lattner 5621f746071SGreg Clayton // Only check for inline functions if 5631f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 5641f746071SGreg Clayton 565b9c1b51eSKate Stone bp = target 566b9c1b51eSKate Stone ->CreateBreakpoint(&(m_options.m_modules), file, 567b9c1b51eSKate Stone m_options.m_line_num, m_options.m_offset_addr, 568b9c1b51eSKate Stone check_inlines, m_options.m_skip_prologue, 569b9c1b51eSKate Stone internal, m_options.m_hardware, 570b9c1b51eSKate Stone m_options.m_move_to_nearest_code) 571b9c1b51eSKate Stone .get(); 572b9c1b51eSKate Stone } break; 5736eee5aa0SGreg Clayton 57430fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 575055a08a4SJim Ingham { 576b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 577b9c1b51eSKate Stone // with the library, and 578b9c1b51eSKate Stone // use that. That way the address breakpoint will track the load location 579b9c1b51eSKate Stone // of the library. 580055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 581b9c1b51eSKate Stone if (num_modules_specified == 1) { 582b9c1b51eSKate Stone const FileSpec *file_spec = 583b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 584b9c1b51eSKate Stone bp = target 585b9c1b51eSKate Stone ->CreateAddressInModuleBreakpoint(m_options.m_load_addr, 586b9c1b51eSKate Stone internal, file_spec, 587b9c1b51eSKate Stone m_options.m_hardware) 588b9c1b51eSKate Stone .get(); 589b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 590b9c1b51eSKate Stone bp = target 591b9c1b51eSKate Stone ->CreateBreakpoint(m_options.m_load_addr, internal, 592b9c1b51eSKate Stone m_options.m_hardware) 593b9c1b51eSKate Stone .get(); 594b9c1b51eSKate Stone } else { 595b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 596b9c1b51eSKate Stone "address breakpoints."); 597055a08a4SJim Ingham result.SetStatus(eReturnStatusFailed); 598055a08a4SJim Ingham return false; 599055a08a4SJim Ingham } 60030fdc8d8SChris Lattner break; 601055a08a4SJim Ingham } 60230fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 6030c5cd90dSGreg Clayton { 6040c5cd90dSGreg Clayton uint32_t name_type_mask = m_options.m_func_name_type_mask; 6050c5cd90dSGreg Clayton 6060c5cd90dSGreg Clayton if (name_type_mask == 0) 607e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 6080c5cd90dSGreg Clayton 609b9c1b51eSKate Stone bp = target 610b9c1b51eSKate Stone ->CreateBreakpoint( 611b9c1b51eSKate Stone &(m_options.m_modules), &(m_options.m_filenames), 612b9c1b51eSKate Stone m_options.m_func_names, name_type_mask, m_options.m_language, 613b9c1b51eSKate Stone m_options.m_offset_addr, m_options.m_skip_prologue, internal, 614b9c1b51eSKate Stone m_options.m_hardware) 615b9c1b51eSKate Stone .get(); 616b9c1b51eSKate Stone } break; 6170c5cd90dSGreg Clayton 618b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 619b9c1b51eSKate Stone // name 62030fdc8d8SChris Lattner { 62195eae423SZachary Turner RegularExpression regexp(m_options.m_func_regexp); 622b9c1b51eSKate Stone if (!regexp.IsValid()) { 623969795f1SJim Ingham char err_str[1024]; 624969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 625b9c1b51eSKate Stone result.AppendErrorWithFormat( 626b9c1b51eSKate Stone "Function name regular expression could not be compiled: \"%s\"", 627969795f1SJim Ingham err_str); 62830fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 629969795f1SJim Ingham return false; 63030fdc8d8SChris Lattner } 63187df91b8SJim Ingham 632b9c1b51eSKate Stone bp = target 633b9c1b51eSKate Stone ->CreateFuncRegexBreakpoint( 634b9c1b51eSKate Stone &(m_options.m_modules), &(m_options.m_filenames), regexp, 635b9c1b51eSKate Stone m_options.m_language, m_options.m_skip_prologue, internal, 636b9c1b51eSKate Stone m_options.m_hardware) 637b9c1b51eSKate Stone .get(); 638e14dc268SJim Ingham } 639e14dc268SJim Ingham break; 640969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 641969795f1SJim Ingham { 642c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 64387df91b8SJim Ingham 644b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 645969795f1SJim Ingham FileSpec file; 646b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 647b9c1b51eSKate Stone result.AppendError( 648b9c1b51eSKate Stone "No files provided and could not find default file."); 64987df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 65087df91b8SJim Ingham return false; 651b9c1b51eSKate Stone } else { 65287df91b8SJim Ingham m_options.m_filenames.Append(file); 65387df91b8SJim Ingham } 65487df91b8SJim Ingham } 6550c5cd90dSGreg Clayton 65695eae423SZachary Turner RegularExpression regexp(m_options.m_source_text_regexp); 657b9c1b51eSKate Stone if (!regexp.IsValid()) { 658969795f1SJim Ingham char err_str[1024]; 659969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 660b9c1b51eSKate Stone result.AppendErrorWithFormat( 661b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"", 662969795f1SJim Ingham err_str); 663969795f1SJim Ingham result.SetStatus(eReturnStatusFailed); 664969795f1SJim Ingham return false; 665969795f1SJim Ingham } 666b9c1b51eSKate Stone bp = target 667b9c1b51eSKate Stone ->CreateSourceRegexBreakpoint( 668b9c1b51eSKate Stone &(m_options.m_modules), &(m_options.m_filenames), 669b9c1b51eSKate Stone m_options.m_source_regex_func_names, regexp, internal, 670b9c1b51eSKate Stone m_options.m_hardware, m_options.m_move_to_nearest_code) 671b9c1b51eSKate Stone .get(); 672b9c1b51eSKate Stone } break; 673b9c1b51eSKate Stone case eSetTypeException: { 674a72b31c7SJim Ingham Error precond_error; 675b9c1b51eSKate Stone bp = target 676b9c1b51eSKate Stone ->CreateExceptionBreakpoint( 677b9c1b51eSKate Stone m_options.m_exception_language, m_options.m_catch_bp, 678b9c1b51eSKate Stone m_options.m_throw_bp, internal, 679b9c1b51eSKate Stone &m_options.m_exception_extra_args, &precond_error) 680b9c1b51eSKate Stone .get(); 681b9c1b51eSKate Stone if (precond_error.Fail()) { 682b9c1b51eSKate Stone result.AppendErrorWithFormat( 683b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 684a72b31c7SJim Ingham precond_error.AsCString()); 685a72b31c7SJim Ingham target->RemoveBreakpointByID(bp->GetID()); 686a72b31c7SJim Ingham result.SetStatus(eReturnStatusFailed); 687a72b31c7SJim Ingham return false; 688a72b31c7SJim Ingham } 689b9c1b51eSKate Stone } break; 69030fdc8d8SChris Lattner default: 69130fdc8d8SChris Lattner break; 69230fdc8d8SChris Lattner } 69330fdc8d8SChris Lattner 6941b54c88cSJim Ingham // Now set the various options that were passed in: 695b9c1b51eSKate Stone if (bp) { 6961b54c88cSJim Ingham if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 6971b54c88cSJim Ingham bp->SetThreadID(m_options.m_thread_id); 6981b54c88cSJim Ingham 699c982c768SGreg Clayton if (m_options.m_thread_index != UINT32_MAX) 7001b54c88cSJim Ingham bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); 7011b54c88cSJim Ingham 7021b54c88cSJim Ingham if (!m_options.m_thread_name.empty()) 703b9c1b51eSKate Stone bp->GetOptions()->GetThreadSpec()->SetName( 704b9c1b51eSKate Stone m_options.m_thread_name.c_str()); 7051b54c88cSJim Ingham 7061b54c88cSJim Ingham if (!m_options.m_queue_name.empty()) 707b9c1b51eSKate Stone bp->GetOptions()->GetThreadSpec()->SetQueueName( 708b9c1b51eSKate Stone m_options.m_queue_name.c_str()); 7091b54c88cSJim Ingham 710c982c768SGreg Clayton if (m_options.m_ignore_count != 0) 7111b54c88cSJim Ingham bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); 7127d49c9c8SJohnny Chen 7137d49c9c8SJohnny Chen if (!m_options.m_condition.empty()) 7147d49c9c8SJohnny Chen bp->GetOptions()->SetCondition(m_options.m_condition.c_str()); 715ca36cd16SJim Ingham 716b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 717ff9a91eaSJim Ingham Error name_error; 718ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) { 719ff9a91eaSJim Ingham bp->AddName(name.c_str(), name_error); 720ff9a91eaSJim Ingham if (name_error.Fail()) { 721ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s", 722ff9a91eaSJim Ingham name.c_str()); 723ff9a91eaSJim Ingham target->RemoveBreakpointByID(bp->GetID()); 724ff9a91eaSJim Ingham result.SetStatus(eReturnStatusFailed); 725ff9a91eaSJim Ingham return false; 726ff9a91eaSJim Ingham } 727ff9a91eaSJim Ingham } 7285e09c8c3SJim Ingham } 7295e09c8c3SJim Ingham 730ca36cd16SJim Ingham bp->SetOneShot(m_options.m_one_shot); 7311b54c88cSJim Ingham } 7321b54c88cSJim Ingham 733b9c1b51eSKate Stone if (bp) { 73485e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 7351391cc7dSJim Ingham const bool show_locations = false; 736b9c1b51eSKate Stone bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 737b9c1b51eSKate Stone show_locations); 7384aeb1989SJim Ingham if (target == m_interpreter.GetDebugger().GetDummyTarget()) 739b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 740b9c1b51eSKate Stone "into future targets.\n"); 741b9c1b51eSKate Stone else { 742b9c1b51eSKate Stone // Don't print out this warning for exception breakpoints. They can get 743b9c1b51eSKate Stone // set before the target 744b9c1b51eSKate Stone // is set, but we won't know how to actually set the breakpoint till we 745b9c1b51eSKate Stone // run. 746b9c1b51eSKate Stone if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) { 747b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 748b9c1b51eSKate Stone "actual locations.\n"); 7494aeb1989SJim Ingham } 7504aeb1989SJim Ingham } 75130fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 752b9c1b51eSKate Stone } else if (!bp) { 75330fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 75430fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 75530fdc8d8SChris Lattner } 75630fdc8d8SChris Lattner 75730fdc8d8SChris Lattner return result.Succeeded(); 75830fdc8d8SChris Lattner } 75930fdc8d8SChris Lattner 7605a988416SJim Ingham private: 761b9c1b51eSKate Stone bool GetDefaultFile(Target *target, FileSpec &file, 762b9c1b51eSKate Stone CommandReturnObject &result) { 7635a988416SJim Ingham uint32_t default_line; 7645a988416SJim Ingham // First use the Source Manager's default file. 7655a988416SJim Ingham // Then use the current stack frame's file. 766b9c1b51eSKate Stone if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 767b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 768b9c1b51eSKate Stone if (cur_frame == nullptr) { 769b9c1b51eSKate Stone result.AppendError( 770b9c1b51eSKate Stone "No selected frame to use to find the default file."); 7715a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 7725a988416SJim Ingham return false; 773b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 774b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 775b9c1b51eSKate Stone "file, it has no debug info."); 7765a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 7775a988416SJim Ingham return false; 778b9c1b51eSKate Stone } else { 779b9c1b51eSKate Stone const SymbolContext &sc = 780b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 781b9c1b51eSKate Stone if (sc.line_entry.file) { 7825a988416SJim Ingham file = sc.line_entry.file; 783b9c1b51eSKate Stone } else { 784b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 785b9c1b51eSKate Stone "use as the default file."); 7865a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 7875a988416SJim Ingham return false; 7885a988416SJim Ingham } 7895a988416SJim Ingham } 7905a988416SJim Ingham } 7915a988416SJim Ingham return true; 7925a988416SJim Ingham } 7935a988416SJim Ingham 7945a988416SJim Ingham CommandOptions m_options; 7955a988416SJim Ingham }; 7969e85e5a8SEugene Zelenko 7975a988416SJim Ingham //------------------------------------------------------------------------- 7985a988416SJim Ingham // CommandObjectBreakpointModify 7995a988416SJim Ingham //------------------------------------------------------------------------- 8001f0f5b5bSZachary Turner 8011f0f5b5bSZachary Turner #pragma mark Modify::CommandOptions 8021f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_modify_options[] = { 8031f0f5b5bSZachary Turner // clang-format off 8041f0f5b5bSZachary Turner { 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." }, 8051f0f5b5bSZachary Turner { 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." }, 8061f0f5b5bSZachary Turner { 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." }, 8071f0f5b5bSZachary Turner { 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." }, 8081f0f5b5bSZachary Turner { 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." }, 8091f0f5b5bSZachary Turner { 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." }, 8101f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, 8111f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." }, 8121f0f5b5bSZachary Turner { LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." }, 8131f0f5b5bSZachary Turner { 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." }, 8141f0f5b5bSZachary Turner // clang-format on 8151f0f5b5bSZachary Turner }; 8161f0f5b5bSZachary Turner 8175a988416SJim Ingham #pragma mark Modify 8185a988416SJim Ingham 819b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 8205a988416SJim Ingham public: 821b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 822b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 823b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 824b9c1b51eSKate Stone "breakpoints in the executable. " 825b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 826b9c1b51eSKate Stone "created breakpoint. " 827b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 828b9c1b51eSKate Stone "empty argument clears the modification.", 8299e85e5a8SEugene Zelenko nullptr), 830b9c1b51eSKate Stone m_options() { 8315a988416SJim Ingham CommandArgumentEntry arg; 832b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 833b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 834b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 835b9c1b51eSKate Stone // arguments vector. 8365a988416SJim Ingham m_arguments.push_back(arg); 8375a988416SJim Ingham } 8385a988416SJim Ingham 8399e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 8405a988416SJim Ingham 841b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 8425a988416SJim Ingham 843b9c1b51eSKate Stone class CommandOptions : public Options { 8445a988416SJim Ingham public: 845b9c1b51eSKate Stone CommandOptions() 846b9c1b51eSKate Stone : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), 847b9c1b51eSKate Stone m_thread_id_passed(false), m_thread_index(UINT32_MAX), 848b9c1b51eSKate Stone m_thread_index_passed(false), m_thread_name(), m_queue_name(), 849b9c1b51eSKate Stone m_condition(), m_one_shot(false), m_enable_passed(false), 850b9c1b51eSKate Stone m_enable_value(false), m_name_passed(false), m_queue_passed(false), 851b9c1b51eSKate Stone m_condition_passed(false), m_one_shot_passed(false), 852b9c1b51eSKate Stone m_use_dummy(false) {} 8535a988416SJim Ingham 8549e85e5a8SEugene Zelenko ~CommandOptions() override = default; 8555a988416SJim Ingham 856b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 857b9c1b51eSKate Stone ExecutionContext *execution_context) override { 8585a988416SJim Ingham Error error; 8593bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 8605a988416SJim Ingham 861b9c1b51eSKate Stone switch (short_option) { 8625a988416SJim Ingham case 'c': 8639e85e5a8SEugene Zelenko if (option_arg != nullptr) 8645a988416SJim Ingham m_condition.assign(option_arg); 8655a988416SJim Ingham else 8665a988416SJim Ingham m_condition.clear(); 8675a988416SJim Ingham m_condition_passed = true; 8685a988416SJim Ingham break; 8695a988416SJim Ingham case 'd': 8705a988416SJim Ingham m_enable_passed = true; 8715a988416SJim Ingham m_enable_value = false; 8725a988416SJim Ingham break; 87333df7cd3SJim Ingham case 'D': 87433df7cd3SJim Ingham m_use_dummy = true; 87533df7cd3SJim Ingham break; 8765a988416SJim Ingham case 'e': 8775a988416SJim Ingham m_enable_passed = true; 8785a988416SJim Ingham m_enable_value = true; 8795a988416SJim Ingham break; 8805a988416SJim Ingham case 'i': 8815275aaa0SVince Harron m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 8825a988416SJim Ingham if (m_ignore_count == UINT32_MAX) 883b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid ignore count '%s'", 884b9c1b51eSKate Stone option_arg); 8855a988416SJim Ingham break; 886b9c1b51eSKate Stone case 'o': { 887ca36cd16SJim Ingham bool value, success; 888ecbb0bb1SZachary Turner value = Args::StringToBoolean( 889ecbb0bb1SZachary Turner llvm::StringRef::withNullAsEmpty(option_arg), false, &success); 890b9c1b51eSKate Stone if (success) { 891ca36cd16SJim Ingham m_one_shot_passed = true; 892ca36cd16SJim Ingham m_one_shot = value; 893b9c1b51eSKate Stone } else 894b9c1b51eSKate Stone error.SetErrorStringWithFormat( 895b9c1b51eSKate Stone "invalid boolean value '%s' passed for -o option", option_arg); 896b9c1b51eSKate Stone } break; 8975a988416SJim Ingham case 't': 898b9c1b51eSKate Stone if (option_arg[0] == '\0') { 8995a988416SJim Ingham m_thread_id = LLDB_INVALID_THREAD_ID; 9005a988416SJim Ingham m_thread_id_passed = true; 901b9c1b51eSKate Stone } else { 902b9c1b51eSKate Stone m_thread_id = 903b9c1b51eSKate Stone StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 9045a988416SJim Ingham if (m_thread_id == LLDB_INVALID_THREAD_ID) 905b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread id string '%s'", 906b9c1b51eSKate Stone option_arg); 9075a988416SJim Ingham else 9085a988416SJim Ingham m_thread_id_passed = true; 9095a988416SJim Ingham } 9105a988416SJim Ingham break; 9115a988416SJim Ingham case 'T': 9129e85e5a8SEugene Zelenko if (option_arg != nullptr) 9135a988416SJim Ingham m_thread_name.assign(option_arg); 9145a988416SJim Ingham else 9155a988416SJim Ingham m_thread_name.clear(); 9165a988416SJim Ingham m_name_passed = true; 9175a988416SJim Ingham break; 9185a988416SJim Ingham case 'q': 9199e85e5a8SEugene Zelenko if (option_arg != nullptr) 9205a988416SJim Ingham m_queue_name.assign(option_arg); 9215a988416SJim Ingham else 9225a988416SJim Ingham m_queue_name.clear(); 9235a988416SJim Ingham m_queue_passed = true; 9245a988416SJim Ingham break; 9255a988416SJim Ingham case 'x': 926b9c1b51eSKate Stone if (option_arg[0] == '\n') { 9275a988416SJim Ingham m_thread_index = UINT32_MAX; 9285a988416SJim Ingham m_thread_index_passed = true; 929b9c1b51eSKate Stone } else { 9305275aaa0SVince Harron m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 9315a988416SJim Ingham if (m_thread_id == UINT32_MAX) 932b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid thread index string '%s'", 933b9c1b51eSKate Stone option_arg); 9345a988416SJim Ingham else 9355a988416SJim Ingham m_thread_index_passed = true; 9365a988416SJim Ingham } 9375a988416SJim Ingham break; 9385a988416SJim Ingham default: 939b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 940b9c1b51eSKate Stone short_option); 9415a988416SJim Ingham break; 9425a988416SJim Ingham } 9435a988416SJim Ingham 9445a988416SJim Ingham return error; 9455a988416SJim Ingham } 9469e85e5a8SEugene Zelenko 947b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 9485a988416SJim Ingham m_ignore_count = 0; 9495a988416SJim Ingham m_thread_id = LLDB_INVALID_THREAD_ID; 9505a988416SJim Ingham m_thread_id_passed = false; 9515a988416SJim Ingham m_thread_index = UINT32_MAX; 9525a988416SJim Ingham m_thread_index_passed = false; 9535a988416SJim Ingham m_thread_name.clear(); 9545a988416SJim Ingham m_queue_name.clear(); 9555a988416SJim Ingham m_condition.clear(); 956ca36cd16SJim Ingham m_one_shot = false; 9575a988416SJim Ingham m_enable_passed = false; 9585a988416SJim Ingham m_queue_passed = false; 9595a988416SJim Ingham m_name_passed = false; 9605a988416SJim Ingham m_condition_passed = false; 961ca36cd16SJim Ingham m_one_shot_passed = false; 96233df7cd3SJim Ingham m_use_dummy = false; 9635a988416SJim Ingham } 9645a988416SJim Ingham 9651f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 96670602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_modify_options); 9671f0f5b5bSZachary Turner } 9685a988416SJim Ingham 9695a988416SJim Ingham // Instance variables to hold the values for command options. 9705a988416SJim Ingham 9715a988416SJim Ingham uint32_t m_ignore_count; 9725a988416SJim Ingham lldb::tid_t m_thread_id; 9735a988416SJim Ingham bool m_thread_id_passed; 9745a988416SJim Ingham uint32_t m_thread_index; 9755a988416SJim Ingham bool m_thread_index_passed; 9765a988416SJim Ingham std::string m_thread_name; 9775a988416SJim Ingham std::string m_queue_name; 9785a988416SJim Ingham std::string m_condition; 979ca36cd16SJim Ingham bool m_one_shot; 9805a988416SJim Ingham bool m_enable_passed; 9815a988416SJim Ingham bool m_enable_value; 9825a988416SJim Ingham bool m_name_passed; 9835a988416SJim Ingham bool m_queue_passed; 9845a988416SJim Ingham bool m_condition_passed; 985ca36cd16SJim Ingham bool m_one_shot_passed; 98633df7cd3SJim Ingham bool m_use_dummy; 9875a988416SJim Ingham }; 9885a988416SJim Ingham 9895a988416SJim Ingham protected: 990b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 99133df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 992b9c1b51eSKate Stone if (target == nullptr) { 9935a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 9945a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9955a988416SJim Ingham return false; 9965a988416SJim Ingham } 9975a988416SJim Ingham 998bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 999bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 10005a988416SJim Ingham 10015a988416SJim Ingham BreakpointIDList valid_bp_ids; 10025a988416SJim Ingham 1003b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1004b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 10055a988416SJim Ingham 1006b9c1b51eSKate Stone if (result.Succeeded()) { 10075a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1008b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 10095a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 10105a988416SJim Ingham 1011b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1012b9c1b51eSKate Stone Breakpoint *bp = 1013b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1014b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1015b9c1b51eSKate Stone BreakpointLocation *location = 1016b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1017b9c1b51eSKate Stone if (location) { 10185a988416SJim Ingham if (m_options.m_thread_id_passed) 10195a988416SJim Ingham location->SetThreadID(m_options.m_thread_id); 10205a988416SJim Ingham 10215a988416SJim Ingham if (m_options.m_thread_index_passed) 10225a988416SJim Ingham location->SetThreadIndex(m_options.m_thread_index); 10235a988416SJim Ingham 10245a988416SJim Ingham if (m_options.m_name_passed) 10255a988416SJim Ingham location->SetThreadName(m_options.m_thread_name.c_str()); 10265a988416SJim Ingham 10275a988416SJim Ingham if (m_options.m_queue_passed) 10285a988416SJim Ingham location->SetQueueName(m_options.m_queue_name.c_str()); 10295a988416SJim Ingham 10305a988416SJim Ingham if (m_options.m_ignore_count != 0) 10315a988416SJim Ingham location->SetIgnoreCount(m_options.m_ignore_count); 10325a988416SJim Ingham 10335a988416SJim Ingham if (m_options.m_enable_passed) 10345a988416SJim Ingham location->SetEnabled(m_options.m_enable_value); 10355a988416SJim Ingham 10365a988416SJim Ingham if (m_options.m_condition_passed) 10375a988416SJim Ingham location->SetCondition(m_options.m_condition.c_str()); 10385a988416SJim Ingham } 1039b9c1b51eSKate Stone } else { 10405a988416SJim Ingham if (m_options.m_thread_id_passed) 10415a988416SJim Ingham bp->SetThreadID(m_options.m_thread_id); 10425a988416SJim Ingham 10435a988416SJim Ingham if (m_options.m_thread_index_passed) 10445a988416SJim Ingham bp->SetThreadIndex(m_options.m_thread_index); 10455a988416SJim Ingham 10465a988416SJim Ingham if (m_options.m_name_passed) 10475a988416SJim Ingham bp->SetThreadName(m_options.m_thread_name.c_str()); 10485a988416SJim Ingham 10495a988416SJim Ingham if (m_options.m_queue_passed) 10505a988416SJim Ingham bp->SetQueueName(m_options.m_queue_name.c_str()); 10515a988416SJim Ingham 10525a988416SJim Ingham if (m_options.m_ignore_count != 0) 10535a988416SJim Ingham bp->SetIgnoreCount(m_options.m_ignore_count); 10545a988416SJim Ingham 10555a988416SJim Ingham if (m_options.m_enable_passed) 10565a988416SJim Ingham bp->SetEnabled(m_options.m_enable_value); 10575a988416SJim Ingham 10585a988416SJim Ingham if (m_options.m_condition_passed) 10595a988416SJim Ingham bp->SetCondition(m_options.m_condition.c_str()); 10605a988416SJim Ingham } 10615a988416SJim Ingham } 10625a988416SJim Ingham } 10635a988416SJim Ingham } 10645a988416SJim Ingham 10655a988416SJim Ingham return result.Succeeded(); 10665a988416SJim Ingham } 10675a988416SJim Ingham 10685a988416SJim Ingham private: 10695a988416SJim Ingham CommandOptions m_options; 10705a988416SJim Ingham }; 10715a988416SJim Ingham 10725a988416SJim Ingham //------------------------------------------------------------------------- 10735a988416SJim Ingham // CommandObjectBreakpointEnable 10745a988416SJim Ingham //------------------------------------------------------------------------- 10755a988416SJim Ingham #pragma mark Enable 10765a988416SJim Ingham 1077b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 10785a988416SJim Ingham public: 1079b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 1080b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 1081b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 1082b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 1083b9c1b51eSKate Stone nullptr) { 10845a988416SJim Ingham CommandArgumentEntry arg; 1085b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1086b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1087b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1088b9c1b51eSKate Stone // arguments vector. 10895a988416SJim Ingham m_arguments.push_back(arg); 10905a988416SJim Ingham } 10915a988416SJim Ingham 10929e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 10935a988416SJim Ingham 10945a988416SJim Ingham protected: 1095b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1096893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1097b9c1b51eSKate Stone if (target == nullptr) { 10985a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 10995a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11005a988416SJim Ingham return false; 11015a988416SJim Ingham } 11025a988416SJim Ingham 1103bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1104bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 11055a988416SJim Ingham 11065a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 11075a988416SJim Ingham 11085a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 11095a988416SJim Ingham 1110b9c1b51eSKate Stone if (num_breakpoints == 0) { 11115a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 11125a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11135a988416SJim Ingham return false; 11145a988416SJim Ingham } 11155a988416SJim Ingham 111611eb9c64SZachary Turner if (command.empty()) { 11175a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 11185a988416SJim Ingham target->EnableAllBreakpoints(); 1119b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 1120b9c1b51eSKate Stone " breakpoints)\n", 1121b9c1b51eSKate Stone (uint64_t)num_breakpoints); 11225a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1123b9c1b51eSKate Stone } else { 11245a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 11255a988416SJim Ingham BreakpointIDList valid_bp_ids; 1126b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1127b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 11285a988416SJim Ingham 1129b9c1b51eSKate Stone if (result.Succeeded()) { 11305a988416SJim Ingham int enable_count = 0; 11315a988416SJim Ingham int loc_count = 0; 11325a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1133b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 11345a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 11355a988416SJim Ingham 1136b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1137b9c1b51eSKate Stone Breakpoint *breakpoint = 1138b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1139b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1140b9c1b51eSKate Stone BreakpointLocation *location = 1141b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1142b9c1b51eSKate Stone if (location) { 11435a988416SJim Ingham location->SetEnabled(true); 11445a988416SJim Ingham ++loc_count; 11455a988416SJim Ingham } 1146b9c1b51eSKate Stone } else { 11475a988416SJim Ingham breakpoint->SetEnabled(true); 11485a988416SJim Ingham ++enable_count; 11495a988416SJim Ingham } 11505a988416SJim Ingham } 11515a988416SJim Ingham } 1152b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 1153b9c1b51eSKate Stone enable_count + loc_count); 11545a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 11555a988416SJim Ingham } 11565a988416SJim Ingham } 11575a988416SJim Ingham 11585a988416SJim Ingham return result.Succeeded(); 11595a988416SJim Ingham } 11605a988416SJim Ingham }; 11615a988416SJim Ingham 11625a988416SJim Ingham //------------------------------------------------------------------------- 11635a988416SJim Ingham // CommandObjectBreakpointDisable 11645a988416SJim Ingham //------------------------------------------------------------------------- 11655a988416SJim Ingham #pragma mark Disable 11665a988416SJim Ingham 1167b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 11685a988416SJim Ingham public: 11697428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 1170b9c1b51eSKate Stone : CommandObjectParsed( 1171b9c1b51eSKate Stone interpreter, "breakpoint disable", 1172b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 11737428a18cSKate Stone "them. If none are specified, disable all " 11747428a18cSKate Stone "breakpoints.", 1175b9c1b51eSKate Stone nullptr) { 1176b9c1b51eSKate Stone SetHelpLong( 1177b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 11787428a18cSKate Stone If none are specified, disable all breakpoints." 11797428a18cSKate Stone R"( 1180ea671fbdSKate Stone 11817428a18cSKate Stone )" 11827428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 11837428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 11847428a18cSKate Stone R"( 1185ea671fbdSKate Stone 1186ea671fbdSKate Stone (lldb) break disable 1 1187ea671fbdSKate Stone (lldb) break enable 1.1 1188ea671fbdSKate Stone 1189ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 1190ea671fbdSKate Stone 1191ea671fbdSKate Stone (lldb) break disable 1.* 1192ea671fbdSKate Stone (lldb) break enable 1.1 1193ea671fbdSKate Stone 11947428a18cSKate Stone )" 11957428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 11967428a18cSKate Stone the second re-enables the first location."); 1197b0fac509SJim Ingham 11985a988416SJim Ingham CommandArgumentEntry arg; 1199b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1200b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1201b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1202b9c1b51eSKate Stone // arguments vector. 12035a988416SJim Ingham m_arguments.push_back(arg); 12045a988416SJim Ingham } 12055a988416SJim Ingham 12069e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 12075a988416SJim Ingham 12085a988416SJim Ingham protected: 1209b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1210893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1211b9c1b51eSKate Stone if (target == nullptr) { 12125a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 12135a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 12145a988416SJim Ingham return false; 12155a988416SJim Ingham } 12165a988416SJim Ingham 1217bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1218bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 12195a988416SJim Ingham 12205a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 12215a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 12225a988416SJim Ingham 1223b9c1b51eSKate Stone if (num_breakpoints == 0) { 12245a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 12255a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 12265a988416SJim Ingham return false; 12275a988416SJim Ingham } 12285a988416SJim Ingham 122911eb9c64SZachary Turner if (command.empty()) { 12305a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 12315a988416SJim Ingham target->DisableAllBreakpoints(); 1232b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1233b9c1b51eSKate Stone " breakpoints)\n", 1234b9c1b51eSKate Stone (uint64_t)num_breakpoints); 12355a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1236b9c1b51eSKate Stone } else { 12375a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 12385a988416SJim Ingham BreakpointIDList valid_bp_ids; 12395a988416SJim Ingham 1240b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1241b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 12425a988416SJim Ingham 1243b9c1b51eSKate Stone if (result.Succeeded()) { 12445a988416SJim Ingham int disable_count = 0; 12455a988416SJim Ingham int loc_count = 0; 12465a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1247b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 12485a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 12495a988416SJim Ingham 1250b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1251b9c1b51eSKate Stone Breakpoint *breakpoint = 1252b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1253b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1254b9c1b51eSKate Stone BreakpointLocation *location = 1255b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1256b9c1b51eSKate Stone if (location) { 12575a988416SJim Ingham location->SetEnabled(false); 12585a988416SJim Ingham ++loc_count; 12595a988416SJim Ingham } 1260b9c1b51eSKate Stone } else { 12615a988416SJim Ingham breakpoint->SetEnabled(false); 12625a988416SJim Ingham ++disable_count; 12635a988416SJim Ingham } 12645a988416SJim Ingham } 12655a988416SJim Ingham } 1266b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1267b9c1b51eSKate Stone disable_count + loc_count); 12685a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 12695a988416SJim Ingham } 12705a988416SJim Ingham } 12715a988416SJim Ingham 12725a988416SJim Ingham return result.Succeeded(); 12735a988416SJim Ingham } 12745a988416SJim Ingham }; 12755a988416SJim Ingham 12765a988416SJim Ingham //------------------------------------------------------------------------- 12775a988416SJim Ingham // CommandObjectBreakpointList 12785a988416SJim Ingham //------------------------------------------------------------------------- 12791f0f5b5bSZachary Turner 12801f0f5b5bSZachary Turner #pragma mark List::CommandOptions 12811f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_list_options[] = { 12821f0f5b5bSZachary Turner // clang-format off 12831f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" }, 12841f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." }, 12851f0f5b5bSZachary Turner // FIXME: We need to add an "internal" command, and then add this sort of thing to it. 12861f0f5b5bSZachary Turner // But I need to see it for now, and don't want to wait. 12871f0f5b5bSZachary Turner { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." }, 12881f0f5b5bSZachary Turner { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, 12891f0f5b5bSZachary Turner { 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." }, 12901f0f5b5bSZachary Turner // clang-format on 12911f0f5b5bSZachary Turner }; 12921f0f5b5bSZachary Turner 12935a988416SJim Ingham #pragma mark List 12945a988416SJim Ingham 1295b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 12965a988416SJim Ingham public: 1297b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1298b9c1b51eSKate Stone : CommandObjectParsed( 1299b9c1b51eSKate Stone interpreter, "breakpoint list", 13005a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 13019e85e5a8SEugene Zelenko nullptr), 1302b9c1b51eSKate Stone m_options() { 13035a988416SJim Ingham CommandArgumentEntry arg; 13045a988416SJim Ingham CommandArgumentData bp_id_arg; 13055a988416SJim Ingham 13065a988416SJim Ingham // Define the first (and only) variant of this arg. 13075a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 13085a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 13095a988416SJim Ingham 1310b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1311b9c1b51eSKate Stone // argument entry. 13125a988416SJim Ingham arg.push_back(bp_id_arg); 13135a988416SJim Ingham 13145a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 13155a988416SJim Ingham m_arguments.push_back(arg); 13165a988416SJim Ingham } 13175a988416SJim Ingham 13189e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 13195a988416SJim Ingham 1320b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 13215a988416SJim Ingham 1322b9c1b51eSKate Stone class CommandOptions : public Options { 13235a988416SJim Ingham public: 1324b9c1b51eSKate Stone CommandOptions() 1325b9c1b51eSKate Stone : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 13265a988416SJim Ingham } 13275a988416SJim Ingham 13289e85e5a8SEugene Zelenko ~CommandOptions() override = default; 13295a988416SJim Ingham 1330b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1331b9c1b51eSKate Stone ExecutionContext *execution_context) override { 13325a988416SJim Ingham Error error; 13333bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 13345a988416SJim Ingham 1335b9c1b51eSKate Stone switch (short_option) { 13365a988416SJim Ingham case 'b': 13375a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 13385a988416SJim Ingham break; 133933df7cd3SJim Ingham case 'D': 134033df7cd3SJim Ingham m_use_dummy = true; 134133df7cd3SJim Ingham break; 13425a988416SJim Ingham case 'f': 13435a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 13445a988416SJim Ingham break; 13455a988416SJim Ingham case 'v': 13465a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 13475a988416SJim Ingham break; 13485a988416SJim Ingham case 'i': 13495a988416SJim Ingham m_internal = true; 13505a988416SJim Ingham break; 13515a988416SJim Ingham default: 1352b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1353b9c1b51eSKate Stone short_option); 13545a988416SJim Ingham break; 13555a988416SJim Ingham } 13565a988416SJim Ingham 13575a988416SJim Ingham return error; 13585a988416SJim Ingham } 13595a988416SJim Ingham 1360b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 13615a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 13625a988416SJim Ingham m_internal = false; 136333df7cd3SJim Ingham m_use_dummy = false; 13645a988416SJim Ingham } 13655a988416SJim Ingham 13661f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 136770602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_list_options); 13681f0f5b5bSZachary Turner } 13695a988416SJim Ingham 13705a988416SJim Ingham // Instance variables to hold the values for command options. 13715a988416SJim Ingham 13725a988416SJim Ingham lldb::DescriptionLevel m_level; 13735a988416SJim Ingham 13745a988416SJim Ingham bool m_internal; 137533df7cd3SJim Ingham bool m_use_dummy; 13765a988416SJim Ingham }; 13775a988416SJim Ingham 13785a988416SJim Ingham protected: 1379b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 138033df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 138133df7cd3SJim Ingham 1382b9c1b51eSKate Stone if (target == nullptr) { 13835a988416SJim Ingham result.AppendError("Invalid target. No current target or breakpoints."); 13845a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13855a988416SJim Ingham return true; 13865a988416SJim Ingham } 13875a988416SJim Ingham 1388b9c1b51eSKate Stone const BreakpointList &breakpoints = 1389b9c1b51eSKate Stone target->GetBreakpointList(m_options.m_internal); 1390bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1391bb19a13cSSaleem Abdulrasool target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); 13925a988416SJim Ingham 13935a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 13945a988416SJim Ingham 1395b9c1b51eSKate Stone if (num_breakpoints == 0) { 13965a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 13975a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13985a988416SJim Ingham return true; 13995a988416SJim Ingham } 14005a988416SJim Ingham 14015a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 14025a988416SJim Ingham 140311eb9c64SZachary Turner if (command.empty()) { 14045a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 14055a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1406b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 14075a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 14085a988416SJim Ingham AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level); 14095a988416SJim Ingham } 14105a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1411b9c1b51eSKate Stone } else { 14125a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 14135a988416SJim Ingham BreakpointIDList valid_bp_ids; 1414b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1415b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 14165a988416SJim Ingham 1417b9c1b51eSKate Stone if (result.Succeeded()) { 1418b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 14195a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1420b9c1b51eSKate Stone Breakpoint *breakpoint = 1421b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1422b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1423b9c1b51eSKate Stone m_options.m_level); 14245a988416SJim Ingham } 14255a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1426b9c1b51eSKate Stone } else { 14277428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 14285a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14295a988416SJim Ingham } 14305a988416SJim Ingham } 14315a988416SJim Ingham 14325a988416SJim Ingham return result.Succeeded(); 14335a988416SJim Ingham } 14345a988416SJim Ingham 14355a988416SJim Ingham private: 14365a988416SJim Ingham CommandOptions m_options; 14375a988416SJim Ingham }; 14385a988416SJim Ingham 14395a988416SJim Ingham //------------------------------------------------------------------------- 14405a988416SJim Ingham // CommandObjectBreakpointClear 14415a988416SJim Ingham //------------------------------------------------------------------------- 14421f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions 14431f0f5b5bSZachary Turner 14441f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_clear_options[] = { 14451f0f5b5bSZachary Turner // clang-format off 14461f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." }, 14471f0f5b5bSZachary Turner { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." } 14481f0f5b5bSZachary Turner // clang-format on 14491f0f5b5bSZachary Turner }; 14501f0f5b5bSZachary Turner 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 15051f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 150670602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_clear_options); 15071f0f5b5bSZachary Turner } 15085a988416SJim Ingham 15095a988416SJim Ingham // Instance variables to hold the values for command options. 15105a988416SJim Ingham 15115a988416SJim Ingham std::string m_filename; 15125a988416SJim Ingham uint32_t m_line_num; 15135a988416SJim Ingham }; 15145a988416SJim Ingham 15155a988416SJim Ingham protected: 1516b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1517893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1518b9c1b51eSKate Stone if (target == nullptr) { 15195a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 15205a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15215a988416SJim Ingham return false; 15225a988416SJim Ingham } 15235a988416SJim Ingham 15245a988416SJim Ingham // The following are the various types of breakpoints that could be cleared: 15255a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 15265a988416SJim Ingham 15275a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 15285a988416SJim Ingham 15295a988416SJim Ingham if (m_options.m_line_num != 0) 15305a988416SJim Ingham break_type = eClearTypeFileAndLine; 15315a988416SJim Ingham 1532bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1533bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 15345a988416SJim Ingham 15355a988416SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 15365a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 15375a988416SJim Ingham 15385a988416SJim Ingham // Early return if there's no breakpoint at all. 1539b9c1b51eSKate Stone if (num_breakpoints == 0) { 15405a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15415a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15425a988416SJim Ingham return result.Succeeded(); 15435a988416SJim Ingham } 15445a988416SJim Ingham 15455a988416SJim Ingham // Find matching breakpoints and delete them. 15465a988416SJim Ingham 15475a988416SJim Ingham // First create a copy of all the IDs. 15485a988416SJim Ingham std::vector<break_id_t> BreakIDs; 15495a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 15509e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 15515a988416SJim Ingham 15525a988416SJim Ingham int num_cleared = 0; 15535a988416SJim Ingham StreamString ss; 1554b9c1b51eSKate Stone switch (break_type) { 15555a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 15565a988416SJim Ingham { 15575a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 15585a988416SJim Ingham BreakpointLocationCollection loc_coll; 15595a988416SJim Ingham 1560b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 15615a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 15625a988416SJim Ingham 1563b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1564b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1565b9c1b51eSKate Stone // remove the breakpoint. 1566b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 15675a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 15685a988416SJim Ingham ss.EOL(); 15695a988416SJim Ingham target->RemoveBreakpointByID(bp->GetID()); 15705a988416SJim Ingham ++num_cleared; 15715a988416SJim Ingham } 15725a988416SJim Ingham } 15735a988416SJim Ingham } 1574b9c1b51eSKate Stone } break; 15755a988416SJim Ingham 15765a988416SJim Ingham default: 15775a988416SJim Ingham break; 15785a988416SJim Ingham } 15795a988416SJim Ingham 1580b9c1b51eSKate Stone if (num_cleared > 0) { 15815a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 15825a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 15835a988416SJim Ingham output_stream << ss.GetData(); 15845a988416SJim Ingham output_stream.EOL(); 15855a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1586b9c1b51eSKate Stone } else { 15875a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15885a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15895a988416SJim Ingham } 15905a988416SJim Ingham 15915a988416SJim Ingham return result.Succeeded(); 15925a988416SJim Ingham } 15935a988416SJim Ingham 15945a988416SJim Ingham private: 15955a988416SJim Ingham CommandOptions m_options; 15965a988416SJim Ingham }; 15975a988416SJim Ingham 15985a988416SJim Ingham //------------------------------------------------------------------------- 15995a988416SJim Ingham // CommandObjectBreakpointDelete 16005a988416SJim Ingham //------------------------------------------------------------------------- 16011f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_delete_options[] = { 16021f0f5b5bSZachary Turner // clang-format off 16031f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." }, 16041f0f5b5bSZachary Turner { 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." }, 16051f0f5b5bSZachary Turner // clang-format on 16061f0f5b5bSZachary Turner }; 16071f0f5b5bSZachary Turner 16085a988416SJim Ingham #pragma mark Delete 16095a988416SJim Ingham 1610b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 16115a988416SJim Ingham public: 1612b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1613b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1614b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1615b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 16169e85e5a8SEugene Zelenko nullptr), 1617b9c1b51eSKate Stone m_options() { 16185a988416SJim Ingham CommandArgumentEntry arg; 1619b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1620b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1621b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1622b9c1b51eSKate Stone // arguments vector. 16235a988416SJim Ingham m_arguments.push_back(arg); 16245a988416SJim Ingham } 16255a988416SJim Ingham 16269e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 16275a988416SJim Ingham 1628b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 162933df7cd3SJim Ingham 1630b9c1b51eSKate Stone class CommandOptions : public Options { 163133df7cd3SJim Ingham public: 1632b9c1b51eSKate Stone CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 163333df7cd3SJim Ingham 16349e85e5a8SEugene Zelenko ~CommandOptions() override = default; 163533df7cd3SJim Ingham 1636b9c1b51eSKate Stone Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1637b9c1b51eSKate Stone ExecutionContext *execution_context) override { 163833df7cd3SJim Ingham Error error; 163933df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 164033df7cd3SJim Ingham 1641b9c1b51eSKate Stone switch (short_option) { 164233df7cd3SJim Ingham case 'f': 164333df7cd3SJim Ingham m_force = true; 164433df7cd3SJim Ingham break; 164533df7cd3SJim Ingham 164633df7cd3SJim Ingham case 'D': 164733df7cd3SJim Ingham m_use_dummy = true; 164833df7cd3SJim Ingham break; 164933df7cd3SJim Ingham 165033df7cd3SJim Ingham default: 1651b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1652b9c1b51eSKate Stone short_option); 165333df7cd3SJim Ingham break; 165433df7cd3SJim Ingham } 165533df7cd3SJim Ingham 165633df7cd3SJim Ingham return error; 165733df7cd3SJim Ingham } 165833df7cd3SJim Ingham 1659b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 166033df7cd3SJim Ingham m_use_dummy = false; 166133df7cd3SJim Ingham m_force = false; 166233df7cd3SJim Ingham } 166333df7cd3SJim Ingham 16641f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 166570602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_delete_options); 16661f0f5b5bSZachary Turner } 166733df7cd3SJim Ingham 166833df7cd3SJim Ingham // Instance variables to hold the values for command options. 166933df7cd3SJim Ingham bool m_use_dummy; 167033df7cd3SJim Ingham bool m_force; 167133df7cd3SJim Ingham }; 167233df7cd3SJim Ingham 16735a988416SJim Ingham protected: 1674b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 167533df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 167633df7cd3SJim Ingham 1677b9c1b51eSKate Stone if (target == nullptr) { 16785a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 16795a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16805a988416SJim Ingham return false; 16815a988416SJim Ingham } 16825a988416SJim Ingham 1683bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1684bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 16855a988416SJim Ingham 16865a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 16875a988416SJim Ingham 16885a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 16895a988416SJim Ingham 1690b9c1b51eSKate Stone if (num_breakpoints == 0) { 16915a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 16925a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16935a988416SJim Ingham return false; 16945a988416SJim Ingham } 16955a988416SJim Ingham 169611eb9c64SZachary Turner if (command.empty()) { 1697b9c1b51eSKate Stone if (!m_options.m_force && 1698b9c1b51eSKate Stone !m_interpreter.Confirm( 1699b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1700b9c1b51eSKate Stone true)) { 17015a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1702b9c1b51eSKate Stone } else { 17035a988416SJim Ingham target->RemoveAllBreakpoints(); 1704b9c1b51eSKate Stone result.AppendMessageWithFormat( 1705b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1706b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 17075a988416SJim Ingham } 17085a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1709b9c1b51eSKate Stone } else { 17105a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 17115a988416SJim Ingham BreakpointIDList valid_bp_ids; 1712b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1713b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 17145a988416SJim Ingham 1715b9c1b51eSKate Stone if (result.Succeeded()) { 17165a988416SJim Ingham int delete_count = 0; 17175a988416SJim Ingham int disable_count = 0; 17185a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1719b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 17205a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 17215a988416SJim Ingham 1722b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1723b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1724b9c1b51eSKate Stone Breakpoint *breakpoint = 1725b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1726b9c1b51eSKate Stone BreakpointLocation *location = 1727b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1728b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1729b9c1b51eSKate Stone // disable them instead. 1730b9c1b51eSKate Stone if (location) { 17315a988416SJim Ingham location->SetEnabled(false); 17325a988416SJim Ingham ++disable_count; 17335a988416SJim Ingham } 1734b9c1b51eSKate Stone } else { 17355a988416SJim Ingham target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 17365a988416SJim Ingham ++delete_count; 17375a988416SJim Ingham } 17385a988416SJim Ingham } 17395a988416SJim Ingham } 1740b9c1b51eSKate Stone result.AppendMessageWithFormat( 1741b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 17425a988416SJim Ingham delete_count, disable_count); 17435a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 17445a988416SJim Ingham } 17455a988416SJim Ingham } 17465a988416SJim Ingham return result.Succeeded(); 17475a988416SJim Ingham } 17489e85e5a8SEugene Zelenko 174933df7cd3SJim Ingham private: 175033df7cd3SJim Ingham CommandOptions m_options; 175133df7cd3SJim Ingham }; 175233df7cd3SJim Ingham 175330fdc8d8SChris Lattner //------------------------------------------------------------------------- 17545e09c8c3SJim Ingham // CommandObjectBreakpointName 17555e09c8c3SJim Ingham //------------------------------------------------------------------------- 17565e09c8c3SJim Ingham 17577428a18cSKate Stone static OptionDefinition g_breakpoint_name_options[] = { 1758ac9c3a62SKate Stone // clang-format off 1759ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, 1760ac9c3a62SKate Stone {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, 1761ac9c3a62SKate 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."}, 1762ac9c3a62SKate Stone // clang-format on 17635e09c8c3SJim Ingham }; 1764b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 17655e09c8c3SJim Ingham public: 1766b9c1b51eSKate Stone BreakpointNameOptionGroup() 1767b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 17685e09c8c3SJim Ingham } 17695e09c8c3SJim Ingham 17709e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 17715e09c8c3SJim Ingham 17721f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 177370602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_name_options); 17745e09c8c3SJim Ingham } 17755e09c8c3SJim Ingham 17768cef4b0bSZachary Turner Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 1777b9c1b51eSKate Stone ExecutionContext *execution_context) override { 17785e09c8c3SJim Ingham Error error; 17795e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 17805e09c8c3SJim Ingham 1781b9c1b51eSKate Stone switch (short_option) { 17825e09c8c3SJim Ingham case 'N': 17838cef4b0bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_value, error) && 1784b9c1b51eSKate Stone error.Success()) 17858cef4b0bSZachary Turner m_name.SetValueFromString(option_value); 17865e09c8c3SJim Ingham break; 17875e09c8c3SJim Ingham 17885e09c8c3SJim Ingham case 'B': 1789c95f7e2aSPavel Labath if (m_breakpoint.SetValueFromString(option_value).Fail()) 1790b9c1b51eSKate Stone error.SetErrorStringWithFormat( 17918cef4b0bSZachary Turner "unrecognized value \"%s\" for breakpoint", 17928cef4b0bSZachary Turner option_value.str().c_str()); 17935e09c8c3SJim Ingham break; 17945e09c8c3SJim Ingham case 'D': 1795c95f7e2aSPavel Labath if (m_use_dummy.SetValueFromString(option_value).Fail()) 1796b9c1b51eSKate Stone error.SetErrorStringWithFormat( 17978cef4b0bSZachary Turner "unrecognized value \"%s\" for use-dummy", 17988cef4b0bSZachary Turner option_value.str().c_str()); 17995e09c8c3SJim Ingham break; 18005e09c8c3SJim Ingham 18015e09c8c3SJim Ingham default: 1802b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized short option '%c'", 1803b9c1b51eSKate Stone short_option); 18045e09c8c3SJim Ingham break; 18055e09c8c3SJim Ingham } 18065e09c8c3SJim Ingham return error; 18075e09c8c3SJim Ingham } 18088cef4b0bSZachary Turner Error SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete; 18095e09c8c3SJim Ingham 1810b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 18115e09c8c3SJim Ingham m_name.Clear(); 18125e09c8c3SJim Ingham m_breakpoint.Clear(); 18135e09c8c3SJim Ingham m_use_dummy.Clear(); 18145e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 18155e09c8c3SJim Ingham } 18165e09c8c3SJim Ingham 18175e09c8c3SJim Ingham OptionValueString m_name; 18185e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 18195e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 18205e09c8c3SJim Ingham }; 18215e09c8c3SJim Ingham 1822b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 18235e09c8c3SJim Ingham public: 1824b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1825b9c1b51eSKate Stone : CommandObjectParsed( 1826b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 18275e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 1828b9c1b51eSKate Stone m_name_options(), m_option_group() { 1829b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1830b9c1b51eSKate Stone // command. 18315e09c8c3SJim Ingham CommandArgumentEntry arg1; 18325e09c8c3SJim Ingham CommandArgumentData id_arg; 18335e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 18345e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 18355e09c8c3SJim Ingham arg1.push_back(id_arg); 18365e09c8c3SJim Ingham m_arguments.push_back(arg1); 18375e09c8c3SJim Ingham 18385e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 18395e09c8c3SJim Ingham m_option_group.Finalize(); 18405e09c8c3SJim Ingham } 18415e09c8c3SJim Ingham 18429e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 18435e09c8c3SJim Ingham 1844b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 18455e09c8c3SJim Ingham 18465e09c8c3SJim Ingham protected: 1847b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1848b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 18495e09c8c3SJim Ingham result.SetError("No name option provided."); 18505e09c8c3SJim Ingham return false; 18515e09c8c3SJim Ingham } 18525e09c8c3SJim Ingham 1853b9c1b51eSKate Stone Target *target = 1854b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 18555e09c8c3SJim Ingham 1856b9c1b51eSKate Stone if (target == nullptr) { 18575e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 18585e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18595e09c8c3SJim Ingham return false; 18605e09c8c3SJim Ingham } 18615e09c8c3SJim Ingham 1862bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1863bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 18645e09c8c3SJim Ingham 18655e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 18665e09c8c3SJim Ingham 18675e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1868b9c1b51eSKate Stone if (num_breakpoints == 0) { 18695e09c8c3SJim Ingham result.SetError("No breakpoints, cannot add names."); 18705e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18715e09c8c3SJim Ingham return false; 18725e09c8c3SJim Ingham } 18735e09c8c3SJim Ingham 18745e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 18755e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1876b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1877b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 18785e09c8c3SJim Ingham 1879b9c1b51eSKate Stone if (result.Succeeded()) { 1880b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 18815e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot add names."); 18825e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 18835e09c8c3SJim Ingham return false; 18845e09c8c3SJim Ingham } 18855e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1886b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1887b9c1b51eSKate Stone lldb::break_id_t bp_id = 1888b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 18895e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1890b9c1b51eSKate Stone Error error; // We don't need to check the error here, since the option 1891b9c1b51eSKate Stone // parser checked it... 18925e09c8c3SJim Ingham bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error); 18935e09c8c3SJim Ingham } 18945e09c8c3SJim Ingham } 18955e09c8c3SJim Ingham 18965e09c8c3SJim Ingham return true; 18975e09c8c3SJim Ingham } 18985e09c8c3SJim Ingham 18995e09c8c3SJim Ingham private: 19005e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19015e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19025e09c8c3SJim Ingham }; 19035e09c8c3SJim Ingham 1904b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 19055e09c8c3SJim Ingham public: 1906b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1907b9c1b51eSKate Stone : CommandObjectParsed( 1908b9c1b51eSKate Stone interpreter, "delete", 19095e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 19105e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 1911b9c1b51eSKate Stone m_name_options(), m_option_group() { 1912b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1913b9c1b51eSKate Stone // command. 19145e09c8c3SJim Ingham CommandArgumentEntry arg1; 19155e09c8c3SJim Ingham CommandArgumentData id_arg; 19165e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 19175e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 19185e09c8c3SJim Ingham arg1.push_back(id_arg); 19195e09c8c3SJim Ingham m_arguments.push_back(arg1); 19205e09c8c3SJim Ingham 19215e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 19225e09c8c3SJim Ingham m_option_group.Finalize(); 19235e09c8c3SJim Ingham } 19245e09c8c3SJim Ingham 19259e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 19265e09c8c3SJim Ingham 1927b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19285e09c8c3SJim Ingham 19295e09c8c3SJim Ingham protected: 1930b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1931b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 19325e09c8c3SJim Ingham result.SetError("No name option provided."); 19335e09c8c3SJim Ingham return false; 19345e09c8c3SJim Ingham } 19355e09c8c3SJim Ingham 1936b9c1b51eSKate Stone Target *target = 1937b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19385e09c8c3SJim Ingham 1939b9c1b51eSKate Stone if (target == nullptr) { 19405e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 19415e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19425e09c8c3SJim Ingham return false; 19435e09c8c3SJim Ingham } 19445e09c8c3SJim Ingham 1945bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1946bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 19475e09c8c3SJim Ingham 19485e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 19495e09c8c3SJim Ingham 19505e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1951b9c1b51eSKate Stone if (num_breakpoints == 0) { 19525e09c8c3SJim Ingham result.SetError("No breakpoints, cannot delete names."); 19535e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19545e09c8c3SJim Ingham return false; 19555e09c8c3SJim Ingham } 19565e09c8c3SJim Ingham 19575e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 19585e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1959b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1960b9c1b51eSKate Stone command, target, result, &valid_bp_ids); 19615e09c8c3SJim Ingham 1962b9c1b51eSKate Stone if (result.Succeeded()) { 1963b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 19645e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot delete names."); 19655e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19665e09c8c3SJim Ingham return false; 19675e09c8c3SJim Ingham } 19685e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 1969b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 1970b9c1b51eSKate Stone lldb::break_id_t bp_id = 1971b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 19725e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 19735e09c8c3SJim Ingham bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue()); 19745e09c8c3SJim Ingham } 19755e09c8c3SJim Ingham } 19765e09c8c3SJim Ingham 19775e09c8c3SJim Ingham return true; 19785e09c8c3SJim Ingham } 19795e09c8c3SJim Ingham 19805e09c8c3SJim Ingham private: 19815e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 19825e09c8c3SJim Ingham OptionGroupOptions m_option_group; 19835e09c8c3SJim Ingham }; 19845e09c8c3SJim Ingham 1985b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 19865e09c8c3SJim Ingham public: 1987b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 1988b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 1989b9c1b51eSKate Stone "List either the names for a breakpoint or the " 1990b9c1b51eSKate Stone "breakpoints for a given name.", 19915e09c8c3SJim Ingham "breakpoint name list <command-options>"), 1992b9c1b51eSKate Stone m_name_options(), m_option_group() { 19935e09c8c3SJim Ingham m_option_group.Append(&m_name_options); 19945e09c8c3SJim Ingham m_option_group.Finalize(); 19955e09c8c3SJim Ingham } 19965e09c8c3SJim Ingham 19979e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 19985e09c8c3SJim Ingham 1999b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 20005e09c8c3SJim Ingham 20015e09c8c3SJim Ingham protected: 2002b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2003b9c1b51eSKate Stone Target *target = 2004b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 20055e09c8c3SJim Ingham 2006b9c1b51eSKate Stone if (target == nullptr) { 20075e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 20085e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20095e09c8c3SJim Ingham return false; 20105e09c8c3SJim Ingham } 20115e09c8c3SJim Ingham 2012b9c1b51eSKate Stone if (m_name_options.m_name.OptionWasSet()) { 20135e09c8c3SJim Ingham const char *name = m_name_options.m_name.GetCurrentValue(); 2014bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2015bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 20165e09c8c3SJim Ingham 20175e09c8c3SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 2018b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2019b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 20205e09c8c3SJim Ingham StreamString s; 20215e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 20225e09c8c3SJim Ingham s.EOL(); 20235e09c8c3SJim Ingham result.AppendMessage(s.GetData()); 20245e09c8c3SJim Ingham } 20255e09c8c3SJim Ingham } 20265e09c8c3SJim Ingham 2027b9c1b51eSKate Stone } else if (m_name_options.m_breakpoint.OptionWasSet()) { 2028b9c1b51eSKate Stone BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID( 2029b9c1b51eSKate Stone m_name_options.m_breakpoint.GetCurrentValue()); 2030b9c1b51eSKate Stone if (bp_sp) { 20315e09c8c3SJim Ingham std::vector<std::string> names; 20325e09c8c3SJim Ingham bp_sp->GetNames(names); 20335e09c8c3SJim Ingham result.AppendMessage("Names:"); 20345e09c8c3SJim Ingham for (auto name : names) 20355e09c8c3SJim Ingham result.AppendMessageWithFormat(" %s\n", name.c_str()); 2036b9c1b51eSKate Stone } else { 2037b9c1b51eSKate Stone result.AppendErrorWithFormat( 2038b9c1b51eSKate Stone "Could not find breakpoint %" PRId64 ".\n", 20395e09c8c3SJim Ingham m_name_options.m_breakpoint.GetCurrentValue()); 20405e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20415e09c8c3SJim Ingham return false; 20425e09c8c3SJim Ingham } 2043b9c1b51eSKate Stone } else { 20445e09c8c3SJim Ingham result.SetError("Must specify -N or -B option to list."); 20455e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20465e09c8c3SJim Ingham return false; 20475e09c8c3SJim Ingham } 20485e09c8c3SJim Ingham return true; 20495e09c8c3SJim Ingham } 20505e09c8c3SJim Ingham 20515e09c8c3SJim Ingham private: 20525e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20535e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20545e09c8c3SJim Ingham }; 20555e09c8c3SJim Ingham 20565e09c8c3SJim Ingham //------------------------------------------------------------------------- 2057e14dc268SJim Ingham // CommandObjectBreakpointName 20585e09c8c3SJim Ingham //------------------------------------------------------------------------- 2059b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 20605e09c8c3SJim Ingham public: 20617428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2062b9c1b51eSKate Stone : CommandObjectMultiword( 2063b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2064b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2065b9c1b51eSKate Stone CommandObjectSP add_command_object( 2066b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2067b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2068b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2069b9c1b51eSKate Stone CommandObjectSP list_command_object( 2070b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 20715e09c8c3SJim Ingham 20725e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 20735e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 20745e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 20755e09c8c3SJim Ingham } 20765e09c8c3SJim Ingham 20779e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 20785e09c8c3SJim Ingham }; 20795e09c8c3SJim Ingham 20805e09c8c3SJim Ingham //------------------------------------------------------------------------- 2081e14dc268SJim Ingham // CommandObjectBreakpointRead 2082e14dc268SJim Ingham //------------------------------------------------------------------------- 20833acdf385SJim Ingham #pragma mark Read::CommandOptions 20841f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_read_options[] = { 20851f0f5b5bSZachary Turner // clang-format off 20861f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." }, 20873acdf385SJim Ingham {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."}, 20881f0f5b5bSZachary Turner // clang-format on 20891f0f5b5bSZachary Turner }; 20901f0f5b5bSZachary Turner 20911f0f5b5bSZachary Turner #pragma mark Read 2092e14dc268SJim Ingham 2093e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed { 2094e14dc268SJim Ingham public: 2095e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2096e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read", 2097e14dc268SJim Ingham "Read and set the breakpoints previously saved to " 2098e14dc268SJim Ingham "a file with \"breakpoint write\". ", 2099e14dc268SJim Ingham nullptr), 2100e14dc268SJim Ingham m_options() { 2101e14dc268SJim Ingham CommandArgumentEntry arg; 2102e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2103e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2104e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2105e14dc268SJim Ingham // arguments vector. 2106e14dc268SJim Ingham m_arguments.push_back(arg); 2107e14dc268SJim Ingham } 2108e14dc268SJim Ingham 2109e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default; 2110e14dc268SJim Ingham 2111e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2112e14dc268SJim Ingham 2113e14dc268SJim Ingham class CommandOptions : public Options { 2114e14dc268SJim Ingham public: 2115e14dc268SJim Ingham CommandOptions() : Options() {} 2116e14dc268SJim Ingham 2117e14dc268SJim Ingham ~CommandOptions() override = default; 2118e14dc268SJim Ingham 2119e14dc268SJim Ingham Error SetOptionValue(uint32_t option_idx, const char *option_arg, 2120e14dc268SJim Ingham ExecutionContext *execution_context) override { 2121e14dc268SJim Ingham Error error; 2122e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2123e14dc268SJim Ingham 2124e14dc268SJim Ingham switch (short_option) { 2125e14dc268SJim Ingham case 'f': 2126e14dc268SJim Ingham m_filename.assign(option_arg); 2127e14dc268SJim Ingham break; 21283acdf385SJim Ingham case 'N': { 21293acdf385SJim Ingham Error name_error; 21303acdf385SJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 21313acdf385SJim Ingham name_error)) { 21323acdf385SJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 21333acdf385SJim Ingham name_error.AsCString()); 21343acdf385SJim Ingham } 21353acdf385SJim Ingham m_names.push_back(option_arg); 21363acdf385SJim Ingham break; 21373acdf385SJim Ingham } 2138e14dc268SJim Ingham default: 2139e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2140e14dc268SJim Ingham short_option); 2141e14dc268SJim Ingham break; 2142e14dc268SJim Ingham } 2143e14dc268SJim Ingham 2144e14dc268SJim Ingham return error; 2145e14dc268SJim Ingham } 2146e14dc268SJim Ingham 2147e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2148e14dc268SJim Ingham m_filename.clear(); 21493acdf385SJim Ingham m_names.clear(); 2150e14dc268SJim Ingham } 2151e14dc268SJim Ingham 21521f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 215370602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_read_options); 21541f0f5b5bSZachary Turner } 2155e14dc268SJim Ingham 2156e14dc268SJim Ingham // Instance variables to hold the values for command options. 2157e14dc268SJim Ingham 2158e14dc268SJim Ingham std::string m_filename; 21593acdf385SJim Ingham std::vector<std::string> m_names; 2160e14dc268SJim Ingham }; 2161e14dc268SJim Ingham 2162e14dc268SJim Ingham protected: 2163e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2164e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2165e14dc268SJim Ingham if (target == nullptr) { 2166e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2167e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2168e14dc268SJim Ingham return false; 2169e14dc268SJim Ingham } 2170e14dc268SJim Ingham 21713acdf385SJim Ingham std::unique_lock<std::recursive_mutex> lock; 21723acdf385SJim Ingham target->GetBreakpointList().GetListMutex(lock); 21733acdf385SJim Ingham 2174e14dc268SJim Ingham FileSpec input_spec(m_options.m_filename, true); 217501f16664SJim Ingham BreakpointIDList new_bps; 21763acdf385SJim Ingham Error error = target->CreateBreakpointsFromFile(input_spec, 21773acdf385SJim Ingham m_options.m_names, new_bps); 2178e14dc268SJim Ingham 2179e14dc268SJim Ingham if (!error.Success()) { 218001f16664SJim Ingham result.AppendError(error.AsCString()); 2181e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 218201f16664SJim Ingham return false; 2183e14dc268SJim Ingham } 21843acdf385SJim Ingham 21853acdf385SJim Ingham Stream &output_stream = result.GetOutputStream(); 21863acdf385SJim Ingham 21873acdf385SJim Ingham size_t num_breakpoints = new_bps.GetSize(); 21883acdf385SJim Ingham if (num_breakpoints == 0) { 21893acdf385SJim Ingham result.AppendMessage("No breakpoints added."); 21903acdf385SJim Ingham } else { 21913acdf385SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 21923acdf385SJim Ingham result.AppendMessage("New breakpoints:"); 21933acdf385SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) { 21943acdf385SJim Ingham BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 21953acdf385SJim Ingham Breakpoint *bp = target->GetBreakpointList() 21963acdf385SJim Ingham .FindBreakpointByID(bp_id.GetBreakpointID()) 21973acdf385SJim Ingham .get(); 21983acdf385SJim Ingham if (bp) 21993acdf385SJim Ingham bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 22003acdf385SJim Ingham false); 22013acdf385SJim Ingham } 22023acdf385SJim Ingham } 2203e14dc268SJim Ingham return result.Succeeded(); 2204e14dc268SJim Ingham } 2205e14dc268SJim Ingham 2206e14dc268SJim Ingham private: 2207e14dc268SJim Ingham CommandOptions m_options; 2208e14dc268SJim Ingham }; 2209e14dc268SJim Ingham 2210e14dc268SJim Ingham //------------------------------------------------------------------------- 2211e14dc268SJim Ingham // CommandObjectBreakpointWrite 2212e14dc268SJim Ingham //------------------------------------------------------------------------- 22131f0f5b5bSZachary Turner #pragma mark Write::CommandOptions 22141f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_write_options[] = { 22151f0f5b5bSZachary Turner // clang-format off 22161f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." }, 22172d3628e1SJim Ingham { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."}, 22181f0f5b5bSZachary Turner // clang-format on 22191f0f5b5bSZachary Turner }; 22201f0f5b5bSZachary Turner 22211f0f5b5bSZachary Turner #pragma mark Write 2222e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed { 2223e14dc268SJim Ingham public: 2224e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2225e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write", 2226e14dc268SJim Ingham "Write the breakpoints listed to a file that can " 2227e14dc268SJim Ingham "be read in with \"breakpoint read\". " 2228e14dc268SJim Ingham "If given no arguments, writes all breakpoints.", 2229e14dc268SJim Ingham nullptr), 2230e14dc268SJim Ingham m_options() { 2231e14dc268SJim Ingham CommandArgumentEntry arg; 2232e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2233e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2234e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2235e14dc268SJim Ingham // arguments vector. 2236e14dc268SJim Ingham m_arguments.push_back(arg); 2237e14dc268SJim Ingham } 2238e14dc268SJim Ingham 2239e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default; 2240e14dc268SJim Ingham 2241e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2242e14dc268SJim Ingham 2243e14dc268SJim Ingham class CommandOptions : public Options { 2244e14dc268SJim Ingham public: 2245e14dc268SJim Ingham CommandOptions() : Options() {} 2246e14dc268SJim Ingham 2247e14dc268SJim Ingham ~CommandOptions() override = default; 2248e14dc268SJim Ingham 2249e14dc268SJim Ingham Error SetOptionValue(uint32_t option_idx, const char *option_arg, 2250e14dc268SJim Ingham ExecutionContext *execution_context) override { 2251e14dc268SJim Ingham Error error; 2252e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2253e14dc268SJim Ingham 2254e14dc268SJim Ingham switch (short_option) { 2255e14dc268SJim Ingham case 'f': 2256e14dc268SJim Ingham m_filename.assign(option_arg); 2257e14dc268SJim Ingham break; 22582d3628e1SJim Ingham case 'a': 22592d3628e1SJim Ingham m_append = true; 22602d3628e1SJim Ingham break; 2261e14dc268SJim Ingham default: 2262e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2263e14dc268SJim Ingham short_option); 2264e14dc268SJim Ingham break; 2265e14dc268SJim Ingham } 2266e14dc268SJim Ingham 2267e14dc268SJim Ingham return error; 2268e14dc268SJim Ingham } 2269e14dc268SJim Ingham 2270e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2271e14dc268SJim Ingham m_filename.clear(); 22722d3628e1SJim Ingham m_append = false; 2273e14dc268SJim Ingham } 2274e14dc268SJim Ingham 22751f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 227670602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_write_options); 22771f0f5b5bSZachary Turner } 2278e14dc268SJim Ingham 2279e14dc268SJim Ingham // Instance variables to hold the values for command options. 2280e14dc268SJim Ingham 2281e14dc268SJim Ingham std::string m_filename; 22822d3628e1SJim Ingham bool m_append = false; 2283e14dc268SJim Ingham }; 2284e14dc268SJim Ingham 2285e14dc268SJim Ingham protected: 2286e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2287e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2288e14dc268SJim Ingham if (target == nullptr) { 2289e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2290e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2291e14dc268SJim Ingham return false; 2292e14dc268SJim Ingham } 2293e14dc268SJim Ingham 2294e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2295e14dc268SJim Ingham target->GetBreakpointList().GetListMutex(lock); 2296e14dc268SJim Ingham 2297e14dc268SJim Ingham BreakpointIDList valid_bp_ids; 229811eb9c64SZachary Turner if (!command.empty()) { 2299e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2300e14dc268SJim Ingham command, target, result, &valid_bp_ids); 2301e14dc268SJim Ingham 230201f16664SJim Ingham if (!result.Succeeded()) { 2303e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2304e14dc268SJim Ingham return false; 2305e14dc268SJim Ingham } 2306e14dc268SJim Ingham } 230701f16664SJim Ingham Error error = target->SerializeBreakpointsToFile( 2308*771ef6d4SMalcolm Parsons FileSpec(m_options.m_filename, true), valid_bp_ids, m_options.m_append); 230901f16664SJim Ingham if (!error.Success()) { 231001f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.", 231101f16664SJim Ingham error.AsCString()); 231201f16664SJim Ingham result.SetStatus(eReturnStatusFailed); 2313e14dc268SJim Ingham } 2314e14dc268SJim Ingham return result.Succeeded(); 2315e14dc268SJim Ingham } 2316e14dc268SJim Ingham 2317e14dc268SJim Ingham private: 2318e14dc268SJim Ingham CommandOptions m_options; 2319e14dc268SJim Ingham }; 2320e14dc268SJim Ingham 2321e14dc268SJim Ingham //------------------------------------------------------------------------- 232230fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 232330fdc8d8SChris Lattner //------------------------------------------------------------------------- 2324ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 232530fdc8d8SChris Lattner 2326b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2327b9c1b51eSKate Stone CommandInterpreter &interpreter) 2328b9c1b51eSKate Stone : CommandObjectMultiword( 2329b9c1b51eSKate Stone interpreter, "breakpoint", 23307428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2331b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2332b9c1b51eSKate Stone CommandObjectSP list_command_object( 2333b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2334b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2335b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2336b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2337b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2338b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2339b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2340b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2341b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2342b9c1b51eSKate Stone CommandObjectSP set_command_object( 2343b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2344b9c1b51eSKate Stone CommandObjectSP command_command_object( 2345b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2346b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2347b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2348b9c1b51eSKate Stone CommandObjectSP name_command_object( 2349b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 2350e14dc268SJim Ingham CommandObjectSP write_command_object( 2351e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter)); 2352e14dc268SJim Ingham CommandObjectSP read_command_object( 2353e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter)); 235430fdc8d8SChris Lattner 2355b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 235630fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 235730fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2358b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2359b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2360ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2361b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2362b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 23635e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 2364e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write"); 2365e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read"); 236630fdc8d8SChris Lattner 236723f59509SGreg Clayton LoadSubCommand("list", list_command_object); 236823f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 236923f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 237023f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 237123f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 237223f59509SGreg Clayton LoadSubCommand("set", set_command_object); 237323f59509SGreg Clayton LoadSubCommand("command", command_command_object); 237423f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 23755e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 2376e14dc268SJim Ingham LoadSubCommand("write", write_command_object); 2377e14dc268SJim Ingham LoadSubCommand("read", read_command_object); 237830fdc8d8SChris Lattner } 237930fdc8d8SChris Lattner 23809e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 238130fdc8d8SChris Lattner 2382b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, 23835e09c8c3SJim Ingham bool allow_locations, 23845e09c8c3SJim Ingham CommandReturnObject &result, 2385b9c1b51eSKate Stone BreakpointIDList *valid_ids) { 238630fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2387b9c1b51eSKate Stone // 2). the full breakpoint & location 2388b9c1b51eSKate Stone // canonical representation 2389b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2390b9c1b51eSKate Stone // representing a range (in which case there 2391b9c1b51eSKate Stone // had *better* be an entry both before & 2392b9c1b51eSKate Stone // after of one of the first two types. 23935e09c8c3SJim Ingham // 4). A breakpoint name 2394b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2395b9c1b51eSKate Stone // one.) 239630fdc8d8SChris Lattner 239730fdc8d8SChris Lattner Args temp_args; 239830fdc8d8SChris Lattner 239911eb9c64SZachary Turner if (args.empty()) { 2400b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2401b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2402b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 240336f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2404b9c1b51eSKate Stone } else { 2405b9c1b51eSKate Stone result.AppendError( 2406b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 240736f3b369SJim Ingham result.SetStatus(eReturnStatusFailed); 240836f3b369SJim Ingham } 240936f3b369SJim Ingham return; 241036f3b369SJim Ingham } 241136f3b369SJim Ingham 2412b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 2413b9c1b51eSKate Stone // directly from the old ARGS to 2414b9c1b51eSKate Stone // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead 2415b9c1b51eSKate Stone // generate a list of strings for 2416b9c1b51eSKate Stone // all the breakpoint ids in the range, and shove all of those breakpoint id 2417b9c1b51eSKate Stone // strings into TEMP_ARGS. 241830fdc8d8SChris Lattner 2419b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2420b9c1b51eSKate Stone result, temp_args); 242130fdc8d8SChris Lattner 2422b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2423b9c1b51eSKate Stone // BreakpointIDList: 242430fdc8d8SChris Lattner 2425b9c1b51eSKate Stone valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(), 2426b9c1b51eSKate Stone temp_args.GetArgumentCount(), result); 242730fdc8d8SChris Lattner 2428b9c1b51eSKate Stone // At this point, all of the breakpoint ids that the user passed in have been 2429b9c1b51eSKate Stone // converted to breakpoint IDs 243030fdc8d8SChris Lattner // and put into valid_ids. 243130fdc8d8SChris Lattner 2432b9c1b51eSKate Stone if (result.Succeeded()) { 2433b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 2434b9c1b51eSKate Stone // ids, go through our tentative list 2435b9c1b51eSKate Stone // of breakpoint id's and verify that they correspond to valid/currently set 2436b9c1b51eSKate Stone // breakpoints. 243730fdc8d8SChris Lattner 2438c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2439b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 244030fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2441b9c1b51eSKate Stone Breakpoint *breakpoint = 2442b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2443b9c1b51eSKate Stone if (breakpoint != nullptr) { 2444c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2445b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 244630fdc8d8SChris Lattner StreamString id_str; 2447b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2448b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2449c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2450b9c1b51eSKate Stone result.AppendErrorWithFormat( 2451b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 245230fdc8d8SChris Lattner id_str.GetData()); 245330fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 245430fdc8d8SChris Lattner } 2455b9c1b51eSKate Stone } else { 2456c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2457b9c1b51eSKate Stone result.AppendErrorWithFormat( 2458b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 24597428a18cSKate Stone cur_bp_id.GetBreakpointID()); 246030fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 246130fdc8d8SChris Lattner } 246230fdc8d8SChris Lattner } 246330fdc8d8SChris Lattner } 246430fdc8d8SChris Lattner } 2465