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 #include "CommandObjectBreakpoint.h" 11 #include "CommandObjectBreakpointCommand.h" 12 13 // C Includes 14 // C++ Includes 15 // Other libraries and framework includes 16 // Project includes 17 #include "lldb/Breakpoint/Breakpoint.h" 18 #include "lldb/Breakpoint/BreakpointIDList.h" 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Interpreter/Options.h" 21 #include "lldb/Core/RegularExpression.h" 22 #include "lldb/Core/StreamString.h" 23 #include "lldb/Interpreter/CommandInterpreter.h" 24 #include "lldb/Interpreter/CommandReturnObject.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Interpreter/CommandCompletions.h" 27 #include "lldb/Target/StackFrame.h" 28 #include "lldb/Target/Thread.h" 29 #include "lldb/Target/ThreadSpec.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 static void 35 AddBreakpointDescription (StreamString *s, Breakpoint *bp, lldb::DescriptionLevel level) 36 { 37 s->IndentMore(); 38 bp->GetDescription (s, level, true); 39 s->IndentLess(); 40 s->EOL(); 41 } 42 43 //------------------------------------------------------------------------- 44 // CommandObjectBreakpointSet::CommandOptions 45 //------------------------------------------------------------------------- 46 #pragma mark Set::CommandOptions 47 48 CommandObjectBreakpointSet::CommandOptions::CommandOptions() : 49 Options (), 50 m_filename (), 51 m_line_num (0), 52 m_column (0), 53 m_ignore_inlines (false), 54 m_func_name (), 55 m_func_name_type_mask (0), 56 m_func_regexp (), 57 m_modules (), 58 m_load_addr(), 59 m_thread_id(LLDB_INVALID_THREAD_ID), 60 m_thread_index (-1), 61 m_thread_name(), 62 m_queue_name(), 63 m_ignore_count (-1) 64 { 65 } 66 67 CommandObjectBreakpointSet::CommandOptions::~CommandOptions () 68 { 69 } 70 71 lldb::OptionDefinition 72 CommandObjectBreakpointSet::CommandOptions::g_option_table[] = 73 { 74 { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, "<shlib-name>", 75 "Set the breakpoint only in this shared library (can use this option multiple times for multiple shlibs)."}, 76 77 { LLDB_OPT_SET_ALL, false, "ignore_count", 'k', required_argument, NULL, 0, "<n>", 78 "Set the number of times this breakpoint is sKipped before stopping." }, 79 80 { LLDB_OPT_SET_ALL, false, "thread_index", 'x', required_argument, NULL, NULL, "<thread_index>", 81 "The breakpoint stops only for the thread whose indeX matches this argument."}, 82 83 { LLDB_OPT_SET_ALL, false, "thread_id", 't', required_argument, NULL, NULL, "<thread_id>", 84 "The breakpoint stops only for the thread whose TID matches this argument."}, 85 86 { LLDB_OPT_SET_ALL, false, "thread_name", 'T', required_argument, NULL, NULL, "<thread_name>", 87 "The breakpoint stops only for the thread whose thread name matches this argument."}, 88 89 { LLDB_OPT_SET_ALL, false, "queue_name", 'q', required_argument, NULL, NULL, "<queue_name>", 90 "The breakpoint stops only for threads in the queue whose name is given by this argument."}, 91 92 { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "<filename>", 93 "Set the breakpoint by source location in this particular file."}, 94 95 { LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, "<linenum>", 96 "Set the breakpoint by source location at this particular line."}, 97 98 // Comment out this option for the moment, as we don't actually use it, but will in the future. 99 // This way users won't see it, but the infrastructure is left in place. 100 // { 0, false, "column", 'c', required_argument, NULL, "<column>", 101 // "Set the breakpoint by source location at this particular column."}, 102 103 { LLDB_OPT_SET_2, true, "address", 'a', required_argument, NULL, 0, "<address>", 104 "Set the breakpoint by address, at the specified address."}, 105 106 { LLDB_OPT_SET_3, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, "<name>", 107 "Set the breakpoint by function name." }, 108 109 { LLDB_OPT_SET_3, false, "basename", 'b', no_argument, NULL, 0, NULL, 110 "Used in conjuction with --name <name> to search function basenames." }, 111 112 { LLDB_OPT_SET_3, false, "fullname", 'F', no_argument, NULL, 0, NULL, 113 "Used in conjuction with --name <name> to search fully qualified function names. For C++ this means namespaces and all arguemnts, and for Objective C this means a full function prototype with class and selector." }, 114 115 { LLDB_OPT_SET_3, false, "selector", 'S', no_argument, NULL, 0, NULL, 116 "Used in conjuction with --name <name> to search objective C selector names." }, 117 118 { LLDB_OPT_SET_3, false, "method", 'm', no_argument, NULL, 0, NULL, 119 "Used in conjuction with --name <name> to search objective C selector C++ method names." }, 120 121 { LLDB_OPT_SET_4, true, "func_regex", 'r', required_argument, NULL, 0, "<regular-expression>", 122 "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." }, 123 124 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 125 }; 126 127 const lldb::OptionDefinition* 128 CommandObjectBreakpointSet::CommandOptions::GetDefinitions () 129 { 130 return g_option_table; 131 } 132 133 Error 134 CommandObjectBreakpointSet::CommandOptions::SetOptionValue (int option_idx, const char *option_arg) 135 { 136 Error error; 137 char short_option = (char) m_getopt_table[option_idx].val; 138 139 switch (short_option) 140 { 141 case 'a': 142 m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0); 143 if (m_load_addr == LLDB_INVALID_ADDRESS) 144 m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16); 145 146 if (m_load_addr == LLDB_INVALID_ADDRESS) 147 error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", optarg); 148 break; 149 150 case 'c': 151 m_column = Args::StringToUInt32 (option_arg, 0); 152 break; 153 154 case 'f': 155 m_filename = option_arg; 156 break; 157 158 case 'l': 159 m_line_num = Args::StringToUInt32 (option_arg, 0); 160 break; 161 162 case 'n': 163 m_func_name = option_arg; 164 break; 165 166 case 'b': 167 m_func_name_type_mask |= eFunctionNameTypeBase; 168 break; 169 170 case 'F': 171 m_func_name_type_mask |= eFunctionNameTypeFull; 172 break; 173 174 case 'S': 175 m_func_name_type_mask |= eFunctionNameTypeSelector; 176 break; 177 178 case 'm': 179 m_func_name_type_mask |= eFunctionNameTypeMethod; 180 break; 181 182 case 'r': 183 m_func_regexp = option_arg; 184 break; 185 186 case 's': 187 { 188 m_modules.push_back (std::string (option_arg)); 189 break; 190 } 191 case 'k': 192 { 193 m_ignore_count = Args::StringToSInt32(optarg, -1, 0); 194 if (m_ignore_count == -1) 195 error.SetErrorStringWithFormat ("Invalid ignore count '%s'.\n", optarg); 196 } 197 break; 198 case 't' : 199 { 200 m_thread_id = Args::StringToUInt64(optarg, LLDB_INVALID_THREAD_ID, 0); 201 if (m_thread_id == LLDB_INVALID_THREAD_ID) 202 error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", optarg); 203 } 204 break; 205 case 'T': 206 m_thread_name = option_arg; 207 break; 208 case 'q': 209 m_queue_name = option_arg; 210 break; 211 case 'x': 212 { 213 m_thread_index = Args::StringToUInt64(optarg, -1, 0); 214 if (m_thread_id == -1) 215 error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", optarg); 216 217 } 218 break; 219 default: 220 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 221 break; 222 } 223 224 return error; 225 } 226 227 void 228 CommandObjectBreakpointSet::CommandOptions::ResetOptionValues () 229 { 230 Options::ResetOptionValues(); 231 232 m_filename.clear(); 233 m_line_num = 0; 234 m_column = 0; 235 m_func_name.clear(); 236 m_func_name_type_mask = 0; 237 m_func_regexp.clear(); 238 m_load_addr = LLDB_INVALID_ADDRESS; 239 m_modules.clear(); 240 m_ignore_count = -1; 241 m_thread_id = LLDB_INVALID_THREAD_ID; 242 m_thread_index = -1; 243 m_thread_name.clear(); 244 m_queue_name.clear(); 245 } 246 247 //------------------------------------------------------------------------- 248 // CommandObjectBreakpointSet 249 //------------------------------------------------------------------------- 250 #pragma mark Set 251 252 CommandObjectBreakpointSet::CommandObjectBreakpointSet () : 253 CommandObject ("breakpoint set", "Sets a breakpoint or set of breakpoints in the executable.", 254 "breakpoint set <cmd-options>") 255 { 256 } 257 258 CommandObjectBreakpointSet::~CommandObjectBreakpointSet () 259 { 260 } 261 262 Options * 263 CommandObjectBreakpointSet::GetOptions () 264 { 265 return &m_options; 266 } 267 268 bool 269 CommandObjectBreakpointSet::Execute 270 ( 271 CommandInterpreter &interpreter, 272 Args& command, 273 CommandReturnObject &result 274 ) 275 { 276 Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); 277 if (target == NULL) 278 { 279 result.AppendError ("Invalid target, set executable file using 'file' command."); 280 result.SetStatus (eReturnStatusFailed); 281 return false; 282 } 283 284 // The following are the various types of breakpoints that could be set: 285 // 1). -f -l -p [-s -g] (setting breakpoint by source location) 286 // 2). -a [-s -g] (setting breakpoint by address) 287 // 3). -n [-s -g] (setting breakpoint by function name) 288 // 4). -r [-s -g] (setting breakpoint by function name regular expression) 289 290 BreakpointSetType break_type = eSetTypeInvalid; 291 292 if (m_options.m_line_num != 0) 293 break_type = eSetTypeFileAndLine; 294 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 295 break_type = eSetTypeAddress; 296 else if (!m_options.m_func_name.empty()) 297 break_type = eSetTypeFunctionName; 298 else if (!m_options.m_func_regexp.empty()) 299 break_type = eSetTypeFunctionRegexp; 300 301 ModuleSP module_sp = target->GetExecutableModule(); 302 Breakpoint *bp = NULL; 303 FileSpec module; 304 bool use_module = false; 305 int num_modules = m_options.m_modules.size(); 306 307 if ((num_modules > 0) && (break_type != eSetTypeAddress)) 308 use_module = true; 309 310 switch (break_type) 311 { 312 case eSetTypeFileAndLine: // Breakpoint by source position 313 { 314 FileSpec file; 315 if (m_options.m_filename.empty()) 316 { 317 StackFrame *cur_frame = interpreter.GetDebugger().GetExecutionContext().frame; 318 if (cur_frame == NULL) 319 { 320 result.AppendError ("Attempting to set breakpoint by line number alone with no selected frame."); 321 result.SetStatus (eReturnStatusFailed); 322 break; 323 } 324 else if (!cur_frame->HasDebugInformation()) 325 { 326 result.AppendError ("Attempting to set breakpoint by line number alone but selected frame has no debug info."); 327 result.SetStatus (eReturnStatusFailed); 328 break; 329 } 330 else 331 { 332 const SymbolContext &context = cur_frame->GetSymbolContext(true); 333 if (context.line_entry.file) 334 { 335 file = context.line_entry.file; 336 } 337 else if (context.comp_unit != NULL) 338 { file = context.comp_unit; 339 } 340 else 341 { 342 result.AppendError ("Attempting to set breakpoint by line number alone but can't find the file for the selected frame."); 343 result.SetStatus (eReturnStatusFailed); 344 break; 345 } 346 } 347 } 348 else 349 { 350 file.SetFile(m_options.m_filename.c_str()); 351 } 352 353 if (use_module) 354 { 355 for (int i = 0; i < num_modules; ++i) 356 { 357 module.SetFile(m_options.m_modules[i].c_str()); 358 bp = target->CreateBreakpoint (&module, 359 file, 360 m_options.m_line_num, 361 m_options.m_ignore_inlines).get(); 362 if (bp) 363 { 364 StreamString &output_stream = result.GetOutputStream(); 365 output_stream.Printf ("Breakpoint created: "); 366 bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief); 367 output_stream.EOL(); 368 result.SetStatus (eReturnStatusSuccessFinishResult); 369 } 370 else 371 { 372 result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n", 373 m_options.m_modules[i].c_str()); 374 result.SetStatus (eReturnStatusFailed); 375 } 376 } 377 } 378 else 379 bp = target->CreateBreakpoint (NULL, 380 file, 381 m_options.m_line_num, 382 m_options.m_ignore_inlines).get(); 383 } 384 break; 385 case eSetTypeAddress: // Breakpoint by address 386 bp = target->CreateBreakpoint (m_options.m_load_addr, false).get(); 387 break; 388 389 case eSetTypeFunctionName: // Breakpoint by function name 390 { 391 uint32_t name_type_mask = m_options.m_func_name_type_mask; 392 393 if (name_type_mask == 0) 394 { 395 396 if (m_options.m_func_name.find('(') != std::string::npos || 397 m_options.m_func_name.find("-[") == 0 || 398 m_options.m_func_name.find("+[") == 0) 399 name_type_mask |= eFunctionNameTypeFull; 400 else 401 name_type_mask |= eFunctionNameTypeBase; 402 } 403 404 405 if (use_module) 406 { 407 for (int i = 0; i < num_modules; ++i) 408 { 409 module.SetFile(m_options.m_modules[i].c_str()); 410 bp = target->CreateBreakpoint (&module, m_options.m_func_name.c_str(), name_type_mask, Breakpoint::Exact).get(); 411 if (bp) 412 { 413 StreamString &output_stream = result.GetOutputStream(); 414 output_stream.Printf ("Breakpoint created: "); 415 bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief); 416 output_stream.EOL(); 417 result.SetStatus (eReturnStatusSuccessFinishResult); 418 } 419 else 420 { 421 result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n", 422 m_options.m_modules[i].c_str()); 423 result.SetStatus (eReturnStatusFailed); 424 } 425 } 426 } 427 else 428 bp = target->CreateBreakpoint (NULL, m_options.m_func_name.c_str(), name_type_mask, Breakpoint::Exact).get(); 429 } 430 break; 431 432 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name 433 { 434 RegularExpression regexp(m_options.m_func_regexp.c_str()); 435 if (use_module) 436 { 437 for (int i = 0; i < num_modules; ++i) 438 { 439 module.SetFile(m_options.m_modules[i].c_str()); 440 bp = target->CreateBreakpoint (&module, regexp).get(); 441 if (bp) 442 { 443 StreamString &output_stream = result.GetOutputStream(); 444 output_stream.Printf ("Breakpoint created: "); 445 bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief); 446 output_stream.EOL(); 447 result.SetStatus (eReturnStatusSuccessFinishResult); 448 } 449 else 450 { 451 result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n", 452 m_options.m_modules[i].c_str()); 453 result.SetStatus (eReturnStatusFailed); 454 } 455 } 456 } 457 else 458 bp = target->CreateBreakpoint (NULL, regexp).get(); 459 } 460 break; 461 462 default: 463 break; 464 } 465 466 // Now set the various options that were passed in: 467 if (bp) 468 { 469 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 470 bp->SetThreadID (m_options.m_thread_id); 471 472 if (m_options.m_thread_index != -1) 473 bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); 474 475 if (!m_options.m_thread_name.empty()) 476 bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str()); 477 478 if (!m_options.m_queue_name.empty()) 479 bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str()); 480 481 if (m_options.m_ignore_count != -1) 482 bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); 483 } 484 485 if (bp && !use_module) 486 { 487 StreamString &output_stream = result.GetOutputStream(); 488 output_stream.Printf ("Breakpoint created: "); 489 bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief); 490 output_stream.EOL(); 491 result.SetStatus (eReturnStatusSuccessFinishResult); 492 } 493 else if (!bp) 494 { 495 result.AppendError ("Breakpoint creation failed: No breakpoint created."); 496 result.SetStatus (eReturnStatusFailed); 497 } 498 499 return result.Succeeded(); 500 } 501 502 //------------------------------------------------------------------------- 503 // CommandObjectMultiwordBreakpoint 504 //------------------------------------------------------------------------- 505 #pragma mark MultiwordBreakpoint 506 507 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInterpreter &interpreter) : 508 CommandObjectMultiword ("breakpoint", 509 "A set of commands for operating on breakpoints.", 510 "breakpoint <command> [<command-options>]") 511 { 512 bool status; 513 514 CommandObjectSP list_command_object (new CommandObjectBreakpointList ()); 515 CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete ()); 516 CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable ()); 517 CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable ()); 518 CommandObjectSP set_command_object (new CommandObjectBreakpointSet ()); 519 CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter)); 520 CommandObjectSP modify_command_object (new CommandObjectBreakpointModify()); 521 522 command_command_object->SetCommandName ("breakpoint command"); 523 enable_command_object->SetCommandName("breakpoint enable"); 524 disable_command_object->SetCommandName("breakpoint disable"); 525 list_command_object->SetCommandName ("breakpoint list"); 526 modify_command_object->SetCommandName ("breakpoint modify"); 527 set_command_object->SetCommandName("breakpoint set"); 528 529 status = LoadSubCommand (interpreter, "list", list_command_object); 530 status = LoadSubCommand (interpreter, "enable", enable_command_object); 531 status = LoadSubCommand (interpreter, "disable", disable_command_object); 532 status = LoadSubCommand (interpreter, "delete", delete_command_object); 533 status = LoadSubCommand (interpreter, "set", set_command_object); 534 status = LoadSubCommand (interpreter, "command", command_command_object); 535 status = LoadSubCommand (interpreter, "modify", modify_command_object); 536 } 537 538 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint () 539 { 540 } 541 542 void 543 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, 544 BreakpointIDList *valid_ids) 545 { 546 // args can be strings representing 1). integers (for breakpoint ids) 547 // 2). the full breakpoint & location canonical representation 548 // 3). the word "to" or a hyphen, representing a range (in which case there 549 // had *better* be an entry both before & after of one of the first two types. 550 551 Args temp_args; 552 553 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to 554 // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead generate a list of strings for 555 // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS. 556 557 BreakpointIDList::FindAndReplaceIDRanges (args, target, result, temp_args); 558 559 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList: 560 561 valid_ids->InsertStringArray ((const char **) temp_args.GetArgumentVector(), temp_args.GetArgumentCount(), result); 562 563 // At this point, all of the breakpoint ids that the user passed in have been converted to breakpoint IDs 564 // and put into valid_ids. 565 566 if (result.Succeeded()) 567 { 568 // Now that we've converted everything from args into a list of breakpoint ids, go through our tentative list 569 // of breakpoint id's and verify that they correspond to valid/currently set breakpoints. 570 571 for (int i = 0; i < valid_ids->Size(); ++i) 572 { 573 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex (i); 574 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 575 if (breakpoint != NULL) 576 { 577 int num_locations = breakpoint->GetNumLocations(); 578 if (cur_bp_id.GetLocationID() > num_locations) 579 { 580 StreamString id_str; 581 BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(), 582 cur_bp_id.GetLocationID()); 583 i = valid_ids->Size() + 1; 584 result.AppendErrorWithFormat ("'%s' is not a currently valid breakpoint/location id.\n", 585 id_str.GetData()); 586 result.SetStatus (eReturnStatusFailed); 587 } 588 } 589 else 590 { 591 i = valid_ids->Size() + 1; 592 result.AppendErrorWithFormat ("'%d' is not a currently valid breakpoint id.\n", cur_bp_id.GetBreakpointID()); 593 result.SetStatus (eReturnStatusFailed); 594 } 595 } 596 } 597 } 598 599 //------------------------------------------------------------------------- 600 // CommandObjectBreakpointList::Options 601 //------------------------------------------------------------------------- 602 #pragma mark List::CommandOptions 603 604 CommandObjectBreakpointList::CommandOptions::CommandOptions() : 605 Options (), 606 m_level (lldb::eDescriptionLevelFull) // Breakpoint List defaults to brief descriptions 607 { 608 } 609 610 CommandObjectBreakpointList::CommandOptions::~CommandOptions () 611 { 612 } 613 614 lldb::OptionDefinition 615 CommandObjectBreakpointList::CommandOptions::g_option_table[] = 616 { 617 { LLDB_OPT_SET_ALL, false, "internal", 'i', no_argument, NULL, 0, NULL, 618 "Show debugger internal breakpoints" }, 619 620 { LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, NULL, 621 "Give a brief description of the breakpoint (no location info)."}, 622 623 // FIXME: We need to add an "internal" command, and then add this sort of thing to it. 624 // But I need to see it for now, and don't want to wait. 625 { LLDB_OPT_SET_2, false, "full", 'f', no_argument, NULL, 0, NULL, 626 "Give a full description of the breakpoint and its locations."}, 627 628 { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, NULL, 629 "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, 630 631 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 632 }; 633 634 const lldb::OptionDefinition* 635 CommandObjectBreakpointList::CommandOptions::GetDefinitions () 636 { 637 return g_option_table; 638 } 639 640 Error 641 CommandObjectBreakpointList::CommandOptions::SetOptionValue (int option_idx, const char *option_arg) 642 { 643 Error error; 644 char short_option = (char) m_getopt_table[option_idx].val; 645 646 switch (short_option) 647 { 648 case 'b': 649 m_level = lldb::eDescriptionLevelBrief; 650 break; 651 case 'f': 652 m_level = lldb::eDescriptionLevelFull; 653 break; 654 case 'v': 655 m_level = lldb::eDescriptionLevelVerbose; 656 break; 657 case 'i': 658 m_internal = true; 659 break; 660 default: 661 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 662 break; 663 } 664 665 return error; 666 } 667 668 void 669 CommandObjectBreakpointList::CommandOptions::ResetOptionValues () 670 { 671 Options::ResetOptionValues(); 672 673 m_level = lldb::eDescriptionLevelFull; 674 m_internal = false; 675 } 676 677 //------------------------------------------------------------------------- 678 // CommandObjectBreakpointList 679 //------------------------------------------------------------------------- 680 #pragma mark List 681 682 CommandObjectBreakpointList::CommandObjectBreakpointList () : 683 CommandObject ("breakpoint list", 684 "List some or all breakpoints at configurable levels of detail.", 685 "breakpoint list [<breakpoint-id>]") 686 { 687 } 688 689 CommandObjectBreakpointList::~CommandObjectBreakpointList () 690 { 691 } 692 693 Options * 694 CommandObjectBreakpointList::GetOptions () 695 { 696 return &m_options; 697 } 698 699 bool 700 CommandObjectBreakpointList::Execute 701 ( 702 CommandInterpreter &interpreter, 703 Args& args, 704 CommandReturnObject &result 705 ) 706 { 707 Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); 708 if (target == NULL) 709 { 710 result.AppendError ("Invalid target, set executable file using 'file' command."); 711 result.SetStatus (eReturnStatusSuccessFinishNoResult); 712 return true; 713 } 714 715 const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal); 716 Mutex::Locker locker; 717 target->GetBreakpointList(m_options.m_internal).GetListMutex(locker); 718 719 size_t num_breakpoints = breakpoints.GetSize(); 720 721 if (num_breakpoints == 0) 722 { 723 result.AppendMessage ("No breakpoints currently set."); 724 result.SetStatus (eReturnStatusSuccessFinishNoResult); 725 return true; 726 } 727 728 StreamString &output_stream = result.GetOutputStream(); 729 730 if (args.GetArgumentCount() == 0) 731 { 732 // No breakpoint selected; show info about all currently set breakpoints. 733 result.AppendMessage ("Current breakpoints:"); 734 for (int i = 0; i < num_breakpoints; ++i) 735 { 736 Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (i).get(); 737 AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level); 738 } 739 result.SetStatus (eReturnStatusSuccessFinishNoResult); 740 } 741 else 742 { 743 // Particular breakpoints selected; show info about that breakpoint. 744 BreakpointIDList valid_bp_ids; 745 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids); 746 747 if (result.Succeeded()) 748 { 749 for (int i = 0; i < valid_bp_ids.Size(); ++i) 750 { 751 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 752 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 753 AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level); 754 } 755 result.SetStatus (eReturnStatusSuccessFinishNoResult); 756 } 757 else 758 { 759 result.AppendError ("Invalid breakpoint id."); 760 result.SetStatus (eReturnStatusFailed); 761 } 762 } 763 764 return result.Succeeded(); 765 } 766 767 //------------------------------------------------------------------------- 768 // CommandObjectBreakpointEnable 769 //------------------------------------------------------------------------- 770 #pragma mark Enable 771 772 CommandObjectBreakpointEnable::CommandObjectBreakpointEnable () : 773 CommandObject ("enable", 774 "Enables the specified disabled breakpoint(s). If no breakpoints are specified, enables all of them.", 775 "breakpoint enable [<breakpoint-id> | <breakpoint-id-list>]") 776 { 777 // This command object can either be called via 'enable' or 'breakpoint enable'. Because it has two different 778 // potential invocation methods, we need to be a little tricky about generating the syntax string. 779 //StreamString tmp_string; 780 //tmp_string.Printf ("%s <breakpoint-id>", GetCommandName()); 781 //m_cmd_syntax.assign (tmp_string.GetData(), tmp_string.GetSize()); 782 } 783 784 785 CommandObjectBreakpointEnable::~CommandObjectBreakpointEnable () 786 { 787 } 788 789 790 bool 791 CommandObjectBreakpointEnable::Execute 792 ( 793 CommandInterpreter &interpreter, 794 Args& args, 795 CommandReturnObject &result 796 ) 797 { 798 Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); 799 if (target == NULL) 800 { 801 result.AppendError ("Invalid target, set executable file using 'file' command."); 802 result.SetStatus (eReturnStatusFailed); 803 return false; 804 } 805 806 Mutex::Locker locker; 807 target->GetBreakpointList().GetListMutex(locker); 808 809 const BreakpointList &breakpoints = target->GetBreakpointList(); 810 811 size_t num_breakpoints = breakpoints.GetSize(); 812 813 if (num_breakpoints == 0) 814 { 815 result.AppendError ("No breakpoints exist to be enabled."); 816 result.SetStatus (eReturnStatusFailed); 817 return false; 818 } 819 820 if (args.GetArgumentCount() == 0) 821 { 822 // No breakpoint selected; enable all currently set breakpoints. 823 target->EnableAllBreakpoints (); 824 result.AppendMessageWithFormat ("All breakpoints enabled. (%d breakpoints)\n", num_breakpoints); 825 result.SetStatus (eReturnStatusSuccessFinishNoResult); 826 } 827 else 828 { 829 // Particular breakpoint selected; enable that breakpoint. 830 BreakpointIDList valid_bp_ids; 831 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids); 832 833 if (result.Succeeded()) 834 { 835 int enable_count = 0; 836 int loc_count = 0; 837 for (int i = 0; i < valid_bp_ids.Size(); ++i) 838 { 839 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 840 841 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 842 { 843 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 844 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 845 { 846 BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get(); 847 if (location) 848 { 849 location->SetEnabled (true); 850 ++loc_count; 851 } 852 } 853 else 854 { 855 breakpoint->SetEnabled (true); 856 ++enable_count; 857 } 858 } 859 } 860 result.AppendMessageWithFormat ("%d breakpoints enabled.\n", enable_count + loc_count); 861 result.SetStatus (eReturnStatusSuccessFinishNoResult); 862 } 863 } 864 865 return result.Succeeded(); 866 } 867 868 //------------------------------------------------------------------------- 869 // CommandObjectBreakpointDisable 870 //------------------------------------------------------------------------- 871 #pragma mark Disable 872 873 CommandObjectBreakpointDisable::CommandObjectBreakpointDisable () : 874 CommandObject ("disable", 875 "Disables the specified breakpoint(s) without removing it/them. If no breakpoints are specified, disables them all.", 876 "disable [<breakpoint-id> | <breakpoint-id-list>]") 877 { 878 // This command object can either be called via 'enable' or 'breakpoint enable'. Because it has two different 879 // potential invocation methods, we need to be a little tricky about generating the syntax string. 880 //StreamString tmp_string; 881 //tmp_string.Printf ("%s <breakpoint-id>", GetCommandName()); 882 //m_cmd_syntax.assign(tmp_string.GetData(), tmp_string.GetSize()); 883 } 884 885 CommandObjectBreakpointDisable::~CommandObjectBreakpointDisable () 886 { 887 } 888 889 bool 890 CommandObjectBreakpointDisable::Execute 891 ( 892 CommandInterpreter &interpreter, 893 Args& args, 894 CommandReturnObject &result 895 ) 896 { 897 Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); 898 if (target == NULL) 899 { 900 result.AppendError ("Invalid target, set executable file using 'file' command."); 901 result.SetStatus (eReturnStatusFailed); 902 return false; 903 } 904 905 Mutex::Locker locker; 906 target->GetBreakpointList().GetListMutex(locker); 907 908 const BreakpointList &breakpoints = target->GetBreakpointList(); 909 size_t num_breakpoints = breakpoints.GetSize(); 910 911 if (num_breakpoints == 0) 912 { 913 result.AppendError ("No breakpoints exist to be disabled."); 914 result.SetStatus (eReturnStatusFailed); 915 return false; 916 } 917 918 if (args.GetArgumentCount() == 0) 919 { 920 // No breakpoint selected; disable all currently set breakpoints. 921 target->DisableAllBreakpoints (); 922 result.AppendMessageWithFormat ("All breakpoints disabled. (%d breakpoints)\n", num_breakpoints); 923 result.SetStatus (eReturnStatusSuccessFinishNoResult); 924 } 925 else 926 { 927 // Particular breakpoint selected; disable that breakpoint. 928 BreakpointIDList valid_bp_ids; 929 930 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids); 931 932 if (result.Succeeded()) 933 { 934 int disable_count = 0; 935 int loc_count = 0; 936 for (int i = 0; i < valid_bp_ids.Size(); ++i) 937 { 938 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 939 940 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 941 { 942 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 943 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 944 { 945 BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get(); 946 if (location) 947 { 948 location->SetEnabled (false); 949 ++loc_count; 950 } 951 } 952 else 953 { 954 breakpoint->SetEnabled (false); 955 ++disable_count; 956 } 957 } 958 } 959 result.AppendMessageWithFormat ("%d breakpoints disabled.\n", disable_count + loc_count); 960 result.SetStatus (eReturnStatusSuccessFinishNoResult); 961 } 962 } 963 964 return result.Succeeded(); 965 } 966 967 //------------------------------------------------------------------------- 968 // CommandObjectBreakpointDelete 969 //------------------------------------------------------------------------- 970 #pragma mark Delete 971 972 CommandObjectBreakpointDelete::CommandObjectBreakpointDelete() : 973 CommandObject ("breakpoint delete", 974 "Delete the specified breakpoint(s). If no breakpoints are specified, deletes them all.", 975 "breakpoint delete [<breakpoint-id> | <breakpoint-id-list>]") 976 { 977 } 978 979 980 CommandObjectBreakpointDelete::~CommandObjectBreakpointDelete () 981 { 982 } 983 984 bool 985 CommandObjectBreakpointDelete::Execute 986 ( 987 CommandInterpreter &interpreter, 988 Args& args, 989 CommandReturnObject &result 990 ) 991 { 992 Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); 993 if (target == NULL) 994 { 995 result.AppendError ("Invalid target, set executable file using 'file' command."); 996 result.SetStatus (eReturnStatusFailed); 997 return false; 998 } 999 1000 Mutex::Locker locker; 1001 target->GetBreakpointList().GetListMutex(locker); 1002 1003 const BreakpointList &breakpoints = target->GetBreakpointList(); 1004 1005 size_t num_breakpoints = breakpoints.GetSize(); 1006 1007 if (num_breakpoints == 0) 1008 { 1009 result.AppendError ("No breakpoints exist to be deleted."); 1010 result.SetStatus (eReturnStatusFailed); 1011 return false; 1012 } 1013 1014 if (args.GetArgumentCount() == 0) 1015 { 1016 // No breakpoint selected; disable all currently set breakpoints. 1017 if (args.GetArgumentCount() != 0) 1018 { 1019 result.AppendErrorWithFormat ("Specify breakpoints to delete with the -i option.\n"); 1020 result.SetStatus (eReturnStatusFailed); 1021 return false; 1022 } 1023 1024 target->RemoveAllBreakpoints (); 1025 result.AppendMessageWithFormat ("All breakpoints removed. (%d breakpoints)\n", num_breakpoints); 1026 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1027 } 1028 else 1029 { 1030 // Particular breakpoint selected; disable that breakpoint. 1031 BreakpointIDList valid_bp_ids; 1032 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids); 1033 1034 if (result.Succeeded()) 1035 { 1036 int delete_count = 0; 1037 int disable_count = 0; 1038 for (int i = 0; i < valid_bp_ids.Size(); ++i) 1039 { 1040 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 1041 1042 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 1043 { 1044 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 1045 { 1046 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 1047 BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get(); 1048 // It makes no sense to try to delete individual locations, so we disable them instead. 1049 if (location) 1050 { 1051 location->SetEnabled (false); 1052 ++disable_count; 1053 } 1054 } 1055 else 1056 { 1057 target->RemoveBreakpointByID (cur_bp_id.GetBreakpointID()); 1058 ++delete_count; 1059 } 1060 } 1061 } 1062 result.AppendMessageWithFormat ("%d breakpoints deleted; %d breakpoint locations disabled.\n", 1063 delete_count, disable_count); 1064 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1065 } 1066 } 1067 return result.Succeeded(); 1068 } 1069 1070 //------------------------------------------------------------------------- 1071 // CommandObjectBreakpointModify::CommandOptions 1072 //------------------------------------------------------------------------- 1073 #pragma mark Modify::CommandOptions 1074 1075 CommandObjectBreakpointModify::CommandOptions::CommandOptions() : 1076 Options (), 1077 m_thread_id(LLDB_INVALID_THREAD_ID), 1078 m_thread_index (-1), 1079 m_thread_name(), 1080 m_queue_name(), 1081 m_ignore_count (-1), 1082 m_enable_passed (false) 1083 { 1084 } 1085 1086 CommandObjectBreakpointModify::CommandOptions::~CommandOptions () 1087 { 1088 } 1089 1090 lldb::OptionDefinition 1091 CommandObjectBreakpointModify::CommandOptions::g_option_table[] = 1092 { 1093 { LLDB_OPT_SET_ALL, false, "ignore_count", 'k', required_argument, NULL, 0, NULL, 1094 "Set the number of times this breakpoint is sKipped before stopping." }, 1095 1096 { LLDB_OPT_SET_ALL, false, "thread_index", 'x', required_argument, NULL, NULL, "<thread_index>", 1097 "The breakpoint stops only for the thread whose indeX matches this argument."}, 1098 1099 { LLDB_OPT_SET_ALL, false, "thread_id", 't', required_argument, NULL, NULL, "<thread_id>", 1100 "The breakpoint stops only for the thread whose TID matches this argument."}, 1101 1102 { LLDB_OPT_SET_ALL, false, "thread_name", 'T', required_argument, NULL, NULL, "<thread_name>", 1103 "The breakpoint stops only for the thread whose thread name matches this argument."}, 1104 1105 { LLDB_OPT_SET_ALL, false, "queue_name", 'q', required_argument, NULL, NULL, "<queue_name>", 1106 "The breakpoint stops only for threads in the queue whose name is given by this argument."}, 1107 1108 { LLDB_OPT_SET_1, false, "enable", 'e', no_argument, NULL, NULL, NULL, 1109 "Enable the breakpoint."}, 1110 1111 { LLDB_OPT_SET_2, false, "disable", 'd', no_argument, NULL, NULL, NULL, 1112 "Disable the breakpoint."}, 1113 1114 1115 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 1116 }; 1117 1118 const lldb::OptionDefinition* 1119 CommandObjectBreakpointModify::CommandOptions::GetDefinitions () 1120 { 1121 return g_option_table; 1122 } 1123 1124 Error 1125 CommandObjectBreakpointModify::CommandOptions::SetOptionValue (int option_idx, const char *option_arg) 1126 { 1127 Error error; 1128 char short_option = (char) m_getopt_table[option_idx].val; 1129 1130 switch (short_option) 1131 { 1132 case 'd': 1133 m_enable_passed = true; 1134 m_enable_value = false; 1135 break; 1136 case 'e': 1137 m_enable_passed = true; 1138 m_enable_value = true; 1139 break; 1140 case 'k': 1141 { 1142 m_ignore_count = Args::StringToSInt32(optarg, -1, 0); 1143 if (m_ignore_count == -1) 1144 error.SetErrorStringWithFormat ("Invalid ignore count '%s'.\n", optarg); 1145 } 1146 break; 1147 case 't' : 1148 { 1149 m_thread_id = Args::StringToUInt64(optarg, LLDB_INVALID_THREAD_ID, 0); 1150 if (m_thread_id == LLDB_INVALID_THREAD_ID) 1151 error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", optarg); 1152 } 1153 break; 1154 case 'T': 1155 if (option_arg != NULL) 1156 m_thread_name = option_arg; 1157 else 1158 m_thread_name.clear(); 1159 m_name_passed = true; 1160 break; 1161 case 'q': 1162 if (option_arg != NULL) 1163 m_queue_name = option_arg; 1164 else 1165 m_queue_name.clear(); 1166 m_queue_passed = true; 1167 break; 1168 case 'x': 1169 { 1170 m_thread_index = Args::StringToUInt64(optarg, -1, 0); 1171 if (m_thread_id == -1) 1172 error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", optarg); 1173 1174 } 1175 break; 1176 default: 1177 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 1178 break; 1179 } 1180 1181 return error; 1182 } 1183 1184 void 1185 CommandObjectBreakpointModify::CommandOptions::ResetOptionValues () 1186 { 1187 Options::ResetOptionValues(); 1188 1189 m_ignore_count = -1; 1190 m_thread_id = LLDB_INVALID_THREAD_ID; 1191 m_thread_index = -1; 1192 m_thread_name.clear(); 1193 m_queue_name.clear(); 1194 m_enable_passed = false; 1195 m_queue_passed = false; 1196 m_name_passed = false; 1197 } 1198 1199 //------------------------------------------------------------------------- 1200 // CommandObjectBreakpointModify 1201 //------------------------------------------------------------------------- 1202 #pragma mark Modify 1203 1204 CommandObjectBreakpointModify::CommandObjectBreakpointModify () : 1205 CommandObject ("breakpoint modify", "Modifys the options on a breakpoint or set of breakpoints in the executable.", 1206 "breakpoint modify <cmd-options> break-id [break-id ...]") 1207 { 1208 } 1209 1210 CommandObjectBreakpointModify::~CommandObjectBreakpointModify () 1211 { 1212 } 1213 1214 Options * 1215 CommandObjectBreakpointModify::GetOptions () 1216 { 1217 return &m_options; 1218 } 1219 1220 bool 1221 CommandObjectBreakpointModify::Execute 1222 ( 1223 CommandInterpreter &interpreter, 1224 Args& command, 1225 CommandReturnObject &result 1226 ) 1227 { 1228 if (command.GetArgumentCount() == 0) 1229 { 1230 result.AppendError ("No breakpoints specified."); 1231 result.SetStatus (eReturnStatusFailed); 1232 return false; 1233 } 1234 1235 Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); 1236 if (target == NULL) 1237 { 1238 result.AppendError ("Invalid target, set executable file using 'file' command."); 1239 result.SetStatus (eReturnStatusFailed); 1240 return false; 1241 } 1242 1243 Mutex::Locker locker; 1244 target->GetBreakpointList().GetListMutex(locker); 1245 1246 BreakpointIDList valid_bp_ids; 1247 1248 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 1249 1250 if (result.Succeeded()) 1251 { 1252 for (int i = 0; i < valid_bp_ids.Size(); ++i) 1253 { 1254 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 1255 1256 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 1257 { 1258 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 1259 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 1260 { 1261 BreakpointLocation *location = bp->FindLocationByID (cur_bp_id.GetLocationID()).get(); 1262 if (location) 1263 { 1264 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 1265 location->SetThreadID (m_options.m_thread_id); 1266 1267 if (m_options.m_thread_index != -1) 1268 location->GetLocationOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); 1269 1270 if (m_options.m_name_passed) 1271 location->GetLocationOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str()); 1272 1273 if (m_options.m_queue_passed) 1274 location->GetLocationOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str()); 1275 1276 if (m_options.m_ignore_count != -1) 1277 location->GetLocationOptions()->SetIgnoreCount(m_options.m_ignore_count); 1278 1279 if (m_options.m_enable_passed) 1280 location->SetEnabled (m_options.m_enable_value); 1281 } 1282 } 1283 else 1284 { 1285 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 1286 bp->SetThreadID (m_options.m_thread_id); 1287 1288 if (m_options.m_thread_index != -1) 1289 bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); 1290 1291 if (m_options.m_name_passed) 1292 bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str()); 1293 1294 if (m_options.m_queue_passed) 1295 bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str()); 1296 1297 if (m_options.m_ignore_count != -1) 1298 bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); 1299 1300 if (m_options.m_enable_passed) 1301 bp->SetEnabled (m_options.m_enable_value); 1302 1303 } 1304 } 1305 } 1306 } 1307 1308 return result.Succeeded(); 1309 } 1310 1311 1312