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