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