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