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