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 12*c8ecc2a9SEugene Zelenko // Other libraries and framework includes 13*c8ecc2a9SEugene Zelenko // Project includes 1430fdc8d8SChris Lattner #include "CommandObjectBreakpointCommand.h" 1530fdc8d8SChris Lattner #include "CommandObjectBreakpoint.h" 1644d93782SGreg Clayton #include "lldb/Core/IOHandler.h" 1730fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h" 1830fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 1930fdc8d8SChris Lattner #include "lldb/Target/Target.h" 2030fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2130fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h" 2230fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h" 2330fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h" 2430fdc8d8SChris Lattner #include "lldb/Breakpoint/StoppointCallbackContext.h" 2530fdc8d8SChris Lattner #include "lldb/Core/State.h" 2630fdc8d8SChris Lattner 2730fdc8d8SChris Lattner using namespace lldb; 2830fdc8d8SChris Lattner using namespace lldb_private; 2930fdc8d8SChris Lattner 3030fdc8d8SChris Lattner //------------------------------------------------------------------------- 3130fdc8d8SChris Lattner // CommandObjectBreakpointCommandAdd 3230fdc8d8SChris Lattner //------------------------------------------------------------------------- 3330fdc8d8SChris Lattner 3444d93782SGreg Clayton class CommandObjectBreakpointCommandAdd : 3544d93782SGreg Clayton public CommandObjectParsed, 3644d93782SGreg Clayton public IOHandlerDelegateMultiline 375a988416SJim Ingham { 385a988416SJim Ingham public: 395a988416SJim Ingham CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) : 405a988416SJim Ingham CommandObjectParsed(interpreter, 41a7015092SGreg Clayton "add", 421bb0750bSJim Ingham "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit." 431bb0750bSJim Ingham " If no breakpoint is specified, adds the commands to the last created breakpoint.", 44*c8ecc2a9SEugene Zelenko nullptr), 45c3d874a5SGreg Clayton IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand), 46eb0103f2SGreg Clayton m_options (interpreter) 4730fdc8d8SChris Lattner { 4830fdc8d8SChris Lattner SetHelpLong ( 49ea671fbdSKate Stone R"( 50ea671fbdSKate Stone General information about entering breakpoint commands 51ea671fbdSKate Stone ------------------------------------------------------ 52ea671fbdSKate Stone 53ea671fbdSKate Stone )" "This command will prompt for commands to be executed when the specified \ 54ea671fbdSKate Stone breakpoint is hit. Each command is typed on its own line following the '> ' \ 55ea671fbdSKate Stone prompt until 'DONE' is entered." R"( 56ea671fbdSKate Stone 57ea671fbdSKate Stone )" "Syntactic errors may not be detected when initially entered, and many \ 58ea671fbdSKate Stone malformed commands can silently fail when executed. If your breakpoint commands \ 59ea671fbdSKate Stone do not appear to be executing, double-check the command syntax." R"( 60ea671fbdSKate Stone 61ea671fbdSKate Stone )" "Note: You may enter any debugger command exactly as you would at the debugger \ 62ea671fbdSKate Stone prompt. There is no limit to the number of commands supplied, but do NOT enter \ 63ea671fbdSKate Stone more than one command per line." R"( 64ea671fbdSKate Stone 65ea671fbdSKate Stone Special information about PYTHON breakpoint commands 66ea671fbdSKate Stone ---------------------------------------------------- 67ea671fbdSKate Stone 68ea671fbdSKate Stone )" "You may enter either one or more lines of Python, including function \ 69ea671fbdSKate Stone definitions or calls to functions that will have been imported by the time \ 70ea671fbdSKate Stone the code executes. Single line breakpoint commands will be interpreted 'as is' \ 71ea671fbdSKate Stone when the breakpoint is hit. Multiple lines of Python will be wrapped in a \ 72ea671fbdSKate Stone generated function, and a call to the function will be attached to the breakpoint." R"( 73ea671fbdSKate Stone 74ea671fbdSKate Stone This auto-generated function is passed in three arguments: 75ea671fbdSKate Stone 76ea671fbdSKate Stone frame: an lldb.SBFrame object for the frame which hit breakpoint. 77ea671fbdSKate Stone 78ea671fbdSKate Stone bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit. 79ea671fbdSKate Stone 80ea671fbdSKate Stone dict: the python session dictionary hit. 81ea671fbdSKate Stone 82ea671fbdSKate Stone )" "When specifying a python function with the --python-function option, you need \ 83ea671fbdSKate Stone to supply the function name prepended by the module name:" R"( 84ea671fbdSKate Stone 85ea671fbdSKate Stone --python-function myutils.breakpoint_callback 86ea671fbdSKate Stone 87ea671fbdSKate Stone The function itself must have the following prototype: 88ea671fbdSKate Stone 89ea671fbdSKate Stone def breakpoint_callback(frame, bp_loc, dict): 90ea671fbdSKate Stone # Your code goes here 91ea671fbdSKate Stone 92ea671fbdSKate Stone )" "The arguments are the same as the arguments passed to generated functions as \ 93ea671fbdSKate Stone described above. Note that the global variable 'lldb.frame' will NOT be updated when \ 94ea671fbdSKate Stone this function is called, so be sure to use the 'frame' argument. The 'frame' argument \ 95ea671fbdSKate Stone can get you to the thread via frame.GetThread(), the thread can get you to the \ 96ea671fbdSKate Stone process via thread.GetProcess(), and the process can get you back to the target \ 97ea671fbdSKate Stone via process.GetTarget()." R"( 98ea671fbdSKate Stone 99ea671fbdSKate Stone )" "Important Note: As Python code gets collected into functions, access to global \ 100ea671fbdSKate Stone variables requires explicit scoping using the 'global' keyword. Be sure to use correct \ 101ea671fbdSKate Stone Python syntax, including indentation, when entering Python breakpoint commands." R"( 102ea671fbdSKate Stone 103ea671fbdSKate Stone Example Python one-line breakpoint command: 104ea671fbdSKate Stone 105ea671fbdSKate Stone (lldb) breakpoint command add -s python 1 106ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end. 107ea671fbdSKate Stone > print "Hit this breakpoint!" 108ea671fbdSKate Stone > DONE 109ea671fbdSKate Stone 110ea671fbdSKate Stone As a convenience, this also works for a short Python one-liner: 111ea671fbdSKate Stone 112ea671fbdSKate Stone (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()' 113ea671fbdSKate Stone (lldb) run 114ea671fbdSKate Stone Launching '.../a.out' (x86_64) 115ea671fbdSKate Stone (lldb) Fri Sep 10 12:17:45 2010 116ea671fbdSKate Stone Process 21778 Stopped 117ea671fbdSKate Stone * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread 118ea671fbdSKate Stone 36 119ea671fbdSKate Stone 37 int c(int val) 120ea671fbdSKate Stone 38 { 121ea671fbdSKate Stone 39 -> return val + 3; 122ea671fbdSKate Stone 40 } 123ea671fbdSKate Stone 41 124ea671fbdSKate Stone 42 int main (int argc, char const *argv[]) 125ea671fbdSKate Stone 126ea671fbdSKate Stone Example multiple line Python breakpoint command: 127ea671fbdSKate Stone 128ea671fbdSKate Stone (lldb) breakpoint command add -s p 1 129ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end. 130ea671fbdSKate Stone > global bp_count 131ea671fbdSKate Stone > bp_count = bp_count + 1 132ea671fbdSKate Stone > print "Hit this breakpoint " + repr(bp_count) + " times!" 133ea671fbdSKate Stone > DONE 134ea671fbdSKate Stone 135ea671fbdSKate Stone Example multiple line Python breakpoint command, using function definition: 136ea671fbdSKate Stone 137ea671fbdSKate Stone (lldb) breakpoint command add -s python 1 138ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end. 139ea671fbdSKate Stone > def breakpoint_output (bp_no): 140ea671fbdSKate Stone > out_string = "Hit breakpoint number " + repr (bp_no) 141ea671fbdSKate Stone > print out_string 142ea671fbdSKate Stone > return True 143ea671fbdSKate Stone > breakpoint_output (1) 144ea671fbdSKate Stone > DONE 145ea671fbdSKate Stone 146ea671fbdSKate Stone )" "In this case, since there is a reference to a global variable, \ 147ea671fbdSKate Stone 'bp_count', you will also need to make sure 'bp_count' exists and is \ 148ea671fbdSKate Stone initialized:" R"( 149ea671fbdSKate Stone 150ea671fbdSKate Stone (lldb) script 151ea671fbdSKate Stone >>> bp_count = 0 152ea671fbdSKate Stone >>> quit() 153ea671fbdSKate Stone 154ea671fbdSKate Stone )" "Your Python code, however organized, can optionally return a value. \ 155ea671fbdSKate Stone If the returned value is False, that tells LLDB not to stop at the breakpoint \ 156ea671fbdSKate Stone to which the code is associated. Returning anything other than False, or even \ 157ea671fbdSKate Stone returning None, or even omitting a return statement entirely, will cause \ 158ea671fbdSKate Stone LLDB to stop." R"( 159ea671fbdSKate Stone 160ea671fbdSKate Stone )" "Final Note: A warning that no breakpoint command was generated when there \ 161ea671fbdSKate Stone are no syntax errors may indicate that a function was declared but never called." 162ea671fbdSKate Stone ); 163405fe67fSCaroline Tice 164405fe67fSCaroline Tice CommandArgumentEntry arg; 165405fe67fSCaroline Tice CommandArgumentData bp_id_arg; 166405fe67fSCaroline Tice 167405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 168405fe67fSCaroline Tice bp_id_arg.arg_type = eArgTypeBreakpointID; 1691bb0750bSJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 170405fe67fSCaroline Tice 171405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 172405fe67fSCaroline Tice arg.push_back (bp_id_arg); 173405fe67fSCaroline Tice 174405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 175405fe67fSCaroline Tice m_arguments.push_back (arg); 17630fdc8d8SChris Lattner } 17730fdc8d8SChris Lattner 178*c8ecc2a9SEugene Zelenko ~CommandObjectBreakpointCommandAdd() override = default; 1795a988416SJim Ingham 18013d21e9aSBruce Mitchener Options * 18113d21e9aSBruce Mitchener GetOptions () override 1825a988416SJim Ingham { 1835a988416SJim Ingham return &m_options; 1845a988416SJim Ingham } 1855a988416SJim Ingham 18613d21e9aSBruce Mitchener void 18713d21e9aSBruce Mitchener IOHandlerActivated (IOHandler &io_handler) override 18844d93782SGreg Clayton { 18944d93782SGreg Clayton StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 19044d93782SGreg Clayton if (output_sp) 19144d93782SGreg Clayton { 19244d93782SGreg Clayton output_sp->PutCString(g_reader_instructions); 19344d93782SGreg Clayton output_sp->Flush(); 19444d93782SGreg Clayton } 19544d93782SGreg Clayton } 19644d93782SGreg Clayton 19713d21e9aSBruce Mitchener void 19813d21e9aSBruce Mitchener IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override 19944d93782SGreg Clayton { 20044d93782SGreg Clayton io_handler.SetIsDone(true); 20144d93782SGreg Clayton 202b5796cb4SJim Ingham std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData(); 203b5796cb4SJim Ingham for (BreakpointOptions *bp_options : *bp_options_vec) 20444d93782SGreg Clayton { 205b5796cb4SJim Ingham if (!bp_options) 206b5796cb4SJim Ingham continue; 207b5796cb4SJim Ingham 20844d93782SGreg Clayton std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); 209*c8ecc2a9SEugene Zelenko if (data_ap) 21044d93782SGreg Clayton { 21144d93782SGreg Clayton data_ap->user_source.SplitIntoLines (line.c_str(), line.size()); 21244d93782SGreg Clayton BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); 21344d93782SGreg Clayton bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp); 21444d93782SGreg Clayton } 21544d93782SGreg Clayton } 21644d93782SGreg Clayton } 21744d93782SGreg Clayton 2185a988416SJim Ingham void 219b5796cb4SJim Ingham CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec, 2205a988416SJim Ingham CommandReturnObject &result) 2215a988416SJim Ingham { 22244d93782SGreg Clayton m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt 22344d93782SGreg Clayton *this, // IOHandlerDelegate 22444d93782SGreg Clayton true, // Run IOHandler in async mode 225b5796cb4SJim Ingham &bp_options_vec); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 2265a988416SJim Ingham } 2275a988416SJim Ingham 2285a988416SJim Ingham /// Set a one-liner as the callback for the breakpoint. 2295a988416SJim Ingham void 230b5796cb4SJim Ingham SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec, 2315a988416SJim Ingham const char *oneliner) 2325a988416SJim Ingham { 233b5796cb4SJim Ingham for (auto bp_options : bp_options_vec) 234b5796cb4SJim Ingham { 2357b0992d9SGreg Clayton std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); 2365a988416SJim Ingham 2375a988416SJim Ingham // It's necessary to set both user_source and script_source to the oneliner. 2385a988416SJim Ingham // The former is used to generate callback description (as in breakpoint command list) 2395a988416SJim Ingham // while the latter is used for Python to interpret during the actual callback. 2405a988416SJim Ingham data_ap->user_source.AppendString (oneliner); 2415a988416SJim Ingham data_ap->script_source.assign (oneliner); 2425a988416SJim Ingham data_ap->stop_on_error = m_options.m_stop_on_error; 2435a988416SJim Ingham 2445a988416SJim Ingham BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); 2455a988416SJim Ingham bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp); 246b5796cb4SJim Ingham } 2475a988416SJim Ingham } 2485a988416SJim Ingham 2495a988416SJim Ingham static bool 2505a988416SJim Ingham BreakpointOptionsCallbackFunction (void *baton, 2515a988416SJim Ingham StoppointCallbackContext *context, 2525a988416SJim Ingham lldb::user_id_t break_id, 2535a988416SJim Ingham lldb::user_id_t break_loc_id) 2545a988416SJim Ingham { 2555a988416SJim Ingham bool ret_value = true; 256*c8ecc2a9SEugene Zelenko if (baton == nullptr) 2575a988416SJim Ingham return true; 2585a988416SJim Ingham 2595a988416SJim Ingham BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton; 2605a988416SJim Ingham StringList &commands = data->user_source; 2615a988416SJim Ingham 2625a988416SJim Ingham if (commands.GetSize() > 0) 2635a988416SJim Ingham { 2645a988416SJim Ingham ExecutionContext exe_ctx (context->exe_ctx_ref); 2655a988416SJim Ingham Target *target = exe_ctx.GetTargetPtr(); 2665a988416SJim Ingham if (target) 2675a988416SJim Ingham { 2685a988416SJim Ingham CommandReturnObject result; 2695a988416SJim Ingham Debugger &debugger = target->GetDebugger(); 2705a988416SJim Ingham // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously 2715a988416SJim Ingham // if the debugger is set up that way. 2725a988416SJim Ingham 2735a988416SJim Ingham StreamSP output_stream (debugger.GetAsyncOutputStream()); 2745a988416SJim Ingham StreamSP error_stream (debugger.GetAsyncErrorStream()); 2755a988416SJim Ingham result.SetImmediateOutputStream (output_stream); 2765a988416SJim Ingham result.SetImmediateErrorStream (error_stream); 2775a988416SJim Ingham 27826c7bf93SJim Ingham CommandInterpreterRunOptions options; 27926c7bf93SJim Ingham options.SetStopOnContinue(true); 28026c7bf93SJim Ingham options.SetStopOnError (data->stop_on_error); 28126c7bf93SJim Ingham options.SetEchoCommands (true); 28226c7bf93SJim Ingham options.SetPrintResults (true); 28326c7bf93SJim Ingham options.SetAddToHistory (false); 2845a988416SJim Ingham 2855a988416SJim Ingham debugger.GetCommandInterpreter().HandleCommands (commands, 2865a988416SJim Ingham &exe_ctx, 28726c7bf93SJim Ingham options, 2885a988416SJim Ingham result); 2895a988416SJim Ingham result.GetImmediateOutputStream()->Flush(); 2905a988416SJim Ingham result.GetImmediateErrorStream()->Flush(); 2915a988416SJim Ingham } 2925a988416SJim Ingham } 2935a988416SJim Ingham return ret_value; 2945a988416SJim Ingham } 2955a988416SJim Ingham 2965a988416SJim Ingham class CommandOptions : public Options 2975a988416SJim Ingham { 2985a988416SJim Ingham public: 2995a988416SJim Ingham CommandOptions (CommandInterpreter &interpreter) : 3005a988416SJim Ingham Options (interpreter), 3015a988416SJim Ingham m_use_commands (false), 3025a988416SJim Ingham m_use_script_language (false), 3035a988416SJim Ingham m_script_language (eScriptLanguageNone), 3045a988416SJim Ingham m_use_one_liner (false), 3055a988416SJim Ingham m_one_liner(), 3065a988416SJim Ingham m_function_name() 30730fdc8d8SChris Lattner { 30830fdc8d8SChris Lattner } 30930fdc8d8SChris Lattner 310*c8ecc2a9SEugene Zelenko ~CommandOptions() override = default; 3115a988416SJim Ingham 31213d21e9aSBruce Mitchener Error 31313d21e9aSBruce Mitchener SetOptionValue (uint32_t option_idx, const char *option_arg) override 3145a988416SJim Ingham { 3155a988416SJim Ingham Error error; 3163bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 3175a988416SJim Ingham 3185a988416SJim Ingham switch (short_option) 3195a988416SJim Ingham { 3205a988416SJim Ingham case 'o': 3215a988416SJim Ingham m_use_one_liner = true; 3225a988416SJim Ingham m_one_liner = option_arg; 3235a988416SJim Ingham break; 3245a988416SJim Ingham 3255a988416SJim Ingham case 's': 3265a988416SJim Ingham m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg, 3275a988416SJim Ingham g_option_table[option_idx].enum_values, 3285a988416SJim Ingham eScriptLanguageNone, 3295a988416SJim Ingham error); 3305a988416SJim Ingham 3315a988416SJim Ingham if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault) 3325a988416SJim Ingham { 3335a988416SJim Ingham m_use_script_language = true; 3345a988416SJim Ingham } 3355a988416SJim Ingham else 3365a988416SJim Ingham { 3375a988416SJim Ingham m_use_script_language = false; 3385a988416SJim Ingham } 3395a988416SJim Ingham break; 3405a988416SJim Ingham 3415a988416SJim Ingham case 'e': 3425a988416SJim Ingham { 3435a988416SJim Ingham bool success = false; 3445a988416SJim Ingham m_stop_on_error = Args::StringToBoolean(option_arg, false, &success); 3455a988416SJim Ingham if (!success) 3465a988416SJim Ingham error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg); 3475a988416SJim Ingham } 3485a988416SJim Ingham break; 3495a988416SJim Ingham 3505a988416SJim Ingham case 'F': 3515a988416SJim Ingham m_use_one_liner = false; 3525a988416SJim Ingham m_use_script_language = true; 3535a988416SJim Ingham m_function_name.assign(option_arg); 3545a988416SJim Ingham break; 3555a988416SJim Ingham 35633df7cd3SJim Ingham case 'D': 35733df7cd3SJim Ingham m_use_dummy = true; 35833df7cd3SJim Ingham break; 35933df7cd3SJim Ingham 3605a988416SJim Ingham default: 3615a988416SJim Ingham break; 3625a988416SJim Ingham } 3635a988416SJim Ingham return error; 3645a988416SJim Ingham } 365*c8ecc2a9SEugene Zelenko 3665a988416SJim Ingham void 36713d21e9aSBruce Mitchener OptionParsingStarting () override 3685a988416SJim Ingham { 3695a988416SJim Ingham m_use_commands = true; 3705a988416SJim Ingham m_use_script_language = false; 3715a988416SJim Ingham m_script_language = eScriptLanguageNone; 3725a988416SJim Ingham 3735a988416SJim Ingham m_use_one_liner = false; 3745a988416SJim Ingham m_stop_on_error = true; 3755a988416SJim Ingham m_one_liner.clear(); 3765a988416SJim Ingham m_function_name.clear(); 37733df7cd3SJim Ingham m_use_dummy = false; 3785a988416SJim Ingham } 3795a988416SJim Ingham 3805a988416SJim Ingham const OptionDefinition* 38113d21e9aSBruce Mitchener GetDefinitions () override 3825a988416SJim Ingham { 3835a988416SJim Ingham return g_option_table; 3845a988416SJim Ingham } 3855a988416SJim Ingham 3865a988416SJim Ingham // Options table: Required for subclasses of Options. 3875a988416SJim Ingham 3885a988416SJim Ingham static OptionDefinition g_option_table[]; 3895a988416SJim Ingham 3905a988416SJim Ingham // Instance variables to hold the values for command options. 3915a988416SJim Ingham 3925a988416SJim Ingham bool m_use_commands; 3935a988416SJim Ingham bool m_use_script_language; 3945a988416SJim Ingham lldb::ScriptLanguage m_script_language; 3955a988416SJim Ingham 3965a988416SJim Ingham // Instance variables to hold the values for one_liner options. 3975a988416SJim Ingham bool m_use_one_liner; 3985a988416SJim Ingham std::string m_one_liner; 3995a988416SJim Ingham bool m_stop_on_error; 4005a988416SJim Ingham std::string m_function_name; 40133df7cd3SJim Ingham bool m_use_dummy; 4025a988416SJim Ingham }; 4035a988416SJim Ingham 4045a988416SJim Ingham protected: 40513d21e9aSBruce Mitchener bool 40613d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 40730fdc8d8SChris Lattner { 40833df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 40930fdc8d8SChris Lattner 410*c8ecc2a9SEugene Zelenko if (target == nullptr) 41130fdc8d8SChris Lattner { 41230fdc8d8SChris Lattner result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands"); 41330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 41430fdc8d8SChris Lattner return false; 41530fdc8d8SChris Lattner } 41630fdc8d8SChris Lattner 41730fdc8d8SChris Lattner const BreakpointList &breakpoints = target->GetBreakpointList(); 41830fdc8d8SChris Lattner size_t num_breakpoints = breakpoints.GetSize(); 41930fdc8d8SChris Lattner 42030fdc8d8SChris Lattner if (num_breakpoints == 0) 42130fdc8d8SChris Lattner { 42230fdc8d8SChris Lattner result.AppendError ("No breakpoints exist to have commands added"); 42330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 42430fdc8d8SChris Lattner return false; 42530fdc8d8SChris Lattner } 42630fdc8d8SChris Lattner 427*c8ecc2a9SEugene Zelenko if (!m_options.m_use_script_language && !m_options.m_function_name.empty()) 4288d4a8010SEnrico Granata { 4298d4a8010SEnrico Granata result.AppendError ("need to enable scripting to have a function run as a breakpoint command"); 4308d4a8010SEnrico Granata result.SetStatus (eReturnStatusFailed); 4318d4a8010SEnrico Granata return false; 4328d4a8010SEnrico Granata } 4338d4a8010SEnrico Granata 43430fdc8d8SChris Lattner BreakpointIDList valid_bp_ids; 4355e09c8c3SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 43630fdc8d8SChris Lattner 437b5796cb4SJim Ingham m_bp_options_vec.clear(); 438b5796cb4SJim Ingham 43930fdc8d8SChris Lattner if (result.Succeeded()) 44030fdc8d8SChris Lattner { 441c982c768SGreg Clayton const size_t count = valid_bp_ids.GetSize(); 442d9916eaeSJim Ingham 443c982c768SGreg Clayton for (size_t i = 0; i < count; ++i) 44430fdc8d8SChris Lattner { 44530fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 44630fdc8d8SChris Lattner if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 44730fdc8d8SChris Lattner { 44830fdc8d8SChris Lattner Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 449*c8ecc2a9SEugene Zelenko BreakpointOptions *bp_options = nullptr; 45039d7d4f0SJohnny Chen if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) 45139d7d4f0SJohnny Chen { 45239d7d4f0SJohnny Chen // This breakpoint does not have an associated location. 45339d7d4f0SJohnny Chen bp_options = bp->GetOptions(); 45439d7d4f0SJohnny Chen } 45539d7d4f0SJohnny Chen else 45630fdc8d8SChris Lattner { 45730fdc8d8SChris Lattner BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); 45839d7d4f0SJohnny Chen // This breakpoint does have an associated location. 45939d7d4f0SJohnny Chen // Get its breakpoint options. 46030fdc8d8SChris Lattner if (bp_loc_sp) 46139d7d4f0SJohnny Chen bp_options = bp_loc_sp->GetLocationOptions(); 46239d7d4f0SJohnny Chen } 463b5796cb4SJim Ingham if (bp_options) 464b5796cb4SJim Ingham m_bp_options_vec.push_back (bp_options); 465b5796cb4SJim Ingham } 466b5796cb4SJim Ingham } 46739d7d4f0SJohnny Chen 46839d7d4f0SJohnny Chen // If we are using script language, get the script interpreter 46939d7d4f0SJohnny Chen // in order to set or collect command callback. Otherwise, call 47039d7d4f0SJohnny Chen // the methods associated with this object. 47130fdc8d8SChris Lattner if (m_options.m_use_script_language) 47230fdc8d8SChris Lattner { 473b5796cb4SJim Ingham ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter(); 47439d7d4f0SJohnny Chen // Special handling for one-liner specified inline. 47539d7d4f0SJohnny Chen if (m_options.m_use_one_liner) 4768d4a8010SEnrico Granata { 477b5796cb4SJim Ingham script_interp->SetBreakpointCommandCallback (m_bp_options_vec, 47839d7d4f0SJohnny Chen m_options.m_one_liner.c_str()); 4798d4a8010SEnrico Granata } 480*c8ecc2a9SEugene Zelenko else if (!m_options.m_function_name.empty()) 4818d4a8010SEnrico Granata { 482b5796cb4SJim Ingham script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec, 483d80102e4SJim Ingham m_options.m_function_name.c_str()); 4848d4a8010SEnrico Granata } 48594de55d5SJohnny Chen else 4868d4a8010SEnrico Granata { 487b5796cb4SJim Ingham script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec, 48830fdc8d8SChris Lattner result); 48930fdc8d8SChris Lattner } 4908d4a8010SEnrico Granata } 49130fdc8d8SChris Lattner else 49230fdc8d8SChris Lattner { 49339d7d4f0SJohnny Chen // Special handling for one-liner specified inline. 49439d7d4f0SJohnny Chen if (m_options.m_use_one_liner) 495b5796cb4SJim Ingham SetBreakpointCommandCallback (m_bp_options_vec, 49639d7d4f0SJohnny Chen m_options.m_one_liner.c_str()); 49739d7d4f0SJohnny Chen else 498b5796cb4SJim Ingham CollectDataForBreakpointCommandCallback (m_bp_options_vec, 499b132097bSGreg Clayton result); 50030fdc8d8SChris Lattner } 50130fdc8d8SChris Lattner } 50230fdc8d8SChris Lattner 50330fdc8d8SChris Lattner return result.Succeeded(); 50430fdc8d8SChris Lattner } 50530fdc8d8SChris Lattner 5065a988416SJim Ingham private: 5075a988416SJim Ingham CommandOptions m_options; 508b5796cb4SJim Ingham std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the breakpoint options that we are currently 509b5796cb4SJim Ingham // collecting commands for. In the CollectData... calls we need 510b5796cb4SJim Ingham // to hand this off to the IOHandler, which may run asynchronously. 511b5796cb4SJim Ingham // So we have to have some way to keep it alive, and not leak it. 512b5796cb4SJim Ingham // Making it an ivar of the command object, which never goes away 513b5796cb4SJim Ingham // achieves this. Note that if we were able to run 514b5796cb4SJim Ingham // the same command concurrently in one interpreter we'd have to 515b5796cb4SJim Ingham // make this "per invocation". But there are many more reasons 516b5796cb4SJim Ingham // why it is not in general safe to do that in lldb at present, 517b5796cb4SJim Ingham // so it isn't worthwhile to come up with a more complex mechanism 518b5796cb4SJim Ingham // to address this particular weakness right now. 5195a988416SJim Ingham static const char *g_reader_instructions; 5205a988416SJim Ingham }; 5215a988416SJim Ingham 5225a988416SJim Ingham const char * 52344d93782SGreg Clayton CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.\n"; 5245a988416SJim Ingham 5255a988416SJim Ingham // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting 5265a988416SJim Ingham // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper. 5275a988416SJim Ingham 5285a988416SJim Ingham static OptionEnumValueElement 5295a988416SJim Ingham g_script_option_enumeration[4] = 53030fdc8d8SChris Lattner { 5315a988416SJim Ingham { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"}, 5325a988416SJim Ingham { eScriptLanguagePython, "python", "Commands are in the Python language."}, 5335a988416SJim Ingham { eSortOrderByName, "default-script", "Commands are in the default scripting language."}, 534*c8ecc2a9SEugene Zelenko { 0, nullptr, nullptr } 5355a988416SJim Ingham }; 53630fdc8d8SChris Lattner 5375a988416SJim Ingham OptionDefinition 5385a988416SJim Ingham CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] = 53930fdc8d8SChris Lattner { 540*c8ecc2a9SEugene Zelenko { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, 5415a988416SJim Ingham "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, 54230fdc8d8SChris Lattner 543*c8ecc2a9SEugene Zelenko { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, 5445a988416SJim Ingham "Specify whether breakpoint command execution should terminate on error." }, 54530fdc8d8SChris Lattner 546*c8ecc2a9SEugene Zelenko { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone, 5475a988416SJim Ingham "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."}, 54830fdc8d8SChris Lattner 549*c8ecc2a9SEugene Zelenko { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, 5505a988416SJim Ingham "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."}, 55139d7d4f0SJohnny Chen 552*c8ecc2a9SEugene Zelenko { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 55333df7cd3SJim Ingham "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 55433df7cd3SJim Ingham 555*c8ecc2a9SEugene Zelenko { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 5565a988416SJim Ingham }; 55730fdc8d8SChris Lattner 55830fdc8d8SChris Lattner //------------------------------------------------------------------------- 55993e0f19fSCaroline Tice // CommandObjectBreakpointCommandDelete 56030fdc8d8SChris Lattner //------------------------------------------------------------------------- 56130fdc8d8SChris Lattner 5625a988416SJim Ingham class CommandObjectBreakpointCommandDelete : public CommandObjectParsed 5635a988416SJim Ingham { 5645a988416SJim Ingham public: 5655a988416SJim Ingham CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) : 5665a988416SJim Ingham CommandObjectParsed(interpreter, 56793e0f19fSCaroline Tice "delete", 56893e0f19fSCaroline Tice "Delete the set of commands from a breakpoint.", 569*c8ecc2a9SEugene Zelenko nullptr), 57033df7cd3SJim Ingham m_options (interpreter) 57130fdc8d8SChris Lattner { 572405fe67fSCaroline Tice CommandArgumentEntry arg; 573405fe67fSCaroline Tice CommandArgumentData bp_id_arg; 574405fe67fSCaroline Tice 575405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 576405fe67fSCaroline Tice bp_id_arg.arg_type = eArgTypeBreakpointID; 577405fe67fSCaroline Tice bp_id_arg.arg_repetition = eArgRepeatPlain; 578405fe67fSCaroline Tice 579405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 580405fe67fSCaroline Tice arg.push_back (bp_id_arg); 581405fe67fSCaroline Tice 582405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 583405fe67fSCaroline Tice m_arguments.push_back (arg); 58430fdc8d8SChris Lattner } 58530fdc8d8SChris Lattner 586*c8ecc2a9SEugene Zelenko ~CommandObjectBreakpointCommandDelete() override = default; 5875a988416SJim Ingham 58813d21e9aSBruce Mitchener Options * 58913d21e9aSBruce Mitchener GetOptions () override 59033df7cd3SJim Ingham { 59133df7cd3SJim Ingham return &m_options; 59233df7cd3SJim Ingham } 59333df7cd3SJim Ingham 59433df7cd3SJim Ingham class CommandOptions : public Options 59533df7cd3SJim Ingham { 59633df7cd3SJim Ingham public: 59733df7cd3SJim Ingham CommandOptions (CommandInterpreter &interpreter) : 59833df7cd3SJim Ingham Options (interpreter), 59933df7cd3SJim Ingham m_use_dummy (false) 60033df7cd3SJim Ingham { 60133df7cd3SJim Ingham } 60233df7cd3SJim Ingham 603*c8ecc2a9SEugene Zelenko ~CommandOptions() override = default; 60433df7cd3SJim Ingham 60513d21e9aSBruce Mitchener Error 60613d21e9aSBruce Mitchener SetOptionValue (uint32_t option_idx, const char *option_arg) override 60733df7cd3SJim Ingham { 60833df7cd3SJim Ingham Error error; 60933df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 61033df7cd3SJim Ingham 61133df7cd3SJim Ingham switch (short_option) 61233df7cd3SJim Ingham { 61333df7cd3SJim Ingham case 'D': 61433df7cd3SJim Ingham m_use_dummy = true; 61533df7cd3SJim Ingham break; 61633df7cd3SJim Ingham 61733df7cd3SJim Ingham default: 61833df7cd3SJim Ingham error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 61933df7cd3SJim Ingham break; 62033df7cd3SJim Ingham } 62133df7cd3SJim Ingham 62233df7cd3SJim Ingham return error; 62333df7cd3SJim Ingham } 62433df7cd3SJim Ingham 62533df7cd3SJim Ingham void 62613d21e9aSBruce Mitchener OptionParsingStarting () override 62733df7cd3SJim Ingham { 62833df7cd3SJim Ingham m_use_dummy = false; 62933df7cd3SJim Ingham } 63033df7cd3SJim Ingham 63133df7cd3SJim Ingham const OptionDefinition* 63213d21e9aSBruce Mitchener GetDefinitions () override 63333df7cd3SJim Ingham { 63433df7cd3SJim Ingham return g_option_table; 63533df7cd3SJim Ingham } 63633df7cd3SJim Ingham 63733df7cd3SJim Ingham // Options table: Required for subclasses of Options. 63833df7cd3SJim Ingham 63933df7cd3SJim Ingham static OptionDefinition g_option_table[]; 64033df7cd3SJim Ingham 64133df7cd3SJim Ingham // Instance variables to hold the values for command options. 64233df7cd3SJim Ingham bool m_use_dummy; 64333df7cd3SJim Ingham }; 64433df7cd3SJim Ingham 6455a988416SJim Ingham protected: 64613d21e9aSBruce Mitchener bool 64713d21e9aSBruce Mitchener DoExecute (Args& command, CommandReturnObject &result) override 64830fdc8d8SChris Lattner { 64933df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 65030fdc8d8SChris Lattner 651*c8ecc2a9SEugene Zelenko if (target == nullptr) 65230fdc8d8SChris Lattner { 65393e0f19fSCaroline Tice result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands"); 65430fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 65530fdc8d8SChris Lattner return false; 65630fdc8d8SChris Lattner } 65730fdc8d8SChris Lattner 65830fdc8d8SChris Lattner const BreakpointList &breakpoints = target->GetBreakpointList(); 65930fdc8d8SChris Lattner size_t num_breakpoints = breakpoints.GetSize(); 66030fdc8d8SChris Lattner 66130fdc8d8SChris Lattner if (num_breakpoints == 0) 66230fdc8d8SChris Lattner { 66393e0f19fSCaroline Tice result.AppendError ("No breakpoints exist to have commands deleted"); 66430fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 66530fdc8d8SChris Lattner return false; 66630fdc8d8SChris Lattner } 66730fdc8d8SChris Lattner 66830fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 66930fdc8d8SChris Lattner { 67093e0f19fSCaroline Tice result.AppendError ("No breakpoint specified from which to delete the commands"); 67130fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 67230fdc8d8SChris Lattner return false; 67330fdc8d8SChris Lattner } 67430fdc8d8SChris Lattner 67530fdc8d8SChris Lattner BreakpointIDList valid_bp_ids; 6765e09c8c3SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 67730fdc8d8SChris Lattner 67830fdc8d8SChris Lattner if (result.Succeeded()) 67930fdc8d8SChris Lattner { 680c982c768SGreg Clayton const size_t count = valid_bp_ids.GetSize(); 681c982c768SGreg Clayton for (size_t i = 0; i < count; ++i) 68230fdc8d8SChris Lattner { 68330fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 68430fdc8d8SChris Lattner if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 68530fdc8d8SChris Lattner { 68630fdc8d8SChris Lattner Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 68730fdc8d8SChris Lattner if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 68830fdc8d8SChris Lattner { 68930fdc8d8SChris Lattner BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID())); 69030fdc8d8SChris Lattner if (bp_loc_sp) 69130fdc8d8SChris Lattner bp_loc_sp->ClearCallback(); 69230fdc8d8SChris Lattner else 69330fdc8d8SChris Lattner { 69430fdc8d8SChris Lattner result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 69530fdc8d8SChris Lattner cur_bp_id.GetBreakpointID(), 69630fdc8d8SChris Lattner cur_bp_id.GetLocationID()); 69730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 69830fdc8d8SChris Lattner return false; 69930fdc8d8SChris Lattner } 70030fdc8d8SChris Lattner } 70130fdc8d8SChris Lattner else 70230fdc8d8SChris Lattner { 70330fdc8d8SChris Lattner bp->ClearCallback(); 70430fdc8d8SChris Lattner } 70530fdc8d8SChris Lattner } 70630fdc8d8SChris Lattner } 70730fdc8d8SChris Lattner } 70830fdc8d8SChris Lattner return result.Succeeded(); 70930fdc8d8SChris Lattner } 710*c8ecc2a9SEugene Zelenko 71133df7cd3SJim Ingham private: 71233df7cd3SJim Ingham CommandOptions m_options; 7135a988416SJim Ingham }; 71430fdc8d8SChris Lattner 71533df7cd3SJim Ingham OptionDefinition 71633df7cd3SJim Ingham CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] = 71733df7cd3SJim Ingham { 718*c8ecc2a9SEugene Zelenko { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 71933df7cd3SJim Ingham "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 72033df7cd3SJim Ingham 721*c8ecc2a9SEugene Zelenko { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 72233df7cd3SJim Ingham }; 72333df7cd3SJim Ingham 72430fdc8d8SChris Lattner //------------------------------------------------------------------------- 72530fdc8d8SChris Lattner // CommandObjectBreakpointCommandList 72630fdc8d8SChris Lattner //------------------------------------------------------------------------- 72730fdc8d8SChris Lattner 7285a988416SJim Ingham class CommandObjectBreakpointCommandList : public CommandObjectParsed 7295a988416SJim Ingham { 7305a988416SJim Ingham public: 7315a988416SJim Ingham CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) : 7325a988416SJim Ingham CommandObjectParsed(interpreter, 733a7015092SGreg Clayton "list", 73430fdc8d8SChris Lattner "List the script or set of commands to be executed when the breakpoint is hit.", 735*c8ecc2a9SEugene Zelenko nullptr) 73630fdc8d8SChris Lattner { 737405fe67fSCaroline Tice CommandArgumentEntry arg; 738405fe67fSCaroline Tice CommandArgumentData bp_id_arg; 739405fe67fSCaroline Tice 740405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 741405fe67fSCaroline Tice bp_id_arg.arg_type = eArgTypeBreakpointID; 742405fe67fSCaroline Tice bp_id_arg.arg_repetition = eArgRepeatPlain; 743405fe67fSCaroline Tice 744405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 745405fe67fSCaroline Tice arg.push_back (bp_id_arg); 746405fe67fSCaroline Tice 747405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 748405fe67fSCaroline Tice m_arguments.push_back (arg); 74930fdc8d8SChris Lattner } 75030fdc8d8SChris Lattner 751*c8ecc2a9SEugene Zelenko ~CommandObjectBreakpointCommandList() override = default; 75230fdc8d8SChris Lattner 7535a988416SJim Ingham protected: 75413d21e9aSBruce Mitchener bool 7555a988416SJim Ingham DoExecute (Args& command, 75613d21e9aSBruce Mitchener CommandReturnObject &result) override 75730fdc8d8SChris Lattner { 758a7015092SGreg Clayton Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 75930fdc8d8SChris Lattner 760*c8ecc2a9SEugene Zelenko if (target == nullptr) 76130fdc8d8SChris Lattner { 76230fdc8d8SChris Lattner result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands"); 76330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 76430fdc8d8SChris Lattner return false; 76530fdc8d8SChris Lattner } 76630fdc8d8SChris Lattner 76730fdc8d8SChris Lattner const BreakpointList &breakpoints = target->GetBreakpointList(); 76830fdc8d8SChris Lattner size_t num_breakpoints = breakpoints.GetSize(); 76930fdc8d8SChris Lattner 77030fdc8d8SChris Lattner if (num_breakpoints == 0) 77130fdc8d8SChris Lattner { 77230fdc8d8SChris Lattner result.AppendError ("No breakpoints exist for which to list commands"); 77330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 77430fdc8d8SChris Lattner return false; 77530fdc8d8SChris Lattner } 77630fdc8d8SChris Lattner 77730fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 77830fdc8d8SChris Lattner { 77930fdc8d8SChris Lattner result.AppendError ("No breakpoint specified for which to list the commands"); 78030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 78130fdc8d8SChris Lattner return false; 78230fdc8d8SChris Lattner } 78330fdc8d8SChris Lattner 78430fdc8d8SChris Lattner BreakpointIDList valid_bp_ids; 7855e09c8c3SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 78630fdc8d8SChris Lattner 78730fdc8d8SChris Lattner if (result.Succeeded()) 78830fdc8d8SChris Lattner { 789c982c768SGreg Clayton const size_t count = valid_bp_ids.GetSize(); 790c982c768SGreg Clayton for (size_t i = 0; i < count; ++i) 79130fdc8d8SChris Lattner { 79230fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 79330fdc8d8SChris Lattner if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 79430fdc8d8SChris Lattner { 79530fdc8d8SChris Lattner Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 79630fdc8d8SChris Lattner 79730fdc8d8SChris Lattner if (bp) 79830fdc8d8SChris Lattner { 799*c8ecc2a9SEugene Zelenko const BreakpointOptions *bp_options = nullptr; 80030fdc8d8SChris Lattner if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 80130fdc8d8SChris Lattner { 80230fdc8d8SChris Lattner BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID())); 80330fdc8d8SChris Lattner if (bp_loc_sp) 80405407f6bSJim Ingham bp_options = bp_loc_sp->GetOptionsNoCreate(); 80530fdc8d8SChris Lattner else 80630fdc8d8SChris Lattner { 80730fdc8d8SChris Lattner result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n", 80830fdc8d8SChris Lattner cur_bp_id.GetBreakpointID(), 80930fdc8d8SChris Lattner cur_bp_id.GetLocationID()); 81030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 81130fdc8d8SChris Lattner return false; 81230fdc8d8SChris Lattner } 81330fdc8d8SChris Lattner } 81430fdc8d8SChris Lattner else 81530fdc8d8SChris Lattner { 81630fdc8d8SChris Lattner bp_options = bp->GetOptions(); 81730fdc8d8SChris Lattner } 81830fdc8d8SChris Lattner 81930fdc8d8SChris Lattner if (bp_options) 82030fdc8d8SChris Lattner { 82130fdc8d8SChris Lattner StreamString id_str; 822e16c50a1SJim Ingham BreakpointID::GetCanonicalReference (&id_str, 823e16c50a1SJim Ingham cur_bp_id.GetBreakpointID(), 824e16c50a1SJim Ingham cur_bp_id.GetLocationID()); 8251b54c88cSJim Ingham const Baton *baton = bp_options->GetBaton(); 82630fdc8d8SChris Lattner if (baton) 82730fdc8d8SChris Lattner { 82830fdc8d8SChris Lattner result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData()); 82930fdc8d8SChris Lattner result.GetOutputStream().IndentMore (); 83030fdc8d8SChris Lattner baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull); 83130fdc8d8SChris Lattner result.GetOutputStream().IndentLess (); 83230fdc8d8SChris Lattner } 83330fdc8d8SChris Lattner else 83430fdc8d8SChris Lattner { 835e16c50a1SJim Ingham result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", 836e16c50a1SJim Ingham id_str.GetData()); 83730fdc8d8SChris Lattner } 83830fdc8d8SChris Lattner } 83930fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 84030fdc8d8SChris Lattner } 84130fdc8d8SChris Lattner else 84230fdc8d8SChris Lattner { 84330fdc8d8SChris Lattner result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID()); 84430fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 84530fdc8d8SChris Lattner } 84630fdc8d8SChris Lattner } 84730fdc8d8SChris Lattner } 84830fdc8d8SChris Lattner } 84930fdc8d8SChris Lattner 85030fdc8d8SChris Lattner return result.Succeeded(); 85130fdc8d8SChris Lattner } 8525a988416SJim Ingham }; 85330fdc8d8SChris Lattner 85430fdc8d8SChris Lattner //------------------------------------------------------------------------- 85530fdc8d8SChris Lattner // CommandObjectBreakpointCommand 85630fdc8d8SChris Lattner //------------------------------------------------------------------------- 85730fdc8d8SChris Lattner 8586611103cSGreg Clayton CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) : 859a7015092SGreg Clayton CommandObjectMultiword (interpreter, 860a7015092SGreg Clayton "command", 8617050e0b1SSean Callanan "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').", 86230fdc8d8SChris Lattner "command <sub-command> [<sub-command-options>] <breakpoint-id>") 86330fdc8d8SChris Lattner { 864a7015092SGreg Clayton CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter)); 86593e0f19fSCaroline Tice CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter)); 866a7015092SGreg Clayton CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter)); 86730fdc8d8SChris Lattner 86830fdc8d8SChris Lattner add_command_object->SetCommandName ("breakpoint command add"); 86993e0f19fSCaroline Tice delete_command_object->SetCommandName ("breakpoint command delete"); 87030fdc8d8SChris Lattner list_command_object->SetCommandName ("breakpoint command list"); 87130fdc8d8SChris Lattner 87223f59509SGreg Clayton LoadSubCommand ("add", add_command_object); 87323f59509SGreg Clayton LoadSubCommand ("delete", delete_command_object); 87423f59509SGreg Clayton LoadSubCommand ("list", list_command_object); 87530fdc8d8SChris Lattner } 87630fdc8d8SChris Lattner 877*c8ecc2a9SEugene Zelenko CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand() = default; 878