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