1 //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 // C++ Includes 12 #include <vector> 13 14 // Other libraries and framework includes 15 // Project includes 16 #include "CommandObjectBreakpoint.h" 17 #include "CommandObjectBreakpointCommand.h" 18 #include "lldb/Breakpoint/Breakpoint.h" 19 #include "lldb/Breakpoint/BreakpointIDList.h" 20 #include "lldb/Breakpoint/BreakpointLocation.h" 21 #include "lldb/Core/RegularExpression.h" 22 #include "lldb/Core/StreamString.h" 23 #include "lldb/Host/StringConvert.h" 24 #include "lldb/Interpreter/CommandCompletions.h" 25 #include "lldb/Interpreter/CommandInterpreter.h" 26 #include "lldb/Interpreter/CommandReturnObject.h" 27 #include "lldb/Interpreter/OptionValueBoolean.h" 28 #include "lldb/Interpreter/OptionValueString.h" 29 #include "lldb/Interpreter/OptionValueUInt64.h" 30 #include "lldb/Interpreter/Options.h" 31 #include "lldb/Target/Language.h" 32 #include "lldb/Target/StackFrame.h" 33 #include "lldb/Target/Target.h" 34 #include "lldb/Target/Thread.h" 35 #include "lldb/Target/ThreadSpec.h" 36 37 using namespace lldb; 38 using namespace lldb_private; 39 40 static void AddBreakpointDescription(Stream *s, Breakpoint *bp, 41 lldb::DescriptionLevel level) { 42 s->IndentMore(); 43 bp->GetDescription(s, level, true); 44 s->IndentLess(); 45 s->EOL(); 46 } 47 48 // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to 49 // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. 50 #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2) 51 #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10) 52 #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 53 #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 54 #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) 55 #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) 56 57 static OptionDefinition g_breakpoint_set_options[] = { 58 // clang-format off 59 { 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 " 60 "multiple times to specify multiple shared libraries." }, 61 { 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." }, 62 { 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." }, 63 { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, 64 { 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." }, 65 { 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." }, 66 { 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 " 67 "argument." }, 68 { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." }, 69 { 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 " 70 "this argument." }, 71 { 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 " 72 "lldb only looks for files that are #included if they use the standard include " 73 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " 74 "#included, set target.inline-breakpoint-strategy to \"always\"." }, 75 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." }, 76 77 // Comment out this option for the moment, as we don't actually use it, but will in the future. 78 // This way users won't see it, but the infrastructure is left in place. 79 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>", 80 // "Set the breakpoint by source location at this particular column."}, 81 82 { 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 " 83 "a particular binary, then the address will be converted to a \"file\" " 84 "address, so that the breakpoint will track that binary+offset no matter where " 85 "the binary eventually loads. Alternately, if you also specify the module - " 86 "with the -s option - then the address will be treated as a file address in " 87 "that module, and resolved accordingly. Again, this will allow lldb to track " 88 "that offset on subsequent reloads. The module need not have been loaded at " 89 "the time you specify this breakpoint, and will get resolved when the module " 90 "is loaded." }, 91 { 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 " 92 "one breakpoint for multiple names" }, 93 { 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 " 94 "functions. Can be repeated multiple times." }, 95 { 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 " 96 "namespaces and all arguments, and for Objective C this means a full function " 97 "prototype with class and selector. Can be repeated multiple times to make " 98 "one breakpoint for multiple names." }, 99 { 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 " 100 "make one breakpoint for multiple Selectors." }, 101 { 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 " 102 "make one breakpoint for multiple methods." }, 103 { 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 " 104 "the function name(s)." }, 105 { 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 " 106 "ignored). Can be repeated multiple times to make one breakpoint for multiple " 107 "symbols." }, 108 { 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 " 109 "against the source text in a source file or files specified with the -f " 110 "option. The -f option can be specified more than once. If no source files " 111 "are specified, uses the current \"default source file\". If you want to " 112 "match against all source files, pass the \"--all-files\" option." }, 113 { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches." }, 114 { 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 " 115 "options, on throw but not catch.)" }, 116 { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." }, 117 { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, 118 119 // Don't add this option till it actually does something useful... 120 // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, 121 // "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" }, 122 123 { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression " 124 "(note: currently only implemented for setting breakpoints on identifiers). " 125 "If not set the target.language setting is used." }, 126 { 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. " 127 "If not set the target.skip-prologue setting is used." }, 128 { 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, " 129 "which prime new targets." }, 130 { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." }, 131 { 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. " 132 "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." }, 133 { 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 " 134 "setting is used." }, 135 // clang-format on 136 }; 137 138 //------------------------------------------------------------------------- 139 // CommandObjectBreakpointSet 140 //------------------------------------------------------------------------- 141 142 class CommandObjectBreakpointSet : public CommandObjectParsed { 143 public: 144 typedef enum BreakpointSetType { 145 eSetTypeInvalid, 146 eSetTypeFileAndLine, 147 eSetTypeAddress, 148 eSetTypeFunctionName, 149 eSetTypeFunctionRegexp, 150 eSetTypeSourceRegexp, 151 eSetTypeException 152 } BreakpointSetType; 153 154 CommandObjectBreakpointSet(CommandInterpreter &interpreter) 155 : CommandObjectParsed( 156 interpreter, "breakpoint set", 157 "Sets a breakpoint or set of breakpoints in the executable.", 158 "breakpoint set <cmd-options>"), 159 m_options() {} 160 161 ~CommandObjectBreakpointSet() override = default; 162 163 Options *GetOptions() override { return &m_options; } 164 165 class CommandOptions : public Options { 166 public: 167 CommandOptions() 168 : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0), 169 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone), 170 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(), 171 m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), 172 m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(), 173 m_catch_bp(false), m_throw_bp(true), m_hardware(false), 174 m_exception_language(eLanguageTypeUnknown), 175 m_language(lldb::eLanguageTypeUnknown), 176 m_skip_prologue(eLazyBoolCalculate), m_one_shot(false), 177 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {} 178 179 ~CommandOptions() override = default; 180 181 Error SetOptionValue(uint32_t option_idx, const char *option_arg, 182 ExecutionContext *execution_context) override { 183 Error error; 184 const int short_option = m_getopt_table[option_idx].val; 185 llvm::StringRef option_strref(option_arg ? option_arg : ""); 186 187 switch (short_option) { 188 case 'a': { 189 m_load_addr = Args::StringToAddress(execution_context, option_arg, 190 LLDB_INVALID_ADDRESS, &error); 191 } break; 192 193 case 'A': 194 m_all_files = true; 195 break; 196 197 case 'b': 198 m_func_names.push_back(option_arg); 199 m_func_name_type_mask |= eFunctionNameTypeBase; 200 break; 201 202 case 'C': { 203 bool success; 204 m_column = StringConvert::ToUInt32(option_arg, 0, 0, &success); 205 if (!success) 206 error.SetErrorStringWithFormat("invalid column number: %s", 207 option_arg); 208 break; 209 } 210 211 case 'c': 212 m_condition.assign(option_arg); 213 break; 214 215 case 'D': 216 m_use_dummy = true; 217 break; 218 219 case 'E': { 220 LanguageType language = 221 Language::GetLanguageTypeFromString(option_strref); 222 223 switch (language) { 224 case eLanguageTypeC89: 225 case eLanguageTypeC: 226 case eLanguageTypeC99: 227 case eLanguageTypeC11: 228 m_exception_language = eLanguageTypeC; 229 break; 230 case eLanguageTypeC_plus_plus: 231 case eLanguageTypeC_plus_plus_03: 232 case eLanguageTypeC_plus_plus_11: 233 case eLanguageTypeC_plus_plus_14: 234 m_exception_language = eLanguageTypeC_plus_plus; 235 break; 236 case eLanguageTypeObjC: 237 m_exception_language = eLanguageTypeObjC; 238 break; 239 case eLanguageTypeObjC_plus_plus: 240 error.SetErrorStringWithFormat( 241 "Set exception breakpoints separately for c++ and objective-c"); 242 break; 243 case eLanguageTypeUnknown: 244 error.SetErrorStringWithFormat( 245 "Unknown language type: '%s' for exception breakpoint", 246 option_arg); 247 break; 248 default: 249 error.SetErrorStringWithFormat( 250 "Unsupported language type: '%s' for exception breakpoint", 251 option_arg); 252 } 253 } break; 254 255 case 'f': 256 m_filenames.AppendIfUnique(FileSpec(option_arg, false)); 257 break; 258 259 case 'F': 260 m_func_names.push_back(option_arg); 261 m_func_name_type_mask |= eFunctionNameTypeFull; 262 break; 263 264 case 'h': { 265 bool success; 266 m_catch_bp = Args::StringToBoolean(option_strref, true, &success); 267 if (!success) 268 error.SetErrorStringWithFormat( 269 "Invalid boolean value for on-catch option: '%s'", option_arg); 270 } break; 271 272 case 'H': 273 m_hardware = true; 274 break; 275 276 case 'i': 277 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 278 if (m_ignore_count == UINT32_MAX) 279 error.SetErrorStringWithFormat("invalid ignore count '%s'", 280 option_arg); 281 break; 282 283 case 'K': { 284 bool success; 285 bool value; 286 value = Args::StringToBoolean(option_strref, true, &success); 287 if (value) 288 m_skip_prologue = eLazyBoolYes; 289 else 290 m_skip_prologue = eLazyBoolNo; 291 292 if (!success) 293 error.SetErrorStringWithFormat( 294 "Invalid boolean value for skip prologue option: '%s'", 295 option_arg); 296 } break; 297 298 case 'l': { 299 bool success; 300 m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success); 301 if (!success) 302 error.SetErrorStringWithFormat("invalid line number: %s.", 303 option_arg); 304 break; 305 } 306 307 case 'L': 308 m_language = Language::GetLanguageTypeFromString(option_strref); 309 if (m_language == eLanguageTypeUnknown) 310 error.SetErrorStringWithFormat( 311 "Unknown language type: '%s' for breakpoint", option_arg); 312 break; 313 314 case 'm': { 315 bool success; 316 bool value; 317 value = Args::StringToBoolean(option_strref, true, &success); 318 if (value) 319 m_move_to_nearest_code = eLazyBoolYes; 320 else 321 m_move_to_nearest_code = eLazyBoolNo; 322 323 if (!success) 324 error.SetErrorStringWithFormat( 325 "Invalid boolean value for move-to-nearest-code option: '%s'", 326 option_arg); 327 break; 328 } 329 330 case 'M': 331 m_func_names.push_back(option_arg); 332 m_func_name_type_mask |= eFunctionNameTypeMethod; 333 break; 334 335 case 'n': 336 m_func_names.push_back(option_arg); 337 m_func_name_type_mask |= eFunctionNameTypeAuto; 338 break; 339 340 case 'N': { 341 if (BreakpointID::StringIsBreakpointName(option_strref, error)) 342 m_breakpoint_names.push_back(option_arg); 343 else 344 error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 345 option_arg); 346 break; 347 } 348 349 case 'R': { 350 lldb::addr_t tmp_offset_addr; 351 tmp_offset_addr = 352 Args::StringToAddress(execution_context, option_arg, 0, &error); 353 if (error.Success()) 354 m_offset_addr = tmp_offset_addr; 355 } break; 356 357 case 'o': 358 m_one_shot = true; 359 break; 360 361 case 'O': 362 m_exception_extra_args.AppendArgument(llvm::StringRef("-O")); 363 m_exception_extra_args.AppendArgument(option_strref); 364 break; 365 366 case 'p': 367 m_source_text_regexp.assign(option_arg); 368 break; 369 370 case 'q': 371 m_queue_name.assign(option_arg); 372 break; 373 374 case 'r': 375 m_func_regexp.assign(option_arg); 376 break; 377 378 case 's': 379 m_modules.AppendIfUnique(FileSpec(option_arg, false)); 380 break; 381 382 case 'S': 383 m_func_names.push_back(option_arg); 384 m_func_name_type_mask |= eFunctionNameTypeSelector; 385 break; 386 387 case 't': 388 m_thread_id = 389 StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 390 if (m_thread_id == LLDB_INVALID_THREAD_ID) 391 error.SetErrorStringWithFormat("invalid thread id string '%s'", 392 option_arg); 393 break; 394 395 case 'T': 396 m_thread_name.assign(option_arg); 397 break; 398 399 case 'w': { 400 bool success; 401 m_throw_bp = Args::StringToBoolean(option_strref, true, &success); 402 if (!success) 403 error.SetErrorStringWithFormat( 404 "Invalid boolean value for on-throw option: '%s'", option_arg); 405 } break; 406 407 case 'x': 408 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 409 if (m_thread_id == UINT32_MAX) 410 error.SetErrorStringWithFormat("invalid thread index string '%s'", 411 option_arg); 412 break; 413 414 case 'X': 415 m_source_regex_func_names.insert(option_arg); 416 break; 417 418 default: 419 error.SetErrorStringWithFormat("unrecognized option '%c'", 420 short_option); 421 break; 422 } 423 424 return error; 425 } 426 427 void OptionParsingStarting(ExecutionContext *execution_context) override { 428 m_condition.clear(); 429 m_filenames.Clear(); 430 m_line_num = 0; 431 m_column = 0; 432 m_func_names.clear(); 433 m_func_name_type_mask = eFunctionNameTypeNone; 434 m_func_regexp.clear(); 435 m_source_text_regexp.clear(); 436 m_modules.Clear(); 437 m_load_addr = LLDB_INVALID_ADDRESS; 438 m_offset_addr = 0; 439 m_ignore_count = 0; 440 m_thread_id = LLDB_INVALID_THREAD_ID; 441 m_thread_index = UINT32_MAX; 442 m_thread_name.clear(); 443 m_queue_name.clear(); 444 m_catch_bp = false; 445 m_throw_bp = true; 446 m_hardware = false; 447 m_exception_language = eLanguageTypeUnknown; 448 m_language = lldb::eLanguageTypeUnknown; 449 m_skip_prologue = eLazyBoolCalculate; 450 m_one_shot = false; 451 m_use_dummy = false; 452 m_breakpoint_names.clear(); 453 m_all_files = false; 454 m_exception_extra_args.Clear(); 455 m_move_to_nearest_code = eLazyBoolCalculate; 456 m_source_regex_func_names.clear(); 457 } 458 459 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 460 return llvm::makeArrayRef(g_breakpoint_set_options); 461 } 462 463 // Instance variables to hold the values for command options. 464 465 std::string m_condition; 466 FileSpecList m_filenames; 467 uint32_t m_line_num; 468 uint32_t m_column; 469 std::vector<std::string> m_func_names; 470 std::vector<std::string> m_breakpoint_names; 471 uint32_t m_func_name_type_mask; 472 std::string m_func_regexp; 473 std::string m_source_text_regexp; 474 FileSpecList m_modules; 475 lldb::addr_t m_load_addr; 476 lldb::addr_t m_offset_addr; 477 uint32_t m_ignore_count; 478 lldb::tid_t m_thread_id; 479 uint32_t m_thread_index; 480 std::string m_thread_name; 481 std::string m_queue_name; 482 bool m_catch_bp; 483 bool m_throw_bp; 484 bool m_hardware; // Request to use hardware breakpoints 485 lldb::LanguageType m_exception_language; 486 lldb::LanguageType m_language; 487 LazyBool m_skip_prologue; 488 bool m_one_shot; 489 bool m_use_dummy; 490 bool m_all_files; 491 Args m_exception_extra_args; 492 LazyBool m_move_to_nearest_code; 493 std::unordered_set<std::string> m_source_regex_func_names; 494 }; 495 496 protected: 497 bool DoExecute(Args &command, CommandReturnObject &result) override { 498 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 499 500 if (target == nullptr) { 501 result.AppendError("Invalid target. Must set target before setting " 502 "breakpoints (see 'target create' command)."); 503 result.SetStatus(eReturnStatusFailed); 504 return false; 505 } 506 507 // The following are the various types of breakpoints that could be set: 508 // 1). -f -l -p [-s -g] (setting breakpoint by source location) 509 // 2). -a [-s -g] (setting breakpoint by address) 510 // 3). -n [-s -g] (setting breakpoint by function name) 511 // 4). -r [-s -g] (setting breakpoint by function name regular 512 // expression) 513 // 5). -p -f (setting a breakpoint by comparing a reg-exp 514 // to source text) 515 // 6). -E [-w -h] (setting a breakpoint for exceptions for a 516 // given language.) 517 518 BreakpointSetType break_type = eSetTypeInvalid; 519 520 if (m_options.m_line_num != 0) 521 break_type = eSetTypeFileAndLine; 522 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 523 break_type = eSetTypeAddress; 524 else if (!m_options.m_func_names.empty()) 525 break_type = eSetTypeFunctionName; 526 else if (!m_options.m_func_regexp.empty()) 527 break_type = eSetTypeFunctionRegexp; 528 else if (!m_options.m_source_text_regexp.empty()) 529 break_type = eSetTypeSourceRegexp; 530 else if (m_options.m_exception_language != eLanguageTypeUnknown) 531 break_type = eSetTypeException; 532 533 Breakpoint *bp = nullptr; 534 FileSpec module_spec; 535 const bool internal = false; 536 537 // If the user didn't specify skip-prologue, having an offset should turn 538 // that off. 539 if (m_options.m_offset_addr != 0 && 540 m_options.m_skip_prologue == eLazyBoolCalculate) 541 m_options.m_skip_prologue = eLazyBoolNo; 542 543 switch (break_type) { 544 case eSetTypeFileAndLine: // Breakpoint by source position 545 { 546 FileSpec file; 547 const size_t num_files = m_options.m_filenames.GetSize(); 548 if (num_files == 0) { 549 if (!GetDefaultFile(target, file, result)) { 550 result.AppendError("No file supplied and no default file available."); 551 result.SetStatus(eReturnStatusFailed); 552 return false; 553 } 554 } else if (num_files > 1) { 555 result.AppendError("Only one file at a time is allowed for file and " 556 "line breakpoints."); 557 result.SetStatus(eReturnStatusFailed); 558 return false; 559 } else 560 file = m_options.m_filenames.GetFileSpecAtIndex(0); 561 562 // Only check for inline functions if 563 LazyBool check_inlines = eLazyBoolCalculate; 564 565 bp = target 566 ->CreateBreakpoint(&(m_options.m_modules), file, 567 m_options.m_line_num, m_options.m_offset_addr, 568 check_inlines, m_options.m_skip_prologue, 569 internal, m_options.m_hardware, 570 m_options.m_move_to_nearest_code) 571 .get(); 572 } break; 573 574 case eSetTypeAddress: // Breakpoint by address 575 { 576 // If a shared library has been specified, make an lldb_private::Address 577 // with the library, and 578 // use that. That way the address breakpoint will track the load location 579 // of the library. 580 size_t num_modules_specified = m_options.m_modules.GetSize(); 581 if (num_modules_specified == 1) { 582 const FileSpec *file_spec = 583 m_options.m_modules.GetFileSpecPointerAtIndex(0); 584 bp = target 585 ->CreateAddressInModuleBreakpoint(m_options.m_load_addr, 586 internal, file_spec, 587 m_options.m_hardware) 588 .get(); 589 } else if (num_modules_specified == 0) { 590 bp = target 591 ->CreateBreakpoint(m_options.m_load_addr, internal, 592 m_options.m_hardware) 593 .get(); 594 } else { 595 result.AppendError("Only one shared library can be specified for " 596 "address breakpoints."); 597 result.SetStatus(eReturnStatusFailed); 598 return false; 599 } 600 break; 601 } 602 case eSetTypeFunctionName: // Breakpoint by function name 603 { 604 uint32_t name_type_mask = m_options.m_func_name_type_mask; 605 606 if (name_type_mask == 0) 607 name_type_mask = eFunctionNameTypeAuto; 608 609 bp = target 610 ->CreateBreakpoint( 611 &(m_options.m_modules), &(m_options.m_filenames), 612 m_options.m_func_names, name_type_mask, m_options.m_language, 613 m_options.m_offset_addr, m_options.m_skip_prologue, internal, 614 m_options.m_hardware) 615 .get(); 616 } break; 617 618 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 619 // name 620 { 621 RegularExpression regexp(m_options.m_func_regexp); 622 if (!regexp.IsValid()) { 623 char err_str[1024]; 624 regexp.GetErrorAsCString(err_str, sizeof(err_str)); 625 result.AppendErrorWithFormat( 626 "Function name regular expression could not be compiled: \"%s\"", 627 err_str); 628 result.SetStatus(eReturnStatusFailed); 629 return false; 630 } 631 632 bp = target 633 ->CreateFuncRegexBreakpoint( 634 &(m_options.m_modules), &(m_options.m_filenames), regexp, 635 m_options.m_language, m_options.m_skip_prologue, internal, 636 m_options.m_hardware) 637 .get(); 638 } 639 break; 640 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 641 { 642 const size_t num_files = m_options.m_filenames.GetSize(); 643 644 if (num_files == 0 && !m_options.m_all_files) { 645 FileSpec file; 646 if (!GetDefaultFile(target, file, result)) { 647 result.AppendError( 648 "No files provided and could not find default file."); 649 result.SetStatus(eReturnStatusFailed); 650 return false; 651 } else { 652 m_options.m_filenames.Append(file); 653 } 654 } 655 656 RegularExpression regexp(m_options.m_source_text_regexp); 657 if (!regexp.IsValid()) { 658 char err_str[1024]; 659 regexp.GetErrorAsCString(err_str, sizeof(err_str)); 660 result.AppendErrorWithFormat( 661 "Source text regular expression could not be compiled: \"%s\"", 662 err_str); 663 result.SetStatus(eReturnStatusFailed); 664 return false; 665 } 666 bp = target 667 ->CreateSourceRegexBreakpoint( 668 &(m_options.m_modules), &(m_options.m_filenames), 669 m_options.m_source_regex_func_names, regexp, internal, 670 m_options.m_hardware, m_options.m_move_to_nearest_code) 671 .get(); 672 } break; 673 case eSetTypeException: { 674 Error precond_error; 675 bp = target 676 ->CreateExceptionBreakpoint( 677 m_options.m_exception_language, m_options.m_catch_bp, 678 m_options.m_throw_bp, internal, 679 &m_options.m_exception_extra_args, &precond_error) 680 .get(); 681 if (precond_error.Fail()) { 682 result.AppendErrorWithFormat( 683 "Error setting extra exception arguments: %s", 684 precond_error.AsCString()); 685 target->RemoveBreakpointByID(bp->GetID()); 686 result.SetStatus(eReturnStatusFailed); 687 return false; 688 } 689 } break; 690 default: 691 break; 692 } 693 694 // Now set the various options that were passed in: 695 if (bp) { 696 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 697 bp->SetThreadID(m_options.m_thread_id); 698 699 if (m_options.m_thread_index != UINT32_MAX) 700 bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); 701 702 if (!m_options.m_thread_name.empty()) 703 bp->GetOptions()->GetThreadSpec()->SetName( 704 m_options.m_thread_name.c_str()); 705 706 if (!m_options.m_queue_name.empty()) 707 bp->GetOptions()->GetThreadSpec()->SetQueueName( 708 m_options.m_queue_name.c_str()); 709 710 if (m_options.m_ignore_count != 0) 711 bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); 712 713 if (!m_options.m_condition.empty()) 714 bp->GetOptions()->SetCondition(m_options.m_condition.c_str()); 715 716 if (!m_options.m_breakpoint_names.empty()) { 717 Error name_error; 718 for (auto name : m_options.m_breakpoint_names) { 719 bp->AddName(name.c_str(), name_error); 720 if (name_error.Fail()) { 721 result.AppendErrorWithFormat("Invalid breakpoint name: %s", 722 name.c_str()); 723 target->RemoveBreakpointByID(bp->GetID()); 724 result.SetStatus(eReturnStatusFailed); 725 return false; 726 } 727 } 728 } 729 730 bp->SetOneShot(m_options.m_one_shot); 731 } 732 733 if (bp) { 734 Stream &output_stream = result.GetOutputStream(); 735 const bool show_locations = false; 736 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 737 show_locations); 738 if (target == m_interpreter.GetDebugger().GetDummyTarget()) 739 output_stream.Printf("Breakpoint set in dummy target, will get copied " 740 "into future targets.\n"); 741 else { 742 // Don't print out this warning for exception breakpoints. They can get 743 // set before the target 744 // is set, but we won't know how to actually set the breakpoint till we 745 // run. 746 if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) { 747 output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 748 "actual locations.\n"); 749 } 750 } 751 result.SetStatus(eReturnStatusSuccessFinishResult); 752 } else if (!bp) { 753 result.AppendError("Breakpoint creation failed: No breakpoint created."); 754 result.SetStatus(eReturnStatusFailed); 755 } 756 757 return result.Succeeded(); 758 } 759 760 private: 761 bool GetDefaultFile(Target *target, FileSpec &file, 762 CommandReturnObject &result) { 763 uint32_t default_line; 764 // First use the Source Manager's default file. 765 // Then use the current stack frame's file. 766 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 767 StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 768 if (cur_frame == nullptr) { 769 result.AppendError( 770 "No selected frame to use to find the default file."); 771 result.SetStatus(eReturnStatusFailed); 772 return false; 773 } else if (!cur_frame->HasDebugInformation()) { 774 result.AppendError("Cannot use the selected frame to find the default " 775 "file, it has no debug info."); 776 result.SetStatus(eReturnStatusFailed); 777 return false; 778 } else { 779 const SymbolContext &sc = 780 cur_frame->GetSymbolContext(eSymbolContextLineEntry); 781 if (sc.line_entry.file) { 782 file = sc.line_entry.file; 783 } else { 784 result.AppendError("Can't find the file for the selected frame to " 785 "use as the default file."); 786 result.SetStatus(eReturnStatusFailed); 787 return false; 788 } 789 } 790 } 791 return true; 792 } 793 794 CommandOptions m_options; 795 }; 796 797 //------------------------------------------------------------------------- 798 // CommandObjectBreakpointModify 799 //------------------------------------------------------------------------- 800 801 #pragma mark Modify::CommandOptions 802 static OptionDefinition g_breakpoint_modify_options[] = { 803 // clang-format off 804 { 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." }, 805 { 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." }, 806 { 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." }, 807 { 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." }, 808 { 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." }, 809 { 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." }, 810 { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, 811 { LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." }, 812 { LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." }, 813 { 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." }, 814 // clang-format on 815 }; 816 817 #pragma mark Modify 818 819 class CommandObjectBreakpointModify : public CommandObjectParsed { 820 public: 821 CommandObjectBreakpointModify(CommandInterpreter &interpreter) 822 : CommandObjectParsed(interpreter, "breakpoint modify", 823 "Modify the options on a breakpoint or set of " 824 "breakpoints in the executable. " 825 "If no breakpoint is specified, acts on the last " 826 "created breakpoint. " 827 "With the exception of -e, -d and -i, passing an " 828 "empty argument clears the modification.", 829 nullptr), 830 m_options() { 831 CommandArgumentEntry arg; 832 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 833 eArgTypeBreakpointIDRange); 834 // Add the entry for the first argument for this command to the object's 835 // arguments vector. 836 m_arguments.push_back(arg); 837 } 838 839 ~CommandObjectBreakpointModify() override = default; 840 841 Options *GetOptions() override { return &m_options; } 842 843 class CommandOptions : public Options { 844 public: 845 CommandOptions() 846 : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID), 847 m_thread_id_passed(false), m_thread_index(UINT32_MAX), 848 m_thread_index_passed(false), m_thread_name(), m_queue_name(), 849 m_condition(), m_one_shot(false), m_enable_passed(false), 850 m_enable_value(false), m_name_passed(false), m_queue_passed(false), 851 m_condition_passed(false), m_one_shot_passed(false), 852 m_use_dummy(false) {} 853 854 ~CommandOptions() override = default; 855 856 Error SetOptionValue(uint32_t option_idx, const char *option_arg, 857 ExecutionContext *execution_context) override { 858 Error error; 859 const int short_option = m_getopt_table[option_idx].val; 860 861 switch (short_option) { 862 case 'c': 863 if (option_arg != nullptr) 864 m_condition.assign(option_arg); 865 else 866 m_condition.clear(); 867 m_condition_passed = true; 868 break; 869 case 'd': 870 m_enable_passed = true; 871 m_enable_value = false; 872 break; 873 case 'D': 874 m_use_dummy = true; 875 break; 876 case 'e': 877 m_enable_passed = true; 878 m_enable_value = true; 879 break; 880 case 'i': 881 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 882 if (m_ignore_count == UINT32_MAX) 883 error.SetErrorStringWithFormat("invalid ignore count '%s'", 884 option_arg); 885 break; 886 case 'o': { 887 bool value, success; 888 value = Args::StringToBoolean( 889 llvm::StringRef::withNullAsEmpty(option_arg), false, &success); 890 if (success) { 891 m_one_shot_passed = true; 892 m_one_shot = value; 893 } else 894 error.SetErrorStringWithFormat( 895 "invalid boolean value '%s' passed for -o option", option_arg); 896 } break; 897 case 't': 898 if (option_arg[0] == '\0') { 899 m_thread_id = LLDB_INVALID_THREAD_ID; 900 m_thread_id_passed = true; 901 } else { 902 m_thread_id = 903 StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 904 if (m_thread_id == LLDB_INVALID_THREAD_ID) 905 error.SetErrorStringWithFormat("invalid thread id string '%s'", 906 option_arg); 907 else 908 m_thread_id_passed = true; 909 } 910 break; 911 case 'T': 912 if (option_arg != nullptr) 913 m_thread_name.assign(option_arg); 914 else 915 m_thread_name.clear(); 916 m_name_passed = true; 917 break; 918 case 'q': 919 if (option_arg != nullptr) 920 m_queue_name.assign(option_arg); 921 else 922 m_queue_name.clear(); 923 m_queue_passed = true; 924 break; 925 case 'x': 926 if (option_arg[0] == '\n') { 927 m_thread_index = UINT32_MAX; 928 m_thread_index_passed = true; 929 } else { 930 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 931 if (m_thread_id == UINT32_MAX) 932 error.SetErrorStringWithFormat("invalid thread index string '%s'", 933 option_arg); 934 else 935 m_thread_index_passed = true; 936 } 937 break; 938 default: 939 error.SetErrorStringWithFormat("unrecognized option '%c'", 940 short_option); 941 break; 942 } 943 944 return error; 945 } 946 947 void OptionParsingStarting(ExecutionContext *execution_context) override { 948 m_ignore_count = 0; 949 m_thread_id = LLDB_INVALID_THREAD_ID; 950 m_thread_id_passed = false; 951 m_thread_index = UINT32_MAX; 952 m_thread_index_passed = false; 953 m_thread_name.clear(); 954 m_queue_name.clear(); 955 m_condition.clear(); 956 m_one_shot = false; 957 m_enable_passed = false; 958 m_queue_passed = false; 959 m_name_passed = false; 960 m_condition_passed = false; 961 m_one_shot_passed = false; 962 m_use_dummy = false; 963 } 964 965 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 966 return llvm::makeArrayRef(g_breakpoint_modify_options); 967 } 968 969 // Instance variables to hold the values for command options. 970 971 uint32_t m_ignore_count; 972 lldb::tid_t m_thread_id; 973 bool m_thread_id_passed; 974 uint32_t m_thread_index; 975 bool m_thread_index_passed; 976 std::string m_thread_name; 977 std::string m_queue_name; 978 std::string m_condition; 979 bool m_one_shot; 980 bool m_enable_passed; 981 bool m_enable_value; 982 bool m_name_passed; 983 bool m_queue_passed; 984 bool m_condition_passed; 985 bool m_one_shot_passed; 986 bool m_use_dummy; 987 }; 988 989 protected: 990 bool DoExecute(Args &command, CommandReturnObject &result) override { 991 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 992 if (target == nullptr) { 993 result.AppendError("Invalid target. No existing target or breakpoints."); 994 result.SetStatus(eReturnStatusFailed); 995 return false; 996 } 997 998 std::unique_lock<std::recursive_mutex> lock; 999 target->GetBreakpointList().GetListMutex(lock); 1000 1001 BreakpointIDList valid_bp_ids; 1002 1003 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1004 command, target, result, &valid_bp_ids); 1005 1006 if (result.Succeeded()) { 1007 const size_t count = valid_bp_ids.GetSize(); 1008 for (size_t i = 0; i < count; ++i) { 1009 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1010 1011 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1012 Breakpoint *bp = 1013 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1014 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1015 BreakpointLocation *location = 1016 bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1017 if (location) { 1018 if (m_options.m_thread_id_passed) 1019 location->SetThreadID(m_options.m_thread_id); 1020 1021 if (m_options.m_thread_index_passed) 1022 location->SetThreadIndex(m_options.m_thread_index); 1023 1024 if (m_options.m_name_passed) 1025 location->SetThreadName(m_options.m_thread_name.c_str()); 1026 1027 if (m_options.m_queue_passed) 1028 location->SetQueueName(m_options.m_queue_name.c_str()); 1029 1030 if (m_options.m_ignore_count != 0) 1031 location->SetIgnoreCount(m_options.m_ignore_count); 1032 1033 if (m_options.m_enable_passed) 1034 location->SetEnabled(m_options.m_enable_value); 1035 1036 if (m_options.m_condition_passed) 1037 location->SetCondition(m_options.m_condition.c_str()); 1038 } 1039 } else { 1040 if (m_options.m_thread_id_passed) 1041 bp->SetThreadID(m_options.m_thread_id); 1042 1043 if (m_options.m_thread_index_passed) 1044 bp->SetThreadIndex(m_options.m_thread_index); 1045 1046 if (m_options.m_name_passed) 1047 bp->SetThreadName(m_options.m_thread_name.c_str()); 1048 1049 if (m_options.m_queue_passed) 1050 bp->SetQueueName(m_options.m_queue_name.c_str()); 1051 1052 if (m_options.m_ignore_count != 0) 1053 bp->SetIgnoreCount(m_options.m_ignore_count); 1054 1055 if (m_options.m_enable_passed) 1056 bp->SetEnabled(m_options.m_enable_value); 1057 1058 if (m_options.m_condition_passed) 1059 bp->SetCondition(m_options.m_condition.c_str()); 1060 } 1061 } 1062 } 1063 } 1064 1065 return result.Succeeded(); 1066 } 1067 1068 private: 1069 CommandOptions m_options; 1070 }; 1071 1072 //------------------------------------------------------------------------- 1073 // CommandObjectBreakpointEnable 1074 //------------------------------------------------------------------------- 1075 #pragma mark Enable 1076 1077 class CommandObjectBreakpointEnable : public CommandObjectParsed { 1078 public: 1079 CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 1080 : CommandObjectParsed(interpreter, "enable", 1081 "Enable the specified disabled breakpoint(s). If " 1082 "no breakpoints are specified, enable all of them.", 1083 nullptr) { 1084 CommandArgumentEntry arg; 1085 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1086 eArgTypeBreakpointIDRange); 1087 // Add the entry for the first argument for this command to the object's 1088 // arguments vector. 1089 m_arguments.push_back(arg); 1090 } 1091 1092 ~CommandObjectBreakpointEnable() override = default; 1093 1094 protected: 1095 bool DoExecute(Args &command, CommandReturnObject &result) override { 1096 Target *target = GetSelectedOrDummyTarget(); 1097 if (target == nullptr) { 1098 result.AppendError("Invalid target. No existing target or breakpoints."); 1099 result.SetStatus(eReturnStatusFailed); 1100 return false; 1101 } 1102 1103 std::unique_lock<std::recursive_mutex> lock; 1104 target->GetBreakpointList().GetListMutex(lock); 1105 1106 const BreakpointList &breakpoints = target->GetBreakpointList(); 1107 1108 size_t num_breakpoints = breakpoints.GetSize(); 1109 1110 if (num_breakpoints == 0) { 1111 result.AppendError("No breakpoints exist to be enabled."); 1112 result.SetStatus(eReturnStatusFailed); 1113 return false; 1114 } 1115 1116 if (command.empty()) { 1117 // No breakpoint selected; enable all currently set breakpoints. 1118 target->EnableAllBreakpoints(); 1119 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 1120 " breakpoints)\n", 1121 (uint64_t)num_breakpoints); 1122 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1123 } else { 1124 // Particular breakpoint selected; enable that breakpoint. 1125 BreakpointIDList valid_bp_ids; 1126 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1127 command, target, result, &valid_bp_ids); 1128 1129 if (result.Succeeded()) { 1130 int enable_count = 0; 1131 int loc_count = 0; 1132 const size_t count = valid_bp_ids.GetSize(); 1133 for (size_t i = 0; i < count; ++i) { 1134 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1135 1136 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1137 Breakpoint *breakpoint = 1138 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1139 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1140 BreakpointLocation *location = 1141 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1142 if (location) { 1143 location->SetEnabled(true); 1144 ++loc_count; 1145 } 1146 } else { 1147 breakpoint->SetEnabled(true); 1148 ++enable_count; 1149 } 1150 } 1151 } 1152 result.AppendMessageWithFormat("%d breakpoints enabled.\n", 1153 enable_count + loc_count); 1154 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1155 } 1156 } 1157 1158 return result.Succeeded(); 1159 } 1160 }; 1161 1162 //------------------------------------------------------------------------- 1163 // CommandObjectBreakpointDisable 1164 //------------------------------------------------------------------------- 1165 #pragma mark Disable 1166 1167 class CommandObjectBreakpointDisable : public CommandObjectParsed { 1168 public: 1169 CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 1170 : CommandObjectParsed( 1171 interpreter, "breakpoint disable", 1172 "Disable the specified breakpoint(s) without deleting " 1173 "them. If none are specified, disable all " 1174 "breakpoints.", 1175 nullptr) { 1176 SetHelpLong( 1177 "Disable the specified breakpoint(s) without deleting them. \ 1178 If none are specified, disable all breakpoints." 1179 R"( 1180 1181 )" 1182 "Note: disabling a breakpoint will cause none of its locations to be hit \ 1183 regardless of whether individual locations are enabled or disabled. After the sequence:" 1184 R"( 1185 1186 (lldb) break disable 1 1187 (lldb) break enable 1.1 1188 1189 execution will NOT stop at location 1.1. To achieve that, type: 1190 1191 (lldb) break disable 1.* 1192 (lldb) break enable 1.1 1193 1194 )" 1195 "The first command disables all locations for breakpoint 1, \ 1196 the second re-enables the first location."); 1197 1198 CommandArgumentEntry arg; 1199 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1200 eArgTypeBreakpointIDRange); 1201 // Add the entry for the first argument for this command to the object's 1202 // arguments vector. 1203 m_arguments.push_back(arg); 1204 } 1205 1206 ~CommandObjectBreakpointDisable() override = default; 1207 1208 protected: 1209 bool DoExecute(Args &command, CommandReturnObject &result) override { 1210 Target *target = GetSelectedOrDummyTarget(); 1211 if (target == nullptr) { 1212 result.AppendError("Invalid target. No existing target or breakpoints."); 1213 result.SetStatus(eReturnStatusFailed); 1214 return false; 1215 } 1216 1217 std::unique_lock<std::recursive_mutex> lock; 1218 target->GetBreakpointList().GetListMutex(lock); 1219 1220 const BreakpointList &breakpoints = target->GetBreakpointList(); 1221 size_t num_breakpoints = breakpoints.GetSize(); 1222 1223 if (num_breakpoints == 0) { 1224 result.AppendError("No breakpoints exist to be disabled."); 1225 result.SetStatus(eReturnStatusFailed); 1226 return false; 1227 } 1228 1229 if (command.empty()) { 1230 // No breakpoint selected; disable all currently set breakpoints. 1231 target->DisableAllBreakpoints(); 1232 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1233 " breakpoints)\n", 1234 (uint64_t)num_breakpoints); 1235 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1236 } else { 1237 // Particular breakpoint selected; disable that breakpoint. 1238 BreakpointIDList valid_bp_ids; 1239 1240 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1241 command, target, result, &valid_bp_ids); 1242 1243 if (result.Succeeded()) { 1244 int disable_count = 0; 1245 int loc_count = 0; 1246 const size_t count = valid_bp_ids.GetSize(); 1247 for (size_t i = 0; i < count; ++i) { 1248 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1249 1250 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1251 Breakpoint *breakpoint = 1252 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1253 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1254 BreakpointLocation *location = 1255 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1256 if (location) { 1257 location->SetEnabled(false); 1258 ++loc_count; 1259 } 1260 } else { 1261 breakpoint->SetEnabled(false); 1262 ++disable_count; 1263 } 1264 } 1265 } 1266 result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1267 disable_count + loc_count); 1268 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1269 } 1270 } 1271 1272 return result.Succeeded(); 1273 } 1274 }; 1275 1276 //------------------------------------------------------------------------- 1277 // CommandObjectBreakpointList 1278 //------------------------------------------------------------------------- 1279 1280 #pragma mark List::CommandOptions 1281 static OptionDefinition g_breakpoint_list_options[] = { 1282 // clang-format off 1283 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" }, 1284 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." }, 1285 // FIXME: We need to add an "internal" command, and then add this sort of thing to it. 1286 // But I need to see it for now, and don't want to wait. 1287 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." }, 1288 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, 1289 { 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." }, 1290 // clang-format on 1291 }; 1292 1293 #pragma mark List 1294 1295 class CommandObjectBreakpointList : public CommandObjectParsed { 1296 public: 1297 CommandObjectBreakpointList(CommandInterpreter &interpreter) 1298 : CommandObjectParsed( 1299 interpreter, "breakpoint list", 1300 "List some or all breakpoints at configurable levels of detail.", 1301 nullptr), 1302 m_options() { 1303 CommandArgumentEntry arg; 1304 CommandArgumentData bp_id_arg; 1305 1306 // Define the first (and only) variant of this arg. 1307 bp_id_arg.arg_type = eArgTypeBreakpointID; 1308 bp_id_arg.arg_repetition = eArgRepeatOptional; 1309 1310 // There is only one variant this argument could be; put it into the 1311 // argument entry. 1312 arg.push_back(bp_id_arg); 1313 1314 // Push the data for the first argument into the m_arguments vector. 1315 m_arguments.push_back(arg); 1316 } 1317 1318 ~CommandObjectBreakpointList() override = default; 1319 1320 Options *GetOptions() override { return &m_options; } 1321 1322 class CommandOptions : public Options { 1323 public: 1324 CommandOptions() 1325 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 1326 } 1327 1328 ~CommandOptions() override = default; 1329 1330 Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1331 ExecutionContext *execution_context) override { 1332 Error error; 1333 const int short_option = m_getopt_table[option_idx].val; 1334 1335 switch (short_option) { 1336 case 'b': 1337 m_level = lldb::eDescriptionLevelBrief; 1338 break; 1339 case 'D': 1340 m_use_dummy = true; 1341 break; 1342 case 'f': 1343 m_level = lldb::eDescriptionLevelFull; 1344 break; 1345 case 'v': 1346 m_level = lldb::eDescriptionLevelVerbose; 1347 break; 1348 case 'i': 1349 m_internal = true; 1350 break; 1351 default: 1352 error.SetErrorStringWithFormat("unrecognized option '%c'", 1353 short_option); 1354 break; 1355 } 1356 1357 return error; 1358 } 1359 1360 void OptionParsingStarting(ExecutionContext *execution_context) override { 1361 m_level = lldb::eDescriptionLevelFull; 1362 m_internal = false; 1363 m_use_dummy = false; 1364 } 1365 1366 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1367 return llvm::makeArrayRef(g_breakpoint_list_options); 1368 } 1369 1370 // Instance variables to hold the values for command options. 1371 1372 lldb::DescriptionLevel m_level; 1373 1374 bool m_internal; 1375 bool m_use_dummy; 1376 }; 1377 1378 protected: 1379 bool DoExecute(Args &command, CommandReturnObject &result) override { 1380 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1381 1382 if (target == nullptr) { 1383 result.AppendError("Invalid target. No current target or breakpoints."); 1384 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1385 return true; 1386 } 1387 1388 const BreakpointList &breakpoints = 1389 target->GetBreakpointList(m_options.m_internal); 1390 std::unique_lock<std::recursive_mutex> lock; 1391 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); 1392 1393 size_t num_breakpoints = breakpoints.GetSize(); 1394 1395 if (num_breakpoints == 0) { 1396 result.AppendMessage("No breakpoints currently set."); 1397 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1398 return true; 1399 } 1400 1401 Stream &output_stream = result.GetOutputStream(); 1402 1403 if (command.empty()) { 1404 // No breakpoint selected; show info about all currently set breakpoints. 1405 result.AppendMessage("Current breakpoints:"); 1406 for (size_t i = 0; i < num_breakpoints; ++i) { 1407 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1408 AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level); 1409 } 1410 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1411 } else { 1412 // Particular breakpoints selected; show info about that breakpoint. 1413 BreakpointIDList valid_bp_ids; 1414 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1415 command, target, result, &valid_bp_ids); 1416 1417 if (result.Succeeded()) { 1418 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 1419 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1420 Breakpoint *breakpoint = 1421 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1422 AddBreakpointDescription(&output_stream, breakpoint, 1423 m_options.m_level); 1424 } 1425 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1426 } else { 1427 result.AppendError("Invalid breakpoint ID."); 1428 result.SetStatus(eReturnStatusFailed); 1429 } 1430 } 1431 1432 return result.Succeeded(); 1433 } 1434 1435 private: 1436 CommandOptions m_options; 1437 }; 1438 1439 //------------------------------------------------------------------------- 1440 // CommandObjectBreakpointClear 1441 //------------------------------------------------------------------------- 1442 #pragma mark Clear::CommandOptions 1443 1444 static OptionDefinition g_breakpoint_clear_options[] = { 1445 // clang-format off 1446 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." }, 1447 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." } 1448 // clang-format on 1449 }; 1450 1451 #pragma mark Clear 1452 1453 class CommandObjectBreakpointClear : public CommandObjectParsed { 1454 public: 1455 typedef enum BreakpointClearType { 1456 eClearTypeInvalid, 1457 eClearTypeFileAndLine 1458 } BreakpointClearType; 1459 1460 CommandObjectBreakpointClear(CommandInterpreter &interpreter) 1461 : CommandObjectParsed(interpreter, "breakpoint clear", 1462 "Delete or disable breakpoints matching the " 1463 "specified source file and line.", 1464 "breakpoint clear <cmd-options>"), 1465 m_options() {} 1466 1467 ~CommandObjectBreakpointClear() override = default; 1468 1469 Options *GetOptions() override { return &m_options; } 1470 1471 class CommandOptions : public Options { 1472 public: 1473 CommandOptions() : Options(), m_filename(), m_line_num(0) {} 1474 1475 ~CommandOptions() override = default; 1476 1477 Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1478 ExecutionContext *execution_context) override { 1479 Error error; 1480 const int short_option = m_getopt_table[option_idx].val; 1481 1482 switch (short_option) { 1483 case 'f': 1484 m_filename.assign(option_arg); 1485 break; 1486 1487 case 'l': 1488 m_line_num = StringConvert::ToUInt32(option_arg, 0); 1489 break; 1490 1491 default: 1492 error.SetErrorStringWithFormat("unrecognized option '%c'", 1493 short_option); 1494 break; 1495 } 1496 1497 return error; 1498 } 1499 1500 void OptionParsingStarting(ExecutionContext *execution_context) override { 1501 m_filename.clear(); 1502 m_line_num = 0; 1503 } 1504 1505 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1506 return llvm::makeArrayRef(g_breakpoint_clear_options); 1507 } 1508 1509 // Instance variables to hold the values for command options. 1510 1511 std::string m_filename; 1512 uint32_t m_line_num; 1513 }; 1514 1515 protected: 1516 bool DoExecute(Args &command, CommandReturnObject &result) override { 1517 Target *target = GetSelectedOrDummyTarget(); 1518 if (target == nullptr) { 1519 result.AppendError("Invalid target. No existing target or breakpoints."); 1520 result.SetStatus(eReturnStatusFailed); 1521 return false; 1522 } 1523 1524 // The following are the various types of breakpoints that could be cleared: 1525 // 1). -f -l (clearing breakpoint by source location) 1526 1527 BreakpointClearType break_type = eClearTypeInvalid; 1528 1529 if (m_options.m_line_num != 0) 1530 break_type = eClearTypeFileAndLine; 1531 1532 std::unique_lock<std::recursive_mutex> lock; 1533 target->GetBreakpointList().GetListMutex(lock); 1534 1535 BreakpointList &breakpoints = target->GetBreakpointList(); 1536 size_t num_breakpoints = breakpoints.GetSize(); 1537 1538 // Early return if there's no breakpoint at all. 1539 if (num_breakpoints == 0) { 1540 result.AppendError("Breakpoint clear: No breakpoint cleared."); 1541 result.SetStatus(eReturnStatusFailed); 1542 return result.Succeeded(); 1543 } 1544 1545 // Find matching breakpoints and delete them. 1546 1547 // First create a copy of all the IDs. 1548 std::vector<break_id_t> BreakIDs; 1549 for (size_t i = 0; i < num_breakpoints; ++i) 1550 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 1551 1552 int num_cleared = 0; 1553 StreamString ss; 1554 switch (break_type) { 1555 case eClearTypeFileAndLine: // Breakpoint by source position 1556 { 1557 const ConstString filename(m_options.m_filename.c_str()); 1558 BreakpointLocationCollection loc_coll; 1559 1560 for (size_t i = 0; i < num_breakpoints; ++i) { 1561 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 1562 1563 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1564 // If the collection size is 0, it's a full match and we can just 1565 // remove the breakpoint. 1566 if (loc_coll.GetSize() == 0) { 1567 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 1568 ss.EOL(); 1569 target->RemoveBreakpointByID(bp->GetID()); 1570 ++num_cleared; 1571 } 1572 } 1573 } 1574 } break; 1575 1576 default: 1577 break; 1578 } 1579 1580 if (num_cleared > 0) { 1581 Stream &output_stream = result.GetOutputStream(); 1582 output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1583 output_stream << ss.GetData(); 1584 output_stream.EOL(); 1585 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1586 } else { 1587 result.AppendError("Breakpoint clear: No breakpoint cleared."); 1588 result.SetStatus(eReturnStatusFailed); 1589 } 1590 1591 return result.Succeeded(); 1592 } 1593 1594 private: 1595 CommandOptions m_options; 1596 }; 1597 1598 //------------------------------------------------------------------------- 1599 // CommandObjectBreakpointDelete 1600 //------------------------------------------------------------------------- 1601 static OptionDefinition g_breakpoint_delete_options[] = { 1602 // clang-format off 1603 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." }, 1604 { 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." }, 1605 // clang-format on 1606 }; 1607 1608 #pragma mark Delete 1609 1610 class CommandObjectBreakpointDelete : public CommandObjectParsed { 1611 public: 1612 CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1613 : CommandObjectParsed(interpreter, "breakpoint delete", 1614 "Delete the specified breakpoint(s). If no " 1615 "breakpoints are specified, delete them all.", 1616 nullptr), 1617 m_options() { 1618 CommandArgumentEntry arg; 1619 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1620 eArgTypeBreakpointIDRange); 1621 // Add the entry for the first argument for this command to the object's 1622 // arguments vector. 1623 m_arguments.push_back(arg); 1624 } 1625 1626 ~CommandObjectBreakpointDelete() override = default; 1627 1628 Options *GetOptions() override { return &m_options; } 1629 1630 class CommandOptions : public Options { 1631 public: 1632 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 1633 1634 ~CommandOptions() override = default; 1635 1636 Error SetOptionValue(uint32_t option_idx, const char *option_arg, 1637 ExecutionContext *execution_context) override { 1638 Error error; 1639 const int short_option = m_getopt_table[option_idx].val; 1640 1641 switch (short_option) { 1642 case 'f': 1643 m_force = true; 1644 break; 1645 1646 case 'D': 1647 m_use_dummy = true; 1648 break; 1649 1650 default: 1651 error.SetErrorStringWithFormat("unrecognized option '%c'", 1652 short_option); 1653 break; 1654 } 1655 1656 return error; 1657 } 1658 1659 void OptionParsingStarting(ExecutionContext *execution_context) override { 1660 m_use_dummy = false; 1661 m_force = false; 1662 } 1663 1664 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1665 return llvm::makeArrayRef(g_breakpoint_delete_options); 1666 } 1667 1668 // Instance variables to hold the values for command options. 1669 bool m_use_dummy; 1670 bool m_force; 1671 }; 1672 1673 protected: 1674 bool DoExecute(Args &command, CommandReturnObject &result) override { 1675 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1676 1677 if (target == nullptr) { 1678 result.AppendError("Invalid target. No existing target or breakpoints."); 1679 result.SetStatus(eReturnStatusFailed); 1680 return false; 1681 } 1682 1683 std::unique_lock<std::recursive_mutex> lock; 1684 target->GetBreakpointList().GetListMutex(lock); 1685 1686 const BreakpointList &breakpoints = target->GetBreakpointList(); 1687 1688 size_t num_breakpoints = breakpoints.GetSize(); 1689 1690 if (num_breakpoints == 0) { 1691 result.AppendError("No breakpoints exist to be deleted."); 1692 result.SetStatus(eReturnStatusFailed); 1693 return false; 1694 } 1695 1696 if (command.empty()) { 1697 if (!m_options.m_force && 1698 !m_interpreter.Confirm( 1699 "About to delete all breakpoints, do you want to do that?", 1700 true)) { 1701 result.AppendMessage("Operation cancelled..."); 1702 } else { 1703 target->RemoveAllBreakpoints(); 1704 result.AppendMessageWithFormat( 1705 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1706 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 1707 } 1708 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1709 } else { 1710 // Particular breakpoint selected; disable that breakpoint. 1711 BreakpointIDList valid_bp_ids; 1712 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1713 command, target, result, &valid_bp_ids); 1714 1715 if (result.Succeeded()) { 1716 int delete_count = 0; 1717 int disable_count = 0; 1718 const size_t count = valid_bp_ids.GetSize(); 1719 for (size_t i = 0; i < count; ++i) { 1720 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1721 1722 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1723 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1724 Breakpoint *breakpoint = 1725 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1726 BreakpointLocation *location = 1727 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1728 // It makes no sense to try to delete individual locations, so we 1729 // disable them instead. 1730 if (location) { 1731 location->SetEnabled(false); 1732 ++disable_count; 1733 } 1734 } else { 1735 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 1736 ++delete_count; 1737 } 1738 } 1739 } 1740 result.AppendMessageWithFormat( 1741 "%d breakpoints deleted; %d breakpoint locations disabled.\n", 1742 delete_count, disable_count); 1743 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1744 } 1745 } 1746 return result.Succeeded(); 1747 } 1748 1749 private: 1750 CommandOptions m_options; 1751 }; 1752 1753 //------------------------------------------------------------------------- 1754 // CommandObjectBreakpointName 1755 //------------------------------------------------------------------------- 1756 1757 static OptionDefinition g_breakpoint_name_options[] = { 1758 // clang-format off 1759 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, 1760 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, 1761 {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."}, 1762 // clang-format on 1763 }; 1764 class BreakpointNameOptionGroup : public OptionGroup { 1765 public: 1766 BreakpointNameOptionGroup() 1767 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 1768 } 1769 1770 ~BreakpointNameOptionGroup() override = default; 1771 1772 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1773 return llvm::makeArrayRef(g_breakpoint_name_options); 1774 } 1775 1776 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 1777 ExecutionContext *execution_context) override { 1778 Error error; 1779 const int short_option = g_breakpoint_name_options[option_idx].short_option; 1780 1781 switch (short_option) { 1782 case 'N': 1783 if (BreakpointID::StringIsBreakpointName(option_value, error) && 1784 error.Success()) 1785 m_name.SetValueFromString(option_value); 1786 break; 1787 1788 case 'B': 1789 if (m_breakpoint.SetValueFromString(option_value).Fail()) 1790 error.SetErrorStringWithFormat( 1791 "unrecognized value \"%s\" for breakpoint", 1792 option_value.str().c_str()); 1793 break; 1794 case 'D': 1795 if (m_use_dummy.SetValueFromString(option_value).Fail()) 1796 error.SetErrorStringWithFormat( 1797 "unrecognized value \"%s\" for use-dummy", 1798 option_value.str().c_str()); 1799 break; 1800 1801 default: 1802 error.SetErrorStringWithFormat("unrecognized short option '%c'", 1803 short_option); 1804 break; 1805 } 1806 return error; 1807 } 1808 Error SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete; 1809 1810 void OptionParsingStarting(ExecutionContext *execution_context) override { 1811 m_name.Clear(); 1812 m_breakpoint.Clear(); 1813 m_use_dummy.Clear(); 1814 m_use_dummy.SetDefaultValue(false); 1815 } 1816 1817 OptionValueString m_name; 1818 OptionValueUInt64 m_breakpoint; 1819 OptionValueBoolean m_use_dummy; 1820 }; 1821 1822 class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 1823 public: 1824 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1825 : CommandObjectParsed( 1826 interpreter, "add", "Add a name to the breakpoints provided.", 1827 "breakpoint name add <command-options> <breakpoint-id-list>"), 1828 m_name_options(), m_option_group() { 1829 // Create the first variant for the first (and only) argument for this 1830 // command. 1831 CommandArgumentEntry arg1; 1832 CommandArgumentData id_arg; 1833 id_arg.arg_type = eArgTypeBreakpointID; 1834 id_arg.arg_repetition = eArgRepeatOptional; 1835 arg1.push_back(id_arg); 1836 m_arguments.push_back(arg1); 1837 1838 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 1839 m_option_group.Finalize(); 1840 } 1841 1842 ~CommandObjectBreakpointNameAdd() override = default; 1843 1844 Options *GetOptions() override { return &m_option_group; } 1845 1846 protected: 1847 bool DoExecute(Args &command, CommandReturnObject &result) override { 1848 if (!m_name_options.m_name.OptionWasSet()) { 1849 result.SetError("No name option provided."); 1850 return false; 1851 } 1852 1853 Target *target = 1854 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1855 1856 if (target == nullptr) { 1857 result.AppendError("Invalid target. No existing target or breakpoints."); 1858 result.SetStatus(eReturnStatusFailed); 1859 return false; 1860 } 1861 1862 std::unique_lock<std::recursive_mutex> lock; 1863 target->GetBreakpointList().GetListMutex(lock); 1864 1865 const BreakpointList &breakpoints = target->GetBreakpointList(); 1866 1867 size_t num_breakpoints = breakpoints.GetSize(); 1868 if (num_breakpoints == 0) { 1869 result.SetError("No breakpoints, cannot add names."); 1870 result.SetStatus(eReturnStatusFailed); 1871 return false; 1872 } 1873 1874 // Particular breakpoint selected; disable that breakpoint. 1875 BreakpointIDList valid_bp_ids; 1876 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1877 command, target, result, &valid_bp_ids); 1878 1879 if (result.Succeeded()) { 1880 if (valid_bp_ids.GetSize() == 0) { 1881 result.SetError("No breakpoints specified, cannot add names."); 1882 result.SetStatus(eReturnStatusFailed); 1883 return false; 1884 } 1885 size_t num_valid_ids = valid_bp_ids.GetSize(); 1886 for (size_t index = 0; index < num_valid_ids; index++) { 1887 lldb::break_id_t bp_id = 1888 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 1889 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1890 Error error; // We don't need to check the error here, since the option 1891 // parser checked it... 1892 bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error); 1893 } 1894 } 1895 1896 return true; 1897 } 1898 1899 private: 1900 BreakpointNameOptionGroup m_name_options; 1901 OptionGroupOptions m_option_group; 1902 }; 1903 1904 class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 1905 public: 1906 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1907 : CommandObjectParsed( 1908 interpreter, "delete", 1909 "Delete a name from the breakpoints provided.", 1910 "breakpoint name delete <command-options> <breakpoint-id-list>"), 1911 m_name_options(), m_option_group() { 1912 // Create the first variant for the first (and only) argument for this 1913 // command. 1914 CommandArgumentEntry arg1; 1915 CommandArgumentData id_arg; 1916 id_arg.arg_type = eArgTypeBreakpointID; 1917 id_arg.arg_repetition = eArgRepeatOptional; 1918 arg1.push_back(id_arg); 1919 m_arguments.push_back(arg1); 1920 1921 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 1922 m_option_group.Finalize(); 1923 } 1924 1925 ~CommandObjectBreakpointNameDelete() override = default; 1926 1927 Options *GetOptions() override { return &m_option_group; } 1928 1929 protected: 1930 bool DoExecute(Args &command, CommandReturnObject &result) override { 1931 if (!m_name_options.m_name.OptionWasSet()) { 1932 result.SetError("No name option provided."); 1933 return false; 1934 } 1935 1936 Target *target = 1937 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1938 1939 if (target == nullptr) { 1940 result.AppendError("Invalid target. No existing target or breakpoints."); 1941 result.SetStatus(eReturnStatusFailed); 1942 return false; 1943 } 1944 1945 std::unique_lock<std::recursive_mutex> lock; 1946 target->GetBreakpointList().GetListMutex(lock); 1947 1948 const BreakpointList &breakpoints = target->GetBreakpointList(); 1949 1950 size_t num_breakpoints = breakpoints.GetSize(); 1951 if (num_breakpoints == 0) { 1952 result.SetError("No breakpoints, cannot delete names."); 1953 result.SetStatus(eReturnStatusFailed); 1954 return false; 1955 } 1956 1957 // Particular breakpoint selected; disable that breakpoint. 1958 BreakpointIDList valid_bp_ids; 1959 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1960 command, target, result, &valid_bp_ids); 1961 1962 if (result.Succeeded()) { 1963 if (valid_bp_ids.GetSize() == 0) { 1964 result.SetError("No breakpoints specified, cannot delete names."); 1965 result.SetStatus(eReturnStatusFailed); 1966 return false; 1967 } 1968 size_t num_valid_ids = valid_bp_ids.GetSize(); 1969 for (size_t index = 0; index < num_valid_ids; index++) { 1970 lldb::break_id_t bp_id = 1971 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 1972 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1973 bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue()); 1974 } 1975 } 1976 1977 return true; 1978 } 1979 1980 private: 1981 BreakpointNameOptionGroup m_name_options; 1982 OptionGroupOptions m_option_group; 1983 }; 1984 1985 class CommandObjectBreakpointNameList : public CommandObjectParsed { 1986 public: 1987 CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 1988 : CommandObjectParsed(interpreter, "list", 1989 "List either the names for a breakpoint or the " 1990 "breakpoints for a given name.", 1991 "breakpoint name list <command-options>"), 1992 m_name_options(), m_option_group() { 1993 m_option_group.Append(&m_name_options); 1994 m_option_group.Finalize(); 1995 } 1996 1997 ~CommandObjectBreakpointNameList() override = default; 1998 1999 Options *GetOptions() override { return &m_option_group; } 2000 2001 protected: 2002 bool DoExecute(Args &command, CommandReturnObject &result) override { 2003 Target *target = 2004 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 2005 2006 if (target == nullptr) { 2007 result.AppendError("Invalid target. No existing target or breakpoints."); 2008 result.SetStatus(eReturnStatusFailed); 2009 return false; 2010 } 2011 2012 if (m_name_options.m_name.OptionWasSet()) { 2013 const char *name = m_name_options.m_name.GetCurrentValue(); 2014 std::unique_lock<std::recursive_mutex> lock; 2015 target->GetBreakpointList().GetListMutex(lock); 2016 2017 BreakpointList &breakpoints = target->GetBreakpointList(); 2018 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2019 if (bp_sp->MatchesName(name)) { 2020 StreamString s; 2021 bp_sp->GetDescription(&s, eDescriptionLevelBrief); 2022 s.EOL(); 2023 result.AppendMessage(s.GetData()); 2024 } 2025 } 2026 2027 } else if (m_name_options.m_breakpoint.OptionWasSet()) { 2028 BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID( 2029 m_name_options.m_breakpoint.GetCurrentValue()); 2030 if (bp_sp) { 2031 std::vector<std::string> names; 2032 bp_sp->GetNames(names); 2033 result.AppendMessage("Names:"); 2034 for (auto name : names) 2035 result.AppendMessageWithFormat(" %s\n", name.c_str()); 2036 } else { 2037 result.AppendErrorWithFormat( 2038 "Could not find breakpoint %" PRId64 ".\n", 2039 m_name_options.m_breakpoint.GetCurrentValue()); 2040 result.SetStatus(eReturnStatusFailed); 2041 return false; 2042 } 2043 } else { 2044 result.SetError("Must specify -N or -B option to list."); 2045 result.SetStatus(eReturnStatusFailed); 2046 return false; 2047 } 2048 return true; 2049 } 2050 2051 private: 2052 BreakpointNameOptionGroup m_name_options; 2053 OptionGroupOptions m_option_group; 2054 }; 2055 2056 //------------------------------------------------------------------------- 2057 // CommandObjectBreakpointName 2058 //------------------------------------------------------------------------- 2059 class CommandObjectBreakpointName : public CommandObjectMultiword { 2060 public: 2061 CommandObjectBreakpointName(CommandInterpreter &interpreter) 2062 : CommandObjectMultiword( 2063 interpreter, "name", "Commands to manage name tags for breakpoints", 2064 "breakpoint name <subcommand> [<command-options>]") { 2065 CommandObjectSP add_command_object( 2066 new CommandObjectBreakpointNameAdd(interpreter)); 2067 CommandObjectSP delete_command_object( 2068 new CommandObjectBreakpointNameDelete(interpreter)); 2069 CommandObjectSP list_command_object( 2070 new CommandObjectBreakpointNameList(interpreter)); 2071 2072 LoadSubCommand("add", add_command_object); 2073 LoadSubCommand("delete", delete_command_object); 2074 LoadSubCommand("list", list_command_object); 2075 } 2076 2077 ~CommandObjectBreakpointName() override = default; 2078 }; 2079 2080 //------------------------------------------------------------------------- 2081 // CommandObjectBreakpointRead 2082 //------------------------------------------------------------------------- 2083 #pragma mark Read::CommandOptions 2084 static OptionDefinition g_breakpoint_read_options[] = { 2085 // clang-format off 2086 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." }, 2087 {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."}, 2088 // clang-format on 2089 }; 2090 2091 #pragma mark Read 2092 2093 class CommandObjectBreakpointRead : public CommandObjectParsed { 2094 public: 2095 CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2096 : CommandObjectParsed(interpreter, "breakpoint read", 2097 "Read and set the breakpoints previously saved to " 2098 "a file with \"breakpoint write\". ", 2099 nullptr), 2100 m_options() { 2101 CommandArgumentEntry arg; 2102 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2103 eArgTypeBreakpointIDRange); 2104 // Add the entry for the first argument for this command to the object's 2105 // arguments vector. 2106 m_arguments.push_back(arg); 2107 } 2108 2109 ~CommandObjectBreakpointRead() override = default; 2110 2111 Options *GetOptions() override { return &m_options; } 2112 2113 class CommandOptions : public Options { 2114 public: 2115 CommandOptions() : Options() {} 2116 2117 ~CommandOptions() override = default; 2118 2119 Error SetOptionValue(uint32_t option_idx, const char *option_arg, 2120 ExecutionContext *execution_context) override { 2121 Error error; 2122 const int short_option = m_getopt_table[option_idx].val; 2123 2124 switch (short_option) { 2125 case 'f': 2126 m_filename.assign(option_arg); 2127 break; 2128 case 'N': { 2129 Error name_error; 2130 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 2131 name_error)) { 2132 error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 2133 name_error.AsCString()); 2134 } 2135 m_names.push_back(option_arg); 2136 break; 2137 } 2138 default: 2139 error.SetErrorStringWithFormat("unrecognized option '%c'", 2140 short_option); 2141 break; 2142 } 2143 2144 return error; 2145 } 2146 2147 void OptionParsingStarting(ExecutionContext *execution_context) override { 2148 m_filename.clear(); 2149 m_names.clear(); 2150 } 2151 2152 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2153 return llvm::makeArrayRef(g_breakpoint_read_options); 2154 } 2155 2156 // Instance variables to hold the values for command options. 2157 2158 std::string m_filename; 2159 std::vector<std::string> m_names; 2160 }; 2161 2162 protected: 2163 bool DoExecute(Args &command, CommandReturnObject &result) override { 2164 Target *target = GetSelectedOrDummyTarget(); 2165 if (target == nullptr) { 2166 result.AppendError("Invalid target. No existing target or breakpoints."); 2167 result.SetStatus(eReturnStatusFailed); 2168 return false; 2169 } 2170 2171 std::unique_lock<std::recursive_mutex> lock; 2172 target->GetBreakpointList().GetListMutex(lock); 2173 2174 FileSpec input_spec(m_options.m_filename, true); 2175 BreakpointIDList new_bps; 2176 Error error = target->CreateBreakpointsFromFile(input_spec, 2177 m_options.m_names, new_bps); 2178 2179 if (!error.Success()) { 2180 result.AppendError(error.AsCString()); 2181 result.SetStatus(eReturnStatusFailed); 2182 return false; 2183 } 2184 2185 Stream &output_stream = result.GetOutputStream(); 2186 2187 size_t num_breakpoints = new_bps.GetSize(); 2188 if (num_breakpoints == 0) { 2189 result.AppendMessage("No breakpoints added."); 2190 } else { 2191 // No breakpoint selected; show info about all currently set breakpoints. 2192 result.AppendMessage("New breakpoints:"); 2193 for (size_t i = 0; i < num_breakpoints; ++i) { 2194 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 2195 Breakpoint *bp = target->GetBreakpointList() 2196 .FindBreakpointByID(bp_id.GetBreakpointID()) 2197 .get(); 2198 if (bp) 2199 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 2200 false); 2201 } 2202 } 2203 return result.Succeeded(); 2204 } 2205 2206 private: 2207 CommandOptions m_options; 2208 }; 2209 2210 //------------------------------------------------------------------------- 2211 // CommandObjectBreakpointWrite 2212 //------------------------------------------------------------------------- 2213 #pragma mark Write::CommandOptions 2214 static OptionDefinition g_breakpoint_write_options[] = { 2215 // clang-format off 2216 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." }, 2217 { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."}, 2218 // clang-format on 2219 }; 2220 2221 #pragma mark Write 2222 class CommandObjectBreakpointWrite : public CommandObjectParsed { 2223 public: 2224 CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2225 : CommandObjectParsed(interpreter, "breakpoint write", 2226 "Write the breakpoints listed to a file that can " 2227 "be read in with \"breakpoint read\". " 2228 "If given no arguments, writes all breakpoints.", 2229 nullptr), 2230 m_options() { 2231 CommandArgumentEntry arg; 2232 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2233 eArgTypeBreakpointIDRange); 2234 // Add the entry for the first argument for this command to the object's 2235 // arguments vector. 2236 m_arguments.push_back(arg); 2237 } 2238 2239 ~CommandObjectBreakpointWrite() override = default; 2240 2241 Options *GetOptions() override { return &m_options; } 2242 2243 class CommandOptions : public Options { 2244 public: 2245 CommandOptions() : Options() {} 2246 2247 ~CommandOptions() override = default; 2248 2249 Error SetOptionValue(uint32_t option_idx, const char *option_arg, 2250 ExecutionContext *execution_context) override { 2251 Error error; 2252 const int short_option = m_getopt_table[option_idx].val; 2253 2254 switch (short_option) { 2255 case 'f': 2256 m_filename.assign(option_arg); 2257 break; 2258 case 'a': 2259 m_append = true; 2260 break; 2261 default: 2262 error.SetErrorStringWithFormat("unrecognized option '%c'", 2263 short_option); 2264 break; 2265 } 2266 2267 return error; 2268 } 2269 2270 void OptionParsingStarting(ExecutionContext *execution_context) override { 2271 m_filename.clear(); 2272 m_append = false; 2273 } 2274 2275 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2276 return llvm::makeArrayRef(g_breakpoint_write_options); 2277 } 2278 2279 // Instance variables to hold the values for command options. 2280 2281 std::string m_filename; 2282 bool m_append = false; 2283 }; 2284 2285 protected: 2286 bool DoExecute(Args &command, CommandReturnObject &result) override { 2287 Target *target = GetSelectedOrDummyTarget(); 2288 if (target == nullptr) { 2289 result.AppendError("Invalid target. No existing target or breakpoints."); 2290 result.SetStatus(eReturnStatusFailed); 2291 return false; 2292 } 2293 2294 std::unique_lock<std::recursive_mutex> lock; 2295 target->GetBreakpointList().GetListMutex(lock); 2296 2297 BreakpointIDList valid_bp_ids; 2298 if (!command.empty()) { 2299 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2300 command, target, result, &valid_bp_ids); 2301 2302 if (!result.Succeeded()) { 2303 result.SetStatus(eReturnStatusFailed); 2304 return false; 2305 } 2306 } 2307 Error error = target->SerializeBreakpointsToFile( 2308 FileSpec(m_options.m_filename.c_str(), true), valid_bp_ids, 2309 m_options.m_append); 2310 if (!error.Success()) { 2311 result.AppendErrorWithFormat("error serializing breakpoints: %s.", 2312 error.AsCString()); 2313 result.SetStatus(eReturnStatusFailed); 2314 } 2315 return result.Succeeded(); 2316 } 2317 2318 private: 2319 CommandOptions m_options; 2320 }; 2321 2322 //------------------------------------------------------------------------- 2323 // CommandObjectMultiwordBreakpoint 2324 //------------------------------------------------------------------------- 2325 #pragma mark MultiwordBreakpoint 2326 2327 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2328 CommandInterpreter &interpreter) 2329 : CommandObjectMultiword( 2330 interpreter, "breakpoint", 2331 "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2332 "breakpoint <subcommand> [<command-options>]") { 2333 CommandObjectSP list_command_object( 2334 new CommandObjectBreakpointList(interpreter)); 2335 CommandObjectSP enable_command_object( 2336 new CommandObjectBreakpointEnable(interpreter)); 2337 CommandObjectSP disable_command_object( 2338 new CommandObjectBreakpointDisable(interpreter)); 2339 CommandObjectSP clear_command_object( 2340 new CommandObjectBreakpointClear(interpreter)); 2341 CommandObjectSP delete_command_object( 2342 new CommandObjectBreakpointDelete(interpreter)); 2343 CommandObjectSP set_command_object( 2344 new CommandObjectBreakpointSet(interpreter)); 2345 CommandObjectSP command_command_object( 2346 new CommandObjectBreakpointCommand(interpreter)); 2347 CommandObjectSP modify_command_object( 2348 new CommandObjectBreakpointModify(interpreter)); 2349 CommandObjectSP name_command_object( 2350 new CommandObjectBreakpointName(interpreter)); 2351 CommandObjectSP write_command_object( 2352 new CommandObjectBreakpointWrite(interpreter)); 2353 CommandObjectSP read_command_object( 2354 new CommandObjectBreakpointRead(interpreter)); 2355 2356 list_command_object->SetCommandName("breakpoint list"); 2357 enable_command_object->SetCommandName("breakpoint enable"); 2358 disable_command_object->SetCommandName("breakpoint disable"); 2359 clear_command_object->SetCommandName("breakpoint clear"); 2360 delete_command_object->SetCommandName("breakpoint delete"); 2361 set_command_object->SetCommandName("breakpoint set"); 2362 command_command_object->SetCommandName("breakpoint command"); 2363 modify_command_object->SetCommandName("breakpoint modify"); 2364 name_command_object->SetCommandName("breakpoint name"); 2365 write_command_object->SetCommandName("breakpoint write"); 2366 read_command_object->SetCommandName("breakpoint read"); 2367 2368 LoadSubCommand("list", list_command_object); 2369 LoadSubCommand("enable", enable_command_object); 2370 LoadSubCommand("disable", disable_command_object); 2371 LoadSubCommand("clear", clear_command_object); 2372 LoadSubCommand("delete", delete_command_object); 2373 LoadSubCommand("set", set_command_object); 2374 LoadSubCommand("command", command_command_object); 2375 LoadSubCommand("modify", modify_command_object); 2376 LoadSubCommand("name", name_command_object); 2377 LoadSubCommand("write", write_command_object); 2378 LoadSubCommand("read", read_command_object); 2379 } 2380 2381 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 2382 2383 void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, 2384 bool allow_locations, 2385 CommandReturnObject &result, 2386 BreakpointIDList *valid_ids) { 2387 // args can be strings representing 1). integers (for breakpoint ids) 2388 // 2). the full breakpoint & location 2389 // canonical representation 2390 // 3). the word "to" or a hyphen, 2391 // representing a range (in which case there 2392 // had *better* be an entry both before & 2393 // after of one of the first two types. 2394 // 4). A breakpoint name 2395 // If args is empty, we will use the last created breakpoint (if there is 2396 // one.) 2397 2398 Args temp_args; 2399 2400 if (args.empty()) { 2401 if (target->GetLastCreatedBreakpoint()) { 2402 valid_ids->AddBreakpointID(BreakpointID( 2403 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 2404 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2405 } else { 2406 result.AppendError( 2407 "No breakpoint specified and no last created breakpoint."); 2408 result.SetStatus(eReturnStatusFailed); 2409 } 2410 return; 2411 } 2412 2413 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 2414 // directly from the old ARGS to 2415 // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead 2416 // generate a list of strings for 2417 // all the breakpoint ids in the range, and shove all of those breakpoint id 2418 // strings into TEMP_ARGS. 2419 2420 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2421 result, temp_args); 2422 2423 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2424 // BreakpointIDList: 2425 2426 valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(), 2427 temp_args.GetArgumentCount(), result); 2428 2429 // At this point, all of the breakpoint ids that the user passed in have been 2430 // converted to breakpoint IDs 2431 // and put into valid_ids. 2432 2433 if (result.Succeeded()) { 2434 // Now that we've converted everything from args into a list of breakpoint 2435 // ids, go through our tentative list 2436 // of breakpoint id's and verify that they correspond to valid/currently set 2437 // breakpoints. 2438 2439 const size_t count = valid_ids->GetSize(); 2440 for (size_t i = 0; i < count; ++i) { 2441 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2442 Breakpoint *breakpoint = 2443 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2444 if (breakpoint != nullptr) { 2445 const size_t num_locations = breakpoint->GetNumLocations(); 2446 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 2447 StreamString id_str; 2448 BreakpointID::GetCanonicalReference( 2449 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2450 i = valid_ids->GetSize() + 1; 2451 result.AppendErrorWithFormat( 2452 "'%s' is not a currently valid breakpoint/location id.\n", 2453 id_str.GetData()); 2454 result.SetStatus(eReturnStatusFailed); 2455 } 2456 } else { 2457 i = valid_ids->GetSize() + 1; 2458 result.AppendErrorWithFormat( 2459 "'%d' is not a currently valid breakpoint ID.\n", 2460 cur_bp_id.GetBreakpointID()); 2461 result.SetStatus(eReturnStatusFailed); 2462 } 2463 } 2464 } 2465 } 2466