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