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 Options *GetOptions() override { return &m_options; } 823 824 protected: 825 bool DoExecute(Args &command, CommandReturnObject &result) override { 826 Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 827 828 std::unique_lock<std::recursive_mutex> lock; 829 target.GetBreakpointList().GetListMutex(lock); 830 831 BreakpointIDList valid_bp_ids; 832 833 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 834 command, &target, result, &valid_bp_ids, 835 BreakpointName::Permissions::PermissionKinds::disablePerm); 836 837 if (result.Succeeded()) { 838 const size_t count = valid_bp_ids.GetSize(); 839 for (size_t i = 0; i < count; ++i) { 840 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 841 842 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 843 Breakpoint *bp = 844 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 845 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 846 BreakpointLocation *location = 847 bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 848 if (location) 849 location->GetLocationOptions()->CopyOverSetOptions( 850 m_bp_opts.GetBreakpointOptions()); 851 } else { 852 bp->GetOptions()->CopyOverSetOptions( 853 m_bp_opts.GetBreakpointOptions()); 854 } 855 } 856 } 857 } 858 859 return result.Succeeded(); 860 } 861 862 private: 863 BreakpointOptionGroup m_bp_opts; 864 BreakpointDummyOptionGroup m_dummy_opts; 865 OptionGroupOptions m_options; 866 }; 867 868 // CommandObjectBreakpointEnable 869 #pragma mark Enable 870 871 class CommandObjectBreakpointEnable : public CommandObjectParsed { 872 public: 873 CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 874 : CommandObjectParsed(interpreter, "enable", 875 "Enable the specified disabled breakpoint(s). If " 876 "no breakpoints are specified, enable all of them.", 877 nullptr) { 878 CommandArgumentEntry arg; 879 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 880 eArgTypeBreakpointIDRange); 881 // Add the entry for the first argument for this command to the object's 882 // arguments vector. 883 m_arguments.push_back(arg); 884 } 885 886 ~CommandObjectBreakpointEnable() override = default; 887 888 protected: 889 bool DoExecute(Args &command, CommandReturnObject &result) override { 890 Target &target = GetSelectedOrDummyTarget(); 891 892 std::unique_lock<std::recursive_mutex> lock; 893 target.GetBreakpointList().GetListMutex(lock); 894 895 const BreakpointList &breakpoints = target.GetBreakpointList(); 896 897 size_t num_breakpoints = breakpoints.GetSize(); 898 899 if (num_breakpoints == 0) { 900 result.AppendError("No breakpoints exist to be enabled."); 901 result.SetStatus(eReturnStatusFailed); 902 return false; 903 } 904 905 if (command.empty()) { 906 // No breakpoint selected; enable all currently set breakpoints. 907 target.EnableAllowedBreakpoints(); 908 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 909 " breakpoints)\n", 910 (uint64_t)num_breakpoints); 911 result.SetStatus(eReturnStatusSuccessFinishNoResult); 912 } else { 913 // Particular breakpoint selected; enable that breakpoint. 914 BreakpointIDList valid_bp_ids; 915 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 916 command, &target, result, &valid_bp_ids, 917 BreakpointName::Permissions::PermissionKinds::disablePerm); 918 919 if (result.Succeeded()) { 920 int enable_count = 0; 921 int loc_count = 0; 922 const size_t count = valid_bp_ids.GetSize(); 923 for (size_t i = 0; i < count; ++i) { 924 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 925 926 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 927 Breakpoint *breakpoint = 928 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 929 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 930 BreakpointLocation *location = 931 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 932 if (location) { 933 location->SetEnabled(true); 934 ++loc_count; 935 } 936 } else { 937 breakpoint->SetEnabled(true); 938 ++enable_count; 939 } 940 } 941 } 942 result.AppendMessageWithFormat("%d breakpoints enabled.\n", 943 enable_count + loc_count); 944 result.SetStatus(eReturnStatusSuccessFinishNoResult); 945 } 946 } 947 948 return result.Succeeded(); 949 } 950 }; 951 952 // CommandObjectBreakpointDisable 953 #pragma mark Disable 954 955 class CommandObjectBreakpointDisable : public CommandObjectParsed { 956 public: 957 CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 958 : CommandObjectParsed( 959 interpreter, "breakpoint disable", 960 "Disable the specified breakpoint(s) without deleting " 961 "them. If none are specified, disable all " 962 "breakpoints.", 963 nullptr) { 964 SetHelpLong( 965 "Disable the specified breakpoint(s) without deleting them. \ 966 If none are specified, disable all breakpoints." 967 R"( 968 969 )" 970 "Note: disabling a breakpoint will cause none of its locations to be hit \ 971 regardless of whether individual locations are enabled or disabled. After the sequence:" 972 R"( 973 974 (lldb) break disable 1 975 (lldb) break enable 1.1 976 977 execution will NOT stop at location 1.1. To achieve that, type: 978 979 (lldb) break disable 1.* 980 (lldb) break enable 1.1 981 982 )" 983 "The first command disables all locations for breakpoint 1, \ 984 the second re-enables the first location."); 985 986 CommandArgumentEntry arg; 987 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 988 eArgTypeBreakpointIDRange); 989 // Add the entry for the first argument for this command to the object's 990 // arguments vector. 991 m_arguments.push_back(arg); 992 } 993 994 ~CommandObjectBreakpointDisable() override = default; 995 996 protected: 997 bool DoExecute(Args &command, CommandReturnObject &result) override { 998 Target &target = GetSelectedOrDummyTarget(); 999 std::unique_lock<std::recursive_mutex> lock; 1000 target.GetBreakpointList().GetListMutex(lock); 1001 1002 const BreakpointList &breakpoints = target.GetBreakpointList(); 1003 size_t num_breakpoints = breakpoints.GetSize(); 1004 1005 if (num_breakpoints == 0) { 1006 result.AppendError("No breakpoints exist to be disabled."); 1007 result.SetStatus(eReturnStatusFailed); 1008 return false; 1009 } 1010 1011 if (command.empty()) { 1012 // No breakpoint selected; disable all currently set breakpoints. 1013 target.DisableAllowedBreakpoints(); 1014 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1015 " breakpoints)\n", 1016 (uint64_t)num_breakpoints); 1017 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1018 } else { 1019 // Particular breakpoint selected; disable that breakpoint. 1020 BreakpointIDList valid_bp_ids; 1021 1022 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1023 command, &target, result, &valid_bp_ids, 1024 BreakpointName::Permissions::PermissionKinds::disablePerm); 1025 1026 if (result.Succeeded()) { 1027 int disable_count = 0; 1028 int loc_count = 0; 1029 const size_t count = valid_bp_ids.GetSize(); 1030 for (size_t i = 0; i < count; ++i) { 1031 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1032 1033 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1034 Breakpoint *breakpoint = 1035 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1036 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1037 BreakpointLocation *location = 1038 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1039 if (location) { 1040 location->SetEnabled(false); 1041 ++loc_count; 1042 } 1043 } else { 1044 breakpoint->SetEnabled(false); 1045 ++disable_count; 1046 } 1047 } 1048 } 1049 result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1050 disable_count + loc_count); 1051 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1052 } 1053 } 1054 1055 return result.Succeeded(); 1056 } 1057 }; 1058 1059 // CommandObjectBreakpointList 1060 1061 #pragma mark List::CommandOptions 1062 #define LLDB_OPTIONS_breakpoint_list 1063 #include "CommandOptions.inc" 1064 1065 #pragma mark List 1066 1067 class CommandObjectBreakpointList : public CommandObjectParsed { 1068 public: 1069 CommandObjectBreakpointList(CommandInterpreter &interpreter) 1070 : CommandObjectParsed( 1071 interpreter, "breakpoint list", 1072 "List some or all breakpoints at configurable levels of detail.", 1073 nullptr), 1074 m_options() { 1075 CommandArgumentEntry arg; 1076 CommandArgumentData bp_id_arg; 1077 1078 // Define the first (and only) variant of this arg. 1079 bp_id_arg.arg_type = eArgTypeBreakpointID; 1080 bp_id_arg.arg_repetition = eArgRepeatOptional; 1081 1082 // There is only one variant this argument could be; put it into the 1083 // argument entry. 1084 arg.push_back(bp_id_arg); 1085 1086 // Push the data for the first argument into the m_arguments vector. 1087 m_arguments.push_back(arg); 1088 } 1089 1090 ~CommandObjectBreakpointList() override = default; 1091 1092 Options *GetOptions() override { return &m_options; } 1093 1094 class CommandOptions : public Options { 1095 public: 1096 CommandOptions() 1097 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 1098 } 1099 1100 ~CommandOptions() override = default; 1101 1102 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1103 ExecutionContext *execution_context) override { 1104 Status error; 1105 const int short_option = m_getopt_table[option_idx].val; 1106 1107 switch (short_option) { 1108 case 'b': 1109 m_level = lldb::eDescriptionLevelBrief; 1110 break; 1111 case 'D': 1112 m_use_dummy = true; 1113 break; 1114 case 'f': 1115 m_level = lldb::eDescriptionLevelFull; 1116 break; 1117 case 'v': 1118 m_level = lldb::eDescriptionLevelVerbose; 1119 break; 1120 case 'i': 1121 m_internal = true; 1122 break; 1123 default: 1124 llvm_unreachable("Unimplemented option"); 1125 } 1126 1127 return error; 1128 } 1129 1130 void OptionParsingStarting(ExecutionContext *execution_context) override { 1131 m_level = lldb::eDescriptionLevelFull; 1132 m_internal = false; 1133 m_use_dummy = false; 1134 } 1135 1136 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1137 return llvm::makeArrayRef(g_breakpoint_list_options); 1138 } 1139 1140 // Instance variables to hold the values for command options. 1141 1142 lldb::DescriptionLevel m_level; 1143 1144 bool m_internal; 1145 bool m_use_dummy; 1146 }; 1147 1148 protected: 1149 bool DoExecute(Args &command, CommandReturnObject &result) override { 1150 Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1151 1152 const BreakpointList &breakpoints = 1153 target.GetBreakpointList(m_options.m_internal); 1154 std::unique_lock<std::recursive_mutex> lock; 1155 target.GetBreakpointList(m_options.m_internal).GetListMutex(lock); 1156 1157 size_t num_breakpoints = breakpoints.GetSize(); 1158 1159 if (num_breakpoints == 0) { 1160 result.AppendMessage("No breakpoints currently set."); 1161 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1162 return true; 1163 } 1164 1165 Stream &output_stream = result.GetOutputStream(); 1166 1167 if (command.empty()) { 1168 // No breakpoint selected; show info about all currently set breakpoints. 1169 result.AppendMessage("Current breakpoints:"); 1170 for (size_t i = 0; i < num_breakpoints; ++i) { 1171 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1172 if (breakpoint->AllowList()) 1173 AddBreakpointDescription(&output_stream, breakpoint, 1174 m_options.m_level); 1175 } 1176 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1177 } else { 1178 // Particular breakpoints selected; show info about that breakpoint. 1179 BreakpointIDList valid_bp_ids; 1180 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1181 command, &target, result, &valid_bp_ids, 1182 BreakpointName::Permissions::PermissionKinds::listPerm); 1183 1184 if (result.Succeeded()) { 1185 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 1186 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1187 Breakpoint *breakpoint = 1188 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1189 AddBreakpointDescription(&output_stream, breakpoint, 1190 m_options.m_level); 1191 } 1192 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1193 } else { 1194 result.AppendError("Invalid breakpoint ID."); 1195 result.SetStatus(eReturnStatusFailed); 1196 } 1197 } 1198 1199 return result.Succeeded(); 1200 } 1201 1202 private: 1203 CommandOptions m_options; 1204 }; 1205 1206 // CommandObjectBreakpointClear 1207 #pragma mark Clear::CommandOptions 1208 1209 #define LLDB_OPTIONS_breakpoint_clear 1210 #include "CommandOptions.inc" 1211 1212 #pragma mark Clear 1213 1214 class CommandObjectBreakpointClear : public CommandObjectParsed { 1215 public: 1216 enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine }; 1217 1218 CommandObjectBreakpointClear(CommandInterpreter &interpreter) 1219 : CommandObjectParsed(interpreter, "breakpoint clear", 1220 "Delete or disable breakpoints matching the " 1221 "specified source file and line.", 1222 "breakpoint clear <cmd-options>"), 1223 m_options() {} 1224 1225 ~CommandObjectBreakpointClear() override = default; 1226 1227 Options *GetOptions() override { return &m_options; } 1228 1229 class CommandOptions : public Options { 1230 public: 1231 CommandOptions() : Options(), m_filename(), m_line_num(0) {} 1232 1233 ~CommandOptions() override = default; 1234 1235 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1236 ExecutionContext *execution_context) override { 1237 Status error; 1238 const int short_option = m_getopt_table[option_idx].val; 1239 1240 switch (short_option) { 1241 case 'f': 1242 m_filename.assign(std::string(option_arg)); 1243 break; 1244 1245 case 'l': 1246 option_arg.getAsInteger(0, m_line_num); 1247 break; 1248 1249 default: 1250 llvm_unreachable("Unimplemented option"); 1251 } 1252 1253 return error; 1254 } 1255 1256 void OptionParsingStarting(ExecutionContext *execution_context) override { 1257 m_filename.clear(); 1258 m_line_num = 0; 1259 } 1260 1261 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1262 return llvm::makeArrayRef(g_breakpoint_clear_options); 1263 } 1264 1265 // Instance variables to hold the values for command options. 1266 1267 std::string m_filename; 1268 uint32_t m_line_num; 1269 }; 1270 1271 protected: 1272 bool DoExecute(Args &command, CommandReturnObject &result) override { 1273 Target &target = GetSelectedOrDummyTarget(); 1274 1275 // The following are the various types of breakpoints that could be 1276 // cleared: 1277 // 1). -f -l (clearing breakpoint by source location) 1278 1279 BreakpointClearType break_type = eClearTypeInvalid; 1280 1281 if (m_options.m_line_num != 0) 1282 break_type = eClearTypeFileAndLine; 1283 1284 std::unique_lock<std::recursive_mutex> lock; 1285 target.GetBreakpointList().GetListMutex(lock); 1286 1287 BreakpointList &breakpoints = target.GetBreakpointList(); 1288 size_t num_breakpoints = breakpoints.GetSize(); 1289 1290 // Early return if there's no breakpoint at all. 1291 if (num_breakpoints == 0) { 1292 result.AppendError("Breakpoint clear: No breakpoint cleared."); 1293 result.SetStatus(eReturnStatusFailed); 1294 return result.Succeeded(); 1295 } 1296 1297 // Find matching breakpoints and delete them. 1298 1299 // First create a copy of all the IDs. 1300 std::vector<break_id_t> BreakIDs; 1301 for (size_t i = 0; i < num_breakpoints; ++i) 1302 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 1303 1304 int num_cleared = 0; 1305 StreamString ss; 1306 switch (break_type) { 1307 case eClearTypeFileAndLine: // Breakpoint by source position 1308 { 1309 const ConstString filename(m_options.m_filename.c_str()); 1310 BreakpointLocationCollection loc_coll; 1311 1312 for (size_t i = 0; i < num_breakpoints; ++i) { 1313 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 1314 1315 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1316 // If the collection size is 0, it's a full match and we can just 1317 // remove the breakpoint. 1318 if (loc_coll.GetSize() == 0) { 1319 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 1320 ss.EOL(); 1321 target.RemoveBreakpointByID(bp->GetID()); 1322 ++num_cleared; 1323 } 1324 } 1325 } 1326 } break; 1327 1328 default: 1329 break; 1330 } 1331 1332 if (num_cleared > 0) { 1333 Stream &output_stream = result.GetOutputStream(); 1334 output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1335 output_stream << ss.GetString(); 1336 output_stream.EOL(); 1337 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1338 } else { 1339 result.AppendError("Breakpoint clear: No breakpoint cleared."); 1340 result.SetStatus(eReturnStatusFailed); 1341 } 1342 1343 return result.Succeeded(); 1344 } 1345 1346 private: 1347 CommandOptions m_options; 1348 }; 1349 1350 // CommandObjectBreakpointDelete 1351 #define LLDB_OPTIONS_breakpoint_delete 1352 #include "CommandOptions.inc" 1353 1354 #pragma mark Delete 1355 1356 class CommandObjectBreakpointDelete : public CommandObjectParsed { 1357 public: 1358 CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1359 : CommandObjectParsed(interpreter, "breakpoint delete", 1360 "Delete the specified breakpoint(s). If no " 1361 "breakpoints are specified, delete them all.", 1362 nullptr), 1363 m_options() { 1364 CommandArgumentEntry arg; 1365 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1366 eArgTypeBreakpointIDRange); 1367 // Add the entry for the first argument for this command to the object's 1368 // arguments vector. 1369 m_arguments.push_back(arg); 1370 } 1371 1372 ~CommandObjectBreakpointDelete() override = default; 1373 1374 Options *GetOptions() override { return &m_options; } 1375 1376 class CommandOptions : public Options { 1377 public: 1378 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 1379 1380 ~CommandOptions() override = default; 1381 1382 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1383 ExecutionContext *execution_context) override { 1384 Status error; 1385 const int short_option = m_getopt_table[option_idx].val; 1386 1387 switch (short_option) { 1388 case 'f': 1389 m_force = true; 1390 break; 1391 1392 case 'D': 1393 m_use_dummy = true; 1394 break; 1395 1396 default: 1397 llvm_unreachable("Unimplemented option"); 1398 } 1399 1400 return error; 1401 } 1402 1403 void OptionParsingStarting(ExecutionContext *execution_context) override { 1404 m_use_dummy = false; 1405 m_force = false; 1406 } 1407 1408 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1409 return llvm::makeArrayRef(g_breakpoint_delete_options); 1410 } 1411 1412 // Instance variables to hold the values for command options. 1413 bool m_use_dummy; 1414 bool m_force; 1415 }; 1416 1417 protected: 1418 bool DoExecute(Args &command, CommandReturnObject &result) override { 1419 Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1420 1421 std::unique_lock<std::recursive_mutex> lock; 1422 target.GetBreakpointList().GetListMutex(lock); 1423 1424 const BreakpointList &breakpoints = target.GetBreakpointList(); 1425 1426 size_t num_breakpoints = breakpoints.GetSize(); 1427 1428 if (num_breakpoints == 0) { 1429 result.AppendError("No breakpoints exist to be deleted."); 1430 result.SetStatus(eReturnStatusFailed); 1431 return false; 1432 } 1433 1434 if (command.empty()) { 1435 if (!m_options.m_force && 1436 !m_interpreter.Confirm( 1437 "About to delete all breakpoints, do you want to do that?", 1438 true)) { 1439 result.AppendMessage("Operation cancelled..."); 1440 } else { 1441 target.RemoveAllowedBreakpoints(); 1442 result.AppendMessageWithFormat( 1443 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1444 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 1445 } 1446 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1447 } else { 1448 // Particular breakpoint selected; disable that breakpoint. 1449 BreakpointIDList valid_bp_ids; 1450 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1451 command, &target, result, &valid_bp_ids, 1452 BreakpointName::Permissions::PermissionKinds::deletePerm); 1453 1454 if (result.Succeeded()) { 1455 int delete_count = 0; 1456 int disable_count = 0; 1457 const size_t count = valid_bp_ids.GetSize(); 1458 for (size_t i = 0; i < count; ++i) { 1459 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1460 1461 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1462 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1463 Breakpoint *breakpoint = 1464 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1465 BreakpointLocation *location = 1466 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1467 // It makes no sense to try to delete individual locations, so we 1468 // disable them instead. 1469 if (location) { 1470 location->SetEnabled(false); 1471 ++disable_count; 1472 } 1473 } else { 1474 target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 1475 ++delete_count; 1476 } 1477 } 1478 } 1479 result.AppendMessageWithFormat( 1480 "%d breakpoints deleted; %d breakpoint locations disabled.\n", 1481 delete_count, disable_count); 1482 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1483 } 1484 } 1485 return result.Succeeded(); 1486 } 1487 1488 private: 1489 CommandOptions m_options; 1490 }; 1491 1492 // CommandObjectBreakpointName 1493 #define LLDB_OPTIONS_breakpoint_name 1494 #include "CommandOptions.inc" 1495 1496 class BreakpointNameOptionGroup : public OptionGroup { 1497 public: 1498 BreakpointNameOptionGroup() 1499 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 1500 } 1501 1502 ~BreakpointNameOptionGroup() override = default; 1503 1504 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1505 return llvm::makeArrayRef(g_breakpoint_name_options); 1506 } 1507 1508 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1509 ExecutionContext *execution_context) override { 1510 Status error; 1511 const int short_option = g_breakpoint_name_options[option_idx].short_option; 1512 1513 switch (short_option) { 1514 case 'N': 1515 if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1516 error.Success()) 1517 m_name.SetValueFromString(option_arg); 1518 break; 1519 case 'B': 1520 if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1521 error.SetErrorStringWithFormat( 1522 "unrecognized value \"%s\" for breakpoint", 1523 option_arg.str().c_str()); 1524 break; 1525 case 'D': 1526 if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1527 error.SetErrorStringWithFormat( 1528 "unrecognized value \"%s\" for use-dummy", 1529 option_arg.str().c_str()); 1530 break; 1531 case 'H': 1532 m_help_string.SetValueFromString(option_arg); 1533 break; 1534 1535 default: 1536 llvm_unreachable("Unimplemented option"); 1537 } 1538 return error; 1539 } 1540 1541 void OptionParsingStarting(ExecutionContext *execution_context) override { 1542 m_name.Clear(); 1543 m_breakpoint.Clear(); 1544 m_use_dummy.Clear(); 1545 m_use_dummy.SetDefaultValue(false); 1546 m_help_string.Clear(); 1547 } 1548 1549 OptionValueString m_name; 1550 OptionValueUInt64 m_breakpoint; 1551 OptionValueBoolean m_use_dummy; 1552 OptionValueString m_help_string; 1553 }; 1554 1555 #define LLDB_OPTIONS_breakpoint_access 1556 #include "CommandOptions.inc" 1557 1558 class BreakpointAccessOptionGroup : public OptionGroup { 1559 public: 1560 BreakpointAccessOptionGroup() : OptionGroup() {} 1561 1562 ~BreakpointAccessOptionGroup() override = default; 1563 1564 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1565 return llvm::makeArrayRef(g_breakpoint_access_options); 1566 } 1567 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1568 ExecutionContext *execution_context) override { 1569 Status error; 1570 const int short_option = 1571 g_breakpoint_access_options[option_idx].short_option; 1572 1573 switch (short_option) { 1574 case 'L': { 1575 bool value, success; 1576 value = OptionArgParser::ToBoolean(option_arg, false, &success); 1577 if (success) { 1578 m_permissions.SetAllowList(value); 1579 } else 1580 error.SetErrorStringWithFormat( 1581 "invalid boolean value '%s' passed for -L option", 1582 option_arg.str().c_str()); 1583 } break; 1584 case 'A': { 1585 bool value, success; 1586 value = OptionArgParser::ToBoolean(option_arg, false, &success); 1587 if (success) { 1588 m_permissions.SetAllowDisable(value); 1589 } else 1590 error.SetErrorStringWithFormat( 1591 "invalid boolean value '%s' passed for -L option", 1592 option_arg.str().c_str()); 1593 } break; 1594 case 'D': { 1595 bool value, success; 1596 value = OptionArgParser::ToBoolean(option_arg, false, &success); 1597 if (success) { 1598 m_permissions.SetAllowDelete(value); 1599 } else 1600 error.SetErrorStringWithFormat( 1601 "invalid boolean value '%s' passed for -L option", 1602 option_arg.str().c_str()); 1603 } break; 1604 default: 1605 llvm_unreachable("Unimplemented option"); 1606 } 1607 1608 return error; 1609 } 1610 1611 void OptionParsingStarting(ExecutionContext *execution_context) override {} 1612 1613 const BreakpointName::Permissions &GetPermissions() const { 1614 return m_permissions; 1615 } 1616 BreakpointName::Permissions m_permissions; 1617 }; 1618 1619 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1620 public: 1621 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1622 : CommandObjectParsed( 1623 interpreter, "configure", 1624 "Configure the options for the breakpoint" 1625 " name provided. " 1626 "If you provide a breakpoint id, the options will be copied from " 1627 "the breakpoint, otherwise only the options specified will be set " 1628 "on the name.", 1629 "breakpoint name configure <command-options> " 1630 "<breakpoint-name-list>"), 1631 m_bp_opts(), m_option_group() { 1632 // Create the first variant for the first (and only) argument for this 1633 // command. 1634 CommandArgumentEntry arg1; 1635 CommandArgumentData id_arg; 1636 id_arg.arg_type = eArgTypeBreakpointName; 1637 id_arg.arg_repetition = eArgRepeatOptional; 1638 arg1.push_back(id_arg); 1639 m_arguments.push_back(arg1); 1640 1641 m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1642 m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL, 1643 LLDB_OPT_SET_ALL); 1644 m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4, 1645 LLDB_OPT_SET_ALL); 1646 m_option_group.Finalize(); 1647 } 1648 1649 ~CommandObjectBreakpointNameConfigure() override = default; 1650 1651 Options *GetOptions() override { return &m_option_group; } 1652 1653 protected: 1654 bool DoExecute(Args &command, CommandReturnObject &result) override { 1655 1656 const size_t argc = command.GetArgumentCount(); 1657 if (argc == 0) { 1658 result.AppendError("No names provided."); 1659 result.SetStatus(eReturnStatusFailed); 1660 return false; 1661 } 1662 1663 Target &target = GetSelectedOrDummyTarget(false); 1664 1665 std::unique_lock<std::recursive_mutex> lock; 1666 target.GetBreakpointList().GetListMutex(lock); 1667 1668 // Make a pass through first to see that all the names are legal. 1669 for (auto &entry : command.entries()) { 1670 Status error; 1671 if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) { 1672 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1673 entry.c_str(), error.AsCString()); 1674 result.SetStatus(eReturnStatusFailed); 1675 return false; 1676 } 1677 } 1678 // Now configure them, we already pre-checked the names so we don't need to 1679 // check the error: 1680 BreakpointSP bp_sp; 1681 if (m_bp_id.m_breakpoint.OptionWasSet()) { 1682 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1683 bp_sp = target.GetBreakpointByID(bp_id); 1684 if (!bp_sp) { 1685 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1686 bp_id); 1687 result.SetStatus(eReturnStatusFailed); 1688 return false; 1689 } 1690 } 1691 1692 Status error; 1693 for (auto &entry : command.entries()) { 1694 ConstString name(entry.c_str()); 1695 BreakpointName *bp_name = target.FindBreakpointName(name, true, error); 1696 if (!bp_name) 1697 continue; 1698 if (m_bp_id.m_help_string.OptionWasSet()) 1699 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1700 1701 if (bp_sp) 1702 target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(), 1703 m_access_options.GetPermissions()); 1704 else 1705 target.ConfigureBreakpointName(*bp_name, 1706 m_bp_opts.GetBreakpointOptions(), 1707 m_access_options.GetPermissions()); 1708 } 1709 return true; 1710 } 1711 1712 private: 1713 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1714 BreakpointOptionGroup m_bp_opts; 1715 BreakpointAccessOptionGroup m_access_options; 1716 OptionGroupOptions m_option_group; 1717 }; 1718 1719 class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 1720 public: 1721 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1722 : CommandObjectParsed( 1723 interpreter, "add", "Add a name to the breakpoints provided.", 1724 "breakpoint name add <command-options> <breakpoint-id-list>"), 1725 m_name_options(), m_option_group() { 1726 // Create the first variant for the first (and only) argument for this 1727 // command. 1728 CommandArgumentEntry arg1; 1729 CommandArgumentData id_arg; 1730 id_arg.arg_type = eArgTypeBreakpointID; 1731 id_arg.arg_repetition = eArgRepeatOptional; 1732 arg1.push_back(id_arg); 1733 m_arguments.push_back(arg1); 1734 1735 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 1736 m_option_group.Finalize(); 1737 } 1738 1739 ~CommandObjectBreakpointNameAdd() override = default; 1740 1741 Options *GetOptions() override { return &m_option_group; } 1742 1743 protected: 1744 bool DoExecute(Args &command, CommandReturnObject &result) override { 1745 if (!m_name_options.m_name.OptionWasSet()) { 1746 result.SetError("No name option provided."); 1747 return false; 1748 } 1749 1750 Target &target = 1751 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1752 1753 std::unique_lock<std::recursive_mutex> lock; 1754 target.GetBreakpointList().GetListMutex(lock); 1755 1756 const BreakpointList &breakpoints = target.GetBreakpointList(); 1757 1758 size_t num_breakpoints = breakpoints.GetSize(); 1759 if (num_breakpoints == 0) { 1760 result.SetError("No breakpoints, cannot add names."); 1761 result.SetStatus(eReturnStatusFailed); 1762 return false; 1763 } 1764 1765 // Particular breakpoint selected; disable that breakpoint. 1766 BreakpointIDList valid_bp_ids; 1767 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1768 command, &target, result, &valid_bp_ids, 1769 BreakpointName::Permissions::PermissionKinds::listPerm); 1770 1771 if (result.Succeeded()) { 1772 if (valid_bp_ids.GetSize() == 0) { 1773 result.SetError("No breakpoints specified, cannot add names."); 1774 result.SetStatus(eReturnStatusFailed); 1775 return false; 1776 } 1777 size_t num_valid_ids = valid_bp_ids.GetSize(); 1778 const char *bp_name = m_name_options.m_name.GetCurrentValue(); 1779 Status error; // This error reports illegal names, but we've already 1780 // checked that, so we don't need to check it again here. 1781 for (size_t index = 0; index < num_valid_ids; index++) { 1782 lldb::break_id_t bp_id = 1783 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 1784 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1785 target.AddNameToBreakpoint(bp_sp, bp_name, error); 1786 } 1787 } 1788 1789 return true; 1790 } 1791 1792 private: 1793 BreakpointNameOptionGroup m_name_options; 1794 OptionGroupOptions m_option_group; 1795 }; 1796 1797 class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 1798 public: 1799 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1800 : CommandObjectParsed( 1801 interpreter, "delete", 1802 "Delete a name from the breakpoints provided.", 1803 "breakpoint name delete <command-options> <breakpoint-id-list>"), 1804 m_name_options(), m_option_group() { 1805 // Create the first variant for the first (and only) argument for this 1806 // command. 1807 CommandArgumentEntry arg1; 1808 CommandArgumentData id_arg; 1809 id_arg.arg_type = eArgTypeBreakpointID; 1810 id_arg.arg_repetition = eArgRepeatOptional; 1811 arg1.push_back(id_arg); 1812 m_arguments.push_back(arg1); 1813 1814 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 1815 m_option_group.Finalize(); 1816 } 1817 1818 ~CommandObjectBreakpointNameDelete() override = default; 1819 1820 Options *GetOptions() override { return &m_option_group; } 1821 1822 protected: 1823 bool DoExecute(Args &command, CommandReturnObject &result) override { 1824 if (!m_name_options.m_name.OptionWasSet()) { 1825 result.SetError("No name option provided."); 1826 return false; 1827 } 1828 1829 Target &target = 1830 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1831 1832 std::unique_lock<std::recursive_mutex> lock; 1833 target.GetBreakpointList().GetListMutex(lock); 1834 1835 const BreakpointList &breakpoints = target.GetBreakpointList(); 1836 1837 size_t num_breakpoints = breakpoints.GetSize(); 1838 if (num_breakpoints == 0) { 1839 result.SetError("No breakpoints, cannot delete names."); 1840 result.SetStatus(eReturnStatusFailed); 1841 return false; 1842 } 1843 1844 // Particular breakpoint selected; disable that breakpoint. 1845 BreakpointIDList valid_bp_ids; 1846 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1847 command, &target, result, &valid_bp_ids, 1848 BreakpointName::Permissions::PermissionKinds::deletePerm); 1849 1850 if (result.Succeeded()) { 1851 if (valid_bp_ids.GetSize() == 0) { 1852 result.SetError("No breakpoints specified, cannot delete names."); 1853 result.SetStatus(eReturnStatusFailed); 1854 return false; 1855 } 1856 ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 1857 size_t num_valid_ids = valid_bp_ids.GetSize(); 1858 for (size_t index = 0; index < num_valid_ids; index++) { 1859 lldb::break_id_t bp_id = 1860 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 1861 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1862 target.RemoveNameFromBreakpoint(bp_sp, bp_name); 1863 } 1864 } 1865 1866 return true; 1867 } 1868 1869 private: 1870 BreakpointNameOptionGroup m_name_options; 1871 OptionGroupOptions m_option_group; 1872 }; 1873 1874 class CommandObjectBreakpointNameList : public CommandObjectParsed { 1875 public: 1876 CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 1877 : CommandObjectParsed(interpreter, "list", 1878 "List either the names for a breakpoint or info " 1879 "about a given name. With no arguments, lists all " 1880 "names", 1881 "breakpoint name list <command-options>"), 1882 m_name_options(), m_option_group() { 1883 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 1884 m_option_group.Finalize(); 1885 } 1886 1887 ~CommandObjectBreakpointNameList() override = default; 1888 1889 Options *GetOptions() override { return &m_option_group; } 1890 1891 protected: 1892 bool DoExecute(Args &command, CommandReturnObject &result) override { 1893 Target &target = 1894 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1895 1896 std::vector<std::string> name_list; 1897 if (command.empty()) { 1898 target.GetBreakpointNames(name_list); 1899 } else { 1900 for (const Args::ArgEntry &arg : command) { 1901 name_list.push_back(arg.c_str()); 1902 } 1903 } 1904 1905 if (name_list.empty()) { 1906 result.AppendMessage("No breakpoint names found."); 1907 } else { 1908 for (const std::string &name_str : name_list) { 1909 const char *name = name_str.c_str(); 1910 // First print out the options for the name: 1911 Status error; 1912 BreakpointName *bp_name = 1913 target.FindBreakpointName(ConstString(name), false, error); 1914 if (bp_name) { 1915 StreamString s; 1916 result.AppendMessageWithFormat("Name: %s\n", name); 1917 if (bp_name->GetDescription(&s, eDescriptionLevelFull)) { 1918 result.AppendMessage(s.GetString()); 1919 } 1920 1921 std::unique_lock<std::recursive_mutex> lock; 1922 target.GetBreakpointList().GetListMutex(lock); 1923 1924 BreakpointList &breakpoints = target.GetBreakpointList(); 1925 bool any_set = false; 1926 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 1927 if (bp_sp->MatchesName(name)) { 1928 StreamString s; 1929 any_set = true; 1930 bp_sp->GetDescription(&s, eDescriptionLevelBrief); 1931 s.EOL(); 1932 result.AppendMessage(s.GetString()); 1933 } 1934 } 1935 if (!any_set) 1936 result.AppendMessage("No breakpoints using this name."); 1937 } else { 1938 result.AppendMessageWithFormat("Name: %s not found.\n", name); 1939 } 1940 } 1941 } 1942 return true; 1943 } 1944 1945 private: 1946 BreakpointNameOptionGroup m_name_options; 1947 OptionGroupOptions m_option_group; 1948 }; 1949 1950 // CommandObjectBreakpointName 1951 class CommandObjectBreakpointName : public CommandObjectMultiword { 1952 public: 1953 CommandObjectBreakpointName(CommandInterpreter &interpreter) 1954 : CommandObjectMultiword( 1955 interpreter, "name", "Commands to manage name tags for breakpoints", 1956 "breakpoint name <subcommand> [<command-options>]") { 1957 CommandObjectSP add_command_object( 1958 new CommandObjectBreakpointNameAdd(interpreter)); 1959 CommandObjectSP delete_command_object( 1960 new CommandObjectBreakpointNameDelete(interpreter)); 1961 CommandObjectSP list_command_object( 1962 new CommandObjectBreakpointNameList(interpreter)); 1963 CommandObjectSP configure_command_object( 1964 new CommandObjectBreakpointNameConfigure(interpreter)); 1965 1966 LoadSubCommand("add", add_command_object); 1967 LoadSubCommand("delete", delete_command_object); 1968 LoadSubCommand("list", list_command_object); 1969 LoadSubCommand("configure", configure_command_object); 1970 } 1971 1972 ~CommandObjectBreakpointName() override = default; 1973 }; 1974 1975 // CommandObjectBreakpointRead 1976 #pragma mark Read::CommandOptions 1977 #define LLDB_OPTIONS_breakpoint_read 1978 #include "CommandOptions.inc" 1979 1980 #pragma mark Read 1981 1982 class CommandObjectBreakpointRead : public CommandObjectParsed { 1983 public: 1984 CommandObjectBreakpointRead(CommandInterpreter &interpreter) 1985 : CommandObjectParsed(interpreter, "breakpoint read", 1986 "Read and set the breakpoints previously saved to " 1987 "a file with \"breakpoint write\". ", 1988 nullptr), 1989 m_options() { 1990 CommandArgumentEntry arg; 1991 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1992 eArgTypeBreakpointIDRange); 1993 // Add the entry for the first argument for this command to the object's 1994 // arguments vector. 1995 m_arguments.push_back(arg); 1996 } 1997 1998 ~CommandObjectBreakpointRead() override = default; 1999 2000 Options *GetOptions() override { return &m_options; } 2001 2002 class CommandOptions : public Options { 2003 public: 2004 CommandOptions() : Options() {} 2005 2006 ~CommandOptions() override = default; 2007 2008 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2009 ExecutionContext *execution_context) override { 2010 Status error; 2011 const int short_option = m_getopt_table[option_idx].val; 2012 2013 switch (short_option) { 2014 case 'f': 2015 m_filename.assign(std::string(option_arg)); 2016 break; 2017 case 'N': { 2018 Status name_error; 2019 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 2020 name_error)) { 2021 error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 2022 name_error.AsCString()); 2023 } 2024 m_names.push_back(std::string(option_arg)); 2025 break; 2026 } 2027 default: 2028 llvm_unreachable("Unimplemented option"); 2029 } 2030 2031 return error; 2032 } 2033 2034 void OptionParsingStarting(ExecutionContext *execution_context) override { 2035 m_filename.clear(); 2036 m_names.clear(); 2037 } 2038 2039 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2040 return llvm::makeArrayRef(g_breakpoint_read_options); 2041 } 2042 2043 // Instance variables to hold the values for command options. 2044 2045 std::string m_filename; 2046 std::vector<std::string> m_names; 2047 }; 2048 2049 protected: 2050 bool DoExecute(Args &command, CommandReturnObject &result) override { 2051 Target &target = GetSelectedOrDummyTarget(); 2052 2053 std::unique_lock<std::recursive_mutex> lock; 2054 target.GetBreakpointList().GetListMutex(lock); 2055 2056 FileSpec input_spec(m_options.m_filename); 2057 FileSystem::Instance().Resolve(input_spec); 2058 BreakpointIDList new_bps; 2059 Status error = target.CreateBreakpointsFromFile(input_spec, 2060 m_options.m_names, new_bps); 2061 2062 if (!error.Success()) { 2063 result.AppendError(error.AsCString()); 2064 result.SetStatus(eReturnStatusFailed); 2065 return false; 2066 } 2067 2068 Stream &output_stream = result.GetOutputStream(); 2069 2070 size_t num_breakpoints = new_bps.GetSize(); 2071 if (num_breakpoints == 0) { 2072 result.AppendMessage("No breakpoints added."); 2073 } else { 2074 // No breakpoint selected; show info about all currently set breakpoints. 2075 result.AppendMessage("New breakpoints:"); 2076 for (size_t i = 0; i < num_breakpoints; ++i) { 2077 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 2078 Breakpoint *bp = target.GetBreakpointList() 2079 .FindBreakpointByID(bp_id.GetBreakpointID()) 2080 .get(); 2081 if (bp) 2082 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 2083 false); 2084 } 2085 } 2086 return result.Succeeded(); 2087 } 2088 2089 private: 2090 CommandOptions m_options; 2091 }; 2092 2093 // CommandObjectBreakpointWrite 2094 #pragma mark Write::CommandOptions 2095 #define LLDB_OPTIONS_breakpoint_write 2096 #include "CommandOptions.inc" 2097 2098 #pragma mark Write 2099 class CommandObjectBreakpointWrite : public CommandObjectParsed { 2100 public: 2101 CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2102 : CommandObjectParsed(interpreter, "breakpoint write", 2103 "Write the breakpoints listed to a file that can " 2104 "be read in with \"breakpoint read\". " 2105 "If given no arguments, writes all breakpoints.", 2106 nullptr), 2107 m_options() { 2108 CommandArgumentEntry arg; 2109 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2110 eArgTypeBreakpointIDRange); 2111 // Add the entry for the first argument for this command to the object's 2112 // arguments vector. 2113 m_arguments.push_back(arg); 2114 } 2115 2116 ~CommandObjectBreakpointWrite() override = default; 2117 2118 Options *GetOptions() override { return &m_options; } 2119 2120 class CommandOptions : public Options { 2121 public: 2122 CommandOptions() : Options() {} 2123 2124 ~CommandOptions() override = default; 2125 2126 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2127 ExecutionContext *execution_context) override { 2128 Status error; 2129 const int short_option = m_getopt_table[option_idx].val; 2130 2131 switch (short_option) { 2132 case 'f': 2133 m_filename.assign(std::string(option_arg)); 2134 break; 2135 case 'a': 2136 m_append = true; 2137 break; 2138 default: 2139 llvm_unreachable("Unimplemented option"); 2140 } 2141 2142 return error; 2143 } 2144 2145 void OptionParsingStarting(ExecutionContext *execution_context) override { 2146 m_filename.clear(); 2147 m_append = false; 2148 } 2149 2150 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2151 return llvm::makeArrayRef(g_breakpoint_write_options); 2152 } 2153 2154 // Instance variables to hold the values for command options. 2155 2156 std::string m_filename; 2157 bool m_append = false; 2158 }; 2159 2160 protected: 2161 bool DoExecute(Args &command, CommandReturnObject &result) override { 2162 Target &target = GetSelectedOrDummyTarget(); 2163 2164 std::unique_lock<std::recursive_mutex> lock; 2165 target.GetBreakpointList().GetListMutex(lock); 2166 2167 BreakpointIDList valid_bp_ids; 2168 if (!command.empty()) { 2169 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2170 command, &target, result, &valid_bp_ids, 2171 BreakpointName::Permissions::PermissionKinds::listPerm); 2172 2173 if (!result.Succeeded()) { 2174 result.SetStatus(eReturnStatusFailed); 2175 return false; 2176 } 2177 } 2178 FileSpec file_spec(m_options.m_filename); 2179 FileSystem::Instance().Resolve(file_spec); 2180 Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids, 2181 m_options.m_append); 2182 if (!error.Success()) { 2183 result.AppendErrorWithFormat("error serializing breakpoints: %s.", 2184 error.AsCString()); 2185 result.SetStatus(eReturnStatusFailed); 2186 } 2187 return result.Succeeded(); 2188 } 2189 2190 private: 2191 CommandOptions m_options; 2192 }; 2193 2194 // CommandObjectMultiwordBreakpoint 2195 #pragma mark MultiwordBreakpoint 2196 2197 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2198 CommandInterpreter &interpreter) 2199 : CommandObjectMultiword( 2200 interpreter, "breakpoint", 2201 "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2202 "breakpoint <subcommand> [<command-options>]") { 2203 CommandObjectSP list_command_object( 2204 new CommandObjectBreakpointList(interpreter)); 2205 CommandObjectSP enable_command_object( 2206 new CommandObjectBreakpointEnable(interpreter)); 2207 CommandObjectSP disable_command_object( 2208 new CommandObjectBreakpointDisable(interpreter)); 2209 CommandObjectSP clear_command_object( 2210 new CommandObjectBreakpointClear(interpreter)); 2211 CommandObjectSP delete_command_object( 2212 new CommandObjectBreakpointDelete(interpreter)); 2213 CommandObjectSP set_command_object( 2214 new CommandObjectBreakpointSet(interpreter)); 2215 CommandObjectSP command_command_object( 2216 new CommandObjectBreakpointCommand(interpreter)); 2217 CommandObjectSP modify_command_object( 2218 new CommandObjectBreakpointModify(interpreter)); 2219 CommandObjectSP name_command_object( 2220 new CommandObjectBreakpointName(interpreter)); 2221 CommandObjectSP write_command_object( 2222 new CommandObjectBreakpointWrite(interpreter)); 2223 CommandObjectSP read_command_object( 2224 new CommandObjectBreakpointRead(interpreter)); 2225 2226 list_command_object->SetCommandName("breakpoint list"); 2227 enable_command_object->SetCommandName("breakpoint enable"); 2228 disable_command_object->SetCommandName("breakpoint disable"); 2229 clear_command_object->SetCommandName("breakpoint clear"); 2230 delete_command_object->SetCommandName("breakpoint delete"); 2231 set_command_object->SetCommandName("breakpoint set"); 2232 command_command_object->SetCommandName("breakpoint command"); 2233 modify_command_object->SetCommandName("breakpoint modify"); 2234 name_command_object->SetCommandName("breakpoint name"); 2235 write_command_object->SetCommandName("breakpoint write"); 2236 read_command_object->SetCommandName("breakpoint read"); 2237 2238 LoadSubCommand("list", list_command_object); 2239 LoadSubCommand("enable", enable_command_object); 2240 LoadSubCommand("disable", disable_command_object); 2241 LoadSubCommand("clear", clear_command_object); 2242 LoadSubCommand("delete", delete_command_object); 2243 LoadSubCommand("set", set_command_object); 2244 LoadSubCommand("command", command_command_object); 2245 LoadSubCommand("modify", modify_command_object); 2246 LoadSubCommand("name", name_command_object); 2247 LoadSubCommand("write", write_command_object); 2248 LoadSubCommand("read", read_command_object); 2249 } 2250 2251 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 2252 2253 void CommandObjectMultiwordBreakpoint::VerifyIDs( 2254 Args &args, Target *target, bool allow_locations, 2255 CommandReturnObject &result, BreakpointIDList *valid_ids, 2256 BreakpointName::Permissions ::PermissionKinds purpose) { 2257 // args can be strings representing 1). integers (for breakpoint ids) 2258 // 2). the full breakpoint & location 2259 // canonical representation 2260 // 3). the word "to" or a hyphen, 2261 // representing a range (in which case there 2262 // had *better* be an entry both before & 2263 // after of one of the first two types. 2264 // 4). A breakpoint name 2265 // If args is empty, we will use the last created breakpoint (if there is 2266 // one.) 2267 2268 Args temp_args; 2269 2270 if (args.empty()) { 2271 if (target->GetLastCreatedBreakpoint()) { 2272 valid_ids->AddBreakpointID(BreakpointID( 2273 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 2274 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2275 } else { 2276 result.AppendError( 2277 "No breakpoint specified and no last created breakpoint."); 2278 result.SetStatus(eReturnStatusFailed); 2279 } 2280 return; 2281 } 2282 2283 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 2284 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 2285 // id range strings over; instead generate a list of strings for all the 2286 // breakpoint ids in the range, and shove all of those breakpoint id strings 2287 // into TEMP_ARGS. 2288 2289 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2290 purpose, result, temp_args); 2291 2292 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2293 // BreakpointIDList: 2294 2295 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 2296 2297 // At this point, all of the breakpoint ids that the user passed in have 2298 // been converted to breakpoint IDs and put into valid_ids. 2299 2300 if (result.Succeeded()) { 2301 // Now that we've converted everything from args into a list of breakpoint 2302 // ids, go through our tentative list of breakpoint id's and verify that 2303 // they correspond to valid/currently set breakpoints. 2304 2305 const size_t count = valid_ids->GetSize(); 2306 for (size_t i = 0; i < count; ++i) { 2307 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2308 Breakpoint *breakpoint = 2309 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2310 if (breakpoint != nullptr) { 2311 const size_t num_locations = breakpoint->GetNumLocations(); 2312 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 2313 StreamString id_str; 2314 BreakpointID::GetCanonicalReference( 2315 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2316 i = valid_ids->GetSize() + 1; 2317 result.AppendErrorWithFormat( 2318 "'%s' is not a currently valid breakpoint/location id.\n", 2319 id_str.GetData()); 2320 result.SetStatus(eReturnStatusFailed); 2321 } 2322 } else { 2323 i = valid_ids->GetSize() + 1; 2324 result.AppendErrorWithFormat( 2325 "'%d' is not a currently valid breakpoint ID.\n", 2326 cur_bp_id.GetBreakpointID()); 2327 result.SetStatus(eReturnStatusFailed); 2328 } 2329 } 2330 } 2331 } 2332