1254721Semaste//===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/lldb-python.h" 11254721Semaste 12254721Semaste// C Includes 13254721Semaste// C++ Includes 14254721Semaste 15254721Semaste 16254721Semaste#include "CommandObjectBreakpointCommand.h" 17254721Semaste#include "CommandObjectBreakpoint.h" 18254721Semaste 19254721Semaste#include "lldb/Interpreter/CommandInterpreter.h" 20254721Semaste#include "lldb/Interpreter/CommandReturnObject.h" 21254721Semaste#include "lldb/Target/Target.h" 22254721Semaste#include "lldb/Target/Thread.h" 23254721Semaste#include "lldb/Breakpoint/BreakpointIDList.h" 24254721Semaste#include "lldb/Breakpoint/Breakpoint.h" 25254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h" 26254721Semaste#include "lldb/Breakpoint/StoppointCallbackContext.h" 27254721Semaste#include "lldb/Core/State.h" 28254721Semaste 29254721Semasteusing namespace lldb; 30254721Semasteusing namespace lldb_private; 31254721Semaste 32254721Semaste//------------------------------------------------------------------------- 33254721Semaste// CommandObjectBreakpointCommandAdd 34254721Semaste//------------------------------------------------------------------------- 35254721Semaste 36254721Semaste 37254721Semasteclass CommandObjectBreakpointCommandAdd : public CommandObjectParsed 38254721Semaste{ 39254721Semastepublic: 40254721Semaste 41254721Semaste CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) : 42254721Semaste CommandObjectParsed (interpreter, 43254721Semaste "add", 44254721Semaste "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.", 45254721Semaste NULL), 46254721Semaste m_options (interpreter) 47254721Semaste { 48254721Semaste SetHelpLong ( 49254721Semaste"\nGeneral information about entering breakpoint commands\n\ 50254721Semaste------------------------------------------------------\n\ 51254721Semaste\n\ 52254721SemasteThis command will cause you to be prompted to enter the command or set of\n\ 53254721Semastecommands you wish to be executed when the specified breakpoint is hit. You\n\ 54254721Semastewill be told to enter your command(s), and will see a '> 'prompt. Because\n\ 55254721Semasteyou can enter one or many commands to be executed when a breakpoint is hit,\n\ 56254721Semasteyou will continue to be prompted after each new-line that you enter, until you\n\ 57254721Semasteenter the word 'DONE', which will cause the commands you have entered to be\n\ 58254721Semastestored with the breakpoint and executed when the breakpoint is hit.\n\ 59254721Semaste\n\ 60254721SemasteSyntax checking is not necessarily done when breakpoint commands are entered.\n\ 61254721SemasteAn improperly written breakpoint command will attempt to get executed when the\n\ 62254721Semastebreakpoint gets hit, and usually silently fail. If your breakpoint command does\n\ 63254721Semastenot appear to be getting executed, go back and check your syntax.\n\ 64254721Semaste\n\ 65254721SemasteSpecial information about PYTHON breakpoint commands\n\ 66254721Semaste----------------------------------------------------\n\ 67254721Semaste\n\ 68254721SemasteYou may enter either one line of Python, multiple lines of Python (including\n\ 69254721Semastefunction definitions), or specify a Python function in a module that has already,\n\ 70254721Semasteor will be imported. If you enter a single line of Python, that will be passed\n\ 71254721Semasteto the Python interpreter 'as is' when the breakpoint gets hit. If you enter\n\ 72254721Semastefunction definitions, they will be passed to the Python interpreter as soon as\n\ 73254721Semasteyou finish entering the breakpoint command, and they can be called later (don't\n\ 74254721Semasteforget to add calls to them, if you want them called when the breakpoint is\n\ 75254721Semastehit). If you enter multiple lines of Python that are not function definitions,\n\ 76254721Semastethey will be collected into a new, automatically generated Python function, and\n\ 77254721Semastea call to the newly generated function will be attached to the breakpoint.\n\ 78254721Semaste\n\ 79254721Semaste\n\ 80254721SemasteThis auto-generated function is passed in three arguments:\n\ 81254721Semaste\n\ 82254721Semaste frame: a lldb.SBFrame object for the frame which hit breakpoint.\n\ 83254721Semaste bp_loc: a lldb.SBBreakpointLocation object that represents the breakpoint\n\ 84254721Semaste location that was hit.\n\ 85254721Semaste dict: the python session dictionary hit.\n\ 86254721Semaste\n\ 87254721SemasteWhen specifying a python function with the --python-function option, you need\n\ 88254721Semasteto supply the function name prepended by the module name. So if you import a\n\ 89254721Semastemodule named 'myutils' that contains a 'breakpoint_callback' function, you would\n\ 90254721Semastespecify the option as:\n\ 91254721Semaste\n\ 92254721Semaste --python-function myutils.breakpoint_callback\n\ 93254721Semaste\n\ 94254721SemasteThe function itself must have the following prototype:\n\ 95254721Semaste\n\ 96254721Semastedef breakpoint_callback(frame, bp_loc, dict):\n\ 97254721Semaste # Your code goes here\n\ 98254721Semaste\n\ 99254721SemasteThe arguments are the same as the 3 auto generation function arguments listed\n\ 100254721Semasteabove. Note that the global variable 'lldb.frame' will NOT be setup when this\n\ 101254721Semastefunction is called, so be sure to use the 'frame' argument. The 'frame' argument\n\ 102254721Semastecan get you to the thread (frame.GetThread()), the thread can get you to the\n\ 103254721Semasteprocess (thread.GetProcess()), and the process can get you back to the target\n\ 104254721Semaste(process.GetTarget()).\n\ 105254721Semaste\n\ 106254721SemasteImportant Note: Because loose Python code gets collected into functions, if you\n\ 107254721Semastewant to access global variables in the 'loose' code, you need to specify that\n\ 108254721Semastethey are global, using the 'global' keyword. Be sure to use correct Python\n\ 109254721Semastesyntax, including indentation, when entering Python breakpoint commands.\n\ 110254721Semaste\n\ 111254721SemasteAs a third option, you can pass the name of an already existing Python function\n\ 112254721Semasteand that function will be attached to the breakpoint. It will get passed the\n\ 113254721Semasteframe and bp_loc arguments mentioned above.\n\ 114254721Semaste\n\ 115254721SemasteExample Python one-line breakpoint command:\n\ 116254721Semaste\n\ 117254721Semaste(lldb) breakpoint command add -s python 1\n\ 118254721SemasteEnter your Python command(s). Type 'DONE' to end.\n\ 119254721Semaste> print \"Hit this breakpoint!\"\n\ 120254721Semaste> DONE\n\ 121254721Semaste\n\ 122254721SemasteAs a convenience, this also works for a short Python one-liner:\n\ 123254721Semaste(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\"\n\ 124254721Semaste(lldb) run\n\ 125254721SemasteLaunching '.../a.out' (x86_64)\n\ 126254721Semaste(lldb) Fri Sep 10 12:17:45 2010\n\ 127254721SemasteProcess 21778 Stopped\n\ 128254721Semaste* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread\n\ 129254721Semaste 36 \n\ 130254721Semaste 37 int c(int val)\n\ 131254721Semaste 38 {\n\ 132254721Semaste 39 -> return val + 3;\n\ 133254721Semaste 40 }\n\ 134254721Semaste 41 \n\ 135254721Semaste 42 int main (int argc, char const *argv[])\n\ 136254721Semaste(lldb)\n\ 137254721Semaste\n\ 138254721SemasteExample multiple line Python breakpoint command, using function definition:\n\ 139254721Semaste\n\ 140254721Semaste(lldb) breakpoint command add -s python 1\n\ 141254721SemasteEnter your Python command(s). Type 'DONE' to end.\n\ 142254721Semaste> def breakpoint_output (bp_no):\n\ 143254721Semaste> out_string = \"Hit breakpoint number \" + repr (bp_no)\n\ 144254721Semaste> print out_string\n\ 145254721Semaste> return True\n\ 146254721Semaste> breakpoint_output (1)\n\ 147254721Semaste> DONE\n\ 148254721Semaste\n\ 149254721Semaste\n\ 150254721SemasteExample multiple line Python breakpoint command, using 'loose' Python:\n\ 151254721Semaste\n\ 152254721Semaste(lldb) breakpoint command add -s p 1\n\ 153254721SemasteEnter your Python command(s). Type 'DONE' to end.\n\ 154254721Semaste> global bp_count\n\ 155254721Semaste> bp_count = bp_count + 1\n\ 156254721Semaste> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\"\n\ 157254721Semaste> DONE\n\ 158254721Semaste\n\ 159254721SemasteIn this case, since there is a reference to a global variable,\n\ 160254721Semaste'bp_count', you will also need to make sure 'bp_count' exists and is\n\ 161254721Semasteinitialized:\n\ 162254721Semaste\n\ 163254721Semaste(lldb) script\n\ 164254721Semaste>>> bp_count = 0\n\ 165254721Semaste>>> quit()\n\ 166254721Semaste\n\ 167254721Semaste(lldb)\n\ 168254721Semaste\n\ 169254721Semaste\n\ 170254721SemasteYour Python code, however organized, can optionally return a value.\n\ 171254721SemasteIf the returned value is False, that tells LLDB not to stop at the breakpoint\n\ 172254721Semasteto which the code is associated. Returning anything other than False, or even\n\ 173254721Semastereturning None, or even omitting a return statement entirely, will cause\n\ 174254721SemasteLLDB to stop.\n\ 175254721Semaste\n\ 176254721SemasteFinal Note: If you get a warning that no breakpoint command was generated, but\n\ 177254721Semasteyou did not get any syntax errors, you probably forgot to add a call to your\n\ 178254721Semastefunctions.\n\ 179254721Semaste\n\ 180254721SemasteSpecial information about debugger command breakpoint commands\n\ 181254721Semaste--------------------------------------------------------------\n\ 182254721Semaste\n\ 183254721SemasteYou may enter any debugger command, exactly as you would at the debugger prompt.\n\ 184254721SemasteYou may enter as many debugger commands as you like, but do NOT enter more than\n\ 185254721Semasteone command per line.\n" ); 186254721Semaste 187254721Semaste CommandArgumentEntry arg; 188254721Semaste CommandArgumentData bp_id_arg; 189254721Semaste 190254721Semaste // Define the first (and only) variant of this arg. 191254721Semaste bp_id_arg.arg_type = eArgTypeBreakpointID; 192254721Semaste bp_id_arg.arg_repetition = eArgRepeatPlain; 193254721Semaste 194254721Semaste // There is only one variant this argument could be; put it into the argument entry. 195254721Semaste arg.push_back (bp_id_arg); 196254721Semaste 197254721Semaste // Push the data for the first argument into the m_arguments vector. 198254721Semaste m_arguments.push_back (arg); 199254721Semaste } 200254721Semaste 201254721Semaste virtual 202254721Semaste ~CommandObjectBreakpointCommandAdd () {} 203254721Semaste 204254721Semaste virtual Options * 205254721Semaste GetOptions () 206254721Semaste { 207254721Semaste return &m_options; 208254721Semaste } 209254721Semaste 210254721Semaste void 211254721Semaste CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, 212254721Semaste CommandReturnObject &result) 213254721Semaste { 214254721Semaste InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 215254721Semaste std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); 216254721Semaste if (reader_sp && data_ap.get()) 217254721Semaste { 218254721Semaste BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); 219254721Semaste bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp); 220254721Semaste 221254721Semaste Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback, 222254721Semaste bp_options, // baton 223254721Semaste eInputReaderGranularityLine, // token size, to pass to callback function 224254721Semaste "DONE", // end token 225254721Semaste "> ", // prompt 226254721Semaste true)); // echo input 227254721Semaste if (err.Success()) 228254721Semaste { 229254721Semaste m_interpreter.GetDebugger().PushInputReader (reader_sp); 230254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 231254721Semaste } 232254721Semaste else 233254721Semaste { 234254721Semaste result.AppendError (err.AsCString()); 235254721Semaste result.SetStatus (eReturnStatusFailed); 236254721Semaste } 237254721Semaste } 238254721Semaste else 239254721Semaste { 240254721Semaste result.AppendError("out of memory"); 241254721Semaste result.SetStatus (eReturnStatusFailed); 242254721Semaste } 243254721Semaste 244254721Semaste } 245254721Semaste 246254721Semaste /// Set a one-liner as the callback for the breakpoint. 247254721Semaste void 248254721Semaste SetBreakpointCommandCallback (BreakpointOptions *bp_options, 249254721Semaste const char *oneliner) 250254721Semaste { 251254721Semaste std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); 252254721Semaste 253254721Semaste // It's necessary to set both user_source and script_source to the oneliner. 254254721Semaste // The former is used to generate callback description (as in breakpoint command list) 255254721Semaste // while the latter is used for Python to interpret during the actual callback. 256254721Semaste data_ap->user_source.AppendString (oneliner); 257254721Semaste data_ap->script_source.assign (oneliner); 258254721Semaste data_ap->stop_on_error = m_options.m_stop_on_error; 259254721Semaste 260254721Semaste BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); 261254721Semaste bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp); 262254721Semaste 263254721Semaste return; 264254721Semaste } 265254721Semaste 266254721Semaste static size_t 267254721Semaste GenerateBreakpointCommandCallback (void *baton, 268254721Semaste InputReader &reader, 269254721Semaste lldb::InputReaderAction notification, 270254721Semaste const char *bytes, 271254721Semaste size_t bytes_len) 272254721Semaste { 273254721Semaste StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); 274254721Semaste bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 275254721Semaste 276254721Semaste switch (notification) 277254721Semaste { 278254721Semaste case eInputReaderActivate: 279254721Semaste if (!batch_mode) 280254721Semaste { 281254721Semaste out_stream->Printf ("%s\n", g_reader_instructions); 282254721Semaste if (reader.GetPrompt()) 283254721Semaste out_stream->Printf ("%s", reader.GetPrompt()); 284254721Semaste out_stream->Flush(); 285254721Semaste } 286254721Semaste break; 287254721Semaste 288254721Semaste case eInputReaderDeactivate: 289254721Semaste break; 290254721Semaste 291254721Semaste case eInputReaderReactivate: 292254721Semaste if (reader.GetPrompt() && !batch_mode) 293254721Semaste { 294254721Semaste out_stream->Printf ("%s", reader.GetPrompt()); 295254721Semaste out_stream->Flush(); 296254721Semaste } 297254721Semaste break; 298254721Semaste 299254721Semaste case eInputReaderAsynchronousOutputWritten: 300254721Semaste break; 301254721Semaste 302254721Semaste case eInputReaderGotToken: 303254721Semaste if (bytes && bytes_len && baton) 304254721Semaste { 305254721Semaste BreakpointOptions *bp_options = (BreakpointOptions *) baton; 306254721Semaste if (bp_options) 307254721Semaste { 308254721Semaste Baton *bp_options_baton = bp_options->GetBaton(); 309254721Semaste if (bp_options_baton) 310254721Semaste ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len); 311254721Semaste } 312254721Semaste } 313254721Semaste if (!reader.IsDone() && reader.GetPrompt() && !batch_mode) 314254721Semaste { 315254721Semaste out_stream->Printf ("%s", reader.GetPrompt()); 316254721Semaste out_stream->Flush(); 317254721Semaste } 318254721Semaste break; 319254721Semaste 320254721Semaste case eInputReaderInterrupt: 321254721Semaste { 322254721Semaste // Finish, and cancel the breakpoint command. 323254721Semaste reader.SetIsDone (true); 324254721Semaste BreakpointOptions *bp_options = (BreakpointOptions *) baton; 325254721Semaste if (bp_options) 326254721Semaste { 327254721Semaste Baton *bp_options_baton = bp_options->GetBaton (); 328254721Semaste if (bp_options_baton) 329254721Semaste { 330254721Semaste ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear(); 331254721Semaste ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear(); 332254721Semaste } 333254721Semaste } 334254721Semaste if (!batch_mode) 335254721Semaste { 336254721Semaste out_stream->Printf ("Warning: No command attached to breakpoint.\n"); 337254721Semaste out_stream->Flush(); 338254721Semaste } 339254721Semaste } 340254721Semaste break; 341254721Semaste 342254721Semaste case eInputReaderEndOfFile: 343254721Semaste reader.SetIsDone (true); 344254721Semaste break; 345254721Semaste 346254721Semaste case eInputReaderDone: 347254721Semaste break; 348254721Semaste } 349254721Semaste 350254721Semaste return bytes_len; 351254721Semaste } 352254721Semaste 353254721Semaste static bool 354254721Semaste BreakpointOptionsCallbackFunction (void *baton, 355254721Semaste StoppointCallbackContext *context, 356254721Semaste lldb::user_id_t break_id, 357254721Semaste lldb::user_id_t break_loc_id) 358254721Semaste { 359254721Semaste bool ret_value = true; 360254721Semaste if (baton == NULL) 361254721Semaste return true; 362254721Semaste 363254721Semaste 364254721Semaste BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton; 365254721Semaste StringList &commands = data->user_source; 366254721Semaste 367254721Semaste if (commands.GetSize() > 0) 368254721Semaste { 369254721Semaste ExecutionContext exe_ctx (context->exe_ctx_ref); 370254721Semaste Target *target = exe_ctx.GetTargetPtr(); 371254721Semaste if (target) 372254721Semaste { 373254721Semaste CommandReturnObject result; 374254721Semaste Debugger &debugger = target->GetDebugger(); 375254721Semaste // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously 376254721Semaste // if the debugger is set up that way. 377254721Semaste 378254721Semaste StreamSP output_stream (debugger.GetAsyncOutputStream()); 379254721Semaste StreamSP error_stream (debugger.GetAsyncErrorStream()); 380254721Semaste result.SetImmediateOutputStream (output_stream); 381254721Semaste result.SetImmediateErrorStream (error_stream); 382254721Semaste 383254721Semaste bool stop_on_continue = true; 384254721Semaste bool echo_commands = false; 385254721Semaste bool print_results = true; 386254721Semaste 387254721Semaste debugger.GetCommandInterpreter().HandleCommands (commands, 388254721Semaste &exe_ctx, 389254721Semaste stop_on_continue, 390254721Semaste data->stop_on_error, 391254721Semaste echo_commands, 392254721Semaste print_results, 393254721Semaste eLazyBoolNo, 394254721Semaste result); 395254721Semaste result.GetImmediateOutputStream()->Flush(); 396254721Semaste result.GetImmediateErrorStream()->Flush(); 397254721Semaste } 398254721Semaste } 399254721Semaste return ret_value; 400254721Semaste } 401254721Semaste 402254721Semaste class CommandOptions : public Options 403254721Semaste { 404254721Semaste public: 405254721Semaste 406254721Semaste CommandOptions (CommandInterpreter &interpreter) : 407254721Semaste Options (interpreter), 408254721Semaste m_use_commands (false), 409254721Semaste m_use_script_language (false), 410254721Semaste m_script_language (eScriptLanguageNone), 411254721Semaste m_use_one_liner (false), 412254721Semaste m_one_liner(), 413254721Semaste m_function_name() 414254721Semaste { 415254721Semaste } 416254721Semaste 417254721Semaste virtual 418254721Semaste ~CommandOptions () {} 419254721Semaste 420254721Semaste virtual Error 421254721Semaste SetOptionValue (uint32_t option_idx, const char *option_arg) 422254721Semaste { 423254721Semaste Error error; 424254721Semaste const int short_option = m_getopt_table[option_idx].val; 425254721Semaste 426254721Semaste switch (short_option) 427254721Semaste { 428254721Semaste case 'o': 429254721Semaste m_use_one_liner = true; 430254721Semaste m_one_liner = option_arg; 431254721Semaste break; 432254721Semaste 433254721Semaste case 's': 434254721Semaste m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg, 435254721Semaste g_option_table[option_idx].enum_values, 436254721Semaste eScriptLanguageNone, 437254721Semaste error); 438254721Semaste 439254721Semaste if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault) 440254721Semaste { 441254721Semaste m_use_script_language = true; 442254721Semaste } 443254721Semaste else 444254721Semaste { 445254721Semaste m_use_script_language = false; 446254721Semaste } 447254721Semaste break; 448254721Semaste 449254721Semaste case 'e': 450254721Semaste { 451254721Semaste bool success = false; 452254721Semaste m_stop_on_error = Args::StringToBoolean(option_arg, false, &success); 453254721Semaste if (!success) 454254721Semaste error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg); 455254721Semaste } 456254721Semaste break; 457254721Semaste 458254721Semaste case 'F': 459254721Semaste { 460254721Semaste m_use_one_liner = false; 461254721Semaste m_use_script_language = true; 462254721Semaste m_function_name.assign(option_arg); 463254721Semaste } 464254721Semaste break; 465254721Semaste 466254721Semaste default: 467254721Semaste break; 468254721Semaste } 469254721Semaste return error; 470254721Semaste } 471254721Semaste void 472254721Semaste OptionParsingStarting () 473254721Semaste { 474254721Semaste m_use_commands = true; 475254721Semaste m_use_script_language = false; 476254721Semaste m_script_language = eScriptLanguageNone; 477254721Semaste 478254721Semaste m_use_one_liner = false; 479254721Semaste m_stop_on_error = true; 480254721Semaste m_one_liner.clear(); 481254721Semaste m_function_name.clear(); 482254721Semaste } 483254721Semaste 484254721Semaste const OptionDefinition* 485254721Semaste GetDefinitions () 486254721Semaste { 487254721Semaste return g_option_table; 488254721Semaste } 489254721Semaste 490254721Semaste // Options table: Required for subclasses of Options. 491254721Semaste 492254721Semaste static OptionDefinition g_option_table[]; 493254721Semaste 494254721Semaste // Instance variables to hold the values for command options. 495254721Semaste 496254721Semaste bool m_use_commands; 497254721Semaste bool m_use_script_language; 498254721Semaste lldb::ScriptLanguage m_script_language; 499254721Semaste 500254721Semaste // Instance variables to hold the values for one_liner options. 501254721Semaste bool m_use_one_liner; 502254721Semaste std::string m_one_liner; 503254721Semaste bool m_stop_on_error; 504254721Semaste std::string m_function_name; 505254721Semaste }; 506254721Semaste 507254721Semasteprotected: 508254721Semaste virtual bool 509254721Semaste DoExecute (Args& command, CommandReturnObject &result) 510254721Semaste { 511254721Semaste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 512254721Semaste 513254721Semaste if (target == NULL) 514254721Semaste { 515254721Semaste result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands"); 516254721Semaste result.SetStatus (eReturnStatusFailed); 517254721Semaste return false; 518254721Semaste } 519254721Semaste 520254721Semaste const BreakpointList &breakpoints = target->GetBreakpointList(); 521254721Semaste size_t num_breakpoints = breakpoints.GetSize(); 522254721Semaste 523254721Semaste if (num_breakpoints == 0) 524254721Semaste { 525254721Semaste result.AppendError ("No breakpoints exist to have commands added"); 526254721Semaste result.SetStatus (eReturnStatusFailed); 527254721Semaste return false; 528254721Semaste } 529254721Semaste 530254721Semaste if (m_options.m_use_script_language == false && m_options.m_function_name.size()) 531254721Semaste { 532254721Semaste result.AppendError ("need to enable scripting to have a function run as a breakpoint command"); 533254721Semaste result.SetStatus (eReturnStatusFailed); 534254721Semaste return false; 535254721Semaste } 536254721Semaste 537254721Semaste BreakpointIDList valid_bp_ids; 538254721Semaste CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 539254721Semaste 540254721Semaste if (result.Succeeded()) 541254721Semaste { 542254721Semaste const size_t count = valid_bp_ids.GetSize(); 543254721Semaste if (count > 1) 544254721Semaste { 545254721Semaste result.AppendError ("can only add commands to one breakpoint at a time."); 546254721Semaste result.SetStatus (eReturnStatusFailed); 547254721Semaste return false; 548254721Semaste } 549254721Semaste 550254721Semaste for (size_t i = 0; i < count; ++i) 551254721Semaste { 552254721Semaste BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 553254721Semaste if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 554254721Semaste { 555254721Semaste Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 556254721Semaste BreakpointOptions *bp_options = NULL; 557254721Semaste if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) 558254721Semaste { 559254721Semaste // This breakpoint does not have an associated location. 560254721Semaste bp_options = bp->GetOptions(); 561254721Semaste } 562254721Semaste else 563254721Semaste { 564254721Semaste BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); 565254721Semaste // This breakpoint does have an associated location. 566254721Semaste // Get its breakpoint options. 567254721Semaste if (bp_loc_sp) 568254721Semaste bp_options = bp_loc_sp->GetLocationOptions(); 569254721Semaste } 570254721Semaste 571254721Semaste // Skip this breakpoint if bp_options is not good. 572254721Semaste if (bp_options == NULL) continue; 573254721Semaste 574254721Semaste // If we are using script language, get the script interpreter 575254721Semaste // in order to set or collect command callback. Otherwise, call 576254721Semaste // the methods associated with this object. 577254721Semaste if (m_options.m_use_script_language) 578254721Semaste { 579254721Semaste // Special handling for one-liner specified inline. 580254721Semaste if (m_options.m_use_one_liner) 581254721Semaste { 582254721Semaste m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, 583254721Semaste m_options.m_one_liner.c_str()); 584254721Semaste } 585254721Semaste // Special handling for using a Python function by name 586254721Semaste // instead of extending the breakpoint callback data structures, we just automatize 587254721Semaste // what the user would do manually: make their breakpoint command be a function call 588254721Semaste else if (m_options.m_function_name.size()) 589254721Semaste { 590254721Semaste std::string oneliner("return "); 591254721Semaste oneliner += m_options.m_function_name; 592254721Semaste oneliner += "(frame, bp_loc, internal_dict)"; 593254721Semaste m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, 594254721Semaste oneliner.c_str()); 595254721Semaste } 596254721Semaste else 597254721Semaste { 598254721Semaste m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options, 599254721Semaste result); 600254721Semaste } 601254721Semaste } 602254721Semaste else 603254721Semaste { 604254721Semaste // Special handling for one-liner specified inline. 605254721Semaste if (m_options.m_use_one_liner) 606254721Semaste SetBreakpointCommandCallback (bp_options, 607254721Semaste m_options.m_one_liner.c_str()); 608254721Semaste else 609254721Semaste CollectDataForBreakpointCommandCallback (bp_options, 610254721Semaste result); 611254721Semaste } 612254721Semaste } 613254721Semaste } 614254721Semaste } 615254721Semaste 616254721Semaste return result.Succeeded(); 617254721Semaste } 618254721Semaste 619254721Semasteprivate: 620254721Semaste CommandOptions m_options; 621254721Semaste static const char *g_reader_instructions; 622254721Semaste 623254721Semaste}; 624254721Semaste 625254721Semasteconst char * 626254721SemasteCommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end."; 627254721Semaste 628254721Semaste// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting 629254721Semaste// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper. 630254721Semaste 631254721Semastestatic OptionEnumValueElement 632254721Semasteg_script_option_enumeration[4] = 633254721Semaste{ 634254721Semaste { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"}, 635254721Semaste { eScriptLanguagePython, "python", "Commands are in the Python language."}, 636254721Semaste { eSortOrderByName, "default-script", "Commands are in the default scripting language."}, 637254721Semaste { 0, NULL, NULL } 638254721Semaste}; 639254721Semaste 640254721SemasteOptionDefinition 641254721SemasteCommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] = 642254721Semaste{ 643254721Semaste { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeOneLiner, 644254721Semaste "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, 645254721Semaste 646254721Semaste { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, 647254721Semaste "Specify whether breakpoint command execution should terminate on error." }, 648254721Semaste 649254721Semaste { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, 0, eArgTypeNone, 650254721Semaste "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."}, 651254721Semaste 652254721Semaste { LLDB_OPT_SET_2, false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction, 653254721Semaste "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."}, 654254721Semaste 655254721Semaste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 656254721Semaste}; 657254721Semaste 658254721Semaste//------------------------------------------------------------------------- 659254721Semaste// CommandObjectBreakpointCommandDelete 660254721Semaste//------------------------------------------------------------------------- 661254721Semaste 662254721Semasteclass CommandObjectBreakpointCommandDelete : public CommandObjectParsed 663254721Semaste{ 664254721Semastepublic: 665254721Semaste CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) : 666254721Semaste CommandObjectParsed (interpreter, 667254721Semaste "delete", 668254721Semaste "Delete the set of commands from a breakpoint.", 669254721Semaste NULL) 670254721Semaste { 671254721Semaste CommandArgumentEntry arg; 672254721Semaste CommandArgumentData bp_id_arg; 673254721Semaste 674254721Semaste // Define the first (and only) variant of this arg. 675254721Semaste bp_id_arg.arg_type = eArgTypeBreakpointID; 676254721Semaste bp_id_arg.arg_repetition = eArgRepeatPlain; 677254721Semaste 678254721Semaste // There is only one variant this argument could be; put it into the argument entry. 679254721Semaste arg.push_back (bp_id_arg); 680254721Semaste 681254721Semaste // Push the data for the first argument into the m_arguments vector. 682254721Semaste m_arguments.push_back (arg); 683254721Semaste } 684254721Semaste 685254721Semaste 686254721Semaste virtual 687254721Semaste ~CommandObjectBreakpointCommandDelete () {} 688254721Semaste 689254721Semasteprotected: 690254721Semaste virtual bool 691254721Semaste DoExecute (Args& command, CommandReturnObject &result) 692254721Semaste { 693254721Semaste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 694254721Semaste 695254721Semaste if (target == NULL) 696254721Semaste { 697254721Semaste result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands"); 698254721Semaste result.SetStatus (eReturnStatusFailed); 699254721Semaste return false; 700254721Semaste } 701254721Semaste 702254721Semaste const BreakpointList &breakpoints = target->GetBreakpointList(); 703254721Semaste size_t num_breakpoints = breakpoints.GetSize(); 704254721Semaste 705254721Semaste if (num_breakpoints == 0) 706254721Semaste { 707254721Semaste result.AppendError ("No breakpoints exist to have commands deleted"); 708254721Semaste result.SetStatus (eReturnStatusFailed); 709254721Semaste return false; 710254721Semaste } 711254721Semaste 712254721Semaste if (command.GetArgumentCount() == 0) 713254721Semaste { 714254721Semaste result.AppendError ("No breakpoint specified from which to delete the commands"); 715254721Semaste result.SetStatus (eReturnStatusFailed); 716254721Semaste return false; 717254721Semaste } 718254721Semaste 719254721Semaste BreakpointIDList valid_bp_ids; 720254721Semaste CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 721254721Semaste 722254721Semaste if (result.Succeeded()) 723254721Semaste { 724254721Semaste const size_t count = valid_bp_ids.GetSize(); 725254721Semaste for (size_t i = 0; i < count; ++i) 726254721Semaste { 727254721Semaste BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 728254721Semaste if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 729254721Semaste { 730254721Semaste Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 731254721Semaste if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 732254721Semaste { 733254721Semaste BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID())); 734254721Semaste if (bp_loc_sp) 735254721Semaste bp_loc_sp->ClearCallback(); 736254721Semaste else 737254721Semaste { 738254721Semaste result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 739254721Semaste cur_bp_id.GetBreakpointID(), 740254721Semaste cur_bp_id.GetLocationID()); 741254721Semaste result.SetStatus (eReturnStatusFailed); 742254721Semaste return false; 743254721Semaste } 744254721Semaste } 745254721Semaste else 746254721Semaste { 747254721Semaste bp->ClearCallback(); 748254721Semaste } 749254721Semaste } 750254721Semaste } 751254721Semaste } 752254721Semaste return result.Succeeded(); 753254721Semaste } 754254721Semaste}; 755254721Semaste 756254721Semaste//------------------------------------------------------------------------- 757254721Semaste// CommandObjectBreakpointCommandList 758254721Semaste//------------------------------------------------------------------------- 759254721Semaste 760254721Semasteclass CommandObjectBreakpointCommandList : public CommandObjectParsed 761254721Semaste{ 762254721Semastepublic: 763254721Semaste CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) : 764254721Semaste CommandObjectParsed (interpreter, 765254721Semaste "list", 766254721Semaste "List the script or set of commands to be executed when the breakpoint is hit.", 767254721Semaste NULL) 768254721Semaste { 769254721Semaste CommandArgumentEntry arg; 770254721Semaste CommandArgumentData bp_id_arg; 771254721Semaste 772254721Semaste // Define the first (and only) variant of this arg. 773254721Semaste bp_id_arg.arg_type = eArgTypeBreakpointID; 774254721Semaste bp_id_arg.arg_repetition = eArgRepeatPlain; 775254721Semaste 776254721Semaste // There is only one variant this argument could be; put it into the argument entry. 777254721Semaste arg.push_back (bp_id_arg); 778254721Semaste 779254721Semaste // Push the data for the first argument into the m_arguments vector. 780254721Semaste m_arguments.push_back (arg); 781254721Semaste } 782254721Semaste 783254721Semaste virtual 784254721Semaste ~CommandObjectBreakpointCommandList () {} 785254721Semaste 786254721Semasteprotected: 787254721Semaste virtual bool 788254721Semaste DoExecute (Args& command, 789254721Semaste CommandReturnObject &result) 790254721Semaste { 791254721Semaste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 792254721Semaste 793254721Semaste if (target == NULL) 794254721Semaste { 795254721Semaste result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands"); 796254721Semaste result.SetStatus (eReturnStatusFailed); 797254721Semaste return false; 798254721Semaste } 799254721Semaste 800254721Semaste const BreakpointList &breakpoints = target->GetBreakpointList(); 801254721Semaste size_t num_breakpoints = breakpoints.GetSize(); 802254721Semaste 803254721Semaste if (num_breakpoints == 0) 804254721Semaste { 805254721Semaste result.AppendError ("No breakpoints exist for which to list commands"); 806254721Semaste result.SetStatus (eReturnStatusFailed); 807254721Semaste return false; 808254721Semaste } 809254721Semaste 810254721Semaste if (command.GetArgumentCount() == 0) 811254721Semaste { 812254721Semaste result.AppendError ("No breakpoint specified for which to list the commands"); 813254721Semaste result.SetStatus (eReturnStatusFailed); 814254721Semaste return false; 815254721Semaste } 816254721Semaste 817254721Semaste BreakpointIDList valid_bp_ids; 818254721Semaste CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 819254721Semaste 820254721Semaste if (result.Succeeded()) 821254721Semaste { 822254721Semaste const size_t count = valid_bp_ids.GetSize(); 823254721Semaste for (size_t i = 0; i < count; ++i) 824254721Semaste { 825254721Semaste BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 826254721Semaste if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 827254721Semaste { 828254721Semaste Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 829254721Semaste 830254721Semaste if (bp) 831254721Semaste { 832254721Semaste const BreakpointOptions *bp_options = NULL; 833254721Semaste if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 834254721Semaste { 835254721Semaste BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); 836254721Semaste if (bp_loc_sp) 837254721Semaste bp_options = bp_loc_sp->GetOptionsNoCreate(); 838254721Semaste else 839254721Semaste { 840254721Semaste result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 841254721Semaste cur_bp_id.GetBreakpointID(), 842254721Semaste cur_bp_id.GetLocationID()); 843254721Semaste result.SetStatus (eReturnStatusFailed); 844254721Semaste return false; 845254721Semaste } 846254721Semaste } 847254721Semaste else 848254721Semaste { 849254721Semaste bp_options = bp->GetOptions(); 850254721Semaste } 851254721Semaste 852254721Semaste if (bp_options) 853254721Semaste { 854254721Semaste StreamString id_str; 855254721Semaste BreakpointID::GetCanonicalReference (&id_str, 856254721Semaste cur_bp_id.GetBreakpointID(), 857254721Semaste cur_bp_id.GetLocationID()); 858254721Semaste const Baton *baton = bp_options->GetBaton(); 859254721Semaste if (baton) 860254721Semaste { 861254721Semaste result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData()); 862254721Semaste result.GetOutputStream().IndentMore (); 863254721Semaste baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull); 864254721Semaste result.GetOutputStream().IndentLess (); 865254721Semaste } 866254721Semaste else 867254721Semaste { 868254721Semaste result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", 869254721Semaste id_str.GetData()); 870254721Semaste } 871254721Semaste } 872254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 873254721Semaste } 874254721Semaste else 875254721Semaste { 876254721Semaste result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID()); 877254721Semaste result.SetStatus (eReturnStatusFailed); 878254721Semaste } 879254721Semaste 880254721Semaste } 881254721Semaste } 882254721Semaste } 883254721Semaste 884254721Semaste return result.Succeeded(); 885254721Semaste } 886254721Semaste}; 887254721Semaste 888254721Semaste//------------------------------------------------------------------------- 889254721Semaste// CommandObjectBreakpointCommand 890254721Semaste//------------------------------------------------------------------------- 891254721Semaste 892254721SemasteCommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) : 893254721Semaste CommandObjectMultiword (interpreter, 894254721Semaste "command", 895254721Semaste "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').", 896254721Semaste "command <sub-command> [<sub-command-options>] <breakpoint-id>") 897254721Semaste{ 898254721Semaste CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter)); 899254721Semaste CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter)); 900254721Semaste CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter)); 901254721Semaste 902254721Semaste add_command_object->SetCommandName ("breakpoint command add"); 903254721Semaste delete_command_object->SetCommandName ("breakpoint command delete"); 904254721Semaste list_command_object->SetCommandName ("breakpoint command list"); 905254721Semaste 906254721Semaste LoadSubCommand ("add", add_command_object); 907254721Semaste LoadSubCommand ("delete", delete_command_object); 908254721Semaste LoadSubCommand ("list", list_command_object); 909254721Semaste} 910254721Semaste 911254721SemasteCommandObjectBreakpointCommand::~CommandObjectBreakpointCommand () 912254721Semaste{ 913254721Semaste} 914254721Semaste 915254721Semaste 916