130fdc8d8SChris Lattner //===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner // C Includes 1130fdc8d8SChris Lattner // C++ Includes 1230fdc8d8SChris Lattner 1330fdc8d8SChris Lattner 1430fdc8d8SChris Lattner #include "CommandObjectBreakpointCommand.h" 1530fdc8d8SChris Lattner #include "CommandObjectBreakpoint.h" 1630fdc8d8SChris Lattner 1744d93782SGreg Clayton #include "lldb/Core/IOHandler.h" 1830fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h" 1930fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 2030fdc8d8SChris Lattner #include "lldb/Target/Target.h" 2130fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h" 2330fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h" 2430fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h" 2530fdc8d8SChris Lattner #include "lldb/Breakpoint/StoppointCallbackContext.h" 2630fdc8d8SChris Lattner #include "lldb/Core/State.h" 2730fdc8d8SChris Lattner 2830fdc8d8SChris Lattner using namespace lldb; 2930fdc8d8SChris Lattner using namespace lldb_private; 3030fdc8d8SChris Lattner 3130fdc8d8SChris Lattner //------------------------------------------------------------------------- 3230fdc8d8SChris Lattner // CommandObjectBreakpointCommandAdd 3330fdc8d8SChris Lattner //------------------------------------------------------------------------- 3430fdc8d8SChris Lattner 3530fdc8d8SChris Lattner 3644d93782SGreg Clayton class CommandObjectBreakpointCommandAdd : 3744d93782SGreg Clayton public CommandObjectParsed, 3844d93782SGreg Clayton public IOHandlerDelegateMultiline 395a988416SJim Ingham { 405a988416SJim Ingham public: 415a988416SJim Ingham 425a988416SJim Ingham CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) : 435a988416SJim Ingham CommandObjectParsed (interpreter, 44a7015092SGreg Clayton "add", 451bb0750bSJim Ingham "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit." 461bb0750bSJim Ingham " If no breakpoint is specified, adds the commands to the last created breakpoint.", 47eb0103f2SGreg Clayton NULL), 48c3d874a5SGreg Clayton IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand), 49eb0103f2SGreg Clayton m_options (interpreter) 5030fdc8d8SChris Lattner { 5130fdc8d8SChris Lattner SetHelpLong ( 52*ea671fbdSKate Stone R"( 53*ea671fbdSKate Stone General information about entering breakpoint commands 54*ea671fbdSKate Stone ------------------------------------------------------ 55*ea671fbdSKate Stone 56*ea671fbdSKate Stone )" "This command will prompt for commands to be executed when the specified \ 57*ea671fbdSKate Stone breakpoint is hit. Each command is typed on its own line following the '> ' \ 58*ea671fbdSKate Stone prompt until 'DONE' is entered." R"( 59*ea671fbdSKate Stone 60*ea671fbdSKate Stone )" "Syntactic errors may not be detected when initially entered, and many \ 61*ea671fbdSKate Stone malformed commands can silently fail when executed. If your breakpoint commands \ 62*ea671fbdSKate Stone do not appear to be executing, double-check the command syntax." R"( 63*ea671fbdSKate Stone 64*ea671fbdSKate Stone )" "Note: You may enter any debugger command exactly as you would at the debugger \ 65*ea671fbdSKate Stone prompt. There is no limit to the number of commands supplied, but do NOT enter \ 66*ea671fbdSKate Stone more than one command per line." R"( 67*ea671fbdSKate Stone 68*ea671fbdSKate Stone Special information about PYTHON breakpoint commands 69*ea671fbdSKate Stone ---------------------------------------------------- 70*ea671fbdSKate Stone 71*ea671fbdSKate Stone )" "You may enter either one or more lines of Python, including function \ 72*ea671fbdSKate Stone definitions or calls to functions that will have been imported by the time \ 73*ea671fbdSKate Stone the code executes. Single line breakpoint commands will be interpreted 'as is' \ 74*ea671fbdSKate Stone when the breakpoint is hit. Multiple lines of Python will be wrapped in a \ 75*ea671fbdSKate Stone generated function, and a call to the function will be attached to the breakpoint." R"( 76*ea671fbdSKate Stone 77*ea671fbdSKate Stone This auto-generated function is passed in three arguments: 78*ea671fbdSKate Stone 79*ea671fbdSKate Stone frame: an lldb.SBFrame object for the frame which hit breakpoint. 80*ea671fbdSKate Stone 81*ea671fbdSKate Stone bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit. 82*ea671fbdSKate Stone 83*ea671fbdSKate Stone dict: the python session dictionary hit. 84*ea671fbdSKate Stone 85*ea671fbdSKate Stone )" "When specifying a python function with the --python-function option, you need \ 86*ea671fbdSKate Stone to supply the function name prepended by the module name:" R"( 87*ea671fbdSKate Stone 88*ea671fbdSKate Stone --python-function myutils.breakpoint_callback 89*ea671fbdSKate Stone 90*ea671fbdSKate Stone The function itself must have the following prototype: 91*ea671fbdSKate Stone 92*ea671fbdSKate Stone def breakpoint_callback(frame, bp_loc, dict): 93*ea671fbdSKate Stone # Your code goes here 94*ea671fbdSKate Stone 95*ea671fbdSKate Stone )" "The arguments are the same as the arguments passed to generated functions as \ 96*ea671fbdSKate Stone described above. Note that the global variable 'lldb.frame' will NOT be updated when \ 97*ea671fbdSKate Stone this function is called, so be sure to use the 'frame' argument. The 'frame' argument \ 98*ea671fbdSKate Stone can get you to the thread via frame.GetThread(), the thread can get you to the \ 99*ea671fbdSKate Stone process via thread.GetProcess(), and the process can get you back to the target \ 100*ea671fbdSKate Stone via process.GetTarget()." R"( 101*ea671fbdSKate Stone 102*ea671fbdSKate Stone )" "Important Note: As Python code gets collected into functions, access to global \ 103*ea671fbdSKate Stone variables requires explicit scoping using the 'global' keyword. Be sure to use correct \ 104*ea671fbdSKate Stone Python syntax, including indentation, when entering Python breakpoint commands." R"( 105*ea671fbdSKate Stone 106*ea671fbdSKate Stone Example Python one-line breakpoint command: 107*ea671fbdSKate Stone 108*ea671fbdSKate Stone (lldb) breakpoint command add -s python 1 109*ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end. 110*ea671fbdSKate Stone > print "Hit this breakpoint!" 111*ea671fbdSKate Stone > DONE 112*ea671fbdSKate Stone 113*ea671fbdSKate Stone As a convenience, this also works for a short Python one-liner: 114*ea671fbdSKate Stone 115*ea671fbdSKate Stone (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()' 116*ea671fbdSKate Stone (lldb) run 117*ea671fbdSKate Stone Launching '.../a.out' (x86_64) 118*ea671fbdSKate Stone (lldb) Fri Sep 10 12:17:45 2010 119*ea671fbdSKate Stone Process 21778 Stopped 120*ea671fbdSKate Stone * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread 121*ea671fbdSKate Stone 36 122*ea671fbdSKate Stone 37 int c(int val) 123*ea671fbdSKate Stone 38 { 124*ea671fbdSKate Stone 39 -> return val + 3; 125*ea671fbdSKate Stone 40 } 126*ea671fbdSKate Stone 41 127*ea671fbdSKate Stone 42 int main (int argc, char const *argv[]) 128*ea671fbdSKate Stone 129*ea671fbdSKate Stone Example multiple line Python breakpoint command: 130*ea671fbdSKate Stone 131*ea671fbdSKate Stone (lldb) breakpoint command add -s p 1 132*ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end. 133*ea671fbdSKate Stone > global bp_count 134*ea671fbdSKate Stone > bp_count = bp_count + 1 135*ea671fbdSKate Stone > print "Hit this breakpoint " + repr(bp_count) + " times!" 136*ea671fbdSKate Stone > DONE 137*ea671fbdSKate Stone 138*ea671fbdSKate Stone Example multiple line Python breakpoint command, using function definition: 139*ea671fbdSKate Stone 140*ea671fbdSKate Stone (lldb) breakpoint command add -s python 1 141*ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end. 142*ea671fbdSKate Stone > def breakpoint_output (bp_no): 143*ea671fbdSKate Stone > out_string = "Hit breakpoint number " + repr (bp_no) 144*ea671fbdSKate Stone > print out_string 145*ea671fbdSKate Stone > return True 146*ea671fbdSKate Stone > breakpoint_output (1) 147*ea671fbdSKate Stone > DONE 148*ea671fbdSKate Stone 149*ea671fbdSKate Stone )" "In this case, since there is a reference to a global variable, \ 150*ea671fbdSKate Stone 'bp_count', you will also need to make sure 'bp_count' exists and is \ 151*ea671fbdSKate Stone initialized:" R"( 152*ea671fbdSKate Stone 153*ea671fbdSKate Stone (lldb) script 154*ea671fbdSKate Stone >>> bp_count = 0 155*ea671fbdSKate Stone >>> quit() 156*ea671fbdSKate Stone 157*ea671fbdSKate Stone )" "Your Python code, however organized, can optionally return a value. \ 158*ea671fbdSKate Stone If the returned value is False, that tells LLDB not to stop at the breakpoint \ 159*ea671fbdSKate Stone to which the code is associated. Returning anything other than False, or even \ 160*ea671fbdSKate Stone returning None, or even omitting a return statement entirely, will cause \ 161*ea671fbdSKate Stone LLDB to stop." R"( 162*ea671fbdSKate Stone 163*ea671fbdSKate Stone )" "Final Note: A warning that no breakpoint command was generated when there \ 164*ea671fbdSKate Stone are no syntax errors may indicate that a function was declared but never called." 165*ea671fbdSKate Stone ); 166405fe67fSCaroline Tice 167405fe67fSCaroline Tice CommandArgumentEntry arg; 168405fe67fSCaroline Tice CommandArgumentData bp_id_arg; 169405fe67fSCaroline Tice 170405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 171405fe67fSCaroline Tice bp_id_arg.arg_type = eArgTypeBreakpointID; 1721bb0750bSJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 173405fe67fSCaroline Tice 174405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 175405fe67fSCaroline Tice arg.push_back (bp_id_arg); 176405fe67fSCaroline Tice 177405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 178405fe67fSCaroline Tice m_arguments.push_back (arg); 17930fdc8d8SChris Lattner } 18030fdc8d8SChris Lattner 1815a988416SJim Ingham virtual 1825a988416SJim Ingham ~CommandObjectBreakpointCommandAdd () {} 1835a988416SJim Ingham 1845a988416SJim Ingham virtual Options * 1855a988416SJim Ingham GetOptions () 1865a988416SJim Ingham { 1875a988416SJim Ingham return &m_options; 1885a988416SJim Ingham } 1895a988416SJim Ingham 19044d93782SGreg Clayton virtual void 19144d93782SGreg Clayton IOHandlerActivated (IOHandler &io_handler) 19244d93782SGreg Clayton { 19344d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 19444d93782SGreg Clayton if (output_sp) 19544d93782SGreg Clayton { 19644d93782SGreg Clayton output_sp->PutCString(g_reader_instructions); 19744d93782SGreg Clayton output_sp->Flush(); 19844d93782SGreg Clayton } 19944d93782SGreg Clayton } 20044d93782SGreg Clayton 20144d93782SGreg Clayton 20244d93782SGreg Clayton virtual void 20344d93782SGreg Clayton IOHandlerInputComplete (IOHandler &io_handler, std::string &line) 20444d93782SGreg Clayton { 20544d93782SGreg Clayton io_handler.SetIsDone(true); 20644d93782SGreg Clayton 207b5796cb4SJim Ingham std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData(); 208b5796cb4SJim Ingham for (BreakpointOptions *bp_options : *bp_options_vec) 20944d93782SGreg Clayton { 210b5796cb4SJim Ingham if (!bp_options) 211b5796cb4SJim Ingham continue; 212b5796cb4SJim Ingham 21344d93782SGreg Clayton std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); 21444d93782SGreg Clayton if (data_ap.get()) 21544d93782SGreg Clayton { 21644d93782SGreg Clayton data_ap->user_source.SplitIntoLines (line.c_str(), line.size()); 21744d93782SGreg Clayton BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); 21844d93782SGreg Clayton bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp); 21944d93782SGreg Clayton } 22044d93782SGreg Clayton } 22144d93782SGreg Clayton } 22244d93782SGreg Clayton 2235a988416SJim Ingham void 224b5796cb4SJim Ingham CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec, 2255a988416SJim Ingham CommandReturnObject &result) 2265a988416SJim Ingham { 22744d93782SGreg Clayton m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt 22844d93782SGreg Clayton *this, // IOHandlerDelegate 22944d93782SGreg Clayton true, // Run IOHandler in async mode 230b5796cb4SJim Ingham &bp_options_vec); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 2315a988416SJim Ingham } 2325a988416SJim Ingham 2335a988416SJim Ingham /// Set a one-liner as the callback for the breakpoint. 2345a988416SJim Ingham void 235b5796cb4SJim Ingham SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec, 2365a988416SJim Ingham const char *oneliner) 2375a988416SJim Ingham { 238b5796cb4SJim Ingham for (auto bp_options : bp_options_vec) 239b5796cb4SJim Ingham { 2407b0992d9SGreg Clayton std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); 2415a988416SJim Ingham 2425a988416SJim Ingham // It's necessary to set both user_source and script_source to the oneliner. 2435a988416SJim Ingham // The former is used to generate callback description (as in breakpoint command list) 2445a988416SJim Ingham // while the latter is used for Python to interpret during the actual callback. 2455a988416SJim Ingham data_ap->user_source.AppendString (oneliner); 2465a988416SJim Ingham data_ap->script_source.assign (oneliner); 2475a988416SJim Ingham data_ap->stop_on_error = m_options.m_stop_on_error; 2485a988416SJim Ingham 2495a988416SJim Ingham BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); 2505a988416SJim Ingham bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp); 251b5796cb4SJim Ingham } 2525a988416SJim Ingham return; 2535a988416SJim Ingham } 2545a988416SJim Ingham 2555a988416SJim Ingham static bool 2565a988416SJim Ingham BreakpointOptionsCallbackFunction (void *baton, 2575a988416SJim Ingham StoppointCallbackContext *context, 2585a988416SJim Ingham lldb::user_id_t break_id, 2595a988416SJim Ingham lldb::user_id_t break_loc_id) 2605a988416SJim Ingham { 2615a988416SJim Ingham bool ret_value = true; 2625a988416SJim Ingham if (baton == NULL) 2635a988416SJim Ingham return true; 2645a988416SJim Ingham 2655a988416SJim Ingham 2665a988416SJim Ingham BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton; 2675a988416SJim Ingham StringList &commands = data->user_source; 2685a988416SJim Ingham 2695a988416SJim Ingham if (commands.GetSize() > 0) 2705a988416SJim Ingham { 2715a988416SJim Ingham ExecutionContext exe_ctx (context->exe_ctx_ref); 2725a988416SJim Ingham Target *target = exe_ctx.GetTargetPtr(); 2735a988416SJim Ingham if (target) 2745a988416SJim Ingham { 2755a988416SJim Ingham CommandReturnObject result; 2765a988416SJim Ingham Debugger &debugger = target->GetDebugger(); 2775a988416SJim Ingham // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously 2785a988416SJim Ingham // if the debugger is set up that way. 2795a988416SJim Ingham 2805a988416SJim Ingham StreamSP output_stream (debugger.GetAsyncOutputStream()); 2815a988416SJim Ingham StreamSP error_stream (debugger.GetAsyncErrorStream()); 2825a988416SJim Ingham result.SetImmediateOutputStream (output_stream); 2835a988416SJim Ingham result.SetImmediateErrorStream (error_stream); 2845a988416SJim Ingham 28526c7bf93SJim Ingham CommandInterpreterRunOptions options; 28626c7bf93SJim Ingham options.SetStopOnContinue(true); 28726c7bf93SJim Ingham options.SetStopOnError (data->stop_on_error); 28826c7bf93SJim Ingham options.SetEchoCommands (true); 28926c7bf93SJim Ingham options.SetPrintResults (true); 29026c7bf93SJim Ingham options.SetAddToHistory (false); 2915a988416SJim Ingham 2925a988416SJim Ingham debugger.GetCommandInterpreter().HandleCommands (commands, 2935a988416SJim Ingham &exe_ctx, 29426c7bf93SJim Ingham options, 2955a988416SJim Ingham result); 2965a988416SJim Ingham result.GetImmediateOutputStream()->Flush(); 2975a988416SJim Ingham result.GetImmediateErrorStream()->Flush(); 2985a988416SJim Ingham } 2995a988416SJim Ingham } 3005a988416SJim Ingham return ret_value; 3015a988416SJim Ingham } 3025a988416SJim Ingham 3035a988416SJim Ingham class CommandOptions : public Options 3045a988416SJim Ingham { 3055a988416SJim Ingham public: 3065a988416SJim Ingham 3075a988416SJim Ingham CommandOptions (CommandInterpreter &interpreter) : 3085a988416SJim Ingham Options (interpreter), 3095a988416SJim Ingham m_use_commands (false), 3105a988416SJim Ingham m_use_script_language (false), 3115a988416SJim Ingham m_script_language (eScriptLanguageNone), 3125a988416SJim Ingham m_use_one_liner (false), 3135a988416SJim Ingham m_one_liner(), 3145a988416SJim Ingham m_function_name() 31530fdc8d8SChris Lattner { 31630fdc8d8SChris Lattner } 31730fdc8d8SChris Lattner 3185a988416SJim Ingham virtual 3195a988416SJim Ingham ~CommandOptions () {} 3205a988416SJim Ingham 3215a988416SJim Ingham virtual Error 3225a988416SJim Ingham SetOptionValue (uint32_t option_idx, const char *option_arg) 3235a988416SJim Ingham { 3245a988416SJim Ingham Error error; 3253bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 3265a988416SJim Ingham 3275a988416SJim Ingham switch (short_option) 3285a988416SJim Ingham { 3295a988416SJim Ingham case 'o': 3305a988416SJim Ingham m_use_one_liner = true; 3315a988416SJim Ingham m_one_liner = option_arg; 3325a988416SJim Ingham break; 3335a988416SJim Ingham 3345a988416SJim Ingham case 's': 3355a988416SJim Ingham m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg, 3365a988416SJim Ingham g_option_table[option_idx].enum_values, 3375a988416SJim Ingham eScriptLanguageNone, 3385a988416SJim Ingham error); 3395a988416SJim Ingham 3405a988416SJim Ingham if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault) 3415a988416SJim Ingham { 3425a988416SJim Ingham m_use_script_language = true; 3435a988416SJim Ingham } 3445a988416SJim Ingham else 3455a988416SJim Ingham { 3465a988416SJim Ingham m_use_script_language = false; 3475a988416SJim Ingham } 3485a988416SJim Ingham break; 3495a988416SJim Ingham 3505a988416SJim Ingham case 'e': 3515a988416SJim Ingham { 3525a988416SJim Ingham bool success = false; 3535a988416SJim Ingham m_stop_on_error = Args::StringToBoolean(option_arg, false, &success); 3545a988416SJim Ingham if (!success) 3555a988416SJim Ingham error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg); 3565a988416SJim Ingham } 3575a988416SJim Ingham break; 3585a988416SJim Ingham 3595a988416SJim Ingham case 'F': 3605a988416SJim Ingham { 3615a988416SJim Ingham m_use_one_liner = false; 3625a988416SJim Ingham m_use_script_language = true; 3635a988416SJim Ingham m_function_name.assign(option_arg); 3645a988416SJim Ingham } 3655a988416SJim Ingham break; 3665a988416SJim Ingham 36733df7cd3SJim Ingham case 'D': 36833df7cd3SJim Ingham m_use_dummy = true; 36933df7cd3SJim Ingham break; 37033df7cd3SJim Ingham 3715a988416SJim Ingham default: 3725a988416SJim Ingham break; 3735a988416SJim Ingham } 3745a988416SJim Ingham return error; 3755a988416SJim Ingham } 3765a988416SJim Ingham void 3775a988416SJim Ingham OptionParsingStarting () 3785a988416SJim Ingham { 3795a988416SJim Ingham m_use_commands = true; 3805a988416SJim Ingham m_use_script_language = false; 3815a988416SJim Ingham m_script_language = eScriptLanguageNone; 3825a988416SJim Ingham 3835a988416SJim Ingham m_use_one_liner = false; 3845a988416SJim Ingham m_stop_on_error = true; 3855a988416SJim Ingham m_one_liner.clear(); 3865a988416SJim Ingham m_function_name.clear(); 38733df7cd3SJim Ingham m_use_dummy = false; 3885a988416SJim Ingham } 3895a988416SJim Ingham 3905a988416SJim Ingham const OptionDefinition* 3915a988416SJim Ingham GetDefinitions () 3925a988416SJim Ingham { 3935a988416SJim Ingham return g_option_table; 3945a988416SJim Ingham } 3955a988416SJim Ingham 3965a988416SJim Ingham // Options table: Required for subclasses of Options. 3975a988416SJim Ingham 3985a988416SJim Ingham static OptionDefinition g_option_table[]; 3995a988416SJim Ingham 4005a988416SJim Ingham // Instance variables to hold the values for command options. 4015a988416SJim Ingham 4025a988416SJim Ingham bool m_use_commands; 4035a988416SJim Ingham bool m_use_script_language; 4045a988416SJim Ingham lldb::ScriptLanguage m_script_language; 4055a988416SJim Ingham 4065a988416SJim Ingham // Instance variables to hold the values for one_liner options. 4075a988416SJim Ingham bool m_use_one_liner; 4085a988416SJim Ingham std::string m_one_liner; 4095a988416SJim Ingham bool m_stop_on_error; 4105a988416SJim Ingham std::string m_function_name; 41133df7cd3SJim Ingham bool m_use_dummy; 4125a988416SJim Ingham }; 4135a988416SJim Ingham 4145a988416SJim Ingham protected: 4155a988416SJim Ingham virtual bool 4165a988416SJim Ingham DoExecute (Args& command, CommandReturnObject &result) 41730fdc8d8SChris Lattner { 41833df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 41930fdc8d8SChris Lattner 42030fdc8d8SChris Lattner if (target == NULL) 42130fdc8d8SChris Lattner { 42230fdc8d8SChris Lattner result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands"); 42330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 42430fdc8d8SChris Lattner return false; 42530fdc8d8SChris Lattner } 42630fdc8d8SChris Lattner 42730fdc8d8SChris Lattner const BreakpointList &breakpoints = target->GetBreakpointList(); 42830fdc8d8SChris Lattner size_t num_breakpoints = breakpoints.GetSize(); 42930fdc8d8SChris Lattner 43030fdc8d8SChris Lattner if (num_breakpoints == 0) 43130fdc8d8SChris Lattner { 43230fdc8d8SChris Lattner result.AppendError ("No breakpoints exist to have commands added"); 43330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 43430fdc8d8SChris Lattner return false; 43530fdc8d8SChris Lattner } 43630fdc8d8SChris Lattner 4378d4a8010SEnrico Granata if (m_options.m_use_script_language == false && m_options.m_function_name.size()) 4388d4a8010SEnrico Granata { 4398d4a8010SEnrico Granata result.AppendError ("need to enable scripting to have a function run as a breakpoint command"); 4408d4a8010SEnrico Granata result.SetStatus (eReturnStatusFailed); 4418d4a8010SEnrico Granata return false; 4428d4a8010SEnrico Granata } 4438d4a8010SEnrico Granata 44430fdc8d8SChris Lattner BreakpointIDList valid_bp_ids; 4455e09c8c3SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 44630fdc8d8SChris Lattner 447b5796cb4SJim Ingham m_bp_options_vec.clear(); 448b5796cb4SJim Ingham 44930fdc8d8SChris Lattner if (result.Succeeded()) 45030fdc8d8SChris Lattner { 451c982c768SGreg Clayton const size_t count = valid_bp_ids.GetSize(); 452d9916eaeSJim Ingham 453c982c768SGreg Clayton for (size_t i = 0; i < count; ++i) 45430fdc8d8SChris Lattner { 45530fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 45630fdc8d8SChris Lattner if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 45730fdc8d8SChris Lattner { 45830fdc8d8SChris Lattner Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 45939d7d4f0SJohnny Chen BreakpointOptions *bp_options = NULL; 46039d7d4f0SJohnny Chen if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) 46139d7d4f0SJohnny Chen { 46239d7d4f0SJohnny Chen // This breakpoint does not have an associated location. 46339d7d4f0SJohnny Chen bp_options = bp->GetOptions(); 46439d7d4f0SJohnny Chen } 46539d7d4f0SJohnny Chen else 46630fdc8d8SChris Lattner { 46730fdc8d8SChris Lattner BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); 46839d7d4f0SJohnny Chen // This breakpoint does have an associated location. 46939d7d4f0SJohnny Chen // Get its breakpoint options. 47030fdc8d8SChris Lattner if (bp_loc_sp) 47139d7d4f0SJohnny Chen bp_options = bp_loc_sp->GetLocationOptions(); 47239d7d4f0SJohnny Chen } 473b5796cb4SJim Ingham if (bp_options) 474b5796cb4SJim Ingham m_bp_options_vec.push_back (bp_options); 475b5796cb4SJim Ingham } 476b5796cb4SJim Ingham } 47739d7d4f0SJohnny Chen 47839d7d4f0SJohnny Chen // If we are using script language, get the script interpreter 47939d7d4f0SJohnny Chen // in order to set or collect command callback. Otherwise, call 48039d7d4f0SJohnny Chen // the methods associated with this object. 48130fdc8d8SChris Lattner if (m_options.m_use_script_language) 48230fdc8d8SChris Lattner { 483b5796cb4SJim Ingham ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter(); 48439d7d4f0SJohnny Chen // Special handling for one-liner specified inline. 48539d7d4f0SJohnny Chen if (m_options.m_use_one_liner) 4868d4a8010SEnrico Granata { 487b5796cb4SJim Ingham script_interp->SetBreakpointCommandCallback (m_bp_options_vec, 48839d7d4f0SJohnny Chen m_options.m_one_liner.c_str()); 4898d4a8010SEnrico Granata } 4908d4a8010SEnrico Granata else if (m_options.m_function_name.size()) 4918d4a8010SEnrico Granata { 492b5796cb4SJim Ingham script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec, 493d80102e4SJim Ingham m_options.m_function_name.c_str()); 4948d4a8010SEnrico Granata } 49594de55d5SJohnny Chen else 4968d4a8010SEnrico Granata { 497b5796cb4SJim Ingham script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec, 49830fdc8d8SChris Lattner result); 49930fdc8d8SChris Lattner } 5008d4a8010SEnrico Granata } 50130fdc8d8SChris Lattner else 50230fdc8d8SChris Lattner { 50339d7d4f0SJohnny Chen // Special handling for one-liner specified inline. 50439d7d4f0SJohnny Chen if (m_options.m_use_one_liner) 505b5796cb4SJim Ingham SetBreakpointCommandCallback (m_bp_options_vec, 50639d7d4f0SJohnny Chen m_options.m_one_liner.c_str()); 50739d7d4f0SJohnny Chen else 508b5796cb4SJim Ingham CollectDataForBreakpointCommandCallback (m_bp_options_vec, 509b132097bSGreg Clayton result); 51030fdc8d8SChris Lattner } 511b5796cb4SJim Ingham 51230fdc8d8SChris Lattner } 51330fdc8d8SChris Lattner 51430fdc8d8SChris Lattner return result.Succeeded(); 51530fdc8d8SChris Lattner } 51630fdc8d8SChris Lattner 5175a988416SJim Ingham private: 5185a988416SJim Ingham CommandOptions m_options; 519b5796cb4SJim Ingham std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the breakpoint options that we are currently 520b5796cb4SJim Ingham // collecting commands for. In the CollectData... calls we need 521b5796cb4SJim Ingham // to hand this off to the IOHandler, which may run asynchronously. 522b5796cb4SJim Ingham // So we have to have some way to keep it alive, and not leak it. 523b5796cb4SJim Ingham // Making it an ivar of the command object, which never goes away 524b5796cb4SJim Ingham // achieves this. Note that if we were able to run 525b5796cb4SJim Ingham // the same command concurrently in one interpreter we'd have to 526b5796cb4SJim Ingham // make this "per invocation". But there are many more reasons 527b5796cb4SJim Ingham // why it is not in general safe to do that in lldb at present, 528b5796cb4SJim Ingham // so it isn't worthwhile to come up with a more complex mechanism 529b5796cb4SJim Ingham // to address this particular weakness right now. 5305a988416SJim Ingham static const char *g_reader_instructions; 5315a988416SJim Ingham 5325a988416SJim Ingham }; 5335a988416SJim Ingham 5345a988416SJim Ingham const char * 53544d93782SGreg Clayton CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.\n"; 5365a988416SJim Ingham 5375a988416SJim Ingham // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting 5385a988416SJim Ingham // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper. 5395a988416SJim Ingham 5405a988416SJim Ingham static OptionEnumValueElement 5415a988416SJim Ingham g_script_option_enumeration[4] = 54230fdc8d8SChris Lattner { 5435a988416SJim Ingham { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"}, 5445a988416SJim Ingham { eScriptLanguagePython, "python", "Commands are in the Python language."}, 5455a988416SJim Ingham { eSortOrderByName, "default-script", "Commands are in the default scripting language."}, 5465a988416SJim Ingham { 0, NULL, NULL } 5475a988416SJim Ingham }; 54830fdc8d8SChris Lattner 5495a988416SJim Ingham OptionDefinition 5505a988416SJim Ingham CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] = 55130fdc8d8SChris Lattner { 552d37221dcSZachary Turner { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner, 5535a988416SJim Ingham "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, 55430fdc8d8SChris Lattner 555d37221dcSZachary Turner { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, 5565a988416SJim Ingham "Specify whether breakpoint command execution should terminate on error." }, 55730fdc8d8SChris Lattner 558d37221dcSZachary Turner { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone, 5595a988416SJim Ingham "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."}, 56030fdc8d8SChris Lattner 561d37221dcSZachary Turner { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, 5625a988416SJim Ingham "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."}, 56339d7d4f0SJohnny Chen 56433df7cd3SJim Ingham { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, 56533df7cd3SJim Ingham "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 56633df7cd3SJim Ingham 567d37221dcSZachary Turner { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 5685a988416SJim Ingham }; 56930fdc8d8SChris Lattner 57030fdc8d8SChris Lattner //------------------------------------------------------------------------- 57193e0f19fSCaroline Tice // CommandObjectBreakpointCommandDelete 57230fdc8d8SChris Lattner //------------------------------------------------------------------------- 57330fdc8d8SChris Lattner 5745a988416SJim Ingham class CommandObjectBreakpointCommandDelete : public CommandObjectParsed 5755a988416SJim Ingham { 5765a988416SJim Ingham public: 5775a988416SJim Ingham CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) : 5785a988416SJim Ingham CommandObjectParsed (interpreter, 57993e0f19fSCaroline Tice "delete", 58093e0f19fSCaroline Tice "Delete the set of commands from a breakpoint.", 58133df7cd3SJim Ingham NULL), 58233df7cd3SJim Ingham m_options (interpreter) 58330fdc8d8SChris Lattner { 584405fe67fSCaroline Tice CommandArgumentEntry arg; 585405fe67fSCaroline Tice CommandArgumentData bp_id_arg; 586405fe67fSCaroline Tice 587405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 588405fe67fSCaroline Tice bp_id_arg.arg_type = eArgTypeBreakpointID; 589405fe67fSCaroline Tice bp_id_arg.arg_repetition = eArgRepeatPlain; 590405fe67fSCaroline Tice 591405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 592405fe67fSCaroline Tice arg.push_back (bp_id_arg); 593405fe67fSCaroline Tice 594405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 595405fe67fSCaroline Tice m_arguments.push_back (arg); 59630fdc8d8SChris Lattner } 59730fdc8d8SChris Lattner 59830fdc8d8SChris Lattner 5995a988416SJim Ingham virtual 6005a988416SJim Ingham ~CommandObjectBreakpointCommandDelete () {} 6015a988416SJim Ingham 60233df7cd3SJim Ingham virtual Options * 60333df7cd3SJim Ingham GetOptions () 60433df7cd3SJim Ingham { 60533df7cd3SJim Ingham return &m_options; 60633df7cd3SJim Ingham } 60733df7cd3SJim Ingham 60833df7cd3SJim Ingham class CommandOptions : public Options 60933df7cd3SJim Ingham { 61033df7cd3SJim Ingham public: 61133df7cd3SJim Ingham 61233df7cd3SJim Ingham CommandOptions (CommandInterpreter &interpreter) : 61333df7cd3SJim Ingham Options (interpreter), 61433df7cd3SJim Ingham m_use_dummy (false) 61533df7cd3SJim Ingham { 61633df7cd3SJim Ingham } 61733df7cd3SJim Ingham 61833df7cd3SJim Ingham virtual 61933df7cd3SJim Ingham ~CommandOptions () {} 62033df7cd3SJim Ingham 62133df7cd3SJim Ingham virtual Error 62233df7cd3SJim Ingham SetOptionValue (uint32_t option_idx, const char *option_arg) 62333df7cd3SJim Ingham { 62433df7cd3SJim Ingham Error error; 62533df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 62633df7cd3SJim Ingham 62733df7cd3SJim Ingham switch (short_option) 62833df7cd3SJim Ingham { 62933df7cd3SJim Ingham case 'D': 63033df7cd3SJim Ingham m_use_dummy = true; 63133df7cd3SJim Ingham break; 63233df7cd3SJim Ingham 63333df7cd3SJim Ingham default: 63433df7cd3SJim Ingham error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 63533df7cd3SJim Ingham break; 63633df7cd3SJim Ingham } 63733df7cd3SJim Ingham 63833df7cd3SJim Ingham return error; 63933df7cd3SJim Ingham } 64033df7cd3SJim Ingham 64133df7cd3SJim Ingham void 64233df7cd3SJim Ingham OptionParsingStarting () 64333df7cd3SJim Ingham { 64433df7cd3SJim Ingham m_use_dummy = false; 64533df7cd3SJim Ingham } 64633df7cd3SJim Ingham 64733df7cd3SJim Ingham const OptionDefinition* 64833df7cd3SJim Ingham GetDefinitions () 64933df7cd3SJim Ingham { 65033df7cd3SJim Ingham return g_option_table; 65133df7cd3SJim Ingham } 65233df7cd3SJim Ingham 65333df7cd3SJim Ingham // Options table: Required for subclasses of Options. 65433df7cd3SJim Ingham 65533df7cd3SJim Ingham static OptionDefinition g_option_table[]; 65633df7cd3SJim Ingham 65733df7cd3SJim Ingham // Instance variables to hold the values for command options. 65833df7cd3SJim Ingham bool m_use_dummy; 65933df7cd3SJim Ingham }; 66033df7cd3SJim Ingham 6615a988416SJim Ingham protected: 6625a988416SJim Ingham virtual bool 6635a988416SJim Ingham DoExecute (Args& command, CommandReturnObject &result) 66430fdc8d8SChris Lattner { 66533df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 66630fdc8d8SChris Lattner 66730fdc8d8SChris Lattner if (target == NULL) 66830fdc8d8SChris Lattner { 66993e0f19fSCaroline Tice result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands"); 67030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 67130fdc8d8SChris Lattner return false; 67230fdc8d8SChris Lattner } 67330fdc8d8SChris Lattner 67430fdc8d8SChris Lattner const BreakpointList &breakpoints = target->GetBreakpointList(); 67530fdc8d8SChris Lattner size_t num_breakpoints = breakpoints.GetSize(); 67630fdc8d8SChris Lattner 67730fdc8d8SChris Lattner if (num_breakpoints == 0) 67830fdc8d8SChris Lattner { 67993e0f19fSCaroline Tice result.AppendError ("No breakpoints exist to have commands deleted"); 68030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 68130fdc8d8SChris Lattner return false; 68230fdc8d8SChris Lattner } 68330fdc8d8SChris Lattner 68430fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 68530fdc8d8SChris Lattner { 68693e0f19fSCaroline Tice result.AppendError ("No breakpoint specified from which to delete the commands"); 68730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 68830fdc8d8SChris Lattner return false; 68930fdc8d8SChris Lattner } 69030fdc8d8SChris Lattner 69130fdc8d8SChris Lattner BreakpointIDList valid_bp_ids; 6925e09c8c3SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 69330fdc8d8SChris Lattner 69430fdc8d8SChris Lattner if (result.Succeeded()) 69530fdc8d8SChris Lattner { 696c982c768SGreg Clayton const size_t count = valid_bp_ids.GetSize(); 697c982c768SGreg Clayton for (size_t i = 0; i < count; ++i) 69830fdc8d8SChris Lattner { 69930fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 70030fdc8d8SChris Lattner if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 70130fdc8d8SChris Lattner { 70230fdc8d8SChris Lattner Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 70330fdc8d8SChris Lattner if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 70430fdc8d8SChris Lattner { 70530fdc8d8SChris Lattner BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID())); 70630fdc8d8SChris Lattner if (bp_loc_sp) 70730fdc8d8SChris Lattner bp_loc_sp->ClearCallback(); 70830fdc8d8SChris Lattner else 70930fdc8d8SChris Lattner { 71030fdc8d8SChris Lattner result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 71130fdc8d8SChris Lattner cur_bp_id.GetBreakpointID(), 71230fdc8d8SChris Lattner cur_bp_id.GetLocationID()); 71330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 71430fdc8d8SChris Lattner return false; 71530fdc8d8SChris Lattner } 71630fdc8d8SChris Lattner } 71730fdc8d8SChris Lattner else 71830fdc8d8SChris Lattner { 71930fdc8d8SChris Lattner bp->ClearCallback(); 72030fdc8d8SChris Lattner } 72130fdc8d8SChris Lattner } 72230fdc8d8SChris Lattner } 72330fdc8d8SChris Lattner } 72430fdc8d8SChris Lattner return result.Succeeded(); 72530fdc8d8SChris Lattner } 72633df7cd3SJim Ingham private: 72733df7cd3SJim Ingham CommandOptions m_options; 7285a988416SJim Ingham }; 72930fdc8d8SChris Lattner 73033df7cd3SJim Ingham OptionDefinition 73133df7cd3SJim Ingham CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] = 73233df7cd3SJim Ingham { 73333df7cd3SJim Ingham { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, 73433df7cd3SJim Ingham "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 73533df7cd3SJim Ingham 73633df7cd3SJim Ingham { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 73733df7cd3SJim Ingham }; 73833df7cd3SJim Ingham 73933df7cd3SJim Ingham 74030fdc8d8SChris Lattner //------------------------------------------------------------------------- 74130fdc8d8SChris Lattner // CommandObjectBreakpointCommandList 74230fdc8d8SChris Lattner //------------------------------------------------------------------------- 74330fdc8d8SChris Lattner 7445a988416SJim Ingham class CommandObjectBreakpointCommandList : public CommandObjectParsed 7455a988416SJim Ingham { 7465a988416SJim Ingham public: 7475a988416SJim Ingham CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) : 7485a988416SJim Ingham CommandObjectParsed (interpreter, 749a7015092SGreg Clayton "list", 75030fdc8d8SChris Lattner "List the script or set of commands to be executed when the breakpoint is hit.", 751405fe67fSCaroline Tice NULL) 75230fdc8d8SChris Lattner { 753405fe67fSCaroline Tice CommandArgumentEntry arg; 754405fe67fSCaroline Tice CommandArgumentData bp_id_arg; 755405fe67fSCaroline Tice 756405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 757405fe67fSCaroline Tice bp_id_arg.arg_type = eArgTypeBreakpointID; 758405fe67fSCaroline Tice bp_id_arg.arg_repetition = eArgRepeatPlain; 759405fe67fSCaroline Tice 760405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 761405fe67fSCaroline Tice arg.push_back (bp_id_arg); 762405fe67fSCaroline Tice 763405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 764405fe67fSCaroline Tice m_arguments.push_back (arg); 76530fdc8d8SChris Lattner } 76630fdc8d8SChris Lattner 7675a988416SJim Ingham virtual 7685a988416SJim Ingham ~CommandObjectBreakpointCommandList () {} 76930fdc8d8SChris Lattner 7705a988416SJim Ingham protected: 7715a988416SJim Ingham virtual bool 7725a988416SJim Ingham DoExecute (Args& command, 7735a988416SJim Ingham CommandReturnObject &result) 77430fdc8d8SChris Lattner { 775a7015092SGreg Clayton Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 77630fdc8d8SChris Lattner 77730fdc8d8SChris Lattner if (target == NULL) 77830fdc8d8SChris Lattner { 77930fdc8d8SChris Lattner result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands"); 78030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 78130fdc8d8SChris Lattner return false; 78230fdc8d8SChris Lattner } 78330fdc8d8SChris Lattner 78430fdc8d8SChris Lattner const BreakpointList &breakpoints = target->GetBreakpointList(); 78530fdc8d8SChris Lattner size_t num_breakpoints = breakpoints.GetSize(); 78630fdc8d8SChris Lattner 78730fdc8d8SChris Lattner if (num_breakpoints == 0) 78830fdc8d8SChris Lattner { 78930fdc8d8SChris Lattner result.AppendError ("No breakpoints exist for which to list commands"); 79030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 79130fdc8d8SChris Lattner return false; 79230fdc8d8SChris Lattner } 79330fdc8d8SChris Lattner 79430fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 79530fdc8d8SChris Lattner { 79630fdc8d8SChris Lattner result.AppendError ("No breakpoint specified for which to list the commands"); 79730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 79830fdc8d8SChris Lattner return false; 79930fdc8d8SChris Lattner } 80030fdc8d8SChris Lattner 80130fdc8d8SChris Lattner BreakpointIDList valid_bp_ids; 8025e09c8c3SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 80330fdc8d8SChris Lattner 80430fdc8d8SChris Lattner if (result.Succeeded()) 80530fdc8d8SChris Lattner { 806c982c768SGreg Clayton const size_t count = valid_bp_ids.GetSize(); 807c982c768SGreg Clayton for (size_t i = 0; i < count; ++i) 80830fdc8d8SChris Lattner { 80930fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 81030fdc8d8SChris Lattner if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 81130fdc8d8SChris Lattner { 81230fdc8d8SChris Lattner Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 81330fdc8d8SChris Lattner 81430fdc8d8SChris Lattner if (bp) 81530fdc8d8SChris Lattner { 8161b54c88cSJim Ingham const BreakpointOptions *bp_options = NULL; 81730fdc8d8SChris Lattner if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 81830fdc8d8SChris Lattner { 81930fdc8d8SChris Lattner BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); 82030fdc8d8SChris Lattner if (bp_loc_sp) 82105407f6bSJim Ingham bp_options = bp_loc_sp->GetOptionsNoCreate(); 82230fdc8d8SChris Lattner else 82330fdc8d8SChris Lattner { 82430fdc8d8SChris Lattner result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 82530fdc8d8SChris Lattner cur_bp_id.GetBreakpointID(), 82630fdc8d8SChris Lattner cur_bp_id.GetLocationID()); 82730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 82830fdc8d8SChris Lattner return false; 82930fdc8d8SChris Lattner } 83030fdc8d8SChris Lattner } 83130fdc8d8SChris Lattner else 83230fdc8d8SChris Lattner { 83330fdc8d8SChris Lattner bp_options = bp->GetOptions(); 83430fdc8d8SChris Lattner } 83530fdc8d8SChris Lattner 83630fdc8d8SChris Lattner if (bp_options) 83730fdc8d8SChris Lattner { 83830fdc8d8SChris Lattner StreamString id_str; 839e16c50a1SJim Ingham BreakpointID::GetCanonicalReference (&id_str, 840e16c50a1SJim Ingham cur_bp_id.GetBreakpointID(), 841e16c50a1SJim Ingham cur_bp_id.GetLocationID()); 8421b54c88cSJim Ingham const Baton *baton = bp_options->GetBaton(); 84330fdc8d8SChris Lattner if (baton) 84430fdc8d8SChris Lattner { 84530fdc8d8SChris Lattner result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData()); 84630fdc8d8SChris Lattner result.GetOutputStream().IndentMore (); 84730fdc8d8SChris Lattner baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull); 84830fdc8d8SChris Lattner result.GetOutputStream().IndentLess (); 84930fdc8d8SChris Lattner } 85030fdc8d8SChris Lattner else 85130fdc8d8SChris Lattner { 852e16c50a1SJim Ingham result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", 853e16c50a1SJim Ingham id_str.GetData()); 85430fdc8d8SChris Lattner } 85530fdc8d8SChris Lattner } 85630fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 85730fdc8d8SChris Lattner } 85830fdc8d8SChris Lattner else 85930fdc8d8SChris Lattner { 86030fdc8d8SChris Lattner result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID()); 86130fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 86230fdc8d8SChris Lattner } 86330fdc8d8SChris Lattner 86430fdc8d8SChris Lattner } 86530fdc8d8SChris Lattner } 86630fdc8d8SChris Lattner } 86730fdc8d8SChris Lattner 86830fdc8d8SChris Lattner return result.Succeeded(); 86930fdc8d8SChris Lattner } 8705a988416SJim Ingham }; 87130fdc8d8SChris Lattner 87230fdc8d8SChris Lattner //------------------------------------------------------------------------- 87330fdc8d8SChris Lattner // CommandObjectBreakpointCommand 87430fdc8d8SChris Lattner //------------------------------------------------------------------------- 87530fdc8d8SChris Lattner 8766611103cSGreg Clayton CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) : 877a7015092SGreg Clayton CommandObjectMultiword (interpreter, 878a7015092SGreg Clayton "command", 8797050e0b1SSean Callanan "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').", 88030fdc8d8SChris Lattner "command <sub-command> [<sub-command-options>] <breakpoint-id>") 88130fdc8d8SChris Lattner { 882a7015092SGreg Clayton CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter)); 88393e0f19fSCaroline Tice CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter)); 884a7015092SGreg Clayton CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter)); 88530fdc8d8SChris Lattner 88630fdc8d8SChris Lattner add_command_object->SetCommandName ("breakpoint command add"); 88793e0f19fSCaroline Tice delete_command_object->SetCommandName ("breakpoint command delete"); 88830fdc8d8SChris Lattner list_command_object->SetCommandName ("breakpoint command list"); 88930fdc8d8SChris Lattner 89023f59509SGreg Clayton LoadSubCommand ("add", add_command_object); 89123f59509SGreg Clayton LoadSubCommand ("delete", delete_command_object); 89223f59509SGreg Clayton LoadSubCommand ("list", list_command_object); 89330fdc8d8SChris Lattner } 89430fdc8d8SChris Lattner 89530fdc8d8SChris Lattner CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand () 89630fdc8d8SChris Lattner { 89730fdc8d8SChris Lattner } 89830fdc8d8SChris Lattner 89930fdc8d8SChris Lattner 900