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