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 if (command.empty() && !m_options.m_delete_disabled) { 1462 if (!m_options.m_force && 1463 !m_interpreter.Confirm( 1464 "About to delete all breakpoints, do you want to do that?", 1465 true)) { 1466 result.AppendMessage("Operation cancelled..."); 1467 } else { 1468 target.RemoveAllowedBreakpoints(); 1469 result.AppendMessageWithFormat( 1470 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1471 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 1472 } 1473 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1474 } else { 1475 // Particular breakpoint selected; disable that breakpoint. 1476 BreakpointIDList valid_bp_ids; 1477 1478 if (m_options.m_delete_disabled) { 1479 BreakpointIDList excluded_bp_ids; 1480 1481 if (!command.empty()) { 1482 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1483 command, &target, result, &excluded_bp_ids, 1484 BreakpointName::Permissions::PermissionKinds::deletePerm); 1485 } 1486 for (auto breakpoint_sp : breakpoints.Breakpoints()) { 1487 if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) { 1488 BreakpointID bp_id(breakpoint_sp->GetID()); 1489 size_t pos = 0; 1490 if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos)) 1491 valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID()); 1492 } 1493 } 1494 if (valid_bp_ids.GetSize() == 0) { 1495 result.AppendError("No disabled breakpoints."); 1496 return false; 1497 } 1498 } else { 1499 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1500 command, &target, result, &valid_bp_ids, 1501 BreakpointName::Permissions::PermissionKinds::deletePerm); 1502 } 1503 1504 if (result.Succeeded()) { 1505 int delete_count = 0; 1506 int disable_count = 0; 1507 const size_t count = valid_bp_ids.GetSize(); 1508 for (size_t i = 0; i < count; ++i) { 1509 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1510 1511 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1512 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1513 Breakpoint *breakpoint = 1514 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1515 BreakpointLocation *location = 1516 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1517 // It makes no sense to try to delete individual locations, so we 1518 // disable them instead. 1519 if (location) { 1520 location->SetEnabled(false); 1521 ++disable_count; 1522 } 1523 } else { 1524 target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 1525 ++delete_count; 1526 } 1527 } 1528 } 1529 result.AppendMessageWithFormat( 1530 "%d breakpoints deleted; %d breakpoint locations disabled.\n", 1531 delete_count, disable_count); 1532 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1533 } 1534 } 1535 return result.Succeeded(); 1536 } 1537 1538 private: 1539 CommandOptions m_options; 1540 }; 1541 1542 // CommandObjectBreakpointName 1543 #define LLDB_OPTIONS_breakpoint_name 1544 #include "CommandOptions.inc" 1545 1546 class BreakpointNameOptionGroup : public OptionGroup { 1547 public: 1548 BreakpointNameOptionGroup() 1549 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 1550 } 1551 1552 ~BreakpointNameOptionGroup() override = default; 1553 1554 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1555 return llvm::makeArrayRef(g_breakpoint_name_options); 1556 } 1557 1558 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1559 ExecutionContext *execution_context) override { 1560 Status error; 1561 const int short_option = g_breakpoint_name_options[option_idx].short_option; 1562 1563 switch (short_option) { 1564 case 'N': 1565 if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1566 error.Success()) 1567 m_name.SetValueFromString(option_arg); 1568 break; 1569 case 'B': 1570 if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1571 error.SetErrorStringWithFormat( 1572 "unrecognized value \"%s\" for breakpoint", 1573 option_arg.str().c_str()); 1574 break; 1575 case 'D': 1576 if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1577 error.SetErrorStringWithFormat( 1578 "unrecognized value \"%s\" for use-dummy", 1579 option_arg.str().c_str()); 1580 break; 1581 case 'H': 1582 m_help_string.SetValueFromString(option_arg); 1583 break; 1584 1585 default: 1586 llvm_unreachable("Unimplemented option"); 1587 } 1588 return error; 1589 } 1590 1591 void OptionParsingStarting(ExecutionContext *execution_context) override { 1592 m_name.Clear(); 1593 m_breakpoint.Clear(); 1594 m_use_dummy.Clear(); 1595 m_use_dummy.SetDefaultValue(false); 1596 m_help_string.Clear(); 1597 } 1598 1599 OptionValueString m_name; 1600 OptionValueUInt64 m_breakpoint; 1601 OptionValueBoolean m_use_dummy; 1602 OptionValueString m_help_string; 1603 }; 1604 1605 #define LLDB_OPTIONS_breakpoint_access 1606 #include "CommandOptions.inc" 1607 1608 class BreakpointAccessOptionGroup : public OptionGroup { 1609 public: 1610 BreakpointAccessOptionGroup() : OptionGroup() {} 1611 1612 ~BreakpointAccessOptionGroup() override = default; 1613 1614 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1615 return llvm::makeArrayRef(g_breakpoint_access_options); 1616 } 1617 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1618 ExecutionContext *execution_context) override { 1619 Status error; 1620 const int short_option = 1621 g_breakpoint_access_options[option_idx].short_option; 1622 1623 switch (short_option) { 1624 case 'L': { 1625 bool value, success; 1626 value = OptionArgParser::ToBoolean(option_arg, false, &success); 1627 if (success) { 1628 m_permissions.SetAllowList(value); 1629 } else 1630 error.SetErrorStringWithFormat( 1631 "invalid boolean value '%s' passed for -L option", 1632 option_arg.str().c_str()); 1633 } break; 1634 case 'A': { 1635 bool value, success; 1636 value = OptionArgParser::ToBoolean(option_arg, false, &success); 1637 if (success) { 1638 m_permissions.SetAllowDisable(value); 1639 } else 1640 error.SetErrorStringWithFormat( 1641 "invalid boolean value '%s' passed for -L option", 1642 option_arg.str().c_str()); 1643 } break; 1644 case 'D': { 1645 bool value, success; 1646 value = OptionArgParser::ToBoolean(option_arg, false, &success); 1647 if (success) { 1648 m_permissions.SetAllowDelete(value); 1649 } else 1650 error.SetErrorStringWithFormat( 1651 "invalid boolean value '%s' passed for -L option", 1652 option_arg.str().c_str()); 1653 } break; 1654 default: 1655 llvm_unreachable("Unimplemented option"); 1656 } 1657 1658 return error; 1659 } 1660 1661 void OptionParsingStarting(ExecutionContext *execution_context) override {} 1662 1663 const BreakpointName::Permissions &GetPermissions() const { 1664 return m_permissions; 1665 } 1666 BreakpointName::Permissions m_permissions; 1667 }; 1668 1669 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1670 public: 1671 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1672 : CommandObjectParsed( 1673 interpreter, "configure", 1674 "Configure the options for the breakpoint" 1675 " name provided. " 1676 "If you provide a breakpoint id, the options will be copied from " 1677 "the breakpoint, otherwise only the options specified will be set " 1678 "on the name.", 1679 "breakpoint name configure <command-options> " 1680 "<breakpoint-name-list>"), 1681 m_bp_opts(), m_option_group() { 1682 // Create the first variant for the first (and only) argument for this 1683 // command. 1684 CommandArgumentEntry arg1; 1685 CommandArgumentData id_arg; 1686 id_arg.arg_type = eArgTypeBreakpointName; 1687 id_arg.arg_repetition = eArgRepeatOptional; 1688 arg1.push_back(id_arg); 1689 m_arguments.push_back(arg1); 1690 1691 m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1692 m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL, 1693 LLDB_OPT_SET_ALL); 1694 m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4, 1695 LLDB_OPT_SET_ALL); 1696 m_option_group.Finalize(); 1697 } 1698 1699 ~CommandObjectBreakpointNameConfigure() override = default; 1700 1701 Options *GetOptions() override { return &m_option_group; } 1702 1703 protected: 1704 bool DoExecute(Args &command, CommandReturnObject &result) override { 1705 1706 const size_t argc = command.GetArgumentCount(); 1707 if (argc == 0) { 1708 result.AppendError("No names provided."); 1709 return false; 1710 } 1711 1712 Target &target = GetSelectedOrDummyTarget(false); 1713 1714 std::unique_lock<std::recursive_mutex> lock; 1715 target.GetBreakpointList().GetListMutex(lock); 1716 1717 // Make a pass through first to see that all the names are legal. 1718 for (auto &entry : command.entries()) { 1719 Status error; 1720 if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) { 1721 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1722 entry.c_str(), error.AsCString()); 1723 return false; 1724 } 1725 } 1726 // Now configure them, we already pre-checked the names so we don't need to 1727 // check the error: 1728 BreakpointSP bp_sp; 1729 if (m_bp_id.m_breakpoint.OptionWasSet()) { 1730 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1731 bp_sp = target.GetBreakpointByID(bp_id); 1732 if (!bp_sp) { 1733 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1734 bp_id); 1735 return false; 1736 } 1737 } 1738 1739 Status error; 1740 for (auto &entry : command.entries()) { 1741 ConstString name(entry.c_str()); 1742 BreakpointName *bp_name = target.FindBreakpointName(name, true, error); 1743 if (!bp_name) 1744 continue; 1745 if (m_bp_id.m_help_string.OptionWasSet()) 1746 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1747 1748 if (bp_sp) 1749 target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(), 1750 m_access_options.GetPermissions()); 1751 else 1752 target.ConfigureBreakpointName(*bp_name, 1753 m_bp_opts.GetBreakpointOptions(), 1754 m_access_options.GetPermissions()); 1755 } 1756 return true; 1757 } 1758 1759 private: 1760 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1761 BreakpointOptionGroup m_bp_opts; 1762 BreakpointAccessOptionGroup m_access_options; 1763 OptionGroupOptions m_option_group; 1764 }; 1765 1766 class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 1767 public: 1768 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1769 : CommandObjectParsed( 1770 interpreter, "add", "Add a name to the breakpoints provided.", 1771 "breakpoint name add <command-options> <breakpoint-id-list>"), 1772 m_name_options(), m_option_group() { 1773 // Create the first variant for the first (and only) argument for this 1774 // command. 1775 CommandArgumentEntry arg1; 1776 CommandArgumentData id_arg; 1777 id_arg.arg_type = eArgTypeBreakpointID; 1778 id_arg.arg_repetition = eArgRepeatOptional; 1779 arg1.push_back(id_arg); 1780 m_arguments.push_back(arg1); 1781 1782 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 1783 m_option_group.Finalize(); 1784 } 1785 1786 ~CommandObjectBreakpointNameAdd() override = default; 1787 1788 void 1789 HandleArgumentCompletion(CompletionRequest &request, 1790 OptionElementVector &opt_element_vector) override { 1791 CommandCompletions::InvokeCommonCompletionCallbacks( 1792 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 1793 request, nullptr); 1794 } 1795 1796 Options *GetOptions() override { return &m_option_group; } 1797 1798 protected: 1799 bool DoExecute(Args &command, CommandReturnObject &result) override { 1800 if (!m_name_options.m_name.OptionWasSet()) { 1801 result.SetError("No name option provided."); 1802 return false; 1803 } 1804 1805 Target &target = 1806 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1807 1808 std::unique_lock<std::recursive_mutex> lock; 1809 target.GetBreakpointList().GetListMutex(lock); 1810 1811 const BreakpointList &breakpoints = target.GetBreakpointList(); 1812 1813 size_t num_breakpoints = breakpoints.GetSize(); 1814 if (num_breakpoints == 0) { 1815 result.SetError("No breakpoints, cannot add names."); 1816 return false; 1817 } 1818 1819 // Particular breakpoint selected; disable that breakpoint. 1820 BreakpointIDList valid_bp_ids; 1821 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1822 command, &target, result, &valid_bp_ids, 1823 BreakpointName::Permissions::PermissionKinds::listPerm); 1824 1825 if (result.Succeeded()) { 1826 if (valid_bp_ids.GetSize() == 0) { 1827 result.SetError("No breakpoints specified, cannot add names."); 1828 return false; 1829 } 1830 size_t num_valid_ids = valid_bp_ids.GetSize(); 1831 const char *bp_name = m_name_options.m_name.GetCurrentValue(); 1832 Status error; // This error reports illegal names, but we've already 1833 // checked that, so we don't need to check it again here. 1834 for (size_t index = 0; index < num_valid_ids; index++) { 1835 lldb::break_id_t bp_id = 1836 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 1837 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1838 target.AddNameToBreakpoint(bp_sp, bp_name, error); 1839 } 1840 } 1841 1842 return true; 1843 } 1844 1845 private: 1846 BreakpointNameOptionGroup m_name_options; 1847 OptionGroupOptions m_option_group; 1848 }; 1849 1850 class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 1851 public: 1852 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1853 : CommandObjectParsed( 1854 interpreter, "delete", 1855 "Delete a name from the breakpoints provided.", 1856 "breakpoint name delete <command-options> <breakpoint-id-list>"), 1857 m_name_options(), m_option_group() { 1858 // Create the first variant for the first (and only) argument for this 1859 // command. 1860 CommandArgumentEntry arg1; 1861 CommandArgumentData id_arg; 1862 id_arg.arg_type = eArgTypeBreakpointID; 1863 id_arg.arg_repetition = eArgRepeatOptional; 1864 arg1.push_back(id_arg); 1865 m_arguments.push_back(arg1); 1866 1867 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 1868 m_option_group.Finalize(); 1869 } 1870 1871 ~CommandObjectBreakpointNameDelete() override = default; 1872 1873 void 1874 HandleArgumentCompletion(CompletionRequest &request, 1875 OptionElementVector &opt_element_vector) override { 1876 CommandCompletions::InvokeCommonCompletionCallbacks( 1877 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 1878 request, nullptr); 1879 } 1880 1881 Options *GetOptions() override { return &m_option_group; } 1882 1883 protected: 1884 bool DoExecute(Args &command, CommandReturnObject &result) override { 1885 if (!m_name_options.m_name.OptionWasSet()) { 1886 result.SetError("No name option provided."); 1887 return false; 1888 } 1889 1890 Target &target = 1891 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1892 1893 std::unique_lock<std::recursive_mutex> lock; 1894 target.GetBreakpointList().GetListMutex(lock); 1895 1896 const BreakpointList &breakpoints = target.GetBreakpointList(); 1897 1898 size_t num_breakpoints = breakpoints.GetSize(); 1899 if (num_breakpoints == 0) { 1900 result.SetError("No breakpoints, cannot delete names."); 1901 return false; 1902 } 1903 1904 // Particular breakpoint selected; disable that breakpoint. 1905 BreakpointIDList valid_bp_ids; 1906 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1907 command, &target, result, &valid_bp_ids, 1908 BreakpointName::Permissions::PermissionKinds::deletePerm); 1909 1910 if (result.Succeeded()) { 1911 if (valid_bp_ids.GetSize() == 0) { 1912 result.SetError("No breakpoints specified, cannot delete names."); 1913 return false; 1914 } 1915 ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 1916 size_t num_valid_ids = valid_bp_ids.GetSize(); 1917 for (size_t index = 0; index < num_valid_ids; index++) { 1918 lldb::break_id_t bp_id = 1919 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 1920 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1921 target.RemoveNameFromBreakpoint(bp_sp, bp_name); 1922 } 1923 } 1924 1925 return true; 1926 } 1927 1928 private: 1929 BreakpointNameOptionGroup m_name_options; 1930 OptionGroupOptions m_option_group; 1931 }; 1932 1933 class CommandObjectBreakpointNameList : public CommandObjectParsed { 1934 public: 1935 CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 1936 : CommandObjectParsed(interpreter, "list", 1937 "List either the names for a breakpoint or info " 1938 "about a given name. With no arguments, lists all " 1939 "names", 1940 "breakpoint name list <command-options>"), 1941 m_name_options(), m_option_group() { 1942 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 1943 m_option_group.Finalize(); 1944 } 1945 1946 ~CommandObjectBreakpointNameList() override = default; 1947 1948 Options *GetOptions() override { return &m_option_group; } 1949 1950 protected: 1951 bool DoExecute(Args &command, CommandReturnObject &result) override { 1952 Target &target = 1953 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1954 1955 std::vector<std::string> name_list; 1956 if (command.empty()) { 1957 target.GetBreakpointNames(name_list); 1958 } else { 1959 for (const Args::ArgEntry &arg : command) { 1960 name_list.push_back(arg.c_str()); 1961 } 1962 } 1963 1964 if (name_list.empty()) { 1965 result.AppendMessage("No breakpoint names found."); 1966 } else { 1967 for (const std::string &name_str : name_list) { 1968 const char *name = name_str.c_str(); 1969 // First print out the options for the name: 1970 Status error; 1971 BreakpointName *bp_name = 1972 target.FindBreakpointName(ConstString(name), false, error); 1973 if (bp_name) { 1974 StreamString s; 1975 result.AppendMessageWithFormat("Name: %s\n", name); 1976 if (bp_name->GetDescription(&s, eDescriptionLevelFull)) { 1977 result.AppendMessage(s.GetString()); 1978 } 1979 1980 std::unique_lock<std::recursive_mutex> lock; 1981 target.GetBreakpointList().GetListMutex(lock); 1982 1983 BreakpointList &breakpoints = target.GetBreakpointList(); 1984 bool any_set = false; 1985 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 1986 if (bp_sp->MatchesName(name)) { 1987 StreamString s; 1988 any_set = true; 1989 bp_sp->GetDescription(&s, eDescriptionLevelBrief); 1990 s.EOL(); 1991 result.AppendMessage(s.GetString()); 1992 } 1993 } 1994 if (!any_set) 1995 result.AppendMessage("No breakpoints using this name."); 1996 } else { 1997 result.AppendMessageWithFormat("Name: %s not found.\n", name); 1998 } 1999 } 2000 } 2001 return true; 2002 } 2003 2004 private: 2005 BreakpointNameOptionGroup m_name_options; 2006 OptionGroupOptions m_option_group; 2007 }; 2008 2009 // CommandObjectBreakpointName 2010 class CommandObjectBreakpointName : public CommandObjectMultiword { 2011 public: 2012 CommandObjectBreakpointName(CommandInterpreter &interpreter) 2013 : CommandObjectMultiword( 2014 interpreter, "name", "Commands to manage name tags for breakpoints", 2015 "breakpoint name <subcommand> [<command-options>]") { 2016 CommandObjectSP add_command_object( 2017 new CommandObjectBreakpointNameAdd(interpreter)); 2018 CommandObjectSP delete_command_object( 2019 new CommandObjectBreakpointNameDelete(interpreter)); 2020 CommandObjectSP list_command_object( 2021 new CommandObjectBreakpointNameList(interpreter)); 2022 CommandObjectSP configure_command_object( 2023 new CommandObjectBreakpointNameConfigure(interpreter)); 2024 2025 LoadSubCommand("add", add_command_object); 2026 LoadSubCommand("delete", delete_command_object); 2027 LoadSubCommand("list", list_command_object); 2028 LoadSubCommand("configure", configure_command_object); 2029 } 2030 2031 ~CommandObjectBreakpointName() override = default; 2032 }; 2033 2034 // CommandObjectBreakpointRead 2035 #pragma mark Read::CommandOptions 2036 #define LLDB_OPTIONS_breakpoint_read 2037 #include "CommandOptions.inc" 2038 2039 #pragma mark Read 2040 2041 class CommandObjectBreakpointRead : public CommandObjectParsed { 2042 public: 2043 CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2044 : CommandObjectParsed(interpreter, "breakpoint read", 2045 "Read and set the breakpoints previously saved to " 2046 "a file with \"breakpoint write\". ", 2047 nullptr), 2048 m_options() {} 2049 2050 ~CommandObjectBreakpointRead() override = default; 2051 2052 Options *GetOptions() override { return &m_options; } 2053 2054 class CommandOptions : public Options { 2055 public: 2056 CommandOptions() : Options() {} 2057 2058 ~CommandOptions() override = default; 2059 2060 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2061 ExecutionContext *execution_context) override { 2062 Status error; 2063 const int short_option = m_getopt_table[option_idx].val; 2064 2065 switch (short_option) { 2066 case 'f': 2067 m_filename.assign(std::string(option_arg)); 2068 break; 2069 case 'N': { 2070 Status name_error; 2071 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 2072 name_error)) { 2073 error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 2074 name_error.AsCString()); 2075 } 2076 m_names.push_back(std::string(option_arg)); 2077 break; 2078 } 2079 default: 2080 llvm_unreachable("Unimplemented option"); 2081 } 2082 2083 return error; 2084 } 2085 2086 void OptionParsingStarting(ExecutionContext *execution_context) override { 2087 m_filename.clear(); 2088 m_names.clear(); 2089 } 2090 2091 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2092 return llvm::makeArrayRef(g_breakpoint_read_options); 2093 } 2094 2095 void HandleOptionArgumentCompletion( 2096 CompletionRequest &request, OptionElementVector &opt_element_vector, 2097 int opt_element_index, CommandInterpreter &interpreter) override { 2098 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 2099 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 2100 2101 switch (GetDefinitions()[opt_defs_index].short_option) { 2102 case 'f': 2103 CommandCompletions::InvokeCommonCompletionCallbacks( 2104 interpreter, CommandCompletions::eDiskFileCompletion, request, 2105 nullptr); 2106 break; 2107 2108 case 'N': 2109 llvm::Optional<FileSpec> file_spec; 2110 const llvm::StringRef dash_f("-f"); 2111 for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) { 2112 if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) { 2113 file_spec.emplace( 2114 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1)); 2115 break; 2116 } 2117 } 2118 if (!file_spec) 2119 return; 2120 2121 FileSystem::Instance().Resolve(*file_spec); 2122 Status error; 2123 StructuredData::ObjectSP input_data_sp = 2124 StructuredData::ParseJSONFromFile(*file_spec, error); 2125 if (!error.Success()) 2126 return; 2127 2128 StructuredData::Array *bkpt_array = input_data_sp->GetAsArray(); 2129 if (!bkpt_array) 2130 return; 2131 2132 const size_t num_bkpts = bkpt_array->GetSize(); 2133 for (size_t i = 0; i < num_bkpts; i++) { 2134 StructuredData::ObjectSP bkpt_object_sp = 2135 bkpt_array->GetItemAtIndex(i); 2136 if (!bkpt_object_sp) 2137 return; 2138 2139 StructuredData::Dictionary *bkpt_dict = 2140 bkpt_object_sp->GetAsDictionary(); 2141 if (!bkpt_dict) 2142 return; 2143 2144 StructuredData::ObjectSP bkpt_data_sp = 2145 bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey()); 2146 if (!bkpt_data_sp) 2147 return; 2148 2149 bkpt_dict = bkpt_data_sp->GetAsDictionary(); 2150 if (!bkpt_dict) 2151 return; 2152 2153 StructuredData::Array *names_array; 2154 2155 if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array)) 2156 return; 2157 2158 size_t num_names = names_array->GetSize(); 2159 2160 for (size_t i = 0; i < num_names; i++) { 2161 llvm::StringRef name; 2162 if (names_array->GetItemAtIndexAsString(i, name)) 2163 request.TryCompleteCurrentArg(name); 2164 } 2165 } 2166 } 2167 } 2168 2169 std::string m_filename; 2170 std::vector<std::string> m_names; 2171 }; 2172 2173 protected: 2174 bool DoExecute(Args &command, CommandReturnObject &result) override { 2175 Target &target = GetSelectedOrDummyTarget(); 2176 2177 std::unique_lock<std::recursive_mutex> lock; 2178 target.GetBreakpointList().GetListMutex(lock); 2179 2180 FileSpec input_spec(m_options.m_filename); 2181 FileSystem::Instance().Resolve(input_spec); 2182 BreakpointIDList new_bps; 2183 Status error = target.CreateBreakpointsFromFile(input_spec, 2184 m_options.m_names, new_bps); 2185 2186 if (!error.Success()) { 2187 result.AppendError(error.AsCString()); 2188 return false; 2189 } 2190 2191 Stream &output_stream = result.GetOutputStream(); 2192 2193 size_t num_breakpoints = new_bps.GetSize(); 2194 if (num_breakpoints == 0) { 2195 result.AppendMessage("No breakpoints added."); 2196 } else { 2197 // No breakpoint selected; show info about all currently set breakpoints. 2198 result.AppendMessage("New breakpoints:"); 2199 for (size_t i = 0; i < num_breakpoints; ++i) { 2200 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 2201 Breakpoint *bp = target.GetBreakpointList() 2202 .FindBreakpointByID(bp_id.GetBreakpointID()) 2203 .get(); 2204 if (bp) 2205 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 2206 false); 2207 } 2208 } 2209 return result.Succeeded(); 2210 } 2211 2212 private: 2213 CommandOptions m_options; 2214 }; 2215 2216 // CommandObjectBreakpointWrite 2217 #pragma mark Write::CommandOptions 2218 #define LLDB_OPTIONS_breakpoint_write 2219 #include "CommandOptions.inc" 2220 2221 #pragma mark Write 2222 class CommandObjectBreakpointWrite : public CommandObjectParsed { 2223 public: 2224 CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2225 : CommandObjectParsed(interpreter, "breakpoint write", 2226 "Write the breakpoints listed to a file that can " 2227 "be read in with \"breakpoint read\". " 2228 "If given no arguments, writes all breakpoints.", 2229 nullptr), 2230 m_options() { 2231 CommandArgumentEntry arg; 2232 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2233 eArgTypeBreakpointIDRange); 2234 // Add the entry for the first argument for this command to the object's 2235 // arguments vector. 2236 m_arguments.push_back(arg); 2237 } 2238 2239 ~CommandObjectBreakpointWrite() override = default; 2240 2241 void 2242 HandleArgumentCompletion(CompletionRequest &request, 2243 OptionElementVector &opt_element_vector) override { 2244 CommandCompletions::InvokeCommonCompletionCallbacks( 2245 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 2246 request, nullptr); 2247 } 2248 2249 Options *GetOptions() override { return &m_options; } 2250 2251 class CommandOptions : public Options { 2252 public: 2253 CommandOptions() : Options() {} 2254 2255 ~CommandOptions() override = default; 2256 2257 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2258 ExecutionContext *execution_context) override { 2259 Status error; 2260 const int short_option = m_getopt_table[option_idx].val; 2261 2262 switch (short_option) { 2263 case 'f': 2264 m_filename.assign(std::string(option_arg)); 2265 break; 2266 case 'a': 2267 m_append = true; 2268 break; 2269 default: 2270 llvm_unreachable("Unimplemented option"); 2271 } 2272 2273 return error; 2274 } 2275 2276 void OptionParsingStarting(ExecutionContext *execution_context) override { 2277 m_filename.clear(); 2278 m_append = false; 2279 } 2280 2281 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2282 return llvm::makeArrayRef(g_breakpoint_write_options); 2283 } 2284 2285 // Instance variables to hold the values for command options. 2286 2287 std::string m_filename; 2288 bool m_append = false; 2289 }; 2290 2291 protected: 2292 bool DoExecute(Args &command, CommandReturnObject &result) override { 2293 Target &target = GetSelectedOrDummyTarget(); 2294 2295 std::unique_lock<std::recursive_mutex> lock; 2296 target.GetBreakpointList().GetListMutex(lock); 2297 2298 BreakpointIDList valid_bp_ids; 2299 if (!command.empty()) { 2300 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2301 command, &target, result, &valid_bp_ids, 2302 BreakpointName::Permissions::PermissionKinds::listPerm); 2303 2304 if (!result.Succeeded()) { 2305 result.SetStatus(eReturnStatusFailed); 2306 return false; 2307 } 2308 } 2309 FileSpec file_spec(m_options.m_filename); 2310 FileSystem::Instance().Resolve(file_spec); 2311 Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids, 2312 m_options.m_append); 2313 if (!error.Success()) { 2314 result.AppendErrorWithFormat("error serializing breakpoints: %s.", 2315 error.AsCString()); 2316 } 2317 return result.Succeeded(); 2318 } 2319 2320 private: 2321 CommandOptions m_options; 2322 }; 2323 2324 // CommandObjectMultiwordBreakpoint 2325 #pragma mark MultiwordBreakpoint 2326 2327 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2328 CommandInterpreter &interpreter) 2329 : CommandObjectMultiword( 2330 interpreter, "breakpoint", 2331 "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2332 "breakpoint <subcommand> [<command-options>]") { 2333 CommandObjectSP list_command_object( 2334 new CommandObjectBreakpointList(interpreter)); 2335 CommandObjectSP enable_command_object( 2336 new CommandObjectBreakpointEnable(interpreter)); 2337 CommandObjectSP disable_command_object( 2338 new CommandObjectBreakpointDisable(interpreter)); 2339 CommandObjectSP clear_command_object( 2340 new CommandObjectBreakpointClear(interpreter)); 2341 CommandObjectSP delete_command_object( 2342 new CommandObjectBreakpointDelete(interpreter)); 2343 CommandObjectSP set_command_object( 2344 new CommandObjectBreakpointSet(interpreter)); 2345 CommandObjectSP command_command_object( 2346 new CommandObjectBreakpointCommand(interpreter)); 2347 CommandObjectSP modify_command_object( 2348 new CommandObjectBreakpointModify(interpreter)); 2349 CommandObjectSP name_command_object( 2350 new CommandObjectBreakpointName(interpreter)); 2351 CommandObjectSP write_command_object( 2352 new CommandObjectBreakpointWrite(interpreter)); 2353 CommandObjectSP read_command_object( 2354 new CommandObjectBreakpointRead(interpreter)); 2355 2356 list_command_object->SetCommandName("breakpoint list"); 2357 enable_command_object->SetCommandName("breakpoint enable"); 2358 disable_command_object->SetCommandName("breakpoint disable"); 2359 clear_command_object->SetCommandName("breakpoint clear"); 2360 delete_command_object->SetCommandName("breakpoint delete"); 2361 set_command_object->SetCommandName("breakpoint set"); 2362 command_command_object->SetCommandName("breakpoint command"); 2363 modify_command_object->SetCommandName("breakpoint modify"); 2364 name_command_object->SetCommandName("breakpoint name"); 2365 write_command_object->SetCommandName("breakpoint write"); 2366 read_command_object->SetCommandName("breakpoint read"); 2367 2368 LoadSubCommand("list", list_command_object); 2369 LoadSubCommand("enable", enable_command_object); 2370 LoadSubCommand("disable", disable_command_object); 2371 LoadSubCommand("clear", clear_command_object); 2372 LoadSubCommand("delete", delete_command_object); 2373 LoadSubCommand("set", set_command_object); 2374 LoadSubCommand("command", command_command_object); 2375 LoadSubCommand("modify", modify_command_object); 2376 LoadSubCommand("name", name_command_object); 2377 LoadSubCommand("write", write_command_object); 2378 LoadSubCommand("read", read_command_object); 2379 } 2380 2381 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 2382 2383 void CommandObjectMultiwordBreakpoint::VerifyIDs( 2384 Args &args, Target *target, bool allow_locations, 2385 CommandReturnObject &result, BreakpointIDList *valid_ids, 2386 BreakpointName::Permissions ::PermissionKinds purpose) { 2387 // args can be strings representing 1). integers (for breakpoint ids) 2388 // 2). the full breakpoint & location 2389 // canonical representation 2390 // 3). the word "to" or a hyphen, 2391 // representing a range (in which case there 2392 // had *better* be an entry both before & 2393 // after of one of the first two types. 2394 // 4). A breakpoint name 2395 // If args is empty, we will use the last created breakpoint (if there is 2396 // one.) 2397 2398 Args temp_args; 2399 2400 if (args.empty()) { 2401 if (target->GetLastCreatedBreakpoint()) { 2402 valid_ids->AddBreakpointID(BreakpointID( 2403 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 2404 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2405 } else { 2406 result.AppendError( 2407 "No breakpoint specified and no last created breakpoint."); 2408 } 2409 return; 2410 } 2411 2412 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 2413 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 2414 // id range strings over; instead generate a list of strings for all the 2415 // breakpoint ids in the range, and shove all of those breakpoint id strings 2416 // into TEMP_ARGS. 2417 2418 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2419 purpose, result, temp_args); 2420 2421 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2422 // BreakpointIDList: 2423 2424 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 2425 2426 // At this point, all of the breakpoint ids that the user passed in have 2427 // been converted to breakpoint IDs and put into valid_ids. 2428 2429 if (result.Succeeded()) { 2430 // Now that we've converted everything from args into a list of breakpoint 2431 // ids, go through our tentative list of breakpoint id's and verify that 2432 // they correspond to valid/currently set breakpoints. 2433 2434 const size_t count = valid_ids->GetSize(); 2435 for (size_t i = 0; i < count; ++i) { 2436 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2437 Breakpoint *breakpoint = 2438 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2439 if (breakpoint != nullptr) { 2440 const size_t num_locations = breakpoint->GetNumLocations(); 2441 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 2442 StreamString id_str; 2443 BreakpointID::GetCanonicalReference( 2444 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2445 i = valid_ids->GetSize() + 1; 2446 result.AppendErrorWithFormat( 2447 "'%s' is not a currently valid breakpoint/location id.\n", 2448 id_str.GetData()); 2449 } 2450 } else { 2451 i = valid_ids->GetSize() + 1; 2452 result.AppendErrorWithFormat( 2453 "'%d' is not a currently valid breakpoint ID.\n", 2454 cur_bp_id.GetBreakpointID()); 2455 } 2456 } 2457 } 2458 } 2459