1 //===-- CommandObjectTarget.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "CommandObjectTarget.h"
11 
12 // C Includes
13 #include <errno.h>
14 
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Interpreter/Args.h"
19 #include "lldb/Core/Debugger.h"
20 #include "lldb/Core/InputReader.h"
21 #include "lldb/Core/State.h"
22 #include "lldb/Core/Timer.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/CommandReturnObject.h"
25 #include "lldb/Interpreter/OptionGroupArchitecture.h"
26 #include "lldb/Interpreter/OptionGroupPlatform.h"
27 #include "lldb/Target/Process.h"
28 #include "lldb/Target/StackFrame.h"
29 #include "lldb/Target/Thread.h"
30 #include "lldb/Target/ThreadSpec.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 
36 
37 static void
38 DumpTargetInfo (uint32_t target_idx, Target *target, const char *prefix_cstr, bool show_stopped_process_status, Stream &strm)
39 {
40     ArchSpec &target_arch = target->GetArchitecture();
41 
42     ModuleSP exe_module_sp (target->GetExecutableModule ());
43     char exe_path[PATH_MAX];
44     bool exe_valid = false;
45     if (exe_module_sp)
46         exe_valid = exe_module_sp->GetFileSpec().GetPath (exe_path, sizeof(exe_path));
47 
48     if (!exe_valid)
49         ::strcpy (exe_path, "<none>");
50 
51     strm.Printf ("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx, exe_path);
52 
53     uint32_t properties = 0;
54     if (target_arch.IsValid())
55     {
56         strm.Printf ("%sarch=%s", properties++ > 0 ? ", " : " ( ", target_arch.GetTriple().str().c_str());
57         properties++;
58     }
59     PlatformSP platform_sp (target->GetPlatform());
60     if (platform_sp)
61         strm.Printf ("%splatform=%s", properties++ > 0 ? ", " : " ( ", platform_sp->GetName());
62 
63     ProcessSP process_sp (target->GetProcessSP());
64     bool show_process_status = false;
65     if (process_sp)
66     {
67         lldb::pid_t pid = process_sp->GetID();
68         StateType state = process_sp->GetState();
69         if (show_stopped_process_status)
70             show_process_status = StateIsStoppedState(state);
71         const char *state_cstr = StateAsCString (state);
72         if (pid != LLDB_INVALID_PROCESS_ID)
73             strm.Printf ("%spid=%i", properties++ > 0 ? ", " : " ( ", pid);
74         strm.Printf ("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr);
75     }
76     if (properties > 0)
77         strm.PutCString (" )\n");
78     else
79         strm.EOL();
80     if (show_process_status)
81     {
82         const bool only_threads_with_stop_reason = true;
83         const uint32_t start_frame = 0;
84         const uint32_t num_frames = 1;
85         const uint32_t num_frames_with_source = 1;
86         process_sp->GetStatus (strm);
87         process_sp->GetThreadStatus (strm,
88                                      only_threads_with_stop_reason,
89                                      start_frame,
90                                      num_frames,
91                                      num_frames_with_source);
92 
93     }
94 }
95 
96 static uint32_t
97 DumpTargetList (TargetList &target_list, bool show_stopped_process_status, Stream &strm)
98 {
99     const uint32_t num_targets = target_list.GetNumTargets();
100     if (num_targets)
101     {
102         TargetSP selected_target_sp (target_list.GetSelectedTarget());
103         strm.PutCString ("Current targets:\n");
104         for (uint32_t i=0; i<num_targets; ++i)
105         {
106             TargetSP target_sp (target_list.GetTargetAtIndex (i));
107             if (target_sp)
108             {
109                 bool is_selected = target_sp.get() == selected_target_sp.get();
110                 DumpTargetInfo (i,
111                                 target_sp.get(),
112                                 is_selected ? "* " : "  ",
113                                 show_stopped_process_status,
114                                 strm);
115             }
116         }
117     }
118     return num_targets;
119 }
120 #pragma mark CommandObjectTargetCreate
121 
122 //-------------------------------------------------------------------------
123 // "target create"
124 //-------------------------------------------------------------------------
125 
126 class CommandObjectTargetCreate : public CommandObject
127 {
128 public:
129     CommandObjectTargetCreate(CommandInterpreter &interpreter) :
130         CommandObject (interpreter,
131                        "target create",
132                        "Create a target using the argument as the main executable.",
133                        NULL),
134         m_option_group (interpreter),
135         m_file_options (),
136         m_platform_options(true) // Do include the "--platform" option in the platform settings by passing true
137     {
138         CommandArgumentEntry arg;
139         CommandArgumentData file_arg;
140 
141         // Define the first (and only) variant of this arg.
142             file_arg.arg_type = eArgTypeFilename;
143         file_arg.arg_repetition = eArgRepeatPlain;
144 
145         // There is only one variant this argument could be; put it into the argument entry.
146         arg.push_back (file_arg);
147 
148         // Push the data for the first argument into the m_arguments vector.
149         m_arguments.push_back (arg);
150 
151         m_option_group.Append (&m_file_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
152         m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
153         m_option_group.Finalize();
154     }
155 
156     ~CommandObjectTargetCreate ()
157     {
158     }
159 
160     Options *
161     GetOptions ()
162     {
163         return &m_option_group;
164     }
165 
166     bool
167     Execute (Args& command, CommandReturnObject &result)
168     {
169         const int argc = command.GetArgumentCount();
170         if (argc == 1)
171         {
172             const char *file_path = command.GetArgumentAtIndex(0);
173             Timer scoped_timer(__PRETTY_FUNCTION__, "(lldb) target create '%s'", file_path);
174             FileSpec file_spec (file_path, true);
175 
176             bool select = true;
177             PlatformSP platform_sp;
178 
179             Error error;
180 
181             if (m_platform_options.PlatformWasSpecified ())
182             {
183                 platform_sp = m_platform_options.CreatePlatformWithOptions(m_interpreter, select, error);
184                 if (!platform_sp)
185                 {
186                     result.AppendError(error.AsCString());
187                     result.SetStatus (eReturnStatusFailed);
188                     return false;
189                 }
190             }
191             ArchSpec file_arch;
192 
193             const char *arch_cstr = m_file_options.GetArchitectureName();
194             if (arch_cstr)
195             {
196                 if (!platform_sp)
197                     platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
198                 if (!m_file_options.GetArchitecture(platform_sp.get(), file_arch))
199                 {
200                     result.AppendErrorWithFormat("invalid architecture '%s'\n", arch_cstr);
201                     result.SetStatus (eReturnStatusFailed);
202                     return false;
203                 }
204             }
205 
206             if (! file_spec.Exists() && !file_spec.ResolveExecutableLocation())
207             {
208                 result.AppendErrorWithFormat ("File '%s' does not exist.\n", file_path);
209                 result.SetStatus (eReturnStatusFailed);
210                 return false;
211             }
212 
213             TargetSP target_sp;
214             Debugger &debugger = m_interpreter.GetDebugger();
215             error = debugger.GetTargetList().CreateTarget (debugger, file_spec, file_arch, true, target_sp);
216 
217             if (target_sp)
218             {
219                 debugger.GetTargetList().SetSelectedTarget(target_sp.get());
220                 result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, target_sp->GetArchitecture().GetArchitectureName());
221                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
222             }
223             else
224             {
225                 result.AppendError(error.AsCString());
226                 result.SetStatus (eReturnStatusFailed);
227             }
228         }
229         else
230         {
231             result.AppendErrorWithFormat("'%s' takes exactly one executable path argument.\n", m_cmd_name.c_str());
232             result.SetStatus (eReturnStatusFailed);
233         }
234         return result.Succeeded();
235 
236     }
237 
238     int
239     HandleArgumentCompletion (Args &input,
240                               int &cursor_index,
241                               int &cursor_char_position,
242                               OptionElementVector &opt_element_vector,
243                               int match_start_point,
244                               int max_return_elements,
245                               bool &word_complete,
246                               StringList &matches)
247     {
248         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
249         completion_str.erase (cursor_char_position);
250 
251         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
252                                                              CommandCompletions::eDiskFileCompletion,
253                                                              completion_str.c_str(),
254                                                              match_start_point,
255                                                              max_return_elements,
256                                                              NULL,
257                                                              word_complete,
258                                                              matches);
259         return matches.GetSize();
260     }
261 private:
262     OptionGroupOptions m_option_group;
263     OptionGroupArchitecture m_file_options;
264     OptionGroupPlatform m_platform_options;
265 
266 };
267 
268 #pragma mark CommandObjectTargetList
269 
270 //----------------------------------------------------------------------
271 // "target list"
272 //----------------------------------------------------------------------
273 
274 class CommandObjectTargetList : public CommandObject
275 {
276 public:
277     CommandObjectTargetList (CommandInterpreter &interpreter) :
278         CommandObject (interpreter,
279                        "target list",
280                        "List all current targets in the current debug session.",
281                        NULL,
282                        0)
283     {
284     }
285 
286     virtual
287     ~CommandObjectTargetList ()
288     {
289     }
290 
291     virtual bool
292     Execute (Args& args, CommandReturnObject &result)
293     {
294         if (args.GetArgumentCount() == 0)
295         {
296             Stream &strm = result.GetOutputStream();
297 
298             bool show_stopped_process_status = false;
299             if (DumpTargetList (m_interpreter.GetDebugger().GetTargetList(), show_stopped_process_status, strm) == 0)
300             {
301                 strm.PutCString ("No targets.\n");
302             }
303         }
304         else
305         {
306             result.AppendError ("the 'target list' command takes no arguments\n");
307             result.SetStatus (eReturnStatusFailed);
308         }
309         return result.Succeeded();
310     }
311 };
312 
313 
314 #pragma mark CommandObjectTargetSelect
315 
316 //----------------------------------------------------------------------
317 // "target select"
318 //----------------------------------------------------------------------
319 
320 class CommandObjectTargetSelect : public CommandObject
321 {
322 public:
323     CommandObjectTargetSelect (CommandInterpreter &interpreter) :
324         CommandObject (interpreter,
325                        "target select",
326                        "Select a target as the current target by target index.",
327                        NULL,
328                        0)
329     {
330     }
331 
332     virtual
333     ~CommandObjectTargetSelect ()
334     {
335     }
336 
337     virtual bool
338     Execute (Args& args, CommandReturnObject &result)
339     {
340         if (args.GetArgumentCount() == 1)
341         {
342             bool success = false;
343             const char *target_idx_arg = args.GetArgumentAtIndex(0);
344             uint32_t target_idx = Args::StringToUInt32 (target_idx_arg, UINT32_MAX, 0, &success);
345             if (success)
346             {
347                 TargetList &target_list = m_interpreter.GetDebugger().GetTargetList();
348                 const uint32_t num_targets = target_list.GetNumTargets();
349                 if (target_idx < num_targets)
350                 {
351                     TargetSP target_sp (target_list.GetTargetAtIndex (target_idx));
352                     if (target_sp)
353                     {
354                         Stream &strm = result.GetOutputStream();
355                         target_list.SetSelectedTarget (target_sp.get());
356                         bool show_stopped_process_status = false;
357                         DumpTargetList (target_list, show_stopped_process_status, strm);
358                     }
359                     else
360                     {
361                         result.AppendErrorWithFormat ("target #%u is NULL in target list\n", target_idx);
362                         result.SetStatus (eReturnStatusFailed);
363                     }
364                 }
365                 else
366                 {
367                     result.AppendErrorWithFormat ("index %u is out of range, valid target indexes are 0 - %u\n",
368                                                   target_idx,
369                                                   num_targets - 1);
370                     result.SetStatus (eReturnStatusFailed);
371                 }
372             }
373             else
374             {
375                 result.AppendErrorWithFormat("invalid index string value '%s'\n", target_idx_arg);
376                 result.SetStatus (eReturnStatusFailed);
377             }
378         }
379         else
380         {
381             result.AppendError ("'target select' takes a single argument: a target index\n");
382             result.SetStatus (eReturnStatusFailed);
383         }
384         return result.Succeeded();
385     }
386 };
387 
388 
389 #pragma mark CommandObjectTargetImageSearchPaths
390 
391 class CommandObjectTargetImageSearchPathsAdd : public CommandObject
392 {
393 public:
394 
395     CommandObjectTargetImageSearchPathsAdd (CommandInterpreter &interpreter) :
396         CommandObject (interpreter,
397                        "target image-search-paths add",
398                        "Add new image search paths substitution pairs to the current target.",
399                        NULL)
400     {
401         CommandArgumentEntry arg;
402         CommandArgumentData old_prefix_arg;
403         CommandArgumentData new_prefix_arg;
404 
405         // Define the first variant of this arg pair.
406         old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
407         old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
408 
409         // Define the first variant of this arg pair.
410         new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
411         new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
412 
413         // There are two required arguments that must always occur together, i.e. an argument "pair".  Because they
414         // must always occur together, they are treated as two variants of one argument rather than two independent
415         // arguments.  Push them both into the first argument position for m_arguments...
416 
417         arg.push_back (old_prefix_arg);
418         arg.push_back (new_prefix_arg);
419 
420         m_arguments.push_back (arg);
421     }
422 
423     ~CommandObjectTargetImageSearchPathsAdd ()
424     {
425     }
426 
427     bool
428     Execute (Args& command,
429              CommandReturnObject &result)
430     {
431         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
432         if (target)
433         {
434             uint32_t argc = command.GetArgumentCount();
435             if (argc & 1)
436             {
437                 result.AppendError ("add requires an even number of arguments\n");
438                 result.SetStatus (eReturnStatusFailed);
439             }
440             else
441             {
442                 for (uint32_t i=0; i<argc; i+=2)
443                 {
444                     const char *from = command.GetArgumentAtIndex(i);
445                     const char *to = command.GetArgumentAtIndex(i+1);
446 
447                     if (from[0] && to[0])
448                     {
449                         bool last_pair = ((argc - i) == 2);
450                         target->GetImageSearchPathList().Append (ConstString(from),
451                                                                  ConstString(to),
452                                                                  last_pair); // Notify if this is the last pair
453                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
454                     }
455                     else
456                     {
457                         if (from[0])
458                             result.AppendError ("<path-prefix> can't be empty\n");
459                         else
460                             result.AppendError ("<new-path-prefix> can't be empty\n");
461                         result.SetStatus (eReturnStatusFailed);
462                     }
463                 }
464             }
465         }
466         else
467         {
468             result.AppendError ("invalid target\n");
469             result.SetStatus (eReturnStatusFailed);
470         }
471         return result.Succeeded();
472     }
473 };
474 
475 class CommandObjectTargetImageSearchPathsClear : public CommandObject
476 {
477 public:
478 
479     CommandObjectTargetImageSearchPathsClear (CommandInterpreter &interpreter) :
480         CommandObject (interpreter,
481                        "target image-search-paths clear",
482                        "Clear all current image search path substitution pairs from the current target.",
483                        "target image-search-paths clear")
484     {
485     }
486 
487     ~CommandObjectTargetImageSearchPathsClear ()
488     {
489     }
490 
491     bool
492     Execute (Args& command,
493              CommandReturnObject &result)
494     {
495         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
496         if (target)
497         {
498             bool notify = true;
499             target->GetImageSearchPathList().Clear(notify);
500             result.SetStatus (eReturnStatusSuccessFinishNoResult);
501         }
502         else
503         {
504             result.AppendError ("invalid target\n");
505             result.SetStatus (eReturnStatusFailed);
506         }
507         return result.Succeeded();
508     }
509 };
510 
511 class CommandObjectTargetImageSearchPathsInsert : public CommandObject
512 {
513 public:
514 
515     CommandObjectTargetImageSearchPathsInsert (CommandInterpreter &interpreter) :
516         CommandObject (interpreter,
517                        "target image-search-paths insert",
518                        "Insert a new image search path substitution pair into the current target at the specified index.",
519                        NULL)
520     {
521         CommandArgumentEntry arg1;
522         CommandArgumentEntry arg2;
523         CommandArgumentData index_arg;
524         CommandArgumentData old_prefix_arg;
525         CommandArgumentData new_prefix_arg;
526 
527         // Define the first and only variant of this arg.
528         index_arg.arg_type = eArgTypeIndex;
529         index_arg.arg_repetition = eArgRepeatPlain;
530 
531         // Put the one and only variant into the first arg for m_arguments:
532         arg1.push_back (index_arg);
533 
534         // Define the first variant of this arg pair.
535         old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
536         old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
537 
538         // Define the first variant of this arg pair.
539         new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
540         new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
541 
542         // There are two required arguments that must always occur together, i.e. an argument "pair".  Because they
543         // must always occur together, they are treated as two variants of one argument rather than two independent
544         // arguments.  Push them both into the same argument position for m_arguments...
545 
546         arg2.push_back (old_prefix_arg);
547         arg2.push_back (new_prefix_arg);
548 
549         // Add arguments to m_arguments.
550         m_arguments.push_back (arg1);
551         m_arguments.push_back (arg2);
552     }
553 
554     ~CommandObjectTargetImageSearchPathsInsert ()
555     {
556     }
557 
558     bool
559     Execute (Args& command,
560              CommandReturnObject &result)
561     {
562         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
563         if (target)
564         {
565             uint32_t argc = command.GetArgumentCount();
566             // check for at least 3 arguments and an odd nubmer of parameters
567             if (argc >= 3 && argc & 1)
568             {
569                 bool success = false;
570 
571                 uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
572 
573                 if (!success)
574                 {
575                     result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0));
576                     result.SetStatus (eReturnStatusFailed);
577                     return result.Succeeded();
578                 }
579 
580                 // shift off the index
581                 command.Shift();
582                 argc = command.GetArgumentCount();
583 
584                 for (uint32_t i=0; i<argc; i+=2, ++insert_idx)
585                 {
586                     const char *from = command.GetArgumentAtIndex(i);
587                     const char *to = command.GetArgumentAtIndex(i+1);
588 
589                     if (from[0] && to[0])
590                     {
591                         bool last_pair = ((argc - i) == 2);
592                         target->GetImageSearchPathList().Insert (ConstString(from),
593                                                                  ConstString(to),
594                                                                  insert_idx,
595                                                                  last_pair);
596                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
597                     }
598                     else
599                     {
600                         if (from[0])
601                             result.AppendError ("<path-prefix> can't be empty\n");
602                         else
603                             result.AppendError ("<new-path-prefix> can't be empty\n");
604                         result.SetStatus (eReturnStatusFailed);
605                         return false;
606                     }
607                 }
608             }
609             else
610             {
611                 result.AppendError ("insert requires at least three arguments\n");
612                 result.SetStatus (eReturnStatusFailed);
613                 return result.Succeeded();
614             }
615 
616         }
617         else
618         {
619             result.AppendError ("invalid target\n");
620             result.SetStatus (eReturnStatusFailed);
621         }
622         return result.Succeeded();
623     }
624 };
625 
626 class CommandObjectTargetImageSearchPathsList : public CommandObject
627 {
628 public:
629 
630     CommandObjectTargetImageSearchPathsList (CommandInterpreter &interpreter) :
631         CommandObject (interpreter,
632                        "target image-search-paths list",
633                        "List all current image search path substitution pairs in the current target.",
634                        "target image-search-paths list")
635     {
636     }
637 
638     ~CommandObjectTargetImageSearchPathsList ()
639     {
640     }
641 
642     bool
643     Execute (Args& command,
644              CommandReturnObject &result)
645     {
646         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
647         if (target)
648         {
649             if (command.GetArgumentCount() != 0)
650             {
651                 result.AppendError ("list takes no arguments\n");
652                 result.SetStatus (eReturnStatusFailed);
653                 return result.Succeeded();
654             }
655 
656             target->GetImageSearchPathList().Dump(&result.GetOutputStream());
657             result.SetStatus (eReturnStatusSuccessFinishResult);
658         }
659         else
660         {
661             result.AppendError ("invalid target\n");
662             result.SetStatus (eReturnStatusFailed);
663         }
664         return result.Succeeded();
665     }
666 };
667 
668 class CommandObjectTargetImageSearchPathsQuery : public CommandObject
669 {
670 public:
671 
672     CommandObjectTargetImageSearchPathsQuery (CommandInterpreter &interpreter) :
673     CommandObject (interpreter,
674                    "target image-search-paths query",
675                    "Transform a path using the first applicable image search path.",
676                    NULL)
677     {
678         CommandArgumentEntry arg;
679         CommandArgumentData path_arg;
680 
681         // Define the first (and only) variant of this arg.
682         path_arg.arg_type = eArgTypePath;
683         path_arg.arg_repetition = eArgRepeatPlain;
684 
685         // There is only one variant this argument could be; put it into the argument entry.
686         arg.push_back (path_arg);
687 
688         // Push the data for the first argument into the m_arguments vector.
689         m_arguments.push_back (arg);
690     }
691 
692     ~CommandObjectTargetImageSearchPathsQuery ()
693     {
694     }
695 
696     bool
697     Execute (Args& command,
698              CommandReturnObject &result)
699     {
700         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
701         if (target)
702         {
703             if (command.GetArgumentCount() != 1)
704             {
705                 result.AppendError ("query requires one argument\n");
706                 result.SetStatus (eReturnStatusFailed);
707                 return result.Succeeded();
708             }
709 
710             ConstString orig(command.GetArgumentAtIndex(0));
711             ConstString transformed;
712             if (target->GetImageSearchPathList().RemapPath(orig, transformed))
713                 result.GetOutputStream().Printf("%s\n", transformed.GetCString());
714             else
715                 result.GetOutputStream().Printf("%s\n", orig.GetCString());
716 
717             result.SetStatus (eReturnStatusSuccessFinishResult);
718         }
719         else
720         {
721             result.AppendError ("invalid target\n");
722             result.SetStatus (eReturnStatusFailed);
723         }
724         return result.Succeeded();
725     }
726 };
727 
728 // TODO: implement the target select later when we start doing multiple targets
729 //#pragma mark CommandObjectTargetSelect
730 //
731 ////-------------------------------------------------------------------------
732 //// CommandObjectTargetSelect
733 ////-------------------------------------------------------------------------
734 //
735 //class CommandObjectTargetSelect : public CommandObject
736 //{
737 //public:
738 //
739 //    CommandObjectTargetSelect () :
740 //    CommandObject (interpreter,
741 //                   frame select",
742 //                   "Select the current frame by index in the current thread.",
743 //                   "frame select <frame-index>")
744 //    {
745 //    }
746 //
747 //    ~CommandObjectTargetSelect ()
748 //    {
749 //    }
750 //
751 //    bool
752 //    Execute (Args& command,
753 //             Debugger *context,
754 //             CommandInterpreter &m_interpreter,
755 //             CommandReturnObject &result)
756 //    {
757 //        ExecutionContext exe_ctx (context->GetExecutionContext());
758 //        if (exe_ctx.thread)
759 //        {
760 //            if (command.GetArgumentCount() == 1)
761 //            {
762 //                const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
763 //
764 //                const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
765 //                const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
766 //                if (frame_idx < num_frames)
767 //                {
768 //                    exe_ctx.thread->SetSelectedFrameByIndex (frame_idx);
769 //                    exe_ctx.frame = exe_ctx.thread->GetSelectedFrame ().get();
770 //
771 //                    if (exe_ctx.frame)
772 //                    {
773 //                        if (DisplayFrameForExecutionContext (exe_ctx.thread,
774 //                                                             exe_ctx.frame,
775 //                                                             m_interpreter,
776 //                                                             result.GetOutputStream(),
777 //                                                             true,
778 //                                                             true,
779 //                                                             3,
780 //                                                             3))
781 //                        {
782 //                            result.SetStatus (eReturnStatusSuccessFinishResult);
783 //                            return result.Succeeded();
784 //                        }
785 //                    }
786 //                }
787 //                if (frame_idx == UINT32_MAX)
788 //                    result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr);
789 //                else
790 //                    result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
791 //            }
792 //            else
793 //            {
794 //                result.AppendError ("invalid arguments");
795 //                result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str());
796 //            }
797 //        }
798 //        else
799 //        {
800 //            result.AppendError ("no current thread");
801 //        }
802 //        result.SetStatus (eReturnStatusFailed);
803 //        return false;
804 //    }
805 //};
806 
807 
808 #pragma mark CommandObjectMultiwordImageSearchPaths
809 
810 //-------------------------------------------------------------------------
811 // CommandObjectMultiwordImageSearchPaths
812 //-------------------------------------------------------------------------
813 
814 class CommandObjectMultiwordImageSearchPaths : public CommandObjectMultiword
815 {
816 public:
817 
818     CommandObjectMultiwordImageSearchPaths (CommandInterpreter &interpreter) :
819         CommandObjectMultiword (interpreter,
820                                 "target image-search-paths",
821                                 "A set of commands for operating on debugger target image search paths.",
822                                 "target image-search-paths <subcommand> [<subcommand-options>]")
823     {
824         LoadSubCommand ("add",     CommandObjectSP (new CommandObjectTargetImageSearchPathsAdd (interpreter)));
825         LoadSubCommand ("clear",   CommandObjectSP (new CommandObjectTargetImageSearchPathsClear (interpreter)));
826         LoadSubCommand ("insert",  CommandObjectSP (new CommandObjectTargetImageSearchPathsInsert (interpreter)));
827         LoadSubCommand ("list",    CommandObjectSP (new CommandObjectTargetImageSearchPathsList (interpreter)));
828         LoadSubCommand ("query",   CommandObjectSP (new CommandObjectTargetImageSearchPathsQuery (interpreter)));
829     }
830 
831     ~CommandObjectMultiwordImageSearchPaths()
832     {
833     }
834 };
835 
836 #pragma mark CommandObjectTargetStopHookAdd
837 
838 //-------------------------------------------------------------------------
839 // CommandObjectTargetStopHookAdd
840 //-------------------------------------------------------------------------
841 
842 class CommandObjectTargetStopHookAdd : public CommandObject
843 {
844 public:
845 
846     class CommandOptions : public Options
847     {
848     public:
849         CommandOptions (CommandInterpreter &interpreter) :
850             Options(interpreter),
851             m_line_start(0),
852             m_line_end (UINT_MAX),
853             m_func_name_type_mask (eFunctionNameTypeAuto),
854             m_sym_ctx_specified (false),
855             m_thread_specified (false)
856         {
857         }
858 
859         ~CommandOptions () {}
860 
861         const OptionDefinition*
862         GetDefinitions ()
863         {
864             return g_option_table;
865         }
866 
867         virtual Error
868         SetOptionValue (uint32_t option_idx, const char *option_arg)
869         {
870             Error error;
871             char short_option = (char) m_getopt_table[option_idx].val;
872             bool success;
873 
874             switch (short_option)
875             {
876                 case 'c':
877                     m_class_name = option_arg;
878                     m_sym_ctx_specified = true;
879                 break;
880 
881                 case 'e':
882                     m_line_end = Args::StringToUInt32 (option_arg, UINT_MAX, 0, &success);
883                     if (!success)
884                     {
885                         error.SetErrorStringWithFormat ("Invalid end line number: \"%s\".", option_arg);
886                         break;
887                     }
888                     m_sym_ctx_specified = true;
889                 break;
890 
891                 case 'l':
892                     m_line_start = Args::StringToUInt32 (option_arg, 0, 0, &success);
893                     if (!success)
894                     {
895                         error.SetErrorStringWithFormat ("Invalid start line number: \"%s\".", option_arg);
896                         break;
897                     }
898                     m_sym_ctx_specified = true;
899                 break;
900 
901                 case 'n':
902                     m_function_name = option_arg;
903                     m_func_name_type_mask |= eFunctionNameTypeAuto;
904                     m_sym_ctx_specified = true;
905                 break;
906 
907                 case 'f':
908                     m_file_name = option_arg;
909                     m_sym_ctx_specified = true;
910                 break;
911                 case 's':
912                     m_module_name = option_arg;
913                     m_sym_ctx_specified = true;
914                 break;
915                 case 't' :
916                 {
917                     m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
918                     if (m_thread_id == LLDB_INVALID_THREAD_ID)
919                        error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", option_arg);
920                     m_thread_specified = true;
921                 }
922                 break;
923                 case 'T':
924                     m_thread_name = option_arg;
925                     m_thread_specified = true;
926                 break;
927                 case 'q':
928                     m_queue_name = option_arg;
929                     m_thread_specified = true;
930                     break;
931                 case 'x':
932                 {
933                     m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
934                     if (m_thread_id == UINT32_MAX)
935                        error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", option_arg);
936                     m_thread_specified = true;
937                 }
938                 break;
939                 default:
940                     error.SetErrorStringWithFormat ("Unrecognized option %c.");
941                 break;
942             }
943             return error;
944         }
945 
946         void
947         OptionParsingStarting ()
948         {
949             m_class_name.clear();
950             m_function_name.clear();
951             m_line_start = 0;
952             m_line_end = UINT_MAX;
953             m_file_name.clear();
954             m_module_name.clear();
955             m_func_name_type_mask = eFunctionNameTypeAuto;
956             m_thread_id = LLDB_INVALID_THREAD_ID;
957             m_thread_index = UINT32_MAX;
958             m_thread_name.clear();
959             m_queue_name.clear();
960 
961             m_sym_ctx_specified = false;
962             m_thread_specified = false;
963         }
964 
965 
966         static OptionDefinition g_option_table[];
967 
968         std::string m_class_name;
969         std::string m_function_name;
970         uint32_t    m_line_start;
971         uint32_t    m_line_end;
972         std::string m_file_name;
973         std::string m_module_name;
974         uint32_t m_func_name_type_mask;  // A pick from lldb::FunctionNameType.
975         lldb::tid_t m_thread_id;
976         uint32_t m_thread_index;
977         std::string m_thread_name;
978         std::string m_queue_name;
979         bool        m_sym_ctx_specified;
980         bool        m_thread_specified;
981 
982     };
983 
984     Options *
985     GetOptions ()
986     {
987         return &m_options;
988     }
989 
990     CommandObjectTargetStopHookAdd (CommandInterpreter &interpreter) :
991         CommandObject (interpreter,
992                        "target stop-hook add ",
993                        "Add a hook to be executed when the target stops.",
994                        "target stop-hook add"),
995         m_options (interpreter)
996     {
997     }
998 
999     ~CommandObjectTargetStopHookAdd ()
1000     {
1001     }
1002 
1003     static size_t
1004     ReadCommandsCallbackFunction (void *baton,
1005                                   InputReader &reader,
1006                                   lldb::InputReaderAction notification,
1007                                   const char *bytes,
1008                                   size_t bytes_len)
1009     {
1010         File &out_file = reader.GetDebugger().GetOutputFile();
1011         Target::StopHook *new_stop_hook = ((Target::StopHook *) baton);
1012 
1013         switch (notification)
1014         {
1015         case eInputReaderActivate:
1016             out_file.Printf ("%s\n", "Enter your stop hook command(s).  Type 'DONE' to end.");
1017             if (reader.GetPrompt())
1018                 out_file.Printf ("%s", reader.GetPrompt());
1019             out_file.Flush();
1020             break;
1021 
1022         case eInputReaderDeactivate:
1023             break;
1024 
1025         case eInputReaderReactivate:
1026             if (reader.GetPrompt())
1027             {
1028                 out_file.Printf ("%s", reader.GetPrompt());
1029                 out_file.Flush();
1030             }
1031             break;
1032 
1033         case eInputReaderGotToken:
1034             if (bytes && bytes_len && baton)
1035             {
1036                 StringList *commands = new_stop_hook->GetCommandPointer();
1037                 if (commands)
1038                 {
1039                     commands->AppendString (bytes, bytes_len);
1040                 }
1041             }
1042             if (!reader.IsDone() && reader.GetPrompt())
1043             {
1044                 out_file.Printf ("%s", reader.GetPrompt());
1045                 out_file.Flush();
1046             }
1047             break;
1048 
1049         case eInputReaderInterrupt:
1050             {
1051                 // Finish, and cancel the stop hook.
1052                 new_stop_hook->GetTarget()->RemoveStopHookByID(new_stop_hook->GetID());
1053                 out_file.Printf ("Stop hook cancelled.\n");
1054 
1055                 reader.SetIsDone (true);
1056             }
1057             break;
1058 
1059         case eInputReaderEndOfFile:
1060             reader.SetIsDone (true);
1061             break;
1062 
1063         case eInputReaderDone:
1064             out_file.Printf ("Stop hook #%d added.\n", new_stop_hook->GetID());
1065             break;
1066         }
1067 
1068         return bytes_len;
1069     }
1070 
1071     bool
1072     Execute (Args& command,
1073              CommandReturnObject &result)
1074     {
1075         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1076         if (target)
1077         {
1078             Target::StopHookSP new_hook_sp;
1079             target->AddStopHook (new_hook_sp);
1080 
1081             //  First step, make the specifier.
1082             std::auto_ptr<SymbolContextSpecifier> specifier_ap;
1083             if (m_options.m_sym_ctx_specified)
1084             {
1085                 specifier_ap.reset(new SymbolContextSpecifier(m_interpreter.GetDebugger().GetSelectedTarget()));
1086 
1087                 if (!m_options.m_module_name.empty())
1088                 {
1089                     specifier_ap->AddSpecification (m_options.m_module_name.c_str(), SymbolContextSpecifier::eModuleSpecified);
1090                 }
1091 
1092                 if (!m_options.m_class_name.empty())
1093                 {
1094                     specifier_ap->AddSpecification (m_options.m_class_name.c_str(), SymbolContextSpecifier::eClassOrNamespaceSpecified);
1095                 }
1096 
1097                 if (!m_options.m_file_name.empty())
1098                 {
1099                     specifier_ap->AddSpecification (m_options.m_file_name.c_str(), SymbolContextSpecifier::eFileSpecified);
1100                 }
1101 
1102                 if (m_options.m_line_start != 0)
1103                 {
1104                     specifier_ap->AddLineSpecification (m_options.m_line_start, SymbolContextSpecifier::eLineStartSpecified);
1105                 }
1106 
1107                 if (m_options.m_line_end != UINT_MAX)
1108                 {
1109                     specifier_ap->AddLineSpecification (m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
1110                 }
1111 
1112                 if (!m_options.m_function_name.empty())
1113                 {
1114                     specifier_ap->AddSpecification (m_options.m_function_name.c_str(), SymbolContextSpecifier::eFunctionSpecified);
1115                 }
1116             }
1117 
1118             if (specifier_ap.get())
1119                 new_hook_sp->SetSpecifier (specifier_ap.release());
1120 
1121             // Next see if any of the thread options have been entered:
1122 
1123             if (m_options.m_thread_specified)
1124             {
1125                 ThreadSpec *thread_spec = new ThreadSpec();
1126 
1127                 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
1128                 {
1129                     thread_spec->SetTID (m_options.m_thread_id);
1130                 }
1131 
1132                 if (m_options.m_thread_index != UINT32_MAX)
1133                     thread_spec->SetIndex (m_options.m_thread_index);
1134 
1135                 if (!m_options.m_thread_name.empty())
1136                     thread_spec->SetName (m_options.m_thread_name.c_str());
1137 
1138                 if (!m_options.m_queue_name.empty())
1139                     thread_spec->SetQueueName (m_options.m_queue_name.c_str());
1140 
1141                 new_hook_sp->SetThreadSpecifier (thread_spec);
1142 
1143             }
1144             // Next gather up the command list, we'll push an input reader and suck the data from that directly into
1145             // the new stop hook's command string.
1146 
1147             InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
1148             if (!reader_sp)
1149             {
1150                 result.AppendError("out of memory\n");
1151                 result.SetStatus (eReturnStatusFailed);
1152                 target->RemoveStopHookByID (new_hook_sp->GetID());
1153                 return false;
1154             }
1155 
1156             Error err (reader_sp->Initialize (CommandObjectTargetStopHookAdd::ReadCommandsCallbackFunction,
1157                                               new_hook_sp.get(), // baton
1158                                               eInputReaderGranularityLine,  // token size, to pass to callback function
1159                                               "DONE",                       // end token
1160                                               "> ",                         // prompt
1161                                               true));                       // echo input
1162             if (!err.Success())
1163             {
1164                 result.AppendError (err.AsCString());
1165                 result.SetStatus (eReturnStatusFailed);
1166                 target->RemoveStopHookByID (new_hook_sp->GetID());
1167                 return false;
1168             }
1169             m_interpreter.GetDebugger().PushInputReader (reader_sp);
1170 
1171             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1172         }
1173         else
1174         {
1175             result.AppendError ("invalid target\n");
1176             result.SetStatus (eReturnStatusFailed);
1177         }
1178 
1179         return result.Succeeded();
1180     }
1181 private:
1182     CommandOptions m_options;
1183 };
1184 
1185 OptionDefinition
1186 CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] =
1187 {
1188     { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
1189         "Set the module within which the stop-hook is to be run."},
1190     { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, NULL, eArgTypeThreadIndex,
1191         "The stop hook is run only for the thread whose index matches this argument."},
1192     { LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, NULL, eArgTypeThreadID,
1193         "The stop hook is run only for the thread whose TID matches this argument."},
1194     { LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, NULL, eArgTypeThreadName,
1195         "The stop hook is run only for the thread whose thread name matches this argument."},
1196     { LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, NULL, eArgTypeQueueName,
1197         "The stop hook is run only for threads in the queue whose name is given by this argument."},
1198     { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
1199         "Specify the source file within which the stop-hook is to be run." },
1200     { LLDB_OPT_SET_1, false, "start-line", 'l', required_argument, NULL, 0, eArgTypeLineNum,
1201         "Set the start of the line range for which the stop-hook is to be run."},
1202     { LLDB_OPT_SET_1, false, "end-line", 'e', required_argument, NULL, 0, eArgTypeLineNum,
1203         "Set the end of the line range for which the stop-hook is to be run."},
1204     { LLDB_OPT_SET_2, false, "classname", 'c', required_argument, NULL, NULL, eArgTypeClassName,
1205         "Specify the class within which the stop-hook is to be run." },
1206     { LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
1207         "Set the function name within which the stop hook will be run." },
1208     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1209 };
1210 
1211 #pragma mark CommandObjectTargetStopHookDelete
1212 
1213 //-------------------------------------------------------------------------
1214 // CommandObjectTargetStopHookDelete
1215 //-------------------------------------------------------------------------
1216 
1217 class CommandObjectTargetStopHookDelete : public CommandObject
1218 {
1219 public:
1220 
1221     CommandObjectTargetStopHookDelete (CommandInterpreter &interpreter) :
1222         CommandObject (interpreter,
1223                        "target stop-hook delete [<id>]",
1224                        "Delete a stop-hook.",
1225                        "target stop-hook delete")
1226     {
1227     }
1228 
1229     ~CommandObjectTargetStopHookDelete ()
1230     {
1231     }
1232 
1233     bool
1234     Execute (Args& command,
1235              CommandReturnObject &result)
1236     {
1237         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1238         if (target)
1239         {
1240             // FIXME: see if we can use the breakpoint id style parser?
1241             size_t num_args = command.GetArgumentCount();
1242             if (num_args == 0)
1243             {
1244                 if (!m_interpreter.Confirm ("Delete all stop hooks?", true))
1245                 {
1246                     result.SetStatus (eReturnStatusFailed);
1247                     return false;
1248                 }
1249                 else
1250                 {
1251                     target->RemoveAllStopHooks();
1252                 }
1253             }
1254             else
1255             {
1256                 bool success;
1257                 for (size_t i = 0; i < num_args; i++)
1258                 {
1259                     lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success);
1260                     if (!success)
1261                     {
1262                         result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i));
1263                         result.SetStatus(eReturnStatusFailed);
1264                         return false;
1265                     }
1266                     success = target->RemoveStopHookByID (user_id);
1267                     if (!success)
1268                     {
1269                         result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i));
1270                         result.SetStatus(eReturnStatusFailed);
1271                         return false;
1272                     }
1273                 }
1274             }
1275             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1276         }
1277         else
1278         {
1279             result.AppendError ("invalid target\n");
1280             result.SetStatus (eReturnStatusFailed);
1281         }
1282 
1283         return result.Succeeded();
1284     }
1285 };
1286 #pragma mark CommandObjectTargetStopHookEnableDisable
1287 
1288 //-------------------------------------------------------------------------
1289 // CommandObjectTargetStopHookEnableDisable
1290 //-------------------------------------------------------------------------
1291 
1292 class CommandObjectTargetStopHookEnableDisable : public CommandObject
1293 {
1294 public:
1295 
1296     CommandObjectTargetStopHookEnableDisable (CommandInterpreter &interpreter, bool enable, const char *name, const char *help, const char *syntax) :
1297         CommandObject (interpreter,
1298                        name,
1299                        help,
1300                        syntax),
1301         m_enable (enable)
1302     {
1303     }
1304 
1305     ~CommandObjectTargetStopHookEnableDisable ()
1306     {
1307     }
1308 
1309     bool
1310     Execute (Args& command,
1311              CommandReturnObject &result)
1312     {
1313         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1314         if (target)
1315         {
1316             // FIXME: see if we can use the breakpoint id style parser?
1317             size_t num_args = command.GetArgumentCount();
1318             bool success;
1319 
1320             if (num_args == 0)
1321             {
1322                 target->SetAllStopHooksActiveState (m_enable);
1323             }
1324             else
1325             {
1326                 for (size_t i = 0; i < num_args; i++)
1327                 {
1328                     lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success);
1329                     if (!success)
1330                     {
1331                         result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i));
1332                         result.SetStatus(eReturnStatusFailed);
1333                         return false;
1334                     }
1335                     success = target->SetStopHookActiveStateByID (user_id, m_enable);
1336                     if (!success)
1337                     {
1338                         result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i));
1339                         result.SetStatus(eReturnStatusFailed);
1340                         return false;
1341                     }
1342                 }
1343             }
1344             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1345         }
1346         else
1347         {
1348             result.AppendError ("invalid target\n");
1349             result.SetStatus (eReturnStatusFailed);
1350         }
1351         return result.Succeeded();
1352     }
1353 private:
1354     bool m_enable;
1355 };
1356 
1357 #pragma mark CommandObjectTargetStopHookList
1358 
1359 //-------------------------------------------------------------------------
1360 // CommandObjectTargetStopHookList
1361 //-------------------------------------------------------------------------
1362 
1363 class CommandObjectTargetStopHookList : public CommandObject
1364 {
1365 public:
1366 
1367     CommandObjectTargetStopHookList (CommandInterpreter &interpreter) :
1368         CommandObject (interpreter,
1369                        "target stop-hook list [<type>]",
1370                        "List all stop-hooks.",
1371                        "target stop-hook list")
1372     {
1373     }
1374 
1375     ~CommandObjectTargetStopHookList ()
1376     {
1377     }
1378 
1379     bool
1380     Execute (Args& command,
1381              CommandReturnObject &result)
1382     {
1383         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1384         if (target)
1385         {
1386             bool notify = true;
1387             target->GetImageSearchPathList().Clear(notify);
1388             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1389         }
1390         else
1391         {
1392             result.AppendError ("invalid target\n");
1393             result.SetStatus (eReturnStatusFailed);
1394         }
1395 
1396         size_t num_hooks = target->GetNumStopHooks ();
1397         if (num_hooks == 0)
1398         {
1399             result.GetOutputStream().PutCString ("No stop hooks.\n");
1400         }
1401         else
1402         {
1403             for (size_t i = 0; i < num_hooks; i++)
1404             {
1405                 Target::StopHookSP this_hook = target->GetStopHookAtIndex (i);
1406                 if (i > 0)
1407                     result.GetOutputStream().PutCString ("\n");
1408                 this_hook->GetDescription (&(result.GetOutputStream()), eDescriptionLevelFull);
1409             }
1410         }
1411         return result.Succeeded();
1412     }
1413 };
1414 
1415 #pragma mark CommandObjectMultiwordTargetStopHooks
1416 //-------------------------------------------------------------------------
1417 // CommandObjectMultiwordTargetStopHooks
1418 //-------------------------------------------------------------------------
1419 
1420 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword
1421 {
1422 public:
1423 
1424     CommandObjectMultiwordTargetStopHooks (CommandInterpreter &interpreter) :
1425         CommandObjectMultiword (interpreter,
1426                                 "target stop-hook",
1427                                 "A set of commands for operating on debugger target stop-hooks.",
1428                                 "target stop-hook <subcommand> [<subcommand-options>]")
1429     {
1430         LoadSubCommand ("add",      CommandObjectSP (new CommandObjectTargetStopHookAdd (interpreter)));
1431         LoadSubCommand ("delete",   CommandObjectSP (new CommandObjectTargetStopHookDelete (interpreter)));
1432         LoadSubCommand ("disable",  CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter,
1433                                                                                                    false,
1434                                                                                                    "target stop-hook disable [<id>]",
1435                                                                                                    "Disable a stop-hook.",
1436                                                                                                    "target stop-hook disable")));
1437         LoadSubCommand ("enable",   CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter,
1438                                                                                                    true,
1439                                                                                                    "target stop-hook enable [<id>]",
1440                                                                                                    "Enable a stop-hook.",
1441                                                                                                    "target stop-hook enable")));
1442         LoadSubCommand ("list",     CommandObjectSP (new CommandObjectTargetStopHookList (interpreter)));
1443     }
1444 
1445     ~CommandObjectMultiwordTargetStopHooks()
1446     {
1447     }
1448 };
1449 
1450 
1451 
1452 #pragma mark CommandObjectMultiwordTarget
1453 
1454 //-------------------------------------------------------------------------
1455 // CommandObjectMultiwordTarget
1456 //-------------------------------------------------------------------------
1457 
1458 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter &interpreter) :
1459     CommandObjectMultiword (interpreter,
1460                             "target",
1461                             "A set of commands for operating on debugger targets.",
1462                             "target <subcommand> [<subcommand-options>]")
1463 {
1464 
1465     LoadSubCommand ("create",    CommandObjectSP (new CommandObjectTargetCreate (interpreter)));
1466     LoadSubCommand ("list",      CommandObjectSP (new CommandObjectTargetList   (interpreter)));
1467     LoadSubCommand ("select",    CommandObjectSP (new CommandObjectTargetSelect (interpreter)));
1468     LoadSubCommand ("stop-hook", CommandObjectSP (new CommandObjectMultiwordTargetStopHooks (interpreter)));
1469     LoadSubCommand ("image-search-paths", CommandObjectSP (new CommandObjectMultiwordImageSearchPaths (interpreter)));
1470 }
1471 
1472 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget ()
1473 {
1474 }
1475 
1476 
1477