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() = default; 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() = default; 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() = default; 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() = default; 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() = default; 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() = default; 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 breakpoint names") { 2022 2023 2024 SetHelpLong( 2025 R"( 2026 Breakpoint names provide a general tagging mechanism for breakpoints. Each 2027 breakpoint name can be added to any number of breakpoints, and each breakpoint 2028 can have any number of breakpoint names attached to it. For instance: 2029 2030 (lldb) break name add -N MyName 1-10 2031 2032 adds the name MyName to breakpoints 1-10, and: 2033 2034 (lldb) break set -n myFunc -N Name1 -N Name2 2035 2036 adds two names to the breakpoint set at myFunc. 2037 2038 They have a number of interrelated uses: 2039 2040 1) They provide a stable way to refer to a breakpoint (e.g. in another 2041 breakpoint's action). Using the breakpoint ID for this purpose is fragile, since 2042 it depends on the order of breakpoint creation. Giving a name to the breakpoint 2043 you want to act on, and then referring to it by name, is more robust: 2044 2045 (lldb) break set -n myFunc -N BKPT1 2046 (lldb) break set -n myOtherFunc -C "break disable BKPT1" 2047 2048 2) This is actually just a specific use of a more general feature of breakpoint 2049 names. The <breakpt-id-list> argument type used to specify one or more 2050 breakpoints in most of the commands that deal with breakpoints also accepts 2051 breakpoint names. That allows you to refer to one breakpoint in a stable 2052 manner, but also makes them a convenient grouping mechanism, allowing you to 2053 easily act on a group of breakpoints by using their name, for instance disabling 2054 them all in one action: 2055 2056 (lldb) break set -n myFunc -N Group1 2057 (lldb) break set -n myOtherFunc -N Group1 2058 (lldb) break disable Group1 2059 2060 3) But breakpoint names are also entities in their own right, and can be 2061 configured with all the modifiable attributes of a breakpoint. Then when you 2062 add a breakpoint name to a breakpoint, the breakpoint will be configured to 2063 match the state of the breakpoint name. The link between the name and the 2064 breakpoints sharing it remains live, so if you change the configuration on the 2065 name, it will also change the configurations on the breakpoints: 2066 2067 (lldb) break name configure -i 10 IgnoreSome 2068 (lldb) break set -n myFunc -N IgnoreSome 2069 (lldb) break list IgnoreSome 2070 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 10 enabled 2071 Names: 2072 IgnoreSome 2073 (lldb) break name configure -i 5 IgnoreSome 2074 (lldb) break list IgnoreSome 2075 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 5 enabled 2076 Names: 2077 IgnoreSome 2078 2079 Options that are not configured on a breakpoint name don't affect the value of 2080 those options on the breakpoints they are added to. So for instance, if Name1 2081 has the -i option configured and Name2 the -c option, adding both names to a 2082 breakpoint will set the -i option from Name1 and the -c option from Name2, and 2083 the other options will be unaltered. 2084 2085 If you add multiple names to a breakpoint which have configured values for 2086 the same option, the last name added's value wins. 2087 2088 The "liveness" of these settings is one way, from name to breakpoint. 2089 If you use "break modify" to change an option that is also configured on a name 2090 which that breakpoint has, the "break modify" command will override the setting 2091 for that breakpoint, but won't change the value configured in the name or on the 2092 other breakpoints sharing that name. 2093 2094 4) Breakpoint names are also a convenient way to copy option sets from one 2095 breakpoint to another. Using the -B option to "breakpoint name configure" makes 2096 a name configured with all the options of the original breakpoint. Then 2097 adding that name to another breakpoint copies over all the values from the 2098 original breakpoint to the new one. 2099 2100 5) You can also use breakpoint names to hide breakpoints from the breakpoint 2101 operations that act on all breakpoints: "break delete", "break disable" and 2102 "break list". You do that by specifying a "false" value for the 2103 --allow-{list,delete,disable} options to "breakpoint name configure" and then 2104 adding that name to a breakpoint. 2105 2106 This won't keep the breakpoint from being deleted or disabled if you refer to it 2107 specifically by ID. The point of the feature is to make sure users don't 2108 inadvertently delete or disable useful breakpoints (e.g. ones an IDE is using 2109 for its own purposes) as part of a "delete all" or "disable all" operation. The 2110 list hiding is because it's confusing for people to see breakpoints they 2111 didn't set. 2112 2113 )"); 2114 CommandObjectSP add_command_object( 2115 new CommandObjectBreakpointNameAdd(interpreter)); 2116 CommandObjectSP delete_command_object( 2117 new CommandObjectBreakpointNameDelete(interpreter)); 2118 CommandObjectSP list_command_object( 2119 new CommandObjectBreakpointNameList(interpreter)); 2120 CommandObjectSP configure_command_object( 2121 new CommandObjectBreakpointNameConfigure(interpreter)); 2122 2123 LoadSubCommand("add", add_command_object); 2124 LoadSubCommand("delete", delete_command_object); 2125 LoadSubCommand("list", list_command_object); 2126 LoadSubCommand("configure", configure_command_object); 2127 } 2128 2129 ~CommandObjectBreakpointName() override = default; 2130 }; 2131 2132 // CommandObjectBreakpointRead 2133 #pragma mark Read::CommandOptions 2134 #define LLDB_OPTIONS_breakpoint_read 2135 #include "CommandOptions.inc" 2136 2137 #pragma mark Read 2138 2139 class CommandObjectBreakpointRead : public CommandObjectParsed { 2140 public: 2141 CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2142 : CommandObjectParsed(interpreter, "breakpoint read", 2143 "Read and set the breakpoints previously saved to " 2144 "a file with \"breakpoint write\". ", 2145 nullptr) {} 2146 2147 ~CommandObjectBreakpointRead() override = default; 2148 2149 Options *GetOptions() override { return &m_options; } 2150 2151 class CommandOptions : public Options { 2152 public: 2153 CommandOptions() = default; 2154 2155 ~CommandOptions() override = default; 2156 2157 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2158 ExecutionContext *execution_context) override { 2159 Status error; 2160 const int short_option = m_getopt_table[option_idx].val; 2161 2162 switch (short_option) { 2163 case 'f': 2164 m_filename.assign(std::string(option_arg)); 2165 break; 2166 case 'N': { 2167 Status name_error; 2168 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 2169 name_error)) { 2170 error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 2171 name_error.AsCString()); 2172 } 2173 m_names.push_back(std::string(option_arg)); 2174 break; 2175 } 2176 default: 2177 llvm_unreachable("Unimplemented option"); 2178 } 2179 2180 return error; 2181 } 2182 2183 void OptionParsingStarting(ExecutionContext *execution_context) override { 2184 m_filename.clear(); 2185 m_names.clear(); 2186 } 2187 2188 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2189 return llvm::makeArrayRef(g_breakpoint_read_options); 2190 } 2191 2192 void HandleOptionArgumentCompletion( 2193 CompletionRequest &request, OptionElementVector &opt_element_vector, 2194 int opt_element_index, CommandInterpreter &interpreter) override { 2195 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 2196 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 2197 2198 switch (GetDefinitions()[opt_defs_index].short_option) { 2199 case 'f': 2200 CommandCompletions::InvokeCommonCompletionCallbacks( 2201 interpreter, CommandCompletions::eDiskFileCompletion, request, 2202 nullptr); 2203 break; 2204 2205 case 'N': 2206 llvm::Optional<FileSpec> file_spec; 2207 const llvm::StringRef dash_f("-f"); 2208 for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) { 2209 if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) { 2210 file_spec.emplace( 2211 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1)); 2212 break; 2213 } 2214 } 2215 if (!file_spec) 2216 return; 2217 2218 FileSystem::Instance().Resolve(*file_spec); 2219 Status error; 2220 StructuredData::ObjectSP input_data_sp = 2221 StructuredData::ParseJSONFromFile(*file_spec, error); 2222 if (!error.Success()) 2223 return; 2224 2225 StructuredData::Array *bkpt_array = input_data_sp->GetAsArray(); 2226 if (!bkpt_array) 2227 return; 2228 2229 const size_t num_bkpts = bkpt_array->GetSize(); 2230 for (size_t i = 0; i < num_bkpts; i++) { 2231 StructuredData::ObjectSP bkpt_object_sp = 2232 bkpt_array->GetItemAtIndex(i); 2233 if (!bkpt_object_sp) 2234 return; 2235 2236 StructuredData::Dictionary *bkpt_dict = 2237 bkpt_object_sp->GetAsDictionary(); 2238 if (!bkpt_dict) 2239 return; 2240 2241 StructuredData::ObjectSP bkpt_data_sp = 2242 bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey()); 2243 if (!bkpt_data_sp) 2244 return; 2245 2246 bkpt_dict = bkpt_data_sp->GetAsDictionary(); 2247 if (!bkpt_dict) 2248 return; 2249 2250 StructuredData::Array *names_array; 2251 2252 if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array)) 2253 return; 2254 2255 size_t num_names = names_array->GetSize(); 2256 2257 for (size_t i = 0; i < num_names; i++) { 2258 llvm::StringRef name; 2259 if (names_array->GetItemAtIndexAsString(i, name)) 2260 request.TryCompleteCurrentArg(name); 2261 } 2262 } 2263 } 2264 } 2265 2266 std::string m_filename; 2267 std::vector<std::string> m_names; 2268 }; 2269 2270 protected: 2271 bool DoExecute(Args &command, CommandReturnObject &result) override { 2272 Target &target = GetSelectedOrDummyTarget(); 2273 2274 std::unique_lock<std::recursive_mutex> lock; 2275 target.GetBreakpointList().GetListMutex(lock); 2276 2277 FileSpec input_spec(m_options.m_filename); 2278 FileSystem::Instance().Resolve(input_spec); 2279 BreakpointIDList new_bps; 2280 Status error = target.CreateBreakpointsFromFile(input_spec, 2281 m_options.m_names, new_bps); 2282 2283 if (!error.Success()) { 2284 result.AppendError(error.AsCString()); 2285 return false; 2286 } 2287 2288 Stream &output_stream = result.GetOutputStream(); 2289 2290 size_t num_breakpoints = new_bps.GetSize(); 2291 if (num_breakpoints == 0) { 2292 result.AppendMessage("No breakpoints added."); 2293 } else { 2294 // No breakpoint selected; show info about all currently set breakpoints. 2295 result.AppendMessage("New breakpoints:"); 2296 for (size_t i = 0; i < num_breakpoints; ++i) { 2297 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 2298 Breakpoint *bp = target.GetBreakpointList() 2299 .FindBreakpointByID(bp_id.GetBreakpointID()) 2300 .get(); 2301 if (bp) 2302 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 2303 false); 2304 } 2305 } 2306 return result.Succeeded(); 2307 } 2308 2309 private: 2310 CommandOptions m_options; 2311 }; 2312 2313 // CommandObjectBreakpointWrite 2314 #pragma mark Write::CommandOptions 2315 #define LLDB_OPTIONS_breakpoint_write 2316 #include "CommandOptions.inc" 2317 2318 #pragma mark Write 2319 class CommandObjectBreakpointWrite : public CommandObjectParsed { 2320 public: 2321 CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2322 : CommandObjectParsed(interpreter, "breakpoint write", 2323 "Write the breakpoints listed to a file that can " 2324 "be read in with \"breakpoint read\". " 2325 "If given no arguments, writes all breakpoints.", 2326 nullptr) { 2327 CommandArgumentEntry arg; 2328 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2329 eArgTypeBreakpointIDRange); 2330 // Add the entry for the first argument for this command to the object's 2331 // arguments vector. 2332 m_arguments.push_back(arg); 2333 } 2334 2335 ~CommandObjectBreakpointWrite() override = default; 2336 2337 void 2338 HandleArgumentCompletion(CompletionRequest &request, 2339 OptionElementVector &opt_element_vector) override { 2340 CommandCompletions::InvokeCommonCompletionCallbacks( 2341 GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion, 2342 request, nullptr); 2343 } 2344 2345 Options *GetOptions() override { return &m_options; } 2346 2347 class CommandOptions : public Options { 2348 public: 2349 CommandOptions() = default; 2350 2351 ~CommandOptions() override = default; 2352 2353 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2354 ExecutionContext *execution_context) override { 2355 Status error; 2356 const int short_option = m_getopt_table[option_idx].val; 2357 2358 switch (short_option) { 2359 case 'f': 2360 m_filename.assign(std::string(option_arg)); 2361 break; 2362 case 'a': 2363 m_append = true; 2364 break; 2365 default: 2366 llvm_unreachable("Unimplemented option"); 2367 } 2368 2369 return error; 2370 } 2371 2372 void OptionParsingStarting(ExecutionContext *execution_context) override { 2373 m_filename.clear(); 2374 m_append = false; 2375 } 2376 2377 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2378 return llvm::makeArrayRef(g_breakpoint_write_options); 2379 } 2380 2381 // Instance variables to hold the values for command options. 2382 2383 std::string m_filename; 2384 bool m_append = false; 2385 }; 2386 2387 protected: 2388 bool DoExecute(Args &command, CommandReturnObject &result) override { 2389 Target &target = GetSelectedOrDummyTarget(); 2390 2391 std::unique_lock<std::recursive_mutex> lock; 2392 target.GetBreakpointList().GetListMutex(lock); 2393 2394 BreakpointIDList valid_bp_ids; 2395 if (!command.empty()) { 2396 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2397 command, &target, result, &valid_bp_ids, 2398 BreakpointName::Permissions::PermissionKinds::listPerm); 2399 2400 if (!result.Succeeded()) { 2401 result.SetStatus(eReturnStatusFailed); 2402 return false; 2403 } 2404 } 2405 FileSpec file_spec(m_options.m_filename); 2406 FileSystem::Instance().Resolve(file_spec); 2407 Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids, 2408 m_options.m_append); 2409 if (!error.Success()) { 2410 result.AppendErrorWithFormat("error serializing breakpoints: %s.", 2411 error.AsCString()); 2412 } 2413 return result.Succeeded(); 2414 } 2415 2416 private: 2417 CommandOptions m_options; 2418 }; 2419 2420 // CommandObjectMultiwordBreakpoint 2421 #pragma mark MultiwordBreakpoint 2422 2423 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2424 CommandInterpreter &interpreter) 2425 : CommandObjectMultiword( 2426 interpreter, "breakpoint", 2427 "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2428 "breakpoint <subcommand> [<command-options>]") { 2429 CommandObjectSP list_command_object( 2430 new CommandObjectBreakpointList(interpreter)); 2431 CommandObjectSP enable_command_object( 2432 new CommandObjectBreakpointEnable(interpreter)); 2433 CommandObjectSP disable_command_object( 2434 new CommandObjectBreakpointDisable(interpreter)); 2435 CommandObjectSP clear_command_object( 2436 new CommandObjectBreakpointClear(interpreter)); 2437 CommandObjectSP delete_command_object( 2438 new CommandObjectBreakpointDelete(interpreter)); 2439 CommandObjectSP set_command_object( 2440 new CommandObjectBreakpointSet(interpreter)); 2441 CommandObjectSP command_command_object( 2442 new CommandObjectBreakpointCommand(interpreter)); 2443 CommandObjectSP modify_command_object( 2444 new CommandObjectBreakpointModify(interpreter)); 2445 CommandObjectSP name_command_object( 2446 new CommandObjectBreakpointName(interpreter)); 2447 CommandObjectSP write_command_object( 2448 new CommandObjectBreakpointWrite(interpreter)); 2449 CommandObjectSP read_command_object( 2450 new CommandObjectBreakpointRead(interpreter)); 2451 2452 list_command_object->SetCommandName("breakpoint list"); 2453 enable_command_object->SetCommandName("breakpoint enable"); 2454 disable_command_object->SetCommandName("breakpoint disable"); 2455 clear_command_object->SetCommandName("breakpoint clear"); 2456 delete_command_object->SetCommandName("breakpoint delete"); 2457 set_command_object->SetCommandName("breakpoint set"); 2458 command_command_object->SetCommandName("breakpoint command"); 2459 modify_command_object->SetCommandName("breakpoint modify"); 2460 name_command_object->SetCommandName("breakpoint name"); 2461 write_command_object->SetCommandName("breakpoint write"); 2462 read_command_object->SetCommandName("breakpoint read"); 2463 2464 LoadSubCommand("list", list_command_object); 2465 LoadSubCommand("enable", enable_command_object); 2466 LoadSubCommand("disable", disable_command_object); 2467 LoadSubCommand("clear", clear_command_object); 2468 LoadSubCommand("delete", delete_command_object); 2469 LoadSubCommand("set", set_command_object); 2470 LoadSubCommand("command", command_command_object); 2471 LoadSubCommand("modify", modify_command_object); 2472 LoadSubCommand("name", name_command_object); 2473 LoadSubCommand("write", write_command_object); 2474 LoadSubCommand("read", read_command_object); 2475 } 2476 2477 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 2478 2479 void CommandObjectMultiwordBreakpoint::VerifyIDs( 2480 Args &args, Target *target, bool allow_locations, 2481 CommandReturnObject &result, BreakpointIDList *valid_ids, 2482 BreakpointName::Permissions ::PermissionKinds purpose) { 2483 // args can be strings representing 1). integers (for breakpoint ids) 2484 // 2). the full breakpoint & location 2485 // canonical representation 2486 // 3). the word "to" or a hyphen, 2487 // representing a range (in which case there 2488 // had *better* be an entry both before & 2489 // after of one of the first two types. 2490 // 4). A breakpoint name 2491 // If args is empty, we will use the last created breakpoint (if there is 2492 // one.) 2493 2494 Args temp_args; 2495 2496 if (args.empty()) { 2497 if (target->GetLastCreatedBreakpoint()) { 2498 valid_ids->AddBreakpointID(BreakpointID( 2499 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 2500 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2501 } else { 2502 result.AppendError( 2503 "No breakpoint specified and no last created breakpoint."); 2504 } 2505 return; 2506 } 2507 2508 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 2509 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 2510 // id range strings over; instead generate a list of strings for all the 2511 // breakpoint ids in the range, and shove all of those breakpoint id strings 2512 // into TEMP_ARGS. 2513 2514 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2515 purpose, result, temp_args); 2516 2517 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2518 // BreakpointIDList: 2519 2520 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 2521 2522 // At this point, all of the breakpoint ids that the user passed in have 2523 // been converted to breakpoint IDs and put into valid_ids. 2524 2525 if (result.Succeeded()) { 2526 // Now that we've converted everything from args into a list of breakpoint 2527 // ids, go through our tentative list of breakpoint id's and verify that 2528 // they correspond to valid/currently set breakpoints. 2529 2530 const size_t count = valid_ids->GetSize(); 2531 for (size_t i = 0; i < count; ++i) { 2532 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2533 Breakpoint *breakpoint = 2534 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2535 if (breakpoint != nullptr) { 2536 const size_t num_locations = breakpoint->GetNumLocations(); 2537 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 2538 StreamString id_str; 2539 BreakpointID::GetCanonicalReference( 2540 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2541 i = valid_ids->GetSize() + 1; 2542 result.AppendErrorWithFormat( 2543 "'%s' is not a currently valid breakpoint/location id.\n", 2544 id_str.GetData()); 2545 } 2546 } else { 2547 i = valid_ids->GetSize() + 1; 2548 result.AppendErrorWithFormat( 2549 "'%d' is not a currently valid breakpoint ID.\n", 2550 cur_bp_id.GetBreakpointID()); 2551 } 2552 } 2553 } 2554 } 2555