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