1 //===-- CommandObjectBreakpointCommand.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 13 14 #include "CommandObjectBreakpointCommand.h" 15 #include "CommandObjectBreakpoint.h" 16 17 #include "lldb/Interpreter/CommandInterpreter.h" 18 #include "lldb/Interpreter/CommandReturnObject.h" 19 #include "lldb/Target/Target.h" 20 #include "lldb/Target/Thread.h" 21 #include "lldb/Breakpoint/BreakpointIDList.h" 22 #include "lldb/Breakpoint/Breakpoint.h" 23 #include "lldb/Breakpoint/BreakpointLocation.h" 24 #include "lldb/Breakpoint/StoppointCallbackContext.h" 25 #include "lldb/Core/State.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 //------------------------------------------------------------------------- 31 // CommandObjectBreakpointCommandAdd::CommandOptions 32 //------------------------------------------------------------------------- 33 34 CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions (CommandInterpreter &interpreter) : 35 Options (interpreter), 36 m_use_commands (false), 37 m_use_script_language (false), 38 m_script_language (eScriptLanguageNone), 39 m_use_one_liner (false), 40 m_one_liner() 41 { 42 } 43 44 CommandObjectBreakpointCommandAdd::CommandOptions::~CommandOptions () 45 { 46 } 47 48 // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting 49 // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper. 50 51 static OptionEnumValueElement 52 g_script_option_enumeration[4] = 53 { 54 { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"}, 55 { eScriptLanguagePython, "python", "Commands are in the Python language."}, 56 { eSortOrderByName, "default-script", "Commands are in the default scripting language."}, 57 { 0, NULL, NULL } 58 }; 59 60 OptionDefinition 61 CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] = 62 { 63 { LLDB_OPT_SET_ALL, false, "one-liner", 'o', required_argument, NULL, NULL, eArgTypeOneLiner, 64 "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, 65 66 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, NULL, eArgTypeBoolean, 67 "Specify whether breakpoint command execution should terminate on error." }, 68 69 { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, NULL, eArgTypeNone, 70 "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."}, 71 72 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 73 }; 74 75 const OptionDefinition* 76 CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions () 77 { 78 return g_option_table; 79 } 80 81 82 Error 83 CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue 84 ( 85 uint32_t option_idx, 86 const char *option_arg 87 ) 88 { 89 Error error; 90 char short_option = (char) m_getopt_table[option_idx].val; 91 92 switch (short_option) 93 { 94 case 'o': 95 m_use_one_liner = true; 96 m_one_liner = option_arg; 97 break; 98 99 case 's': 100 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg, 101 g_option_table[option_idx].enum_values, 102 eScriptLanguageNone, 103 error); 104 105 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault) 106 { 107 m_use_commands = false; 108 m_use_script_language = true; 109 } 110 else 111 { 112 m_use_commands = true; 113 m_use_script_language = false; 114 } 115 break; 116 117 case 'e': 118 { 119 bool success = false; 120 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success); 121 if (!success) 122 error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg); 123 } 124 break; 125 126 default: 127 break; 128 } 129 return error; 130 } 131 132 void 133 CommandObjectBreakpointCommandAdd::CommandOptions::OptionParsingStarting () 134 { 135 m_use_commands = true; 136 m_use_script_language = false; 137 m_script_language = eScriptLanguageNone; 138 139 m_use_one_liner = false; 140 m_stop_on_error = true; 141 m_one_liner.clear(); 142 } 143 144 //------------------------------------------------------------------------- 145 // CommandObjectBreakpointCommandAdd 146 //------------------------------------------------------------------------- 147 148 149 CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) : 150 CommandObject (interpreter, 151 "add", 152 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.", 153 NULL), 154 m_options (interpreter) 155 { 156 SetHelpLong ( 157 "\nGeneral information about entering breakpoint commands \n\ 158 ------------------------------------------------------ \n\ 159 \n\ 160 This command will cause you to be prompted to enter the command or set \n\ 161 of commands you wish to be executed when the specified breakpoint is \n\ 162 hit. You will be told to enter your command(s), and will see a '> ' \n\ 163 prompt. Because you can enter one or many commands to be executed when \n\ 164 a breakpoint is hit, you will continue to be prompted after each \n\ 165 new-line that you enter, until you enter the word 'DONE', which will \n\ 166 cause the commands you have entered to be stored with the breakpoint \n\ 167 and executed when the breakpoint is hit. \n\ 168 \n\ 169 Syntax checking is not necessarily done when breakpoint commands are \n\ 170 entered. An improperly written breakpoint command will attempt to get \n\ 171 executed when the breakpoint gets hit, and usually silently fail. If \n\ 172 your breakpoint command does not appear to be getting executed, go \n\ 173 back and check your syntax. \n\ 174 \n\ 175 \n\ 176 Special information about PYTHON breakpoint commands \n\ 177 ---------------------------------------------------- \n\ 178 \n\ 179 You may enter either one line of Python or multiple lines of Python \n\ 180 (including defining whole functions, if desired). If you enter a \n\ 181 single line of Python, that will be passed to the Python interpreter \n\ 182 'as is' when the breakpoint gets hit. If you enter function \n\ 183 definitions, they will be passed to the Python interpreter as soon as \n\ 184 you finish entering the breakpoint command, and they can be called \n\ 185 later (don't forget to add calls to them, if you want them called when \n\ 186 the breakpoint is hit). If you enter multiple lines of Python that \n\ 187 are not function definitions, they will be collected into a new, \n\ 188 automatically generated Python function, and a call to the newly \n\ 189 generated function will be attached to the breakpoint. Important \n\ 190 Note: Because loose Python code gets collected into functions, if you \n\ 191 want to access global variables in the 'loose' code, you need to \n\ 192 specify that they are global, using the 'global' keyword. Be sure to \n\ 193 use correct Python syntax, including indentation, when entering Python \n\ 194 breakpoint commands. \n\ 195 \n\ 196 Example Python one-line breakpoint command: \n\ 197 \n\ 198 (lldb) breakpoint command add -s python 1 \n\ 199 Enter your Python command(s). Type 'DONE' to end. \n\ 200 > print \"Hit this breakpoint!\" \n\ 201 > DONE \n\ 202 \n\ 203 As a convenience, this also works for a short Python one-liner: \n\ 204 (lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\ 205 (lldb) run \n\ 206 Launching '.../a.out' (x86_64) \n\ 207 (lldb) Fri Sep 10 12:17:45 2010 \n\ 208 Process 21778 Stopped \n\ 209 * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\ 210 36 \n\ 211 37 int c(int val)\n\ 212 38 {\n\ 213 39 -> return val + 3;\n\ 214 40 }\n\ 215 41 \n\ 216 42 int main (int argc, char const *argv[])\n\ 217 (lldb) \n\ 218 \n\ 219 Example multiple line Python breakpoint command, using function definition: \n\ 220 \n\ 221 (lldb) breakpoint command add -s python 1 \n\ 222 Enter your Python command(s). Type 'DONE' to end. \n\ 223 > def breakpoint_output (bp_no): \n\ 224 > out_string = \"Hit breakpoint number \" + repr (bp_no) \n\ 225 > print out_string \n\ 226 > return True \n\ 227 > breakpoint_output (1) \n\ 228 > DONE \n\ 229 \n\ 230 \n\ 231 Example multiple line Python breakpoint command, using 'loose' Python: \n\ 232 \n\ 233 (lldb) breakpoint command add -s p 1 \n\ 234 Enter your Python command(s). Type 'DONE' to end. \n\ 235 > global bp_count \n\ 236 > bp_count = bp_count + 1 \n\ 237 > print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\ 238 > DONE \n\ 239 \n\ 240 In this case, since there is a reference to a global variable, \n\ 241 'bp_count', you will also need to make sure 'bp_count' exists and is \n\ 242 initialized: \n\ 243 \n\ 244 (lldb) script \n\ 245 >>> bp_count = 0 \n\ 246 >>> quit() \n\ 247 \n\ 248 (lldb) \n\ 249 \n\ 250 \n\ 251 Final Note: If you get a warning that no breakpoint command was generated, \n\ 252 but you did not get any syntax errors, you probably forgot to add a call \n\ 253 to your functions. \n\ 254 \n\ 255 Special information about debugger command breakpoint commands \n\ 256 -------------------------------------------------------------- \n\ 257 \n\ 258 You may enter any debugger command, exactly as you would at the \n\ 259 debugger prompt. You may enter as many debugger commands as you like, \n\ 260 but do NOT enter more than one command per line. \n" ); 261 262 263 CommandArgumentEntry arg; 264 CommandArgumentData bp_id_arg; 265 266 // Define the first (and only) variant of this arg. 267 bp_id_arg.arg_type = eArgTypeBreakpointID; 268 bp_id_arg.arg_repetition = eArgRepeatPlain; 269 270 // There is only one variant this argument could be; put it into the argument entry. 271 arg.push_back (bp_id_arg); 272 273 // Push the data for the first argument into the m_arguments vector. 274 m_arguments.push_back (arg); 275 } 276 277 CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd () 278 { 279 } 280 281 bool 282 CommandObjectBreakpointCommandAdd::Execute 283 ( 284 Args& command, 285 CommandReturnObject &result 286 ) 287 { 288 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 289 290 if (target == NULL) 291 { 292 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands"); 293 result.SetStatus (eReturnStatusFailed); 294 return false; 295 } 296 297 const BreakpointList &breakpoints = target->GetBreakpointList(); 298 size_t num_breakpoints = breakpoints.GetSize(); 299 300 if (num_breakpoints == 0) 301 { 302 result.AppendError ("No breakpoints exist to have commands added"); 303 result.SetStatus (eReturnStatusFailed); 304 return false; 305 } 306 307 BreakpointIDList valid_bp_ids; 308 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 309 310 if (result.Succeeded()) 311 { 312 const size_t count = valid_bp_ids.GetSize(); 313 for (size_t i = 0; i < count; ++i) 314 { 315 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 316 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 317 { 318 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 319 BreakpointOptions *bp_options = NULL; 320 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) 321 { 322 // This breakpoint does not have an associated location. 323 bp_options = bp->GetOptions(); 324 } 325 else 326 { 327 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); 328 // This breakpoint does have an associated location. 329 // Get its breakpoint options. 330 if (bp_loc_sp) 331 bp_options = bp_loc_sp->GetLocationOptions(); 332 } 333 334 // Skip this breakpoint if bp_options is not good. 335 if (bp_options == NULL) continue; 336 337 // If we are using script language, get the script interpreter 338 // in order to set or collect command callback. Otherwise, call 339 // the methods associated with this object. 340 if (m_options.m_use_script_language) 341 { 342 // Special handling for one-liner specified inline. 343 if (m_options.m_use_one_liner) 344 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, 345 m_options.m_one_liner.c_str()); 346 else 347 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options, 348 result); 349 } 350 else 351 { 352 // Special handling for one-liner specified inline. 353 if (m_options.m_use_one_liner) 354 SetBreakpointCommandCallback (bp_options, 355 m_options.m_one_liner.c_str()); 356 else 357 CollectDataForBreakpointCommandCallback (bp_options, 358 result); 359 } 360 } 361 } 362 } 363 364 return result.Succeeded(); 365 } 366 367 Options * 368 CommandObjectBreakpointCommandAdd::GetOptions () 369 { 370 return &m_options; 371 } 372 373 const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end."; 374 375 void 376 CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback 377 ( 378 BreakpointOptions *bp_options, 379 CommandReturnObject &result 380 ) 381 { 382 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 383 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); 384 if (reader_sp && data_ap.get()) 385 { 386 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); 387 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp); 388 389 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback, 390 bp_options, // baton 391 eInputReaderGranularityLine, // token size, to pass to callback function 392 "DONE", // end token 393 "> ", // prompt 394 true)); // echo input 395 if (err.Success()) 396 { 397 m_interpreter.GetDebugger().PushInputReader (reader_sp); 398 result.SetStatus (eReturnStatusSuccessFinishNoResult); 399 } 400 else 401 { 402 result.AppendError (err.AsCString()); 403 result.SetStatus (eReturnStatusFailed); 404 } 405 } 406 else 407 { 408 result.AppendError("out of memory"); 409 result.SetStatus (eReturnStatusFailed); 410 } 411 412 } 413 414 // Set a one-liner as the callback for the breakpoint. 415 void 416 CommandObjectBreakpointCommandAdd::SetBreakpointCommandCallback (BreakpointOptions *bp_options, 417 const char *oneliner) 418 { 419 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); 420 421 // It's necessary to set both user_source and script_source to the oneliner. 422 // The former is used to generate callback description (as in breakpoint command list) 423 // while the latter is used for Python to interpret during the actual callback. 424 data_ap->user_source.AppendString (oneliner); 425 data_ap->script_source.assign (oneliner); 426 data_ap->stop_on_error = m_options.m_stop_on_error; 427 428 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); 429 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp); 430 431 return; 432 } 433 434 size_t 435 CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback 436 ( 437 void *baton, 438 InputReader &reader, 439 lldb::InputReaderAction notification, 440 const char *bytes, 441 size_t bytes_len 442 ) 443 { 444 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); 445 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 446 447 switch (notification) 448 { 449 case eInputReaderActivate: 450 if (!batch_mode) 451 { 452 out_stream->Printf ("%s\n", g_reader_instructions); 453 if (reader.GetPrompt()) 454 out_stream->Printf ("%s", reader.GetPrompt()); 455 out_stream->Flush(); 456 } 457 break; 458 459 case eInputReaderDeactivate: 460 break; 461 462 case eInputReaderReactivate: 463 if (reader.GetPrompt() && !batch_mode) 464 { 465 out_stream->Printf ("%s", reader.GetPrompt()); 466 out_stream->Flush(); 467 } 468 break; 469 470 case eInputReaderAsynchronousOutputWritten: 471 break; 472 473 case eInputReaderGotToken: 474 if (bytes && bytes_len && baton) 475 { 476 BreakpointOptions *bp_options = (BreakpointOptions *) baton; 477 if (bp_options) 478 { 479 Baton *bp_options_baton = bp_options->GetBaton(); 480 if (bp_options_baton) 481 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len); 482 } 483 } 484 if (!reader.IsDone() && reader.GetPrompt() && !batch_mode) 485 { 486 out_stream->Printf ("%s", reader.GetPrompt()); 487 out_stream->Flush(); 488 } 489 break; 490 491 case eInputReaderInterrupt: 492 { 493 // Finish, and cancel the breakpoint command. 494 reader.SetIsDone (true); 495 BreakpointOptions *bp_options = (BreakpointOptions *) baton; 496 if (bp_options) 497 { 498 Baton *bp_options_baton = bp_options->GetBaton (); 499 if (bp_options_baton) 500 { 501 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear(); 502 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear(); 503 } 504 } 505 if (!batch_mode) 506 { 507 out_stream->Printf ("Warning: No command attached to breakpoint.\n"); 508 out_stream->Flush(); 509 } 510 } 511 break; 512 513 case eInputReaderEndOfFile: 514 reader.SetIsDone (true); 515 break; 516 517 case eInputReaderDone: 518 break; 519 } 520 521 return bytes_len; 522 } 523 524 525 //------------------------------------------------------------------------- 526 // CommandObjectBreakpointCommandDelete 527 //------------------------------------------------------------------------- 528 529 CommandObjectBreakpointCommandDelete::CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) : 530 CommandObject (interpreter, 531 "delete", 532 "Delete the set of commands from a breakpoint.", 533 NULL) 534 { 535 CommandArgumentEntry arg; 536 CommandArgumentData bp_id_arg; 537 538 // Define the first (and only) variant of this arg. 539 bp_id_arg.arg_type = eArgTypeBreakpointID; 540 bp_id_arg.arg_repetition = eArgRepeatPlain; 541 542 // There is only one variant this argument could be; put it into the argument entry. 543 arg.push_back (bp_id_arg); 544 545 // Push the data for the first argument into the m_arguments vector. 546 m_arguments.push_back (arg); 547 } 548 549 CommandObjectBreakpointCommandDelete::~CommandObjectBreakpointCommandDelete () 550 { 551 } 552 553 bool 554 CommandObjectBreakpointCommandDelete::Execute 555 ( 556 Args& command, 557 CommandReturnObject &result 558 ) 559 { 560 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 561 562 if (target == NULL) 563 { 564 result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands"); 565 result.SetStatus (eReturnStatusFailed); 566 return false; 567 } 568 569 const BreakpointList &breakpoints = target->GetBreakpointList(); 570 size_t num_breakpoints = breakpoints.GetSize(); 571 572 if (num_breakpoints == 0) 573 { 574 result.AppendError ("No breakpoints exist to have commands deleted"); 575 result.SetStatus (eReturnStatusFailed); 576 return false; 577 } 578 579 if (command.GetArgumentCount() == 0) 580 { 581 result.AppendError ("No breakpoint specified from which to delete the commands"); 582 result.SetStatus (eReturnStatusFailed); 583 return false; 584 } 585 586 BreakpointIDList valid_bp_ids; 587 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 588 589 if (result.Succeeded()) 590 { 591 const size_t count = valid_bp_ids.GetSize(); 592 for (size_t i = 0; i < count; ++i) 593 { 594 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 595 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 596 { 597 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 598 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 599 { 600 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID())); 601 if (bp_loc_sp) 602 bp_loc_sp->ClearCallback(); 603 else 604 { 605 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 606 cur_bp_id.GetBreakpointID(), 607 cur_bp_id.GetLocationID()); 608 result.SetStatus (eReturnStatusFailed); 609 return false; 610 } 611 } 612 else 613 { 614 bp->ClearCallback(); 615 } 616 } 617 } 618 } 619 return result.Succeeded(); 620 } 621 622 623 //------------------------------------------------------------------------- 624 // CommandObjectBreakpointCommandList 625 //------------------------------------------------------------------------- 626 627 CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) : 628 CommandObject (interpreter, 629 "list", 630 "List the script or set of commands to be executed when the breakpoint is hit.", 631 NULL) 632 { 633 CommandArgumentEntry arg; 634 CommandArgumentData bp_id_arg; 635 636 // Define the first (and only) variant of this arg. 637 bp_id_arg.arg_type = eArgTypeBreakpointID; 638 bp_id_arg.arg_repetition = eArgRepeatPlain; 639 640 // There is only one variant this argument could be; put it into the argument entry. 641 arg.push_back (bp_id_arg); 642 643 // Push the data for the first argument into the m_arguments vector. 644 m_arguments.push_back (arg); 645 } 646 647 CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList () 648 { 649 } 650 651 bool 652 CommandObjectBreakpointCommandList::Execute 653 ( 654 Args& command, 655 CommandReturnObject &result 656 ) 657 { 658 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 659 660 if (target == NULL) 661 { 662 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands"); 663 result.SetStatus (eReturnStatusFailed); 664 return false; 665 } 666 667 const BreakpointList &breakpoints = target->GetBreakpointList(); 668 size_t num_breakpoints = breakpoints.GetSize(); 669 670 if (num_breakpoints == 0) 671 { 672 result.AppendError ("No breakpoints exist for which to list commands"); 673 result.SetStatus (eReturnStatusFailed); 674 return false; 675 } 676 677 if (command.GetArgumentCount() == 0) 678 { 679 result.AppendError ("No breakpoint specified for which to list the commands"); 680 result.SetStatus (eReturnStatusFailed); 681 return false; 682 } 683 684 BreakpointIDList valid_bp_ids; 685 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 686 687 if (result.Succeeded()) 688 { 689 const size_t count = valid_bp_ids.GetSize(); 690 for (size_t i = 0; i < count; ++i) 691 { 692 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 693 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 694 { 695 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 696 697 if (bp) 698 { 699 const BreakpointOptions *bp_options = NULL; 700 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 701 { 702 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); 703 if (bp_loc_sp) 704 bp_options = bp_loc_sp->GetOptionsNoCreate(); 705 else 706 { 707 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 708 cur_bp_id.GetBreakpointID(), 709 cur_bp_id.GetLocationID()); 710 result.SetStatus (eReturnStatusFailed); 711 return false; 712 } 713 } 714 else 715 { 716 bp_options = bp->GetOptions(); 717 } 718 719 if (bp_options) 720 { 721 StreamString id_str; 722 BreakpointID::GetCanonicalReference (&id_str, 723 cur_bp_id.GetBreakpointID(), 724 cur_bp_id.GetLocationID()); 725 const Baton *baton = bp_options->GetBaton(); 726 if (baton) 727 { 728 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData()); 729 result.GetOutputStream().IndentMore (); 730 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull); 731 result.GetOutputStream().IndentLess (); 732 } 733 else 734 { 735 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", 736 id_str.GetData()); 737 } 738 } 739 result.SetStatus (eReturnStatusSuccessFinishResult); 740 } 741 else 742 { 743 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID()); 744 result.SetStatus (eReturnStatusFailed); 745 } 746 747 } 748 } 749 } 750 751 return result.Succeeded(); 752 } 753 754 //------------------------------------------------------------------------- 755 // CommandObjectBreakpointCommand 756 //------------------------------------------------------------------------- 757 758 CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) : 759 CommandObjectMultiword (interpreter, 760 "command", 761 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').", 762 "command <sub-command> [<sub-command-options>] <breakpoint-id>") 763 { 764 bool status; 765 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter)); 766 CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter)); 767 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter)); 768 769 add_command_object->SetCommandName ("breakpoint command add"); 770 delete_command_object->SetCommandName ("breakpoint command delete"); 771 list_command_object->SetCommandName ("breakpoint command list"); 772 773 status = LoadSubCommand ("add", add_command_object); 774 status = LoadSubCommand ("delete", delete_command_object); 775 status = LoadSubCommand ("list", list_command_object); 776 } 777 778 779 CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand () 780 { 781 } 782 783 bool 784 CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction 785 ( 786 void *baton, 787 StoppointCallbackContext *context, 788 lldb::user_id_t break_id, 789 lldb::user_id_t break_loc_id 790 ) 791 { 792 bool ret_value = true; 793 if (baton == NULL) 794 return true; 795 796 797 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton; 798 StringList &commands = data->user_source; 799 800 if (commands.GetSize() > 0) 801 { 802 ExecutionContext exe_ctx (context->exe_ctx_ref); 803 Target *target = exe_ctx.GetTargetPtr(); 804 if (target) 805 { 806 CommandReturnObject result; 807 Debugger &debugger = target->GetDebugger(); 808 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously 809 // if the debugger is set up that way. 810 811 StreamSP output_stream (debugger.GetAsyncOutputStream()); 812 StreamSP error_stream (debugger.GetAsyncErrorStream()); 813 result.SetImmediateOutputStream (output_stream); 814 result.SetImmediateErrorStream (error_stream); 815 816 bool stop_on_continue = true; 817 bool echo_commands = false; 818 bool print_results = true; 819 820 debugger.GetCommandInterpreter().HandleCommands (commands, 821 &exe_ctx, 822 stop_on_continue, 823 data->stop_on_error, 824 echo_commands, 825 print_results, 826 result); 827 result.GetImmediateOutputStream()->Flush(); 828 result.GetImmediateErrorStream()->Flush(); 829 } 830 } 831 return ret_value; 832 } 833 834