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