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