1 | //===-- CommandObjectWatchpointCommand.cpp --------------------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include <vector> |
10 | |
11 | #include "CommandObjectWatchpoint.h" |
12 | #include "CommandObjectWatchpointCommand.h" |
13 | #include "lldb/Breakpoint/StoppointCallbackContext.h" |
14 | #include "lldb/Breakpoint/Watchpoint.h" |
15 | #include "lldb/Core/IOHandler.h" |
16 | #include "lldb/Host/OptionParser.h" |
17 | #include "lldb/Host/StreamFile.h" |
18 | #include "lldb/Interpreter/CommandInterpreter.h" |
19 | #include "lldb/Interpreter/CommandOptionArgumentTable.h" |
20 | #include "lldb/Interpreter/CommandReturnObject.h" |
21 | #include "lldb/Interpreter/OptionArgParser.h" |
22 | #include "lldb/Target/Target.h" |
23 | #include "lldb/lldb-forward.h" |
24 | |
25 | using namespace lldb; |
26 | using namespace lldb_private; |
27 | |
28 | #define LLDB_OPTIONS_watchpoint_command_add |
29 | #include "CommandOptions.inc" |
30 | |
31 | class CommandObjectWatchpointCommandAdd : public CommandObjectParsed, |
32 | public IOHandlerDelegateMultiline { |
33 | public: |
34 | CommandObjectWatchpointCommandAdd(CommandInterpreter &interpreter) |
35 | : CommandObjectParsed(interpreter, "add", |
36 | "Add a set of LLDB commands to a watchpoint, to be " |
37 | "executed whenever the watchpoint is hit. " |
38 | "The commands added to the watchpoint replace any " |
39 | "commands previously added to it.", |
40 | nullptr, eCommandRequiresTarget), |
41 | IOHandlerDelegateMultiline("DONE", |
42 | IOHandlerDelegate::Completion::LLDBCommand) { |
43 | SetHelpLong( |
44 | R"( |
45 | General information about entering watchpoint commands |
46 | ------------------------------------------------------ |
47 | |
48 | )" |
49 | "This command will prompt for commands to be executed when the specified \ |
50 | watchpoint is hit. Each command is typed on its own line following the '> ' \ |
51 | prompt until 'DONE' is entered." |
52 | R"( |
53 | |
54 | )" |
55 | "Syntactic errors may not be detected when initially entered, and many \ |
56 | malformed commands can silently fail when executed. If your watchpoint commands \ |
57 | do not appear to be executing, double-check the command syntax." |
58 | R"( |
59 | |
60 | )" |
61 | "Note: You may enter any debugger command exactly as you would at the debugger \ |
62 | prompt. There is no limit to the number of commands supplied, but do NOT enter \ |
63 | more than one command per line." |
64 | R"( |
65 | |
66 | Special information about PYTHON watchpoint commands |
67 | ---------------------------------------------------- |
68 | |
69 | )" |
70 | "You may enter either one or more lines of Python, including function \ |
71 | definitions or calls to functions that will have been imported by the time \ |
72 | the code executes. Single line watchpoint commands will be interpreted 'as is' \ |
73 | when the watchpoint is hit. Multiple lines of Python will be wrapped in a \ |
74 | generated function, and a call to the function will be attached to the watchpoint." |
75 | R"( |
76 | |
77 | This auto-generated function is passed in three arguments: |
78 | |
79 | frame: an lldb.SBFrame object for the frame which hit the watchpoint. |
80 | |
81 | wp: the watchpoint that was hit. |
82 | |
83 | )" |
84 | "When specifying a python function with the --python-function option, you need \ |
85 | to supply the function name prepended by the module name:" |
86 | R"( |
87 | |
88 | --python-function myutils.watchpoint_callback |
89 | |
90 | The function itself must have the following prototype: |
91 | |
92 | def watchpoint_callback(frame, wp): |
93 | # Your code goes here |
94 | |
95 | )" |
96 | "The arguments are the same as the arguments passed to generated functions as \ |
97 | described above. Note that the global variable 'lldb.frame' will NOT be updated when \ |
98 | this function is called, so be sure to use the 'frame' argument. The 'frame' argument \ |
99 | can get you to the thread via frame.GetThread(), the thread can get you to the \ |
100 | process via thread.GetProcess(), and the process can get you back to the target \ |
101 | via process.GetTarget()." |
102 | R"( |
103 | |
104 | )" |
105 | "Important Note: As Python code gets collected into functions, access to global \ |
106 | variables requires explicit scoping using the 'global' keyword. Be sure to use correct \ |
107 | Python syntax, including indentation, when entering Python watchpoint commands." |
108 | R"( |
109 | |
110 | Example Python one-line watchpoint command: |
111 | |
112 | (lldb) watchpoint command add -s python 1 |
113 | Enter your Python command(s). Type 'DONE' to end. |
114 | > print "Hit this watchpoint!" |
115 | > DONE |
116 | |
117 | As a convenience, this also works for a short Python one-liner: |
118 | |
119 | (lldb) watchpoint command add -s python 1 -o 'import time; print time.asctime()' |
120 | (lldb) run |
121 | Launching '.../a.out' (x86_64) |
122 | (lldb) Fri Sep 10 12:17:45 2010 |
123 | Process 21778 Stopped |
124 | * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread |
125 | 36 |
126 | 37 int c(int val) |
127 | 38 { |
128 | 39 -> return val + 3; |
129 | 40 } |
130 | 41 |
131 | 42 int main (int argc, char const *argv[]) |
132 | |
133 | Example multiple line Python watchpoint command, using function definition: |
134 | |
135 | (lldb) watchpoint command add -s python 1 |
136 | Enter your Python command(s). Type 'DONE' to end. |
137 | > def watchpoint_output (wp_no): |
138 | > out_string = "Hit watchpoint number " + repr (wp_no) |
139 | > print out_string |
140 | > return True |
141 | > watchpoint_output (1) |
142 | > DONE |
143 | |
144 | Example multiple line Python watchpoint command, using 'loose' Python: |
145 | |
146 | (lldb) watchpoint command add -s p 1 |
147 | Enter your Python command(s). Type 'DONE' to end. |
148 | > global wp_count |
149 | > wp_count = wp_count + 1 |
150 | > print "Hit this watchpoint " + repr(wp_count) + " times!" |
151 | > DONE |
152 | |
153 | )" |
154 | "In this case, since there is a reference to a global variable, \ |
155 | 'wp_count', you will also need to make sure 'wp_count' exists and is \ |
156 | initialized:" |
157 | R"( |
158 | |
159 | (lldb) script |
160 | >>> wp_count = 0 |
161 | >>> quit() |
162 | |
163 | )" |
164 | "Final Note: A warning that no watchpoint command was generated when there \ |
165 | are no syntax errors may indicate that a function was declared but never called."); |
166 | |
167 | AddSimpleArgumentList(arg_type: eArgTypeWatchpointID); |
168 | } |
169 | |
170 | ~CommandObjectWatchpointCommandAdd() override = default; |
171 | |
172 | Options *GetOptions() override { return &m_options; } |
173 | |
174 | void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { |
175 | if (interactive) { |
176 | if (lldb::LockableStreamFileSP output_sp = |
177 | io_handler.GetOutputStreamFileSP()) { |
178 | LockedStreamFile locked_stream = output_sp->Lock(); |
179 | locked_stream.PutCString( |
180 | cstr: "Enter your debugger command(s). Type 'DONE' to end.\n"); |
181 | } |
182 | } |
183 | } |
184 | |
185 | void IOHandlerInputComplete(IOHandler &io_handler, |
186 | std::string &line) override { |
187 | io_handler.SetIsDone(true); |
188 | |
189 | // The WatchpointOptions object is owned by the watchpoint or watchpoint |
190 | // location |
191 | WatchpointOptions *wp_options = |
192 | (WatchpointOptions *)io_handler.GetUserData(); |
193 | if (wp_options) { |
194 | std::unique_ptr<WatchpointOptions::CommandData> data_up( |
195 | new WatchpointOptions::CommandData()); |
196 | if (data_up) { |
197 | data_up->user_source.SplitIntoLines(line); |
198 | auto baton_sp = std::make_shared<WatchpointOptions::CommandBaton>( |
199 | std::move(data_up)); |
200 | wp_options->SetCallback(callback: WatchpointOptionsCallbackFunction, baton_sp: baton_sp); |
201 | } |
202 | } |
203 | } |
204 | |
205 | void CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, |
206 | CommandReturnObject &result) { |
207 | m_interpreter.GetLLDBCommandsFromIOHandler( |
208 | prompt: "> ", // Prompt |
209 | delegate&: *this, // IOHandlerDelegate |
210 | baton: wp_options); // Baton for the "io_handler" that will be passed back into |
211 | // our IOHandlerDelegate functions |
212 | } |
213 | |
214 | /// Set a one-liner as the callback for the watchpoint. |
215 | void SetWatchpointCommandCallback(WatchpointOptions *wp_options, |
216 | const char *oneliner) { |
217 | std::unique_ptr<WatchpointOptions::CommandData> data_up( |
218 | new WatchpointOptions::CommandData()); |
219 | |
220 | // It's necessary to set both user_source and script_source to the |
221 | // oneliner. The former is used to generate callback description (as in |
222 | // watchpoint command list) while the latter is used for Python to |
223 | // interpret during the actual callback. |
224 | data_up->user_source.AppendString(oneliner); |
225 | data_up->script_source.assign(oneliner); |
226 | data_up->stop_on_error = m_options.m_stop_on_error; |
227 | |
228 | auto baton_sp = |
229 | std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up)); |
230 | wp_options->SetCallback(callback: WatchpointOptionsCallbackFunction, baton_sp: baton_sp); |
231 | } |
232 | |
233 | static bool |
234 | WatchpointOptionsCallbackFunction(void *baton, |
235 | StoppointCallbackContext *context, |
236 | lldb::user_id_t watch_id) { |
237 | bool ret_value = true; |
238 | if (baton == nullptr) |
239 | return true; |
240 | |
241 | WatchpointOptions::CommandData *data = |
242 | (WatchpointOptions::CommandData *)baton; |
243 | StringList &commands = data->user_source; |
244 | |
245 | if (commands.GetSize() > 0) { |
246 | ExecutionContext exe_ctx(context->exe_ctx_ref); |
247 | Target *target = exe_ctx.GetTargetPtr(); |
248 | if (target) { |
249 | Debugger &debugger = target->GetDebugger(); |
250 | CommandReturnObject result(debugger.GetUseColor()); |
251 | |
252 | // Rig up the results secondary output stream to the debugger's, so the |
253 | // output will come out synchronously if the debugger is set up that |
254 | // way. |
255 | result.SetImmediateOutputStream(debugger.GetAsyncOutputStream()); |
256 | result.SetImmediateErrorStream(debugger.GetAsyncErrorStream()); |
257 | |
258 | CommandInterpreterRunOptions options; |
259 | options.SetStopOnContinue(true); |
260 | options.SetStopOnError(data->stop_on_error); |
261 | options.SetEchoCommands(false); |
262 | options.SetPrintResults(true); |
263 | options.SetPrintErrors(true); |
264 | options.SetAddToHistory(false); |
265 | |
266 | debugger.GetCommandInterpreter().HandleCommands(commands, context: exe_ctx, |
267 | options, result); |
268 | result.GetImmediateOutputStream()->Flush(); |
269 | result.GetImmediateErrorStream()->Flush(); |
270 | } |
271 | } |
272 | return ret_value; |
273 | } |
274 | |
275 | class CommandOptions : public Options { |
276 | public: |
277 | CommandOptions() = default; |
278 | |
279 | ~CommandOptions() override = default; |
280 | |
281 | Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, |
282 | ExecutionContext *execution_context) override { |
283 | Status error; |
284 | const int short_option = m_getopt_table[option_idx].val; |
285 | |
286 | switch (short_option) { |
287 | case 'o': |
288 | m_use_one_liner = true; |
289 | m_one_liner = std::string(option_arg); |
290 | break; |
291 | |
292 | case 's': |
293 | m_script_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum( |
294 | option_arg, GetDefinitions()[option_idx].enum_values, |
295 | eScriptLanguageNone, error); |
296 | |
297 | switch (m_script_language) { |
298 | case eScriptLanguagePython: |
299 | case eScriptLanguageLua: |
300 | m_use_script_language = true; |
301 | break; |
302 | case eScriptLanguageNone: |
303 | case eScriptLanguageUnknown: |
304 | m_use_script_language = false; |
305 | break; |
306 | } |
307 | break; |
308 | |
309 | case 'e': { |
310 | bool success = false; |
311 | m_stop_on_error = |
312 | OptionArgParser::ToBoolean(s: option_arg, fail_value: false, success_ptr: &success); |
313 | if (!success) |
314 | return Status::FromErrorStringWithFormatv( |
315 | "invalid value for stop-on-error: \"{0}\"", option_arg); |
316 | } break; |
317 | |
318 | case 'F': |
319 | m_use_one_liner = false; |
320 | m_function_name.assign(str: std::string(option_arg)); |
321 | break; |
322 | |
323 | default: |
324 | llvm_unreachable("Unimplemented option"); |
325 | } |
326 | return error; |
327 | } |
328 | |
329 | void OptionParsingStarting(ExecutionContext *execution_context) override { |
330 | m_use_commands = true; |
331 | m_use_script_language = false; |
332 | m_script_language = eScriptLanguageNone; |
333 | |
334 | m_use_one_liner = false; |
335 | m_stop_on_error = true; |
336 | m_one_liner.clear(); |
337 | m_function_name.clear(); |
338 | } |
339 | |
340 | llvm::ArrayRef<OptionDefinition> GetDefinitions() override { |
341 | return llvm::ArrayRef(g_watchpoint_command_add_options); |
342 | } |
343 | |
344 | // Instance variables to hold the values for command options. |
345 | |
346 | bool m_use_commands = false; |
347 | bool m_use_script_language = false; |
348 | lldb::ScriptLanguage m_script_language = eScriptLanguageNone; |
349 | |
350 | // Instance variables to hold the values for one_liner options. |
351 | bool m_use_one_liner = false; |
352 | std::string m_one_liner; |
353 | bool m_stop_on_error; |
354 | std::string m_function_name; |
355 | }; |
356 | |
357 | protected: |
358 | void DoExecute(Args &command, CommandReturnObject &result) override { |
359 | Target &target = GetTarget(); |
360 | |
361 | const WatchpointList &watchpoints = target.GetWatchpointList(); |
362 | size_t num_watchpoints = watchpoints.GetSize(); |
363 | |
364 | if (num_watchpoints == 0) { |
365 | result.AppendError(in_string: "No watchpoints exist to have commands added"); |
366 | return; |
367 | } |
368 | |
369 | if (!m_options.m_function_name.empty()) { |
370 | if (!m_options.m_use_script_language) { |
371 | m_options.m_script_language = GetDebugger().GetScriptLanguage(); |
372 | m_options.m_use_script_language = true; |
373 | } |
374 | } |
375 | |
376 | std::vector<uint32_t> valid_wp_ids; |
377 | if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, args&: command, |
378 | wp_ids&: valid_wp_ids)) { |
379 | result.AppendError(in_string: "Invalid watchpoints specification."); |
380 | return; |
381 | } |
382 | |
383 | result.SetStatus(eReturnStatusSuccessFinishNoResult); |
384 | const size_t count = valid_wp_ids.size(); |
385 | for (size_t i = 0; i < count; ++i) { |
386 | uint32_t cur_wp_id = valid_wp_ids.at(i); |
387 | if (cur_wp_id != LLDB_INVALID_WATCH_ID) { |
388 | Watchpoint *wp = target.GetWatchpointList().FindByID(watchID: cur_wp_id).get(); |
389 | // Sanity check wp first. |
390 | if (wp == nullptr) |
391 | continue; |
392 | |
393 | WatchpointOptions *wp_options = wp->GetOptions(); |
394 | // Skip this watchpoint if wp_options is not good. |
395 | if (wp_options == nullptr) |
396 | continue; |
397 | |
398 | // If we are using script language, get the script interpreter in order |
399 | // to set or collect command callback. Otherwise, call the methods |
400 | // associated with this object. |
401 | if (m_options.m_use_script_language) { |
402 | ScriptInterpreter *script_interp = GetDebugger().GetScriptInterpreter( |
403 | /*can_create=*/true, m_options.m_script_language); |
404 | // Special handling for one-liner specified inline. |
405 | if (m_options.m_use_one_liner) { |
406 | script_interp->SetWatchpointCommandCallback( |
407 | wp_options, user_input: m_options.m_one_liner.c_str(), |
408 | /*is_callback=*/false); |
409 | } |
410 | // Special handling for using a Python function by name instead of |
411 | // extending the watchpoint callback data structures, we just |
412 | // automatize what the user would do manually: make their watchpoint |
413 | // command be a function call |
414 | else if (!m_options.m_function_name.empty()) { |
415 | std::string function_signature = m_options.m_function_name; |
416 | function_signature += "(frame, wp, internal_dict)"; |
417 | script_interp->SetWatchpointCommandCallback( |
418 | wp_options, user_input: function_signature.c_str(), /*is_callback=*/true); |
419 | } else { |
420 | script_interp->CollectDataForWatchpointCommandCallback(wp_options, |
421 | result); |
422 | } |
423 | } else { |
424 | // Special handling for one-liner specified inline. |
425 | if (m_options.m_use_one_liner) |
426 | SetWatchpointCommandCallback(wp_options, |
427 | oneliner: m_options.m_one_liner.c_str()); |
428 | else |
429 | CollectDataForWatchpointCommandCallback(wp_options, result); |
430 | } |
431 | } |
432 | } |
433 | } |
434 | |
435 | private: |
436 | CommandOptions m_options; |
437 | }; |
438 | |
439 | // CommandObjectWatchpointCommandDelete |
440 | |
441 | class CommandObjectWatchpointCommandDelete : public CommandObjectParsed { |
442 | public: |
443 | CommandObjectWatchpointCommandDelete(CommandInterpreter &interpreter) |
444 | : CommandObjectParsed(interpreter, "delete", |
445 | "Delete the set of commands from a watchpoint.", |
446 | nullptr, eCommandRequiresTarget) { |
447 | AddSimpleArgumentList(arg_type: eArgTypeWatchpointID); |
448 | } |
449 | |
450 | ~CommandObjectWatchpointCommandDelete() override = default; |
451 | |
452 | protected: |
453 | void DoExecute(Args &command, CommandReturnObject &result) override { |
454 | Target &target = GetTarget(); |
455 | |
456 | const WatchpointList &watchpoints = target.GetWatchpointList(); |
457 | size_t num_watchpoints = watchpoints.GetSize(); |
458 | |
459 | if (num_watchpoints == 0) { |
460 | result.AppendError(in_string: "No watchpoints exist to have commands deleted"); |
461 | return; |
462 | } |
463 | |
464 | if (command.GetArgumentCount() == 0) { |
465 | result.AppendError( |
466 | in_string: "No watchpoint specified from which to delete the commands"); |
467 | return; |
468 | } |
469 | |
470 | std::vector<uint32_t> valid_wp_ids; |
471 | if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, args&: command, |
472 | wp_ids&: valid_wp_ids)) { |
473 | result.AppendError(in_string: "Invalid watchpoints specification."); |
474 | return; |
475 | } |
476 | |
477 | result.SetStatus(eReturnStatusSuccessFinishNoResult); |
478 | const size_t count = valid_wp_ids.size(); |
479 | for (size_t i = 0; i < count; ++i) { |
480 | uint32_t cur_wp_id = valid_wp_ids.at(n: i); |
481 | if (cur_wp_id != LLDB_INVALID_WATCH_ID) { |
482 | Watchpoint *wp = target.GetWatchpointList().FindByID(watchID: cur_wp_id).get(); |
483 | if (wp) |
484 | wp->ClearCallback(); |
485 | } else { |
486 | result.AppendErrorWithFormat(format: "Invalid watchpoint ID: %u.\n", cur_wp_id); |
487 | return; |
488 | } |
489 | } |
490 | } |
491 | }; |
492 | |
493 | // CommandObjectWatchpointCommandList |
494 | |
495 | class CommandObjectWatchpointCommandList : public CommandObjectParsed { |
496 | public: |
497 | CommandObjectWatchpointCommandList(CommandInterpreter &interpreter) |
498 | : CommandObjectParsed(interpreter, "list", |
499 | "List the script or set of commands to be executed " |
500 | "when the watchpoint is hit.", |
501 | nullptr, eCommandRequiresTarget) { |
502 | AddSimpleArgumentList(arg_type: eArgTypeWatchpointID); |
503 | } |
504 | |
505 | ~CommandObjectWatchpointCommandList() override = default; |
506 | |
507 | protected: |
508 | void DoExecute(Args &command, CommandReturnObject &result) override { |
509 | Target &target = GetTarget(); |
510 | |
511 | const WatchpointList &watchpoints = target.GetWatchpointList(); |
512 | size_t num_watchpoints = watchpoints.GetSize(); |
513 | |
514 | if (num_watchpoints == 0) { |
515 | result.AppendError(in_string: "No watchpoints exist for which to list commands"); |
516 | return; |
517 | } |
518 | |
519 | if (command.GetArgumentCount() == 0) { |
520 | result.AppendError( |
521 | in_string: "No watchpoint specified for which to list the commands"); |
522 | return; |
523 | } |
524 | |
525 | std::vector<uint32_t> valid_wp_ids; |
526 | if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, args&: command, |
527 | wp_ids&: valid_wp_ids)) { |
528 | result.AppendError(in_string: "Invalid watchpoints specification."); |
529 | return; |
530 | } |
531 | |
532 | result.SetStatus(eReturnStatusSuccessFinishNoResult); |
533 | const size_t count = valid_wp_ids.size(); |
534 | for (size_t i = 0; i < count; ++i) { |
535 | uint32_t cur_wp_id = valid_wp_ids.at(n: i); |
536 | if (cur_wp_id != LLDB_INVALID_WATCH_ID) { |
537 | Watchpoint *wp = target.GetWatchpointList().FindByID(watchID: cur_wp_id).get(); |
538 | |
539 | if (wp) { |
540 | const WatchpointOptions *wp_options = wp->GetOptions(); |
541 | if (wp_options) { |
542 | // Get the callback baton associated with the current watchpoint. |
543 | const Baton *baton = wp_options->GetBaton(); |
544 | if (baton) { |
545 | result.GetOutputStream().Printf(format: "Watchpoint %u:\n", cur_wp_id); |
546 | baton->GetDescription(s&: result.GetOutputStream().AsRawOstream(), |
547 | level: eDescriptionLevelFull, |
548 | indentation: result.GetOutputStream().GetIndentLevel() + |
549 | 2); |
550 | } else { |
551 | result.AppendMessageWithFormat( |
552 | format: "Watchpoint %u does not have an associated command.\n", |
553 | cur_wp_id); |
554 | } |
555 | } |
556 | result.SetStatus(eReturnStatusSuccessFinishResult); |
557 | } else { |
558 | result.AppendErrorWithFormat(format: "Invalid watchpoint ID: %u.\n", |
559 | cur_wp_id); |
560 | } |
561 | } |
562 | } |
563 | } |
564 | }; |
565 | |
566 | // CommandObjectWatchpointCommand |
567 | |
568 | CommandObjectWatchpointCommand::CommandObjectWatchpointCommand( |
569 | CommandInterpreter &interpreter) |
570 | : CommandObjectMultiword( |
571 | interpreter, "command", |
572 | "Commands for adding, removing and examining LLDB commands " |
573 | "executed when the watchpoint is hit (watchpoint 'commands').", |
574 | "command <sub-command> [<sub-command-options>] <watchpoint-id>") { |
575 | CommandObjectSP add_command_object( |
576 | new CommandObjectWatchpointCommandAdd(interpreter)); |
577 | CommandObjectSP delete_command_object( |
578 | new CommandObjectWatchpointCommandDelete(interpreter)); |
579 | CommandObjectSP list_command_object( |
580 | new CommandObjectWatchpointCommandList(interpreter)); |
581 | |
582 | add_command_object->SetCommandName("watchpoint command add"); |
583 | delete_command_object->SetCommandName("watchpoint command delete"); |
584 | list_command_object->SetCommandName("watchpoint command list"); |
585 | |
586 | LoadSubCommand(cmd_name: "add", command_obj: add_command_object); |
587 | LoadSubCommand(cmd_name: "delete", command_obj: delete_command_object); |
588 | LoadSubCommand(cmd_name: "list", command_obj: list_command_object); |
589 | } |
590 | |
591 | CommandObjectWatchpointCommand::~CommandObjectWatchpointCommand() = default; |
592 |
Definitions
- CommandObjectWatchpointCommandAdd
- CommandObjectWatchpointCommandAdd
- ~CommandObjectWatchpointCommandAdd
- GetOptions
- IOHandlerActivated
- IOHandlerInputComplete
- CollectDataForWatchpointCommandCallback
- SetWatchpointCommandCallback
- WatchpointOptionsCallbackFunction
- CommandOptions
- CommandOptions
- ~CommandOptions
- SetOptionValue
- OptionParsingStarting
- GetDefinitions
- DoExecute
- CommandObjectWatchpointCommandDelete
- CommandObjectWatchpointCommandDelete
- ~CommandObjectWatchpointCommandDelete
- DoExecute
- CommandObjectWatchpointCommandList
- CommandObjectWatchpointCommandList
- ~CommandObjectWatchpointCommandList
- DoExecute
- CommandObjectWatchpointCommand
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more