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