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