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