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