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