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