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