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