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/Section.h"
22 #include "lldb/Core/State.h"
23 #include "lldb/Core/Timer.h"
24 #include "lldb/Core/ValueObjectVariable.h"
25 #include "lldb/Interpreter/CommandInterpreter.h"
26 #include "lldb/Interpreter/CommandReturnObject.h"
27 #include "lldb/Interpreter/Options.h"
28 #include "lldb/Interpreter/OptionGroupArchitecture.h"
29 #include "lldb/Interpreter/OptionGroupBoolean.h"
30 #include "lldb/Interpreter/OptionGroupFile.h"
31 #include "lldb/Interpreter/OptionGroupFormat.h"
32 #include "lldb/Interpreter/OptionGroupVariable.h"
33 #include "lldb/Interpreter/OptionGroupPlatform.h"
34 #include "lldb/Interpreter/OptionGroupUInt64.h"
35 #include "lldb/Interpreter/OptionGroupUUID.h"
36 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
37 #include "lldb/Symbol/LineTable.h"
38 #include "lldb/Symbol/ObjectFile.h"
39 #include "lldb/Symbol/SymbolFile.h"
40 #include "lldb/Symbol/SymbolVendor.h"
41 #include "lldb/Symbol/VariableList.h"
42 #include "lldb/Target/Process.h"
43 #include "lldb/Target/StackFrame.h"
44 #include "lldb/Target/Thread.h"
45 #include "lldb/Target/ThreadSpec.h"
46 
47 using namespace lldb;
48 using namespace lldb_private;
49 
50 
51 
52 static void
53 DumpTargetInfo (uint32_t target_idx, Target *target, const char *prefix_cstr, bool show_stopped_process_status, Stream &strm)
54 {
55     const ArchSpec &target_arch = target->GetArchitecture();
56 
57     Module *exe_module = target->GetExecutableModulePointer();
58     char exe_path[PATH_MAX];
59     bool exe_valid = false;
60     if (exe_module)
61         exe_valid = exe_module->GetFileSpec().GetPath (exe_path, sizeof(exe_path));
62 
63     if (!exe_valid)
64         ::strcpy (exe_path, "<none>");
65 
66     strm.Printf ("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx, exe_path);
67 
68     uint32_t properties = 0;
69     if (target_arch.IsValid())
70     {
71         strm.Printf ("%sarch=%s", properties++ > 0 ? ", " : " ( ", target_arch.GetTriple().str().c_str());
72         properties++;
73     }
74     PlatformSP platform_sp (target->GetPlatform());
75     if (platform_sp)
76         strm.Printf ("%splatform=%s", properties++ > 0 ? ", " : " ( ", platform_sp->GetName());
77 
78     ProcessSP process_sp (target->GetProcessSP());
79     bool show_process_status = false;
80     if (process_sp)
81     {
82         lldb::pid_t pid = process_sp->GetID();
83         StateType state = process_sp->GetState();
84         if (show_stopped_process_status)
85             show_process_status = StateIsStoppedState(state, true);
86         const char *state_cstr = StateAsCString (state);
87         if (pid != LLDB_INVALID_PROCESS_ID)
88             strm.Printf ("%spid=%llu", properties++ > 0 ? ", " : " ( ", pid);
89         strm.Printf ("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr);
90     }
91     if (properties > 0)
92         strm.PutCString (" )\n");
93     else
94         strm.EOL();
95     if (show_process_status)
96     {
97         const bool only_threads_with_stop_reason = true;
98         const uint32_t start_frame = 0;
99         const uint32_t num_frames = 1;
100         const uint32_t num_frames_with_source = 1;
101         process_sp->GetStatus (strm);
102         process_sp->GetThreadStatus (strm,
103                                      only_threads_with_stop_reason,
104                                      start_frame,
105                                      num_frames,
106                                      num_frames_with_source);
107 
108     }
109 }
110 
111 static uint32_t
112 DumpTargetList (TargetList &target_list, bool show_stopped_process_status, Stream &strm)
113 {
114     const uint32_t num_targets = target_list.GetNumTargets();
115     if (num_targets)
116     {
117         TargetSP selected_target_sp (target_list.GetSelectedTarget());
118         strm.PutCString ("Current targets:\n");
119         for (uint32_t i=0; i<num_targets; ++i)
120         {
121             TargetSP target_sp (target_list.GetTargetAtIndex (i));
122             if (target_sp)
123             {
124                 bool is_selected = target_sp.get() == selected_target_sp.get();
125                 DumpTargetInfo (i,
126                                 target_sp.get(),
127                                 is_selected ? "* " : "  ",
128                                 show_stopped_process_status,
129                                 strm);
130             }
131         }
132     }
133     return num_targets;
134 }
135 #pragma mark CommandObjectTargetCreate
136 
137 //-------------------------------------------------------------------------
138 // "target create"
139 //-------------------------------------------------------------------------
140 
141 class CommandObjectTargetCreate : public CommandObject
142 {
143 public:
144     CommandObjectTargetCreate(CommandInterpreter &interpreter) :
145         CommandObject (interpreter,
146                        "target create",
147                        "Create a target using the argument as the main executable.",
148                        NULL),
149         m_option_group (interpreter),
150         m_arch_option (),
151         m_platform_options(true), // Do include the "--platform" option in the platform settings by passing true
152         m_core_file (LLDB_OPT_SET_1, false, "core-file", 'c', 0, eArgTypePath, "Fullpath to a core file to use for this target.")
153     {
154         CommandArgumentEntry arg;
155         CommandArgumentData file_arg;
156 
157         // Define the first (and only) variant of this arg.
158             file_arg.arg_type = eArgTypeFilename;
159         file_arg.arg_repetition = eArgRepeatPlain;
160 
161         // There is only one variant this argument could be; put it into the argument entry.
162         arg.push_back (file_arg);
163 
164         // Push the data for the first argument into the m_arguments vector.
165         m_arguments.push_back (arg);
166 
167         m_option_group.Append (&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
168         m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
169         m_option_group.Append (&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
170         m_option_group.Finalize();
171     }
172 
173     ~CommandObjectTargetCreate ()
174     {
175     }
176 
177     Options *
178     GetOptions ()
179     {
180         return &m_option_group;
181     }
182 
183     bool
184     Execute (Args& command, CommandReturnObject &result)
185     {
186         const int argc = command.GetArgumentCount();
187         FileSpec core_file (m_core_file.GetOptionValue().GetCurrentValue());
188 
189         if (argc == 1 || core_file)
190         {
191             const char *file_path = command.GetArgumentAtIndex(0);
192             Timer scoped_timer(__PRETTY_FUNCTION__, "(lldb) target create '%s'", file_path);
193             FileSpec file_spec;
194 
195             if (file_path)
196                 file_spec.SetFile (file_path, true);
197 
198             TargetSP target_sp;
199             Debugger &debugger = m_interpreter.GetDebugger();
200             const char *arch_cstr = m_arch_option.GetArchitectureName();
201             const bool get_dependent_files = true;
202             Error error (debugger.GetTargetList().CreateTarget (debugger,
203                                                                 file_spec,
204                                                                 arch_cstr,
205                                                                 get_dependent_files,
206                                                                 &m_platform_options,
207                                                                 target_sp));
208 
209             if (target_sp)
210             {
211                 debugger.GetTargetList().SetSelectedTarget(target_sp.get());
212                 if (core_file)
213                 {
214                     char core_path[PATH_MAX];
215                     core_file.GetPath(core_path, sizeof(core_path));
216                     if (core_file.Exists())
217                     {
218                         FileSpec core_file_dir;
219                         core_file_dir.GetDirectory() = core_file.GetDirectory();
220                         target_sp->GetExecutableSearchPaths ().Append (core_file_dir);
221 
222                         ProcessSP process_sp (target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), NULL, &core_file));
223 
224                         if (process_sp)
225                         {
226                             // Seems wierd that we Launch a core file, but that is
227                             // what we do!
228                             error = process_sp->LoadCore();
229 
230                             if (error.Fail())
231                             {
232                                 result.AppendError(error.AsCString("can't find plug-in for core file"));
233                                 result.SetStatus (eReturnStatusFailed);
234                                 return false;
235                             }
236                             else
237                             {
238                                 result.AppendMessageWithFormat ("Core file '%s' (%s) was loaded.\n", core_path, target_sp->GetArchitecture().GetArchitectureName());
239                                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
240                             }
241                         }
242                         else
243                         {
244                             result.AppendErrorWithFormat ("Unable to find process plug-in for core file '%s'\n", core_path);
245                             result.SetStatus (eReturnStatusFailed);
246                         }
247                     }
248                     else
249                     {
250                         result.AppendErrorWithFormat ("Core file '%s' does not exist\n", core_path);
251                         result.SetStatus (eReturnStatusFailed);
252                     }
253                 }
254                 else
255                 {
256                     result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, target_sp->GetArchitecture().GetArchitectureName());
257                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
258                 }
259             }
260             else
261             {
262                 result.AppendError(error.AsCString());
263                 result.SetStatus (eReturnStatusFailed);
264             }
265         }
266         else
267         {
268             result.AppendErrorWithFormat("'%s' takes exactly one executable path argument, or use the --core-file option.\n", m_cmd_name.c_str());
269             result.SetStatus (eReturnStatusFailed);
270         }
271         return result.Succeeded();
272 
273     }
274 
275     int
276     HandleArgumentCompletion (Args &input,
277                               int &cursor_index,
278                               int &cursor_char_position,
279                               OptionElementVector &opt_element_vector,
280                               int match_start_point,
281                               int max_return_elements,
282                               bool &word_complete,
283                               StringList &matches)
284     {
285         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
286         completion_str.erase (cursor_char_position);
287 
288         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
289                                                              CommandCompletions::eDiskFileCompletion,
290                                                              completion_str.c_str(),
291                                                              match_start_point,
292                                                              max_return_elements,
293                                                              NULL,
294                                                              word_complete,
295                                                              matches);
296         return matches.GetSize();
297     }
298 private:
299     OptionGroupOptions m_option_group;
300     OptionGroupArchitecture m_arch_option;
301     OptionGroupPlatform m_platform_options;
302     OptionGroupFile m_core_file;
303 
304 };
305 
306 #pragma mark CommandObjectTargetList
307 
308 //----------------------------------------------------------------------
309 // "target list"
310 //----------------------------------------------------------------------
311 
312 class CommandObjectTargetList : public CommandObject
313 {
314 public:
315     CommandObjectTargetList (CommandInterpreter &interpreter) :
316         CommandObject (interpreter,
317                        "target list",
318                        "List all current targets in the current debug session.",
319                        NULL,
320                        0)
321     {
322     }
323 
324     virtual
325     ~CommandObjectTargetList ()
326     {
327     }
328 
329     virtual bool
330     Execute (Args& args, CommandReturnObject &result)
331     {
332         if (args.GetArgumentCount() == 0)
333         {
334             Stream &strm = result.GetOutputStream();
335 
336             bool show_stopped_process_status = false;
337             if (DumpTargetList (m_interpreter.GetDebugger().GetTargetList(), show_stopped_process_status, strm) == 0)
338             {
339                 strm.PutCString ("No targets.\n");
340             }
341             result.SetStatus (eReturnStatusSuccessFinishResult);
342         }
343         else
344         {
345             result.AppendError ("the 'target list' command takes no arguments\n");
346             result.SetStatus (eReturnStatusFailed);
347         }
348         return result.Succeeded();
349     }
350 };
351 
352 
353 #pragma mark CommandObjectTargetSelect
354 
355 //----------------------------------------------------------------------
356 // "target select"
357 //----------------------------------------------------------------------
358 
359 class CommandObjectTargetSelect : public CommandObject
360 {
361 public:
362     CommandObjectTargetSelect (CommandInterpreter &interpreter) :
363         CommandObject (interpreter,
364                        "target select",
365                        "Select a target as the current target by target index.",
366                        NULL,
367                        0)
368     {
369     }
370 
371     virtual
372     ~CommandObjectTargetSelect ()
373     {
374     }
375 
376     virtual bool
377     Execute (Args& args, CommandReturnObject &result)
378     {
379         if (args.GetArgumentCount() == 1)
380         {
381             bool success = false;
382             const char *target_idx_arg = args.GetArgumentAtIndex(0);
383             uint32_t target_idx = Args::StringToUInt32 (target_idx_arg, UINT32_MAX, 0, &success);
384             if (success)
385             {
386                 TargetList &target_list = m_interpreter.GetDebugger().GetTargetList();
387                 const uint32_t num_targets = target_list.GetNumTargets();
388                 if (target_idx < num_targets)
389                 {
390                     TargetSP target_sp (target_list.GetTargetAtIndex (target_idx));
391                     if (target_sp)
392                     {
393                         Stream &strm = result.GetOutputStream();
394                         target_list.SetSelectedTarget (target_sp.get());
395                         bool show_stopped_process_status = false;
396                         DumpTargetList (target_list, show_stopped_process_status, strm);
397                         result.SetStatus (eReturnStatusSuccessFinishResult);
398                     }
399                     else
400                     {
401                         result.AppendErrorWithFormat ("target #%u is NULL in target list\n", target_idx);
402                         result.SetStatus (eReturnStatusFailed);
403                     }
404                 }
405                 else
406                 {
407                     result.AppendErrorWithFormat ("index %u is out of range, valid target indexes are 0 - %u\n",
408                                                   target_idx,
409                                                   num_targets - 1);
410                     result.SetStatus (eReturnStatusFailed);
411                 }
412             }
413             else
414             {
415                 result.AppendErrorWithFormat("invalid index string value '%s'\n", target_idx_arg);
416                 result.SetStatus (eReturnStatusFailed);
417             }
418         }
419         else
420         {
421             result.AppendError ("'target select' takes a single argument: a target index\n");
422             result.SetStatus (eReturnStatusFailed);
423         }
424         return result.Succeeded();
425     }
426 };
427 
428 #pragma mark CommandObjectTargetSelect
429 
430 //----------------------------------------------------------------------
431 // "target delete"
432 //----------------------------------------------------------------------
433 
434 class CommandObjectTargetDelete : public CommandObject
435 {
436 public:
437     CommandObjectTargetDelete (CommandInterpreter &interpreter) :
438         CommandObject (interpreter,
439                        "target delete",
440                        "Delete one or more targets by target index.",
441                        NULL,
442                        0),
443         m_option_group (interpreter),
444         m_cleanup_option (LLDB_OPT_SET_1, false, "clean", 'c', 0, eArgTypeNone, "Perform extra cleanup to minimize memory consumption after deleting the target.", false)
445     {
446         m_option_group.Append (&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
447         m_option_group.Finalize();
448     }
449 
450     virtual
451     ~CommandObjectTargetDelete ()
452     {
453     }
454 
455     virtual bool
456     Execute (Args& args, CommandReturnObject &result)
457     {
458         const size_t argc = args.GetArgumentCount();
459         std::vector<TargetSP> delete_target_list;
460         TargetList &target_list = m_interpreter.GetDebugger().GetTargetList();
461         bool success = true;
462         TargetSP target_sp;
463         if (argc > 0)
464         {
465             const uint32_t num_targets = target_list.GetNumTargets();
466             for (uint32_t arg_idx = 0; success && arg_idx < argc; ++arg_idx)
467             {
468                 const char *target_idx_arg = args.GetArgumentAtIndex(arg_idx);
469                 uint32_t target_idx = Args::StringToUInt32 (target_idx_arg, UINT32_MAX, 0, &success);
470                 if (success)
471                 {
472                     if (target_idx < num_targets)
473                     {
474                         target_sp = target_list.GetTargetAtIndex (target_idx);
475                         if (target_sp)
476                         {
477                             delete_target_list.push_back (target_sp);
478                             continue;
479                         }
480                     }
481                     result.AppendErrorWithFormat ("target index %u is out of range, valid target indexes are 0 - %u\n",
482                                                   target_idx,
483                                                   num_targets - 1);
484                     result.SetStatus (eReturnStatusFailed);
485                     success = false;
486                 }
487                 else
488                 {
489                     result.AppendErrorWithFormat("invalid target index '%s'\n", target_idx_arg);
490                     result.SetStatus (eReturnStatusFailed);
491                     success = false;
492                 }
493             }
494 
495         }
496         else
497         {
498             target_sp = target_list.GetSelectedTarget();
499             if (target_sp)
500             {
501                 delete_target_list.push_back (target_sp);
502             }
503             else
504             {
505                 result.AppendErrorWithFormat("no target is currently selected\n");
506                 result.SetStatus (eReturnStatusFailed);
507                 success = false;
508             }
509         }
510         if (success)
511         {
512             const size_t num_targets_to_delete = delete_target_list.size();
513             for (size_t idx = 0; idx < num_targets_to_delete; ++idx)
514             {
515                 target_sp = delete_target_list[idx];
516                 target_list.DeleteTarget(target_sp);
517                 target_sp->Destroy();
518             }
519             // If "--clean" was specified, prune any orphaned shared modules from
520             // the global shared module list
521             if (m_cleanup_option.GetOptionValue ())
522             {
523                 ModuleList::RemoveOrphanSharedModules();
524             }
525             result.GetOutputStream().Printf("%u targets deleted.\n", (uint32_t)num_targets_to_delete);
526             result.SetStatus(eReturnStatusSuccessFinishResult);
527         }
528 
529         return result.Succeeded();
530     }
531 
532     Options *
533     GetOptions ()
534     {
535         return &m_option_group;
536     }
537 
538 protected:
539     OptionGroupOptions m_option_group;
540     OptionGroupBoolean m_cleanup_option;
541 };
542 
543 
544 #pragma mark CommandObjectTargetVariable
545 
546 //----------------------------------------------------------------------
547 // "target variable"
548 //----------------------------------------------------------------------
549 
550 class CommandObjectTargetVariable : public CommandObject
551 {
552 public:
553     CommandObjectTargetVariable (CommandInterpreter &interpreter) :
554         CommandObject (interpreter,
555                        "target variable",
556                        "Read global variable(s) prior to running your binary.",
557                        NULL,
558                        0),
559         m_option_group (interpreter),
560         m_option_variable (false), // Don't include frame options
561         m_option_format (eFormatDefault),
562         m_option_compile_units    (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypePath, "A basename or fullpath to a file that contains global variables. This option can be specified multiple times."),
563         m_option_shared_libraries (LLDB_OPT_SET_1, false, "shlib",'s', 0, eArgTypePath, "A basename or fullpath to a shared library to use in the search for global variables. This option can be specified multiple times."),
564         m_varobj_options()
565     {
566         CommandArgumentEntry arg;
567         CommandArgumentData var_name_arg;
568 
569         // Define the first (and only) variant of this arg.
570         var_name_arg.arg_type = eArgTypeVarName;
571         var_name_arg.arg_repetition = eArgRepeatPlus;
572 
573         // There is only one variant this argument could be; put it into the argument entry.
574         arg.push_back (var_name_arg);
575 
576         // Push the data for the first argument into the m_arguments vector.
577         m_arguments.push_back (arg);
578 
579         m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
580         m_option_group.Append (&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
581         m_option_group.Append (&m_option_format, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1);
582         m_option_group.Append (&m_option_compile_units, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
583         m_option_group.Append (&m_option_shared_libraries, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
584         m_option_group.Finalize();
585     }
586 
587     virtual
588     ~CommandObjectTargetVariable ()
589     {
590     }
591 
592     void
593     DumpValueObject (Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp, const char *root_name)
594     {
595         ValueObject::DumpValueObjectOptions options;
596 
597         options.SetPointerDepth(m_varobj_options.ptr_depth)
598                .SetMaximumDepth(m_varobj_options.max_depth)
599                .SetShowTypes(m_varobj_options.show_types)
600                .SetShowLocation(m_varobj_options.show_location)
601                .SetUseObjectiveC(m_varobj_options.use_objc)
602                .SetUseDynamicType(m_varobj_options.use_dynamic)
603                .SetUseSyntheticValue((lldb::SyntheticValueType)m_varobj_options.use_synth)
604                .SetFlatOutput(m_varobj_options.flat_output)
605                .SetOmitSummaryDepth(m_varobj_options.no_summary_depth)
606                .SetIgnoreCap(m_varobj_options.ignore_cap);
607 
608         switch (var_sp->GetScope())
609         {
610             case eValueTypeVariableGlobal:
611                 if (m_option_variable.show_scope)
612                     s.PutCString("GLOBAL: ");
613                 break;
614 
615             case eValueTypeVariableStatic:
616                 if (m_option_variable.show_scope)
617                     s.PutCString("STATIC: ");
618                 break;
619 
620             case eValueTypeVariableArgument:
621                 if (m_option_variable.show_scope)
622                     s.PutCString("   ARG: ");
623                 break;
624 
625             case eValueTypeVariableLocal:
626                 if (m_option_variable.show_scope)
627                     s.PutCString(" LOCAL: ");
628                 break;
629 
630             default:
631                 break;
632         }
633 
634         if (m_option_variable.show_decl)
635         {
636             bool show_fullpaths = false;
637             bool show_module = true;
638             if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
639                 s.PutCString (": ");
640         }
641 
642         const Format format = m_option_format.GetFormat();
643         if (format != eFormatDefault)
644             valobj_sp->SetFormat (format);
645 
646         ValueObject::DumpValueObject (s,
647                                       valobj_sp.get(),
648                                       root_name,
649                                       options,
650                                       format);
651 
652     }
653 
654 
655     static uint32_t GetVariableCallback (void *baton,
656                                          const char *name,
657                                          VariableList &variable_list)
658     {
659         Target *target = static_cast<Target *>(baton);
660         if (target)
661         {
662             return target->GetImages().FindGlobalVariables (ConstString(name),
663                                                             true,
664                                                             UINT32_MAX,
665                                                             variable_list);
666         }
667         return 0;
668     }
669 
670 
671 
672     virtual bool
673     Execute (Args& args, CommandReturnObject &result)
674     {
675         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
676         Target *target = exe_ctx.GetTargetPtr();
677         if (target)
678         {
679             const size_t argc = args.GetArgumentCount();
680             Stream &s = result.GetOutputStream();
681             if (argc > 0)
682             {
683 
684                 for (size_t idx = 0; idx < argc; ++idx)
685                 {
686                     VariableList variable_list;
687                     ValueObjectList valobj_list;
688 
689                     const char *arg = args.GetArgumentAtIndex(idx);
690                     uint32_t matches = 0;
691                     bool use_var_name = false;
692                     if (m_option_variable.use_regex)
693                     {
694                         RegularExpression regex(arg);
695                         if (!regex.IsValid ())
696                         {
697                             result.GetErrorStream().Printf ("error: invalid regular expression: '%s'\n", arg);
698                             result.SetStatus (eReturnStatusFailed);
699                             return false;
700                         }
701                         use_var_name = true;
702                         matches = target->GetImages().FindGlobalVariables (regex,
703                                                                            true,
704                                                                            UINT32_MAX,
705                                                                            variable_list);
706                     }
707                     else
708                     {
709                         Error error (Variable::GetValuesForVariableExpressionPath (arg,
710                                                                                    exe_ctx.GetBestExecutionContextScope(),
711                                                                                    GetVariableCallback,
712                                                                                    target,
713                                                                                    variable_list,
714                                                                                    valobj_list));
715                         matches = variable_list.GetSize();
716                     }
717 
718                     if (matches == 0)
719                     {
720                         result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", arg);
721                         result.SetStatus (eReturnStatusFailed);
722                         return false;
723                     }
724                     else
725                     {
726                         for (uint32_t global_idx=0; global_idx<matches; ++global_idx)
727                         {
728                             VariableSP var_sp (variable_list.GetVariableAtIndex(global_idx));
729                             if (var_sp)
730                             {
731                                 ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(global_idx));
732                                 if (!valobj_sp)
733                                     valobj_sp = ValueObjectVariable::Create (exe_ctx.GetBestExecutionContextScope(), var_sp);
734 
735                                 if (valobj_sp)
736                                     DumpValueObject (s, var_sp, valobj_sp, use_var_name ? var_sp->GetName().GetCString() : arg);
737                             }
738                         }
739                     }
740                 }
741             }
742             else
743             {
744                 bool success = false;
745                 StackFrame *frame = exe_ctx.GetFramePtr();
746                 CompileUnit *comp_unit = NULL;
747                 if (frame)
748                 {
749                     comp_unit = frame->GetSymbolContext (eSymbolContextCompUnit).comp_unit;
750                     if (comp_unit)
751                     {
752                         const bool can_create = true;
753                         VariableListSP comp_unit_varlist_sp (comp_unit->GetVariableList(can_create));
754                         if (comp_unit_varlist_sp)
755                         {
756                             size_t count = comp_unit_varlist_sp->GetSize();
757                             if (count > 0)
758                             {
759                                 s.Printf ("Global variables for %s/%s:\n",
760                                           comp_unit->GetDirectory().GetCString(),
761                                           comp_unit->GetFilename().GetCString());
762 
763                                 success = true;
764                                 for (uint32_t i=0; i<count; ++i)
765                                 {
766                                     VariableSP var_sp (comp_unit_varlist_sp->GetVariableAtIndex(i));
767                                     if (var_sp)
768                                     {
769                                         ValueObjectSP valobj_sp (ValueObjectVariable::Create (exe_ctx.GetBestExecutionContextScope(), var_sp));
770 
771                                         if (valobj_sp)
772                                             DumpValueObject (s, var_sp, valobj_sp, var_sp->GetName().GetCString());
773                                     }
774                                 }
775                             }
776                         }
777                     }
778                 }
779                 if (!success)
780                 {
781                     if (frame)
782                     {
783                         if (comp_unit)
784                             result.AppendErrorWithFormat ("no global variables in current compile unit: %s/%s\n",
785                                                           comp_unit->GetDirectory().GetCString(),
786                                                           comp_unit->GetFilename().GetCString());
787                         else
788                             result.AppendError ("no debug information for frame %u\n", frame->GetFrameIndex());
789                     }
790                     else
791                         result.AppendError ("'target variable' takes one or more global variable names as arguments\n");
792                     result.SetStatus (eReturnStatusFailed);
793                 }
794             }
795         }
796         else
797         {
798             result.AppendError ("invalid target, create a debug target using the 'target create' command");
799             result.SetStatus (eReturnStatusFailed);
800             return false;
801         }
802 
803         if (m_interpreter.TruncationWarningNecessary())
804         {
805             result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
806                                             m_cmd_name.c_str());
807             m_interpreter.TruncationWarningGiven();
808         }
809 
810         return result.Succeeded();
811     }
812 
813     Options *
814     GetOptions ()
815     {
816         return &m_option_group;
817     }
818 
819 protected:
820     OptionGroupOptions m_option_group;
821     OptionGroupVariable m_option_variable;
822     OptionGroupFormat m_option_format;
823     OptionGroupFileList m_option_compile_units;
824     OptionGroupFileList m_option_shared_libraries;
825     OptionGroupValueObjectDisplay m_varobj_options;
826 
827 };
828 
829 
830 #pragma mark CommandObjectTargetModulesSearchPathsAdd
831 
832 class CommandObjectTargetModulesSearchPathsAdd : public CommandObject
833 {
834 public:
835 
836     CommandObjectTargetModulesSearchPathsAdd (CommandInterpreter &interpreter) :
837         CommandObject (interpreter,
838                        "target modules search-paths add",
839                        "Add new image search paths substitution pairs to the current target.",
840                        NULL)
841     {
842         CommandArgumentEntry arg;
843         CommandArgumentData old_prefix_arg;
844         CommandArgumentData new_prefix_arg;
845 
846         // Define the first variant of this arg pair.
847         old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
848         old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
849 
850         // Define the first variant of this arg pair.
851         new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
852         new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
853 
854         // There are two required arguments that must always occur together, i.e. an argument "pair".  Because they
855         // must always occur together, they are treated as two variants of one argument rather than two independent
856         // arguments.  Push them both into the first argument position for m_arguments...
857 
858         arg.push_back (old_prefix_arg);
859         arg.push_back (new_prefix_arg);
860 
861         m_arguments.push_back (arg);
862     }
863 
864     ~CommandObjectTargetModulesSearchPathsAdd ()
865     {
866     }
867 
868     bool
869     Execute (Args& command,
870              CommandReturnObject &result)
871     {
872         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
873         if (target)
874         {
875             uint32_t argc = command.GetArgumentCount();
876             if (argc & 1)
877             {
878                 result.AppendError ("add requires an even number of arguments\n");
879                 result.SetStatus (eReturnStatusFailed);
880             }
881             else
882             {
883                 for (uint32_t i=0; i<argc; i+=2)
884                 {
885                     const char *from = command.GetArgumentAtIndex(i);
886                     const char *to = command.GetArgumentAtIndex(i+1);
887 
888                     if (from[0] && to[0])
889                     {
890                         bool last_pair = ((argc - i) == 2);
891                         target->GetImageSearchPathList().Append (ConstString(from),
892                                                                  ConstString(to),
893                                                                  last_pair); // Notify if this is the last pair
894                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
895                     }
896                     else
897                     {
898                         if (from[0])
899                             result.AppendError ("<path-prefix> can't be empty\n");
900                         else
901                             result.AppendError ("<new-path-prefix> can't be empty\n");
902                         result.SetStatus (eReturnStatusFailed);
903                     }
904                 }
905             }
906         }
907         else
908         {
909             result.AppendError ("invalid target\n");
910             result.SetStatus (eReturnStatusFailed);
911         }
912         return result.Succeeded();
913     }
914 };
915 
916 #pragma mark CommandObjectTargetModulesSearchPathsClear
917 
918 class CommandObjectTargetModulesSearchPathsClear : public CommandObject
919 {
920 public:
921 
922     CommandObjectTargetModulesSearchPathsClear (CommandInterpreter &interpreter) :
923         CommandObject (interpreter,
924                        "target modules search-paths clear",
925                        "Clear all current image search path substitution pairs from the current target.",
926                        "target modules search-paths clear")
927     {
928     }
929 
930     ~CommandObjectTargetModulesSearchPathsClear ()
931     {
932     }
933 
934     bool
935     Execute (Args& command,
936              CommandReturnObject &result)
937     {
938         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
939         if (target)
940         {
941             bool notify = true;
942             target->GetImageSearchPathList().Clear(notify);
943             result.SetStatus (eReturnStatusSuccessFinishNoResult);
944         }
945         else
946         {
947             result.AppendError ("invalid target\n");
948             result.SetStatus (eReturnStatusFailed);
949         }
950         return result.Succeeded();
951     }
952 };
953 
954 #pragma mark CommandObjectTargetModulesSearchPathsInsert
955 
956 class CommandObjectTargetModulesSearchPathsInsert : public CommandObject
957 {
958 public:
959 
960     CommandObjectTargetModulesSearchPathsInsert (CommandInterpreter &interpreter) :
961         CommandObject (interpreter,
962                        "target modules search-paths insert",
963                        "Insert a new image search path substitution pair into the current target at the specified index.",
964                        NULL)
965     {
966         CommandArgumentEntry arg1;
967         CommandArgumentEntry arg2;
968         CommandArgumentData index_arg;
969         CommandArgumentData old_prefix_arg;
970         CommandArgumentData new_prefix_arg;
971 
972         // Define the first and only variant of this arg.
973         index_arg.arg_type = eArgTypeIndex;
974         index_arg.arg_repetition = eArgRepeatPlain;
975 
976         // Put the one and only variant into the first arg for m_arguments:
977         arg1.push_back (index_arg);
978 
979         // Define the first variant of this arg pair.
980         old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
981         old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
982 
983         // Define the first variant of this arg pair.
984         new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
985         new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
986 
987         // There are two required arguments that must always occur together, i.e. an argument "pair".  Because they
988         // must always occur together, they are treated as two variants of one argument rather than two independent
989         // arguments.  Push them both into the same argument position for m_arguments...
990 
991         arg2.push_back (old_prefix_arg);
992         arg2.push_back (new_prefix_arg);
993 
994         // Add arguments to m_arguments.
995         m_arguments.push_back (arg1);
996         m_arguments.push_back (arg2);
997     }
998 
999     ~CommandObjectTargetModulesSearchPathsInsert ()
1000     {
1001     }
1002 
1003     bool
1004     Execute (Args& command,
1005              CommandReturnObject &result)
1006     {
1007         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1008         if (target)
1009         {
1010             uint32_t argc = command.GetArgumentCount();
1011             // check for at least 3 arguments and an odd nubmer of parameters
1012             if (argc >= 3 && argc & 1)
1013             {
1014                 bool success = false;
1015 
1016                 uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
1017 
1018                 if (!success)
1019                 {
1020                     result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0));
1021                     result.SetStatus (eReturnStatusFailed);
1022                     return result.Succeeded();
1023                 }
1024 
1025                 // shift off the index
1026                 command.Shift();
1027                 argc = command.GetArgumentCount();
1028 
1029                 for (uint32_t i=0; i<argc; i+=2, ++insert_idx)
1030                 {
1031                     const char *from = command.GetArgumentAtIndex(i);
1032                     const char *to = command.GetArgumentAtIndex(i+1);
1033 
1034                     if (from[0] && to[0])
1035                     {
1036                         bool last_pair = ((argc - i) == 2);
1037                         target->GetImageSearchPathList().Insert (ConstString(from),
1038                                                                  ConstString(to),
1039                                                                  insert_idx,
1040                                                                  last_pair);
1041                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1042                     }
1043                     else
1044                     {
1045                         if (from[0])
1046                             result.AppendError ("<path-prefix> can't be empty\n");
1047                         else
1048                             result.AppendError ("<new-path-prefix> can't be empty\n");
1049                         result.SetStatus (eReturnStatusFailed);
1050                         return false;
1051                     }
1052                 }
1053             }
1054             else
1055             {
1056                 result.AppendError ("insert requires at least three arguments\n");
1057                 result.SetStatus (eReturnStatusFailed);
1058                 return result.Succeeded();
1059             }
1060 
1061         }
1062         else
1063         {
1064             result.AppendError ("invalid target\n");
1065             result.SetStatus (eReturnStatusFailed);
1066         }
1067         return result.Succeeded();
1068     }
1069 };
1070 
1071 
1072 #pragma mark CommandObjectTargetModulesSearchPathsList
1073 
1074 
1075 class CommandObjectTargetModulesSearchPathsList : public CommandObject
1076 {
1077 public:
1078 
1079     CommandObjectTargetModulesSearchPathsList (CommandInterpreter &interpreter) :
1080         CommandObject (interpreter,
1081                        "target modules search-paths list",
1082                        "List all current image search path substitution pairs in the current target.",
1083                        "target modules search-paths list")
1084     {
1085     }
1086 
1087     ~CommandObjectTargetModulesSearchPathsList ()
1088     {
1089     }
1090 
1091     bool
1092     Execute (Args& command,
1093              CommandReturnObject &result)
1094     {
1095         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1096         if (target)
1097         {
1098             if (command.GetArgumentCount() != 0)
1099             {
1100                 result.AppendError ("list takes no arguments\n");
1101                 result.SetStatus (eReturnStatusFailed);
1102                 return result.Succeeded();
1103             }
1104 
1105             target->GetImageSearchPathList().Dump(&result.GetOutputStream());
1106             result.SetStatus (eReturnStatusSuccessFinishResult);
1107         }
1108         else
1109         {
1110             result.AppendError ("invalid target\n");
1111             result.SetStatus (eReturnStatusFailed);
1112         }
1113         return result.Succeeded();
1114     }
1115 };
1116 
1117 #pragma mark CommandObjectTargetModulesSearchPathsQuery
1118 
1119 class CommandObjectTargetModulesSearchPathsQuery : public CommandObject
1120 {
1121 public:
1122 
1123     CommandObjectTargetModulesSearchPathsQuery (CommandInterpreter &interpreter) :
1124     CommandObject (interpreter,
1125                    "target modules search-paths query",
1126                    "Transform a path using the first applicable image search path.",
1127                    NULL)
1128     {
1129         CommandArgumentEntry arg;
1130         CommandArgumentData path_arg;
1131 
1132         // Define the first (and only) variant of this arg.
1133         path_arg.arg_type = eArgTypePath;
1134         path_arg.arg_repetition = eArgRepeatPlain;
1135 
1136         // There is only one variant this argument could be; put it into the argument entry.
1137         arg.push_back (path_arg);
1138 
1139         // Push the data for the first argument into the m_arguments vector.
1140         m_arguments.push_back (arg);
1141     }
1142 
1143     ~CommandObjectTargetModulesSearchPathsQuery ()
1144     {
1145     }
1146 
1147     bool
1148     Execute (Args& command,
1149              CommandReturnObject &result)
1150     {
1151         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1152         if (target)
1153         {
1154             if (command.GetArgumentCount() != 1)
1155             {
1156                 result.AppendError ("query requires one argument\n");
1157                 result.SetStatus (eReturnStatusFailed);
1158                 return result.Succeeded();
1159             }
1160 
1161             ConstString orig(command.GetArgumentAtIndex(0));
1162             ConstString transformed;
1163             if (target->GetImageSearchPathList().RemapPath(orig, transformed))
1164                 result.GetOutputStream().Printf("%s\n", transformed.GetCString());
1165             else
1166                 result.GetOutputStream().Printf("%s\n", orig.GetCString());
1167 
1168             result.SetStatus (eReturnStatusSuccessFinishResult);
1169         }
1170         else
1171         {
1172             result.AppendError ("invalid target\n");
1173             result.SetStatus (eReturnStatusFailed);
1174         }
1175         return result.Succeeded();
1176     }
1177 };
1178 
1179 //----------------------------------------------------------------------
1180 // Static Helper functions
1181 //----------------------------------------------------------------------
1182 static void
1183 DumpModuleArchitecture (Stream &strm, Module *module, bool full_triple, uint32_t width)
1184 {
1185     if (module)
1186     {
1187         const char *arch_cstr;
1188         if (full_triple)
1189             arch_cstr = module->GetArchitecture().GetTriple().str().c_str();
1190         else
1191             arch_cstr = module->GetArchitecture().GetArchitectureName();
1192         if (width)
1193             strm.Printf("%-*s", width, arch_cstr);
1194         else
1195             strm.PutCString(arch_cstr);
1196     }
1197 }
1198 
1199 static void
1200 DumpModuleUUID (Stream &strm, Module *module)
1201 {
1202     if (module->GetUUID().IsValid())
1203         module->GetUUID().Dump (&strm);
1204     else
1205         strm.PutCString("                                    ");
1206 }
1207 
1208 static uint32_t
1209 DumpCompileUnitLineTable
1210 (
1211  CommandInterpreter &interpreter,
1212  Stream &strm,
1213  Module *module,
1214  const FileSpec &file_spec,
1215  bool load_addresses
1216  )
1217 {
1218     uint32_t num_matches = 0;
1219     if (module)
1220     {
1221         SymbolContextList sc_list;
1222         num_matches = module->ResolveSymbolContextsForFileSpec (file_spec,
1223                                                                 0,
1224                                                                 false,
1225                                                                 eSymbolContextCompUnit,
1226                                                                 sc_list);
1227 
1228         for (uint32_t i=0; i<num_matches; ++i)
1229         {
1230             SymbolContext sc;
1231             if (sc_list.GetContextAtIndex(i, sc))
1232             {
1233                 if (i > 0)
1234                     strm << "\n\n";
1235 
1236                 strm << "Line table for " << *static_cast<FileSpec*> (sc.comp_unit) << " in `"
1237                 << module->GetFileSpec().GetFilename() << "\n";
1238                 LineTable *line_table = sc.comp_unit->GetLineTable();
1239                 if (line_table)
1240                     line_table->GetDescription (&strm,
1241                                                 interpreter.GetExecutionContext().GetTargetPtr(),
1242                                                 lldb::eDescriptionLevelBrief);
1243                 else
1244                     strm << "No line table";
1245             }
1246         }
1247     }
1248     return num_matches;
1249 }
1250 
1251 static void
1252 DumpFullpath (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
1253 {
1254     if (file_spec_ptr)
1255     {
1256         if (width > 0)
1257         {
1258             char fullpath[PATH_MAX];
1259             if (file_spec_ptr->GetPath(fullpath, sizeof(fullpath)))
1260             {
1261                 strm.Printf("%-*s", width, fullpath);
1262                 return;
1263             }
1264         }
1265         else
1266         {
1267             file_spec_ptr->Dump(&strm);
1268             return;
1269         }
1270     }
1271     // Keep the width spacing correct if things go wrong...
1272     if (width > 0)
1273         strm.Printf("%-*s", width, "");
1274 }
1275 
1276 static void
1277 DumpDirectory (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
1278 {
1279     if (file_spec_ptr)
1280     {
1281         if (width > 0)
1282             strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
1283         else
1284             file_spec_ptr->GetDirectory().Dump(&strm);
1285         return;
1286     }
1287     // Keep the width spacing correct if things go wrong...
1288     if (width > 0)
1289         strm.Printf("%-*s", width, "");
1290 }
1291 
1292 static void
1293 DumpBasename (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
1294 {
1295     if (file_spec_ptr)
1296     {
1297         if (width > 0)
1298             strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
1299         else
1300             file_spec_ptr->GetFilename().Dump(&strm);
1301         return;
1302     }
1303     // Keep the width spacing correct if things go wrong...
1304     if (width > 0)
1305         strm.Printf("%-*s", width, "");
1306 }
1307 
1308 
1309 static void
1310 DumpModuleSymtab (CommandInterpreter &interpreter, Stream &strm, Module *module, SortOrder sort_order)
1311 {
1312     if (module)
1313     {
1314         ObjectFile *objfile = module->GetObjectFile ();
1315         if (objfile)
1316         {
1317             Symtab *symtab = objfile->GetSymtab();
1318             if (symtab)
1319                 symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), sort_order);
1320         }
1321     }
1322 }
1323 
1324 static void
1325 DumpModuleSections (CommandInterpreter &interpreter, Stream &strm, Module *module)
1326 {
1327     if (module)
1328     {
1329         ObjectFile *objfile = module->GetObjectFile ();
1330         if (objfile)
1331         {
1332             SectionList *section_list = objfile->GetSectionList();
1333             if (section_list)
1334             {
1335                 strm.PutCString ("Sections for '");
1336                 strm << module->GetFileSpec();
1337                 if (module->GetObjectName())
1338                     strm << '(' << module->GetObjectName() << ')';
1339                 strm.Printf ("' (%s):\n", module->GetArchitecture().GetArchitectureName());
1340                 strm.IndentMore();
1341                 section_list->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), true, UINT32_MAX);
1342                 strm.IndentLess();
1343             }
1344         }
1345     }
1346 }
1347 
1348 static bool
1349 DumpModuleSymbolVendor (Stream &strm, Module *module)
1350 {
1351     if (module)
1352     {
1353         SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
1354         if (symbol_vendor)
1355         {
1356             symbol_vendor->Dump(&strm);
1357             return true;
1358         }
1359     }
1360     return false;
1361 }
1362 
1363 static bool
1364 LookupAddressInModule
1365 (
1366  CommandInterpreter &interpreter,
1367  Stream &strm,
1368  Module *module,
1369  uint32_t resolve_mask,
1370  lldb::addr_t raw_addr,
1371  lldb::addr_t offset,
1372  bool verbose
1373  )
1374 {
1375     if (module)
1376     {
1377         lldb::addr_t addr = raw_addr - offset;
1378         Address so_addr;
1379         SymbolContext sc;
1380         Target *target = interpreter.GetExecutionContext().GetTargetPtr();
1381         if (target && !target->GetSectionLoadList().IsEmpty())
1382         {
1383             if (!target->GetSectionLoadList().ResolveLoadAddress (addr, so_addr))
1384                 return false;
1385             else if (so_addr.GetModulePtr() != module)
1386                 return false;
1387         }
1388         else
1389         {
1390             if (!module->ResolveFileAddress (addr, so_addr))
1391                 return false;
1392         }
1393 
1394         ExecutionContextScope *exe_scope = interpreter.GetExecutionContext().GetBestExecutionContextScope();
1395         strm.IndentMore();
1396         strm.Indent ("    Address: ");
1397         so_addr.Dump (&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
1398         strm.PutCString (" (");
1399         so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset);
1400         strm.PutCString (")\n");
1401         strm.Indent ("    Summary: ");
1402         const uint32_t save_indent = strm.GetIndentLevel ();
1403         strm.SetIndentLevel (save_indent + 13);
1404         so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription);
1405         strm.SetIndentLevel (save_indent);
1406         // Print out detailed address information when verbose is enabled
1407         if (verbose)
1408         {
1409             strm.EOL();
1410             so_addr.Dump (&strm, exe_scope, Address::DumpStyleDetailedSymbolContext);
1411         }
1412         strm.IndentLess();
1413         return true;
1414     }
1415 
1416     return false;
1417 }
1418 
1419 static uint32_t
1420 LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex)
1421 {
1422     if (module)
1423     {
1424         SymbolContext sc;
1425 
1426         ObjectFile *objfile = module->GetObjectFile ();
1427         if (objfile)
1428         {
1429             Symtab *symtab = objfile->GetSymtab();
1430             if (symtab)
1431             {
1432                 uint32_t i;
1433                 std::vector<uint32_t> match_indexes;
1434                 ConstString symbol_name (name);
1435                 uint32_t num_matches = 0;
1436                 if (name_is_regex)
1437                 {
1438                     RegularExpression name_regexp(name);
1439                     num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType (name_regexp,
1440                                                                                    eSymbolTypeAny,
1441                                                                                    match_indexes);
1442                 }
1443                 else
1444                 {
1445                     num_matches = symtab->AppendSymbolIndexesWithName (symbol_name, match_indexes);
1446                 }
1447 
1448 
1449                 if (num_matches > 0)
1450                 {
1451                     strm.Indent ();
1452                     strm.Printf("%u symbols match %s'%s' in ", num_matches,
1453                                 name_is_regex ? "the regular expression " : "", name);
1454                     DumpFullpath (strm, &module->GetFileSpec(), 0);
1455                     strm.PutCString(":\n");
1456                     strm.IndentMore ();
1457                     Symtab::DumpSymbolHeader (&strm);
1458                     for (i=0; i < num_matches; ++i)
1459                     {
1460                         Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
1461                         strm.Indent ();
1462                         symbol->Dump (&strm, interpreter.GetExecutionContext().GetTargetPtr(), i);
1463                     }
1464                     strm.IndentLess ();
1465                     return num_matches;
1466                 }
1467             }
1468         }
1469     }
1470     return 0;
1471 }
1472 
1473 
1474 static void
1475 DumpSymbolContextList (CommandInterpreter &interpreter, Stream &strm, SymbolContextList &sc_list, bool prepend_addr, bool verbose)
1476 {
1477     strm.IndentMore ();
1478     uint32_t i;
1479     const uint32_t num_matches = sc_list.GetSize();
1480 
1481     for (i=0; i<num_matches; ++i)
1482     {
1483         SymbolContext sc;
1484         if (sc_list.GetContextAtIndex(i, sc))
1485         {
1486             strm.Indent();
1487             ExecutionContextScope *exe_scope = interpreter.GetExecutionContext().GetBestExecutionContextScope ();
1488 
1489             if (prepend_addr)
1490             {
1491                 if (sc.line_entry.range.GetBaseAddress().IsValid())
1492                 {
1493                     sc.line_entry.range.GetBaseAddress().Dump (&strm,
1494                                                                exe_scope,
1495                                                                Address::DumpStyleLoadAddress,
1496                                                                Address::DumpStyleModuleWithFileAddress);
1497                     strm.PutCString(" in ");
1498                 }
1499             }
1500 
1501             AddressRange range;
1502 
1503             sc.GetAddressRange(eSymbolContextEverything,
1504                                0,
1505                                true,
1506                                range);
1507 
1508             sc.DumpStopContext(&strm,
1509                                exe_scope,
1510                                range.GetBaseAddress(),
1511                                true,
1512                                true,
1513                                false);
1514 
1515             strm.EOL();
1516             if (verbose)
1517             {
1518                 if (sc.line_entry.range.GetBaseAddress().IsValid())
1519                 {
1520                     if (sc.line_entry.range.GetBaseAddress().Dump (&strm,
1521                                                                    exe_scope,
1522                                                                    Address::DumpStyleDetailedSymbolContext))
1523                         strm.PutCString("\n\n");
1524                 }
1525                 else if (sc.function->GetAddressRange().GetBaseAddress().IsValid())
1526                 {
1527                     if (sc.function->GetAddressRange().GetBaseAddress().Dump (&strm,
1528                                                                               exe_scope,
1529                                                                               Address::DumpStyleDetailedSymbolContext))
1530                         strm.PutCString("\n\n");
1531                 }
1532             }
1533         }
1534     }
1535     strm.IndentLess ();
1536 }
1537 
1538 static uint32_t
1539 LookupFunctionInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex, bool include_inlines, bool verbose)
1540 {
1541     if (module && name && name[0])
1542     {
1543         SymbolContextList sc_list;
1544         const bool include_symbols = false;
1545         const bool append = true;
1546         uint32_t num_matches = 0;
1547         if (name_is_regex)
1548         {
1549             RegularExpression function_name_regex (name);
1550             num_matches = module->FindFunctions (function_name_regex,
1551                                                  include_symbols,
1552                                                  include_inlines,
1553                                                  append,
1554                                                  sc_list);
1555         }
1556         else
1557         {
1558             ConstString function_name (name);
1559             num_matches = module->FindFunctions (function_name,
1560                                                  NULL,
1561                                                  eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
1562                                                  include_symbols,
1563                                                  include_inlines,
1564                                                  append,
1565                                                  sc_list);
1566         }
1567 
1568         if (num_matches)
1569         {
1570             strm.Indent ();
1571             strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
1572             DumpFullpath (strm, &module->GetFileSpec(), 0);
1573             strm.PutCString(":\n");
1574             DumpSymbolContextList (interpreter, strm, sc_list, true, verbose);
1575         }
1576         return num_matches;
1577     }
1578     return 0;
1579 }
1580 
1581 static uint32_t
1582 LookupTypeInModule (CommandInterpreter &interpreter,
1583                     Stream &strm,
1584                     Module *module,
1585                     const char *name_cstr,
1586                     bool name_is_regex)
1587 {
1588     if (module && name_cstr && name_cstr[0])
1589     {
1590         TypeList type_list;
1591         const uint32_t max_num_matches = 1;
1592         uint32_t num_matches = 0;
1593         SymbolContext sc;
1594 
1595         ConstString name(name_cstr);
1596         num_matches = module->FindTypes(sc, name, NULL, true, max_num_matches, type_list);
1597 
1598         if (num_matches)
1599         {
1600             strm.Indent ();
1601             strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
1602             DumpFullpath (strm, &module->GetFileSpec(), 0);
1603             strm.PutCString(":\n");
1604             const uint32_t num_types = type_list.GetSize();
1605             for (uint32_t i=0; i<num_types; ++i)
1606             {
1607                 TypeSP type_sp (type_list.GetTypeAtIndex(i));
1608                 if (type_sp)
1609                 {
1610                     // Resolve the clang type so that any forward references
1611                     // to types that haven't yet been parsed will get parsed.
1612                     type_sp->GetClangFullType ();
1613                     type_sp->GetDescription (&strm, eDescriptionLevelFull, true);
1614                 }
1615                 strm.EOL();
1616             }
1617         }
1618         return num_matches;
1619     }
1620     return 0;
1621 }
1622 
1623 static uint32_t
1624 LookupFileAndLineInModule (CommandInterpreter &interpreter,
1625                            Stream &strm,
1626                            Module *module,
1627                            const FileSpec &file_spec,
1628                            uint32_t line,
1629                            bool check_inlines,
1630                            bool verbose)
1631 {
1632     if (module && file_spec)
1633     {
1634         SymbolContextList sc_list;
1635         const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
1636                                                                               eSymbolContextEverything, sc_list);
1637         if (num_matches > 0)
1638         {
1639             strm.Indent ();
1640             strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
1641             strm << file_spec;
1642             if (line > 0)
1643                 strm.Printf (":%u", line);
1644             strm << " in ";
1645             DumpFullpath (strm, &module->GetFileSpec(), 0);
1646             strm.PutCString(":\n");
1647             DumpSymbolContextList (interpreter, strm, sc_list, true, verbose);
1648             return num_matches;
1649         }
1650     }
1651     return 0;
1652 
1653 }
1654 
1655 
1656 static size_t
1657 FindModulesByName (Target *target,
1658                    const char *module_name,
1659                    ModuleList &module_list,
1660                    bool check_global_list)
1661 {
1662 // Dump specified images (by basename or fullpath)
1663     FileSpec module_file_spec(module_name, false);
1664 
1665     const size_t initial_size = module_list.GetSize ();
1666 
1667     size_t num_matches = 0;
1668 
1669     if (target)
1670     {
1671         num_matches = target->GetImages().FindModules (&module_file_spec,
1672                                                        NULL,
1673                                                        NULL,
1674                                                        NULL,
1675                                                        module_list);
1676 
1677         // Not found in our module list for our target, check the main
1678         // shared module list in case it is a extra file used somewhere
1679         // else
1680         if (num_matches == 0)
1681             num_matches = ModuleList::FindSharedModules (module_file_spec,
1682                                                          target->GetArchitecture(),
1683                                                          NULL,
1684                                                          NULL,
1685                                                          module_list);
1686     }
1687     else
1688     {
1689         num_matches = ModuleList::FindSharedModules (module_file_spec,
1690                                                      ArchSpec(),
1691                                                      NULL,
1692                                                      NULL,
1693                                                      module_list);
1694     }
1695 
1696     if (check_global_list && num_matches == 0)
1697     {
1698         // Check the global list
1699         Mutex::Locker locker(Module::GetAllocationModuleCollectionMutex());
1700         const uint32_t num_modules = Module::GetNumberAllocatedModules();
1701         ModuleSP module_sp;
1702         for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
1703         {
1704             Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
1705 
1706             if (module)
1707             {
1708                 if (FileSpec::Equal(module->GetFileSpec(), module_file_spec, true))
1709                 {
1710                     module_sp = module->shared_from_this();
1711                     module_list.AppendIfNeeded(module_sp);
1712                 }
1713             }
1714         }
1715     }
1716     return module_list.GetSize () - initial_size;
1717 }
1718 
1719 #pragma mark CommandObjectTargetModulesModuleAutoComplete
1720 
1721 //----------------------------------------------------------------------
1722 // A base command object class that can auto complete with module file
1723 // paths
1724 //----------------------------------------------------------------------
1725 
1726 class CommandObjectTargetModulesModuleAutoComplete : public CommandObject
1727 {
1728 public:
1729 
1730     CommandObjectTargetModulesModuleAutoComplete (CommandInterpreter &interpreter,
1731                                       const char *name,
1732                                       const char *help,
1733                                       const char *syntax) :
1734     CommandObject (interpreter, name, help, syntax)
1735     {
1736         CommandArgumentEntry arg;
1737         CommandArgumentData file_arg;
1738 
1739         // Define the first (and only) variant of this arg.
1740         file_arg.arg_type = eArgTypeFilename;
1741         file_arg.arg_repetition = eArgRepeatStar;
1742 
1743         // There is only one variant this argument could be; put it into the argument entry.
1744         arg.push_back (file_arg);
1745 
1746         // Push the data for the first argument into the m_arguments vector.
1747         m_arguments.push_back (arg);
1748     }
1749 
1750     virtual
1751     ~CommandObjectTargetModulesModuleAutoComplete ()
1752     {
1753     }
1754 
1755     virtual int
1756     HandleArgumentCompletion (Args &input,
1757                               int &cursor_index,
1758                               int &cursor_char_position,
1759                               OptionElementVector &opt_element_vector,
1760                               int match_start_point,
1761                               int max_return_elements,
1762                               bool &word_complete,
1763                               StringList &matches)
1764     {
1765         // Arguments are the standard module completer.
1766         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
1767         completion_str.erase (cursor_char_position);
1768 
1769         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
1770                                                              CommandCompletions::eModuleCompletion,
1771                                                              completion_str.c_str(),
1772                                                              match_start_point,
1773                                                              max_return_elements,
1774                                                              NULL,
1775                                                              word_complete,
1776                                                              matches);
1777         return matches.GetSize();
1778     }
1779 };
1780 
1781 #pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1782 
1783 //----------------------------------------------------------------------
1784 // A base command object class that can auto complete with module source
1785 // file paths
1786 //----------------------------------------------------------------------
1787 
1788 class CommandObjectTargetModulesSourceFileAutoComplete : public CommandObject
1789 {
1790 public:
1791 
1792     CommandObjectTargetModulesSourceFileAutoComplete (CommandInterpreter &interpreter,
1793                                           const char *name,
1794                                           const char *help,
1795                                           const char *syntax) :
1796     CommandObject (interpreter, name, help, syntax)
1797     {
1798         CommandArgumentEntry arg;
1799         CommandArgumentData source_file_arg;
1800 
1801         // Define the first (and only) variant of this arg.
1802         source_file_arg.arg_type = eArgTypeSourceFile;
1803         source_file_arg.arg_repetition = eArgRepeatPlus;
1804 
1805         // There is only one variant this argument could be; put it into the argument entry.
1806         arg.push_back (source_file_arg);
1807 
1808         // Push the data for the first argument into the m_arguments vector.
1809         m_arguments.push_back (arg);
1810     }
1811 
1812     virtual
1813     ~CommandObjectTargetModulesSourceFileAutoComplete ()
1814     {
1815     }
1816 
1817     virtual int
1818     HandleArgumentCompletion (Args &input,
1819                               int &cursor_index,
1820                               int &cursor_char_position,
1821                               OptionElementVector &opt_element_vector,
1822                               int match_start_point,
1823                               int max_return_elements,
1824                               bool &word_complete,
1825                               StringList &matches)
1826     {
1827         // Arguments are the standard source file completer.
1828         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
1829         completion_str.erase (cursor_char_position);
1830 
1831         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
1832                                                              CommandCompletions::eSourceFileCompletion,
1833                                                              completion_str.c_str(),
1834                                                              match_start_point,
1835                                                              max_return_elements,
1836                                                              NULL,
1837                                                              word_complete,
1838                                                              matches);
1839         return matches.GetSize();
1840     }
1841 };
1842 
1843 
1844 #pragma mark CommandObjectTargetModulesDumpSymtab
1845 
1846 
1847 class CommandObjectTargetModulesDumpSymtab : public CommandObjectTargetModulesModuleAutoComplete
1848 {
1849 public:
1850     CommandObjectTargetModulesDumpSymtab (CommandInterpreter &interpreter) :
1851     CommandObjectTargetModulesModuleAutoComplete (interpreter,
1852                                       "target modules dump symtab",
1853                                       "Dump the symbol table from one or more target modules.",
1854                                       NULL),
1855     m_options (interpreter)
1856     {
1857     }
1858 
1859     virtual
1860     ~CommandObjectTargetModulesDumpSymtab ()
1861     {
1862     }
1863 
1864     virtual bool
1865     Execute (Args& command,
1866              CommandReturnObject &result)
1867     {
1868         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1869         if (target == NULL)
1870         {
1871             result.AppendError ("invalid target, create a debug target using the 'target create' command");
1872             result.SetStatus (eReturnStatusFailed);
1873             return false;
1874         }
1875         else
1876         {
1877             uint32_t num_dumped = 0;
1878 
1879             uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1880             result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1881             result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1882 
1883             if (command.GetArgumentCount() == 0)
1884             {
1885                 // Dump all sections for all modules images
1886                 const uint32_t num_modules = target->GetImages().GetSize();
1887                 if (num_modules > 0)
1888                 {
1889                     result.GetOutputStream().Printf("Dumping symbol table for %u modules.\n", num_modules);
1890                     for (uint32_t image_idx = 0;  image_idx<num_modules; ++image_idx)
1891                     {
1892                         if (num_dumped > 0)
1893                         {
1894                             result.GetOutputStream().EOL();
1895                             result.GetOutputStream().EOL();
1896                         }
1897                         num_dumped++;
1898                         DumpModuleSymtab (m_interpreter, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx), m_options.m_sort_order);
1899                     }
1900                 }
1901                 else
1902                 {
1903                     result.AppendError ("the target has no associated executable images");
1904                     result.SetStatus (eReturnStatusFailed);
1905                     return false;
1906                 }
1907             }
1908             else
1909             {
1910                 // Dump specified images (by basename or fullpath)
1911                 const char *arg_cstr;
1912                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
1913                 {
1914                     ModuleList module_list;
1915                     const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, true);
1916                     if (num_matches > 0)
1917                     {
1918                         for (size_t i=0; i<num_matches; ++i)
1919                         {
1920                             Module *module = module_list.GetModulePointerAtIndex(i);
1921                             if (module)
1922                             {
1923                                 if (num_dumped > 0)
1924                                 {
1925                                     result.GetOutputStream().EOL();
1926                                     result.GetOutputStream().EOL();
1927                                 }
1928                                 num_dumped++;
1929                                 DumpModuleSymtab (m_interpreter, result.GetOutputStream(), module, m_options.m_sort_order);
1930                             }
1931                         }
1932                     }
1933                     else
1934                         result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
1935                 }
1936             }
1937 
1938             if (num_dumped > 0)
1939                 result.SetStatus (eReturnStatusSuccessFinishResult);
1940             else
1941             {
1942                 result.AppendError ("no matching executable images found");
1943                 result.SetStatus (eReturnStatusFailed);
1944             }
1945         }
1946         return result.Succeeded();
1947     }
1948 
1949     virtual Options *
1950     GetOptions ()
1951     {
1952         return &m_options;
1953     }
1954 
1955     class CommandOptions : public Options
1956     {
1957     public:
1958 
1959         CommandOptions (CommandInterpreter &interpreter) :
1960         Options(interpreter),
1961         m_sort_order (eSortOrderNone)
1962         {
1963         }
1964 
1965         virtual
1966         ~CommandOptions ()
1967         {
1968         }
1969 
1970         virtual Error
1971         SetOptionValue (uint32_t option_idx, const char *option_arg)
1972         {
1973             Error error;
1974             char short_option = (char) m_getopt_table[option_idx].val;
1975 
1976             switch (short_option)
1977             {
1978                 case 's':
1979                     m_sort_order = (SortOrder) Args::StringToOptionEnum (option_arg,
1980                                                                          g_option_table[option_idx].enum_values,
1981                                                                          eSortOrderNone,
1982                                                                          error);
1983                     break;
1984 
1985                 default:
1986                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1987                     break;
1988 
1989             }
1990             return error;
1991         }
1992 
1993         void
1994         OptionParsingStarting ()
1995         {
1996             m_sort_order = eSortOrderNone;
1997         }
1998 
1999         const OptionDefinition*
2000         GetDefinitions ()
2001         {
2002             return g_option_table;
2003         }
2004 
2005         // Options table: Required for subclasses of Options.
2006         static OptionDefinition g_option_table[];
2007 
2008         SortOrder m_sort_order;
2009     };
2010 
2011 protected:
2012 
2013     CommandOptions m_options;
2014 };
2015 
2016 static OptionEnumValueElement
2017 g_sort_option_enumeration[4] =
2018 {
2019     { eSortOrderNone,       "none",     "No sorting, use the original symbol table order."},
2020     { eSortOrderByAddress,  "address",  "Sort output by symbol address."},
2021     { eSortOrderByName,     "name",     "Sort output by symbol name."},
2022     { 0,                    NULL,       NULL }
2023 };
2024 
2025 
2026 OptionDefinition
2027 CommandObjectTargetModulesDumpSymtab::CommandOptions::g_option_table[] =
2028 {
2029     { LLDB_OPT_SET_1, false, "sort", 's', required_argument, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table."},
2030     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2031 };
2032 
2033 #pragma mark CommandObjectTargetModulesDumpSections
2034 
2035 //----------------------------------------------------------------------
2036 // Image section dumping command
2037 //----------------------------------------------------------------------
2038 
2039 class CommandObjectTargetModulesDumpSections : public CommandObjectTargetModulesModuleAutoComplete
2040 {
2041 public:
2042     CommandObjectTargetModulesDumpSections (CommandInterpreter &interpreter) :
2043     CommandObjectTargetModulesModuleAutoComplete (interpreter,
2044                                       "target modules dump sections",
2045                                       "Dump the sections from one or more target modules.",
2046                                       //"target modules dump sections [<file1> ...]")
2047                                       NULL)
2048     {
2049     }
2050 
2051     virtual
2052     ~CommandObjectTargetModulesDumpSections ()
2053     {
2054     }
2055 
2056     virtual bool
2057     Execute (Args& command,
2058              CommandReturnObject &result)
2059     {
2060         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2061         if (target == NULL)
2062         {
2063             result.AppendError ("invalid target, create a debug target using the 'target create' command");
2064             result.SetStatus (eReturnStatusFailed);
2065             return false;
2066         }
2067         else
2068         {
2069             uint32_t num_dumped = 0;
2070 
2071             uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2072             result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2073             result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2074 
2075             if (command.GetArgumentCount() == 0)
2076             {
2077                 // Dump all sections for all modules images
2078                 const uint32_t num_modules = target->GetImages().GetSize();
2079                 if (num_modules > 0)
2080                 {
2081                     result.GetOutputStream().Printf("Dumping sections for %u modules.\n", num_modules);
2082                     for (uint32_t image_idx = 0;  image_idx<num_modules; ++image_idx)
2083                     {
2084                         num_dumped++;
2085                         DumpModuleSections (m_interpreter, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
2086                     }
2087                 }
2088                 else
2089                 {
2090                     result.AppendError ("the target has no associated executable images");
2091                     result.SetStatus (eReturnStatusFailed);
2092                     return false;
2093                 }
2094             }
2095             else
2096             {
2097                 // Dump specified images (by basename or fullpath)
2098                 const char *arg_cstr;
2099                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
2100                 {
2101                     ModuleList module_list;
2102                     const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, true);
2103                     if (num_matches > 0)
2104                     {
2105                         for (size_t i=0; i<num_matches; ++i)
2106                         {
2107                             Module *module = module_list.GetModulePointerAtIndex(i);
2108                             if (module)
2109                             {
2110                                 num_dumped++;
2111                                 DumpModuleSections (m_interpreter, result.GetOutputStream(), module);
2112                             }
2113                         }
2114                     }
2115                     else
2116                     {
2117                         // Check the global list
2118                         Mutex::Locker locker(Module::GetAllocationModuleCollectionMutex());
2119 
2120                         result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
2121                     }
2122                 }
2123             }
2124 
2125             if (num_dumped > 0)
2126                 result.SetStatus (eReturnStatusSuccessFinishResult);
2127             else
2128             {
2129                 result.AppendError ("no matching executable images found");
2130                 result.SetStatus (eReturnStatusFailed);
2131             }
2132         }
2133         return result.Succeeded();
2134     }
2135 };
2136 
2137 
2138 #pragma mark CommandObjectTargetModulesDumpSymfile
2139 
2140 //----------------------------------------------------------------------
2141 // Image debug symbol dumping command
2142 //----------------------------------------------------------------------
2143 
2144 class CommandObjectTargetModulesDumpSymfile : public CommandObjectTargetModulesModuleAutoComplete
2145 {
2146 public:
2147     CommandObjectTargetModulesDumpSymfile (CommandInterpreter &interpreter) :
2148     CommandObjectTargetModulesModuleAutoComplete (interpreter,
2149                                       "target modules dump symfile",
2150                                       "Dump the debug symbol file for one or more target modules.",
2151                                       //"target modules dump symfile [<file1> ...]")
2152                                       NULL)
2153     {
2154     }
2155 
2156     virtual
2157     ~CommandObjectTargetModulesDumpSymfile ()
2158     {
2159     }
2160 
2161     virtual bool
2162     Execute (Args& command,
2163              CommandReturnObject &result)
2164     {
2165         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2166         if (target == NULL)
2167         {
2168             result.AppendError ("invalid target, create a debug target using the 'target create' command");
2169             result.SetStatus (eReturnStatusFailed);
2170             return false;
2171         }
2172         else
2173         {
2174             uint32_t num_dumped = 0;
2175 
2176             uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2177             result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2178             result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2179 
2180             if (command.GetArgumentCount() == 0)
2181             {
2182                 // Dump all sections for all modules images
2183                 const uint32_t num_modules = target->GetImages().GetSize();
2184                 if (num_modules > 0)
2185                 {
2186                     result.GetOutputStream().Printf("Dumping debug symbols for %u modules.\n", num_modules);
2187                     for (uint32_t image_idx = 0;  image_idx<num_modules; ++image_idx)
2188                     {
2189                         if (DumpModuleSymbolVendor (result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx)))
2190                             num_dumped++;
2191                     }
2192                 }
2193                 else
2194                 {
2195                     result.AppendError ("the target has no associated executable images");
2196                     result.SetStatus (eReturnStatusFailed);
2197                     return false;
2198                 }
2199             }
2200             else
2201             {
2202                 // Dump specified images (by basename or fullpath)
2203                 const char *arg_cstr;
2204                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
2205                 {
2206                     ModuleList module_list;
2207                     const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, true);
2208                     if (num_matches > 0)
2209                     {
2210                         for (size_t i=0; i<num_matches; ++i)
2211                         {
2212                             Module *module = module_list.GetModulePointerAtIndex(i);
2213                             if (module)
2214                             {
2215                                 if (DumpModuleSymbolVendor (result.GetOutputStream(), module))
2216                                     num_dumped++;
2217                             }
2218                         }
2219                     }
2220                     else
2221                         result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
2222                 }
2223             }
2224 
2225             if (num_dumped > 0)
2226                 result.SetStatus (eReturnStatusSuccessFinishResult);
2227             else
2228             {
2229                 result.AppendError ("no matching executable images found");
2230                 result.SetStatus (eReturnStatusFailed);
2231             }
2232         }
2233         return result.Succeeded();
2234     }
2235 };
2236 
2237 
2238 #pragma mark CommandObjectTargetModulesDumpLineTable
2239 
2240 //----------------------------------------------------------------------
2241 // Image debug line table dumping command
2242 //----------------------------------------------------------------------
2243 
2244 class CommandObjectTargetModulesDumpLineTable : public CommandObjectTargetModulesSourceFileAutoComplete
2245 {
2246 public:
2247     CommandObjectTargetModulesDumpLineTable (CommandInterpreter &interpreter) :
2248     CommandObjectTargetModulesSourceFileAutoComplete (interpreter,
2249                                           "target modules dump line-table",
2250                                           "Dump the debug symbol file for one or more target modules.",
2251                                           NULL)
2252     {
2253     }
2254 
2255     virtual
2256     ~CommandObjectTargetModulesDumpLineTable ()
2257     {
2258     }
2259 
2260     virtual bool
2261     Execute (Args& command,
2262              CommandReturnObject &result)
2263     {
2264         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2265         if (target == NULL)
2266         {
2267             result.AppendError ("invalid target, create a debug target using the 'target create' command");
2268             result.SetStatus (eReturnStatusFailed);
2269             return false;
2270         }
2271         else
2272         {
2273             ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
2274             uint32_t total_num_dumped = 0;
2275 
2276             uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2277             result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2278             result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2279 
2280             if (command.GetArgumentCount() == 0)
2281             {
2282                 result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
2283                 result.SetStatus (eReturnStatusFailed);
2284             }
2285             else
2286             {
2287                 // Dump specified images (by basename or fullpath)
2288                 const char *arg_cstr;
2289                 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
2290                 {
2291                     FileSpec file_spec(arg_cstr, false);
2292                     const uint32_t num_modules = target->GetImages().GetSize();
2293                     if (num_modules > 0)
2294                     {
2295                         uint32_t num_dumped = 0;
2296                         for (uint32_t i = 0; i<num_modules; ++i)
2297                         {
2298                             if (DumpCompileUnitLineTable (m_interpreter,
2299                                                           result.GetOutputStream(),
2300                                                           target->GetImages().GetModulePointerAtIndex(i),
2301                                                           file_spec,
2302                                                           exe_ctx.GetProcessPtr() && exe_ctx.GetProcessRef().IsAlive()))
2303                                 num_dumped++;
2304                         }
2305                         if (num_dumped == 0)
2306                             result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr);
2307                         else
2308                             total_num_dumped += num_dumped;
2309                     }
2310                 }
2311             }
2312 
2313             if (total_num_dumped > 0)
2314                 result.SetStatus (eReturnStatusSuccessFinishResult);
2315             else
2316             {
2317                 result.AppendError ("no source filenames matched any command arguments");
2318                 result.SetStatus (eReturnStatusFailed);
2319             }
2320         }
2321         return result.Succeeded();
2322     }
2323 };
2324 
2325 
2326 #pragma mark CommandObjectTargetModulesDump
2327 
2328 //----------------------------------------------------------------------
2329 // Dump multi-word command for target modules
2330 //----------------------------------------------------------------------
2331 
2332 class CommandObjectTargetModulesDump : public CommandObjectMultiword
2333 {
2334 public:
2335 
2336     //------------------------------------------------------------------
2337     // Constructors and Destructors
2338     //------------------------------------------------------------------
2339     CommandObjectTargetModulesDump(CommandInterpreter &interpreter) :
2340     CommandObjectMultiword (interpreter,
2341                             "target modules dump",
2342                             "A set of commands for dumping information about one or more target modules.",
2343                             "target modules dump [symtab|sections|symfile|line-table] [<file1> <file2> ...]")
2344     {
2345         LoadSubCommand ("symtab",      CommandObjectSP (new CommandObjectTargetModulesDumpSymtab (interpreter)));
2346         LoadSubCommand ("sections",    CommandObjectSP (new CommandObjectTargetModulesDumpSections (interpreter)));
2347         LoadSubCommand ("symfile",     CommandObjectSP (new CommandObjectTargetModulesDumpSymfile (interpreter)));
2348         LoadSubCommand ("line-table",  CommandObjectSP (new CommandObjectTargetModulesDumpLineTable (interpreter)));
2349     }
2350 
2351     virtual
2352     ~CommandObjectTargetModulesDump()
2353     {
2354     }
2355 };
2356 
2357 class CommandObjectTargetModulesAdd : public CommandObject
2358 {
2359 public:
2360     CommandObjectTargetModulesAdd (CommandInterpreter &interpreter) :
2361     CommandObject (interpreter,
2362                    "target modules add",
2363                    "Add a new module to the current target's modules.",
2364                    "target modules add [<module>]")
2365     {
2366     }
2367 
2368     virtual
2369     ~CommandObjectTargetModulesAdd ()
2370     {
2371     }
2372 
2373     virtual bool
2374     Execute (Args& args,
2375              CommandReturnObject &result)
2376     {
2377         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2378         if (target == NULL)
2379         {
2380             result.AppendError ("invalid target, create a debug target using the 'target create' command");
2381             result.SetStatus (eReturnStatusFailed);
2382             return false;
2383         }
2384         else
2385         {
2386             const size_t argc = args.GetArgumentCount();
2387             if (argc == 0)
2388             {
2389                 result.AppendError ("one or more executable image paths must be specified");
2390                 result.SetStatus (eReturnStatusFailed);
2391                 return false;
2392             }
2393             else
2394             {
2395                 for (size_t i=0; i<argc; ++i)
2396                 {
2397                     const char *path = args.GetArgumentAtIndex(i);
2398                     if (path)
2399                     {
2400                         FileSpec file_spec(path, true);
2401                         ArchSpec arch;
2402                         if (file_spec.Exists())
2403                         {
2404                             ModuleSP module_sp (target->GetSharedModule(file_spec, arch));
2405                             if (!module_sp)
2406                             {
2407                                 result.AppendError ("one or more executable image paths must be specified");
2408                                 result.SetStatus (eReturnStatusFailed);
2409                                 return false;
2410                             }
2411                             result.SetStatus (eReturnStatusSuccessFinishResult);
2412                         }
2413                         else
2414                         {
2415                             char resolved_path[PATH_MAX];
2416                             result.SetStatus (eReturnStatusFailed);
2417                             if (file_spec.GetPath (resolved_path, sizeof(resolved_path)))
2418                             {
2419                                 if (strcmp (resolved_path, path) != 0)
2420                                 {
2421                                     result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", path, resolved_path);
2422                                     break;
2423                                 }
2424                             }
2425                             result.AppendErrorWithFormat ("invalid module path '%s'\n", path);
2426                             break;
2427                         }
2428                     }
2429                 }
2430             }
2431         }
2432         return result.Succeeded();
2433     }
2434 
2435     int
2436     HandleArgumentCompletion (Args &input,
2437                               int &cursor_index,
2438                               int &cursor_char_position,
2439                               OptionElementVector &opt_element_vector,
2440                               int match_start_point,
2441                               int max_return_elements,
2442                               bool &word_complete,
2443                               StringList &matches)
2444     {
2445         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
2446         completion_str.erase (cursor_char_position);
2447 
2448         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
2449                                                              CommandCompletions::eDiskFileCompletion,
2450                                                              completion_str.c_str(),
2451                                                              match_start_point,
2452                                                              max_return_elements,
2453                                                              NULL,
2454                                                              word_complete,
2455                                                              matches);
2456         return matches.GetSize();
2457     }
2458 
2459 };
2460 
2461 class CommandObjectTargetModulesLoad : public CommandObjectTargetModulesModuleAutoComplete
2462 {
2463 public:
2464     CommandObjectTargetModulesLoad (CommandInterpreter &interpreter) :
2465         CommandObjectTargetModulesModuleAutoComplete (interpreter,
2466                                                       "target modules load",
2467                                                       "Set the load addresses for one or more sections in a target module.",
2468                                                       "target modules load [--file <module> --uuid <uuid>] <sect-name> <address> [<sect-name> <address> ....]"),
2469         m_option_group (interpreter),
2470         m_file_option (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypePath, "Fullpath or basename for module to load."),
2471         m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset, "Set the load address for all sections to be the virtual address in the file plus the offset.", 0)
2472     {
2473         m_option_group.Append (&m_uuid_option_group, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2474         m_option_group.Append (&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2475         m_option_group.Append (&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2476         m_option_group.Finalize();
2477     }
2478 
2479     virtual
2480     ~CommandObjectTargetModulesLoad ()
2481     {
2482     }
2483 
2484     virtual bool
2485     Execute (Args& args,
2486              CommandReturnObject &result)
2487     {
2488         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2489         if (target == NULL)
2490         {
2491             result.AppendError ("invalid target, create a debug target using the 'target create' command");
2492             result.SetStatus (eReturnStatusFailed);
2493             return false;
2494         }
2495         else
2496         {
2497             const size_t argc = args.GetArgumentCount();
2498             const FileSpec *file_ptr = NULL;
2499             const UUID *uuid_ptr = NULL;
2500             if (m_file_option.GetOptionValue().OptionWasSet())
2501                 file_ptr = &m_file_option.GetOptionValue().GetCurrentValue();
2502 
2503             if (m_uuid_option_group.GetOptionValue().OptionWasSet())
2504                 uuid_ptr = &m_uuid_option_group.GetOptionValue().GetCurrentValue();
2505 
2506             if (file_ptr || uuid_ptr)
2507             {
2508 
2509                 ModuleList matching_modules;
2510                 const size_t num_matches = target->GetImages().FindModules (file_ptr,   // File spec to match (can be NULL to match by UUID only)
2511                                                                             NULL,       // Architecture
2512                                                                             uuid_ptr,   // UUID to match (can be NULL to not match on UUID)
2513                                                                             NULL,       // Object name
2514                                                                             matching_modules);
2515 
2516                 char path[PATH_MAX];
2517                 if (num_matches == 1)
2518                 {
2519                     Module *module = matching_modules.GetModulePointerAtIndex(0);
2520                     if (module)
2521                     {
2522                         ObjectFile *objfile = module->GetObjectFile();
2523                         if (objfile)
2524                         {
2525                             SectionList *section_list = objfile->GetSectionList();
2526                             if (section_list)
2527                             {
2528                                 if (argc == 0)
2529                                 {
2530                                     if (m_slide_option.GetOptionValue().OptionWasSet())
2531                                     {
2532                                         Module *module = matching_modules.GetModulePointerAtIndex(0);
2533                                         if (module)
2534                                         {
2535                                             ObjectFile *objfile = module->GetObjectFile();
2536                                             if (objfile)
2537                                             {
2538                                                 SectionList *section_list = objfile->GetSectionList();
2539                                                 if (section_list)
2540                                                 {
2541                                                     const size_t num_sections = section_list->GetSize();
2542                                                     const addr_t slide = m_slide_option.GetOptionValue().GetCurrentValue();
2543                                                     for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx)
2544                                                     {
2545                                                         SectionSP section_sp (section_list->GetSectionAtIndex(sect_idx));
2546                                                         if (section_sp)
2547                                                             target->GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), section_sp->GetFileAddress() + slide);
2548                                                     }
2549                                                 }
2550                                             }
2551                                         }
2552                                     }
2553                                     else
2554                                     {
2555                                         result.AppendError ("one or more section name + load address pair must be specified");
2556                                         result.SetStatus (eReturnStatusFailed);
2557                                         return false;
2558                                     }
2559                                 }
2560                                 else
2561                                 {
2562                                     if (m_slide_option.GetOptionValue().OptionWasSet())
2563                                     {
2564                                         result.AppendError ("The \"--slide <offset>\" option can't be used in conjunction with setting section load addresses.\n");
2565                                         result.SetStatus (eReturnStatusFailed);
2566                                         return false;
2567                                     }
2568 
2569                                     for (size_t i=0; i<argc; i += 2)
2570                                     {
2571                                         const char *sect_name = args.GetArgumentAtIndex(i);
2572                                         const char *load_addr_cstr = args.GetArgumentAtIndex(i+1);
2573                                         if (sect_name && load_addr_cstr)
2574                                         {
2575                                             ConstString const_sect_name(sect_name);
2576                                             bool success = false;
2577                                             addr_t load_addr = Args::StringToUInt64(load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success);
2578                                             if (success)
2579                                             {
2580                                                 SectionSP section_sp (section_list->FindSectionByName(const_sect_name));
2581                                                 if (section_sp)
2582                                                 {
2583                                                     target->GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), load_addr);
2584                                                     result.AppendMessageWithFormat("section '%s' loaded at 0x%llx\n", sect_name, load_addr);
2585                                                 }
2586                                                 else
2587                                                 {
2588                                                     result.AppendErrorWithFormat ("no section found that matches the section name '%s'\n", sect_name);
2589                                                     result.SetStatus (eReturnStatusFailed);
2590                                                     break;
2591                                                 }
2592                                             }
2593                                             else
2594                                             {
2595                                                 result.AppendErrorWithFormat ("invalid load address string '%s'\n", load_addr_cstr);
2596                                                 result.SetStatus (eReturnStatusFailed);
2597                                                 break;
2598                                             }
2599                                         }
2600                                         else
2601                                         {
2602                                             if (sect_name)
2603                                                 result.AppendError ("section names must be followed by a load address.\n");
2604                                             else
2605                                                 result.AppendError ("one or more section name + load address pair must be specified.\n");
2606                                             result.SetStatus (eReturnStatusFailed);
2607                                             break;
2608                                         }
2609                                     }
2610                                 }
2611                             }
2612                             else
2613                             {
2614                                 module->GetFileSpec().GetPath (path, sizeof(path));
2615                                 result.AppendErrorWithFormat ("no sections in object file '%s'\n", path);
2616                                 result.SetStatus (eReturnStatusFailed);
2617                             }
2618                         }
2619                         else
2620                         {
2621                             module->GetFileSpec().GetPath (path, sizeof(path));
2622                             result.AppendErrorWithFormat ("no object file for module '%s'\n", path);
2623                             result.SetStatus (eReturnStatusFailed);
2624                         }
2625                     }
2626                     else
2627                     {
2628                         module->GetFileSpec().GetPath (path, sizeof(path));
2629                         result.AppendErrorWithFormat ("invalid module '%s'.\n", path);
2630                         result.SetStatus (eReturnStatusFailed);
2631                     }
2632                 }
2633                 else
2634                 {
2635                     char uuid_cstr[64];
2636                     if (file_ptr)
2637                         file_ptr->GetPath (path, sizeof(path));
2638                     else
2639                         path[0] = '\0';
2640 
2641                     if (uuid_ptr)
2642                         uuid_ptr->GetAsCString(uuid_cstr, sizeof(uuid_cstr));
2643                     else
2644                         uuid_cstr[0] = '\0';
2645                     if (num_matches > 1)
2646                     {
2647                         result.AppendErrorWithFormat ("multiple modules match%s%s%s%s:\n",
2648                                                       path[0] ? " file=" : "",
2649                                                       path,
2650                                                       uuid_cstr[0] ? " uuid=" : "",
2651                                                       uuid_cstr);
2652                         for (size_t i=0; i<num_matches; ++i)
2653                         {
2654                             if (matching_modules.GetModulePointerAtIndex(i)->GetFileSpec().GetPath (path, sizeof(path)))
2655                                 result.AppendMessageWithFormat("%s\n", path);
2656                         }
2657                     }
2658                     else
2659                     {
2660                         result.AppendErrorWithFormat ("no modules were found  that match%s%s%s%s.\n",
2661                                                       path[0] ? " file=" : "",
2662                                                       path,
2663                                                       uuid_cstr[0] ? " uuid=" : "",
2664                                                       uuid_cstr);
2665                     }
2666                     result.SetStatus (eReturnStatusFailed);
2667                 }
2668             }
2669             else
2670             {
2671                 result.AppendError ("either the \"--file <module>\" or the \"--uuid <uuid>\" option must be specified.\n");
2672                 result.SetStatus (eReturnStatusFailed);
2673                 return false;
2674             }
2675         }
2676         return result.Succeeded();
2677     }
2678 
2679     virtual Options *
2680     GetOptions ()
2681     {
2682         return &m_option_group;
2683     }
2684 
2685 protected:
2686     OptionGroupOptions m_option_group;
2687     OptionGroupUUID m_uuid_option_group;
2688     OptionGroupFile m_file_option;
2689     OptionGroupUInt64 m_slide_option;
2690 };
2691 
2692 //----------------------------------------------------------------------
2693 // List images with associated information
2694 //----------------------------------------------------------------------
2695 class CommandObjectTargetModulesList : public CommandObject
2696 {
2697 public:
2698 
2699     class CommandOptions : public Options
2700     {
2701     public:
2702 
2703         CommandOptions (CommandInterpreter &interpreter) :
2704             Options(interpreter),
2705             m_format_array(),
2706             m_use_global_module_list (false),
2707             m_module_addr (LLDB_INVALID_ADDRESS)
2708         {
2709         }
2710 
2711         virtual
2712         ~CommandOptions ()
2713         {
2714         }
2715 
2716         virtual Error
2717         SetOptionValue (uint32_t option_idx, const char *option_arg)
2718         {
2719             char short_option = (char) m_getopt_table[option_idx].val;
2720             if (short_option == 'g')
2721             {
2722                 m_use_global_module_list = true;
2723             }
2724             else if (short_option == 'a')
2725             {
2726                 bool success;
2727                 m_module_addr = Args::StringToAddress(option_arg, LLDB_INVALID_ADDRESS, &success);
2728                 if (!success)
2729                 {
2730                     Error error;
2731                     error.SetErrorStringWithFormat("invalid address: \"%s\"", option_arg);
2732                 }
2733             }
2734             else
2735             {
2736                 uint32_t width = 0;
2737                 if (option_arg)
2738                     width = strtoul (option_arg, NULL, 0);
2739                 m_format_array.push_back(std::make_pair(short_option, width));
2740             }
2741             Error error;
2742             return error;
2743         }
2744 
2745         void
2746         OptionParsingStarting ()
2747         {
2748             m_format_array.clear();
2749             m_use_global_module_list = false;
2750             m_module_addr = LLDB_INVALID_ADDRESS;
2751         }
2752 
2753         const OptionDefinition*
2754         GetDefinitions ()
2755         {
2756             return g_option_table;
2757         }
2758 
2759         // Options table: Required for subclasses of Options.
2760 
2761         static OptionDefinition g_option_table[];
2762 
2763         // Instance variables to hold the values for command options.
2764         typedef std::vector< std::pair<char, uint32_t> > FormatWidthCollection;
2765         FormatWidthCollection m_format_array;
2766         bool m_use_global_module_list;
2767         lldb::addr_t m_module_addr;
2768     };
2769 
2770     CommandObjectTargetModulesList (CommandInterpreter &interpreter) :
2771     CommandObject (interpreter,
2772                    "target modules list",
2773                    "List current executable and dependent shared library images.",
2774                    "target modules list [<cmd-options>]"),
2775         m_options (interpreter)
2776     {
2777     }
2778 
2779     virtual
2780     ~CommandObjectTargetModulesList ()
2781     {
2782     }
2783 
2784     virtual
2785     Options *
2786     GetOptions ()
2787     {
2788         return &m_options;
2789     }
2790 
2791     virtual bool
2792     Execute (Args& command,
2793              CommandReturnObject &result)
2794     {
2795         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2796         const bool use_global_module_list = m_options.m_use_global_module_list;
2797         if (target == NULL && use_global_module_list == false)
2798         {
2799             result.AppendError ("invalid target, create a debug target using the 'target create' command");
2800             result.SetStatus (eReturnStatusFailed);
2801             return false;
2802         }
2803         else
2804         {
2805             if (target)
2806             {
2807                 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2808                 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2809                 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2810             }
2811             // Dump all sections for all modules images
2812             uint32_t num_modules = 0;
2813             Mutex::Locker locker;
2814 
2815             Stream &strm = result.GetOutputStream();
2816 
2817             if (m_options.m_module_addr != LLDB_INVALID_ADDRESS)
2818             {
2819                 if (target)
2820                 {
2821                     Address module_address;
2822                     if (module_address.SetLoadAddress(m_options.m_module_addr, target))
2823                     {
2824                         Module *module = module_address.GetModulePtr();
2825                         if (module)
2826                         {
2827                             PrintModule (target, module, UINT32_MAX, 0, strm);
2828                             result.SetStatus (eReturnStatusSuccessFinishResult);
2829                         }
2830                         else
2831                         {
2832                             result.AppendError ("Couldn't find module matching address: 0x%llx.", m_options.m_module_addr);
2833                             result.SetStatus (eReturnStatusFailed);
2834                         }
2835                     }
2836                     else
2837                     {
2838                         result.AppendError ("Couldn't find module containing address: 0x%llx.", m_options.m_module_addr);
2839                         result.SetStatus (eReturnStatusFailed);
2840                     }
2841                 }
2842                 else
2843                 {
2844                     result.AppendError ("Can only look up modules by address with a valid target.");
2845                     result.SetStatus (eReturnStatusFailed);
2846                 }
2847                 return result.Succeeded();
2848             }
2849 
2850             if (use_global_module_list)
2851             {
2852                 locker.Reset (Module::GetAllocationModuleCollectionMutex()->GetMutex());
2853                 num_modules = Module::GetNumberAllocatedModules();
2854             }
2855             else
2856                 num_modules = target->GetImages().GetSize();
2857 
2858             if (num_modules > 0)
2859             {
2860                 for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
2861                 {
2862                     ModuleSP module_sp;
2863                     Module *module;
2864                     if (use_global_module_list)
2865                     {
2866                         module = Module::GetAllocatedModuleAtIndex(image_idx);
2867                         module_sp = module->shared_from_this();
2868                     }
2869                     else
2870                     {
2871                         module_sp = target->GetImages().GetModuleAtIndex(image_idx);
2872                         module = module_sp.get();
2873                     }
2874 
2875                     int indent = strm.Printf("[%3u] ", image_idx);
2876                     PrintModule (target, module, image_idx, indent, strm);
2877 
2878                 }
2879                 result.SetStatus (eReturnStatusSuccessFinishResult);
2880             }
2881             else
2882             {
2883                 if (use_global_module_list)
2884                     result.AppendError ("the global module list is empty");
2885                 else
2886                     result.AppendError ("the target has no associated executable images");
2887                 result.SetStatus (eReturnStatusFailed);
2888                 return false;
2889             }
2890         }
2891         return result.Succeeded();
2892     }
2893 protected:
2894 
2895     void
2896     PrintModule (Target *target, Module *module, uint32_t idx, int indent, Stream &strm)
2897     {
2898 
2899         bool dump_object_name = false;
2900         if (m_options.m_format_array.empty())
2901         {
2902             m_options.m_format_array.push_back(std::make_pair('u', 0));
2903             m_options.m_format_array.push_back(std::make_pair('h', 0));
2904             m_options.m_format_array.push_back(std::make_pair('f', 0));
2905             m_options.m_format_array.push_back(std::make_pair('S', 0));
2906         }
2907         const size_t num_entries = m_options.m_format_array.size();
2908         bool print_space = false;
2909         for (size_t i=0; i<num_entries; ++i)
2910         {
2911             if (print_space)
2912                 strm.PutChar(' ');
2913             print_space = true;
2914             const char format_char = m_options.m_format_array[i].first;
2915             uint32_t width = m_options.m_format_array[i].second;
2916             switch (format_char)
2917             {
2918                 case 'A':
2919                     DumpModuleArchitecture (strm, module, false, width);
2920                     break;
2921 
2922                 case 't':
2923                     DumpModuleArchitecture (strm, module, true, width);
2924                     break;
2925 
2926                 case 'f':
2927                     DumpFullpath (strm, &module->GetFileSpec(), width);
2928                     dump_object_name = true;
2929                     break;
2930 
2931                 case 'd':
2932                     DumpDirectory (strm, &module->GetFileSpec(), width);
2933                     break;
2934 
2935                 case 'b':
2936                     DumpBasename (strm, &module->GetFileSpec(), width);
2937                     dump_object_name = true;
2938                     break;
2939 
2940                 case 'h':
2941                 case 'o':
2942                     // Image header address
2943                     {
2944                         uint32_t addr_nibble_width = target ? (target->GetArchitecture().GetAddressByteSize() * 2) : 16;
2945 
2946                         ObjectFile *objfile = module->GetObjectFile ();
2947                         if (objfile)
2948                         {
2949                             Address header_addr(objfile->GetHeaderAddress());
2950                             if (header_addr.IsValid())
2951                             {
2952                                 if (target && !target->GetSectionLoadList().IsEmpty())
2953                                 {
2954                                     lldb::addr_t header_load_addr = header_addr.GetLoadAddress (target);
2955                                     if (header_load_addr == LLDB_INVALID_ADDRESS)
2956                                     {
2957                                         header_addr.Dump (&strm, target, Address::DumpStyleModuleWithFileAddress, Address::DumpStyleFileAddress);
2958                                     }
2959                                     else
2960                                     {
2961                                         if (format_char == 'o')
2962                                         {
2963                                             // Show the offset of slide for the image
2964                                             strm.Printf ("0x%*.*llx", addr_nibble_width, addr_nibble_width, header_load_addr - header_addr.GetFileAddress());
2965                                         }
2966                                         else
2967                                         {
2968                                             // Show the load address of the image
2969                                             strm.Printf ("0x%*.*llx", addr_nibble_width, addr_nibble_width, header_load_addr);
2970                                         }
2971                                     }
2972                                     break;
2973                                 }
2974                                 // The address was valid, but the image isn't loaded, output the address in an appropriate format
2975                                 header_addr.Dump (&strm, target, Address::DumpStyleFileAddress);
2976                                 break;
2977                             }
2978                         }
2979                         strm.Printf ("%*s", addr_nibble_width + 2, "");
2980                     }
2981                     break;
2982                 case 'r':
2983                     {
2984                         uint32_t ref_count = 0;
2985                         ModuleSP module_sp (module->shared_from_this());
2986                         if (module_sp)
2987                         {
2988                             // Take one away to make sure we don't count our local "module_sp"
2989                             ref_count = module_sp.use_count() - 1;
2990                         }
2991                         if (width)
2992                             strm.Printf("{%*u}", width, ref_count);
2993                         else
2994                             strm.Printf("{%u}", ref_count);
2995                     }
2996                     break;
2997 
2998                 case 's':
2999                 case 'S':
3000                     {
3001                         SymbolVendor *symbol_vendor = module->GetSymbolVendor();
3002                         if (symbol_vendor)
3003                         {
3004                             SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
3005                             if (symbol_file)
3006                             {
3007                                 if (format_char == 'S')
3008                                 {
3009                                     FileSpec &symfile_spec = symbol_file->GetObjectFile()->GetFileSpec();
3010                                     // Dump symbol file only if different from module file
3011                                     if (!symfile_spec || symfile_spec == module->GetFileSpec())
3012                                     {
3013                                         print_space = false;
3014                                         break;
3015                                     }
3016                                     // Add a newline and indent past the index
3017                                     strm.Printf ("\n%*s", indent, "");
3018                                 }
3019                                 DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
3020                                 dump_object_name = true;
3021                                 break;
3022                             }
3023                         }
3024                         strm.Printf("%.*s", width, "<NONE>");
3025                     }
3026                     break;
3027 
3028                 case 'm':
3029                     module->GetModificationTime().Dump(&strm, width);
3030                     break;
3031 
3032                 case 'p':
3033                     strm.Printf("%p", module);
3034                     break;
3035 
3036                 case 'u':
3037                     DumpModuleUUID(strm, module);
3038                     break;
3039 
3040                 default:
3041                     break;
3042             }
3043 
3044         }
3045         if (dump_object_name)
3046         {
3047             const char *object_name = module->GetObjectName().GetCString();
3048             if (object_name)
3049                 strm.Printf ("(%s)", object_name);
3050         }
3051         strm.EOL();
3052     }
3053 
3054     CommandOptions m_options;
3055 };
3056 
3057 OptionDefinition
3058 CommandObjectTargetModulesList::CommandOptions::g_option_table[] =
3059 {
3060     { LLDB_OPT_SET_1, false, "address",    'a', required_argument, NULL, 0, eArgTypeAddress, "Display the image at this address."},
3061     { LLDB_OPT_SET_1, false, "arch",       'A', optional_argument, NULL, 0, eArgTypeWidth,   "Display the architecture when listing images."},
3062     { LLDB_OPT_SET_1, false, "triple",     't', optional_argument, NULL, 0, eArgTypeWidth,   "Display the triple when listing images."},
3063     { LLDB_OPT_SET_1, false, "header",     'h', no_argument,       NULL, 0, eArgTypeNone,    "Display the image header address as a load address if debugging, a file address otherwise."},
3064     { LLDB_OPT_SET_1, false, "offset",     'o', no_argument,       NULL, 0, eArgTypeNone,    "Display the image header address offset from the header file address (the slide amount)."},
3065     { LLDB_OPT_SET_1, false, "uuid",       'u', no_argument,       NULL, 0, eArgTypeNone,    "Display the UUID when listing images."},
3066     { LLDB_OPT_SET_1, false, "fullpath",   'f', optional_argument, NULL, 0, eArgTypeWidth,   "Display the fullpath to the image object file."},
3067     { LLDB_OPT_SET_1, false, "directory",  'd', optional_argument, NULL, 0, eArgTypeWidth,   "Display the directory with optional width for the image object file."},
3068     { LLDB_OPT_SET_1, false, "basename",   'b', optional_argument, NULL, 0, eArgTypeWidth,   "Display the basename with optional width for the image object file."},
3069     { LLDB_OPT_SET_1, false, "symfile",    's', optional_argument, NULL, 0, eArgTypeWidth,   "Display the fullpath to the image symbol file with optional width."},
3070     { LLDB_OPT_SET_1, false, "symfile-unique", 'S', optional_argument, NULL, 0, eArgTypeWidth,   "Display the symbol file with optional width only if it is different from the executable object file."},
3071     { LLDB_OPT_SET_1, false, "mod-time",   'm', optional_argument, NULL, 0, eArgTypeWidth,   "Display the modification time with optional width of the module."},
3072     { LLDB_OPT_SET_1, false, "ref-count",  'r', optional_argument, NULL, 0, eArgTypeWidth,   "Display the reference count if the module is still in the shared module cache."},
3073     { LLDB_OPT_SET_1, false, "pointer",    'p', optional_argument, NULL, 0, eArgTypeNone,    "Display the module pointer."},
3074     { LLDB_OPT_SET_1, false, "global",     'g', no_argument,       NULL, 0, eArgTypeNone,    "Display the modules from the global module list, not just the current target."},
3075     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3076 };
3077 
3078 
3079 
3080 //----------------------------------------------------------------------
3081 // Lookup information in images
3082 //----------------------------------------------------------------------
3083 class CommandObjectTargetModulesLookup : public CommandObject
3084 {
3085 public:
3086 
3087     enum
3088     {
3089         eLookupTypeInvalid = -1,
3090         eLookupTypeAddress = 0,
3091         eLookupTypeSymbol,
3092         eLookupTypeFileLine,    // Line is optional
3093         eLookupTypeFunction,
3094         eLookupTypeType,
3095         kNumLookupTypes
3096     };
3097 
3098     class CommandOptions : public Options
3099     {
3100     public:
3101 
3102         CommandOptions (CommandInterpreter &interpreter) :
3103         Options(interpreter)
3104         {
3105             OptionParsingStarting();
3106         }
3107 
3108         virtual
3109         ~CommandOptions ()
3110         {
3111         }
3112 
3113         virtual Error
3114         SetOptionValue (uint32_t option_idx, const char *option_arg)
3115         {
3116             Error error;
3117 
3118             char short_option = (char) m_getopt_table[option_idx].val;
3119 
3120             switch (short_option)
3121             {
3122                 case 'a':
3123                     m_type = eLookupTypeAddress;
3124                     m_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
3125                     if (m_addr == LLDB_INVALID_ADDRESS)
3126                         error.SetErrorStringWithFormat ("invalid address string '%s'", option_arg);
3127                     break;
3128 
3129                 case 'o':
3130                     m_offset = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
3131                     if (m_offset == LLDB_INVALID_ADDRESS)
3132                         error.SetErrorStringWithFormat ("invalid offset string '%s'", option_arg);
3133                     break;
3134 
3135                 case 's':
3136                     m_str = option_arg;
3137                     m_type = eLookupTypeSymbol;
3138                     break;
3139 
3140                 case 'f':
3141                     m_file.SetFile (option_arg, false);
3142                     m_type = eLookupTypeFileLine;
3143                     break;
3144 
3145                 case 'i':
3146                     m_include_inlines = false;
3147                     break;
3148 
3149                 case 'l':
3150                     m_line_number = Args::StringToUInt32(option_arg, UINT32_MAX);
3151                     if (m_line_number == UINT32_MAX)
3152                         error.SetErrorStringWithFormat ("invalid line number string '%s'", option_arg);
3153                     else if (m_line_number == 0)
3154                         error.SetErrorString ("zero is an invalid line number");
3155                     m_type = eLookupTypeFileLine;
3156                     break;
3157 
3158                 case 'n':
3159                     m_str = option_arg;
3160                     m_type = eLookupTypeFunction;
3161                     break;
3162 
3163                 case 't':
3164                     m_str = option_arg;
3165                     m_type = eLookupTypeType;
3166                     break;
3167 
3168                 case 'v':
3169                     m_verbose = 1;
3170                     break;
3171 
3172                 case 'r':
3173                     m_use_regex = true;
3174                     break;
3175             }
3176 
3177             return error;
3178         }
3179 
3180         void
3181         OptionParsingStarting ()
3182         {
3183             m_type = eLookupTypeInvalid;
3184             m_str.clear();
3185             m_file.Clear();
3186             m_addr = LLDB_INVALID_ADDRESS;
3187             m_offset = 0;
3188             m_line_number = 0;
3189             m_use_regex = false;
3190             m_include_inlines = true;
3191             m_verbose = false;
3192         }
3193 
3194         const OptionDefinition*
3195         GetDefinitions ()
3196         {
3197             return g_option_table;
3198         }
3199 
3200         // Options table: Required for subclasses of Options.
3201 
3202         static OptionDefinition g_option_table[];
3203         int             m_type;         // Should be a eLookupTypeXXX enum after parsing options
3204         std::string     m_str;          // Holds name lookup
3205         FileSpec        m_file;         // Files for file lookups
3206         lldb::addr_t    m_addr;         // Holds the address to lookup
3207         lldb::addr_t    m_offset;       // Subtract this offset from m_addr before doing lookups.
3208         uint32_t        m_line_number;  // Line number for file+line lookups
3209         bool            m_use_regex;    // Name lookups in m_str are regular expressions.
3210         bool            m_include_inlines;// Check for inline entries when looking up by file/line.
3211         bool            m_verbose;      // Enable verbose lookup info
3212 
3213     };
3214 
3215     CommandObjectTargetModulesLookup (CommandInterpreter &interpreter) :
3216     CommandObject (interpreter,
3217                    "target modules lookup",
3218                    "Look up information within executable and dependent shared library images.",
3219                    NULL),
3220     m_options (interpreter)
3221     {
3222         CommandArgumentEntry arg;
3223         CommandArgumentData file_arg;
3224 
3225         // Define the first (and only) variant of this arg.
3226         file_arg.arg_type = eArgTypeFilename;
3227         file_arg.arg_repetition = eArgRepeatStar;
3228 
3229         // There is only one variant this argument could be; put it into the argument entry.
3230         arg.push_back (file_arg);
3231 
3232         // Push the data for the first argument into the m_arguments vector.
3233         m_arguments.push_back (arg);
3234     }
3235 
3236     virtual
3237     ~CommandObjectTargetModulesLookup ()
3238     {
3239     }
3240 
3241     virtual Options *
3242     GetOptions ()
3243     {
3244         return &m_options;
3245     }
3246 
3247 
3248     bool
3249     LookupInModule (CommandInterpreter &interpreter, Module *module, CommandReturnObject &result, bool &syntax_error)
3250     {
3251         switch (m_options.m_type)
3252         {
3253             case eLookupTypeAddress:
3254                 if (m_options.m_addr != LLDB_INVALID_ADDRESS)
3255                 {
3256                     if (LookupAddressInModule (m_interpreter,
3257                                                result.GetOutputStream(),
3258                                                module,
3259                                                eSymbolContextEverything,
3260                                                m_options.m_addr,
3261                                                m_options.m_offset,
3262                                                m_options.m_verbose))
3263                     {
3264                         result.SetStatus(eReturnStatusSuccessFinishResult);
3265                         return true;
3266                     }
3267                 }
3268                 break;
3269 
3270             case eLookupTypeSymbol:
3271                 if (!m_options.m_str.empty())
3272                 {
3273                     if (LookupSymbolInModule (m_interpreter, result.GetOutputStream(), module, m_options.m_str.c_str(), m_options.m_use_regex))
3274                     {
3275                         result.SetStatus(eReturnStatusSuccessFinishResult);
3276                         return true;
3277                     }
3278                 }
3279                 break;
3280 
3281             case eLookupTypeFileLine:
3282                 if (m_options.m_file)
3283                 {
3284 
3285                     if (LookupFileAndLineInModule (m_interpreter,
3286                                                    result.GetOutputStream(),
3287                                                    module,
3288                                                    m_options.m_file,
3289                                                    m_options.m_line_number,
3290                                                    m_options.m_include_inlines,
3291                                                    m_options.m_verbose))
3292                     {
3293                         result.SetStatus(eReturnStatusSuccessFinishResult);
3294                         return true;
3295                     }
3296                 }
3297                 break;
3298 
3299             case eLookupTypeFunction:
3300                 if (!m_options.m_str.empty())
3301                 {
3302                     if (LookupFunctionInModule (m_interpreter,
3303                                                 result.GetOutputStream(),
3304                                                 module,
3305                                                 m_options.m_str.c_str(),
3306                                                 m_options.m_use_regex,
3307                                                 m_options.m_include_inlines,
3308                                                 m_options.m_verbose))
3309                     {
3310                         result.SetStatus(eReturnStatusSuccessFinishResult);
3311                         return true;
3312                     }
3313                 }
3314                 break;
3315 
3316             case eLookupTypeType:
3317                 if (!m_options.m_str.empty())
3318                 {
3319                     if (LookupTypeInModule (m_interpreter,
3320                                             result.GetOutputStream(),
3321                                             module,
3322                                             m_options.m_str.c_str(),
3323                                             m_options.m_use_regex))
3324                     {
3325                         result.SetStatus(eReturnStatusSuccessFinishResult);
3326                         return true;
3327                     }
3328                 }
3329                 break;
3330 
3331             default:
3332                 m_options.GenerateOptionUsage (result.GetErrorStream(), this);
3333                 syntax_error = true;
3334                 break;
3335         }
3336 
3337         result.SetStatus (eReturnStatusFailed);
3338         return false;
3339     }
3340 
3341     virtual bool
3342     Execute (Args& command,
3343              CommandReturnObject &result)
3344     {
3345         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
3346         if (target == NULL)
3347         {
3348             result.AppendError ("invalid target, create a debug target using the 'target create' command");
3349             result.SetStatus (eReturnStatusFailed);
3350             return false;
3351         }
3352         else
3353         {
3354             bool syntax_error = false;
3355             uint32_t i;
3356             uint32_t num_successful_lookups = 0;
3357             uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
3358             result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3359             result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3360             // Dump all sections for all modules images
3361 
3362             if (command.GetArgumentCount() == 0)
3363             {
3364                 // Dump all sections for all modules images
3365                 const uint32_t num_modules = target->GetImages().GetSize();
3366                 if (num_modules > 0)
3367                 {
3368                     for (i = 0; i<num_modules && syntax_error == false; ++i)
3369                     {
3370                         if (LookupInModule (m_interpreter, target->GetImages().GetModulePointerAtIndex(i), result, syntax_error))
3371                         {
3372                             result.GetOutputStream().EOL();
3373                             num_successful_lookups++;
3374                         }
3375                     }
3376                 }
3377                 else
3378                 {
3379                     result.AppendError ("the target has no associated executable images");
3380                     result.SetStatus (eReturnStatusFailed);
3381                     return false;
3382                 }
3383             }
3384             else
3385             {
3386                 // Dump specified images (by basename or fullpath)
3387                 const char *arg_cstr;
3388                 for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != NULL && syntax_error == false; ++i)
3389                 {
3390                     ModuleList module_list;
3391                     const size_t num_matches = FindModulesByName (target, arg_cstr, module_list, false);
3392                     if (num_matches > 0)
3393                     {
3394                         for (size_t i=0; i<num_matches; ++i)
3395                         {
3396                             Module *module = module_list.GetModulePointerAtIndex(i);
3397                             if (module)
3398                             {
3399                                 if (LookupInModule (m_interpreter, module, result, syntax_error))
3400                                 {
3401                                     result.GetOutputStream().EOL();
3402                                     num_successful_lookups++;
3403                                 }
3404                             }
3405                         }
3406                     }
3407                     else
3408                         result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
3409                 }
3410             }
3411 
3412             if (num_successful_lookups > 0)
3413                 result.SetStatus (eReturnStatusSuccessFinishResult);
3414             else
3415                 result.SetStatus (eReturnStatusFailed);
3416         }
3417         return result.Succeeded();
3418     }
3419 protected:
3420 
3421     CommandOptions m_options;
3422 };
3423 
3424 OptionDefinition
3425 CommandObjectTargetModulesLookup::CommandOptions::g_option_table[] =
3426 {
3427     { LLDB_OPT_SET_1,   true,  "address",    'a', required_argument, NULL, 0, eArgTypeAddress,      "Lookup an address in one or more target modules."},
3428     { LLDB_OPT_SET_1,   false, "offset",     'o', required_argument, NULL, 0, eArgTypeOffset,       "When looking up an address subtract <offset> from any addresses before doing the lookup."},
3429     { LLDB_OPT_SET_2| LLDB_OPT_SET_4
3430       /* FIXME: re-enable this for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_5 */ ,
3431                         false, "regex",      'r', no_argument,       NULL, 0, eArgTypeNone,         "The <name> argument for name lookups are regular expressions."},
3432     { LLDB_OPT_SET_2,   true,  "symbol",     's', required_argument, NULL, 0, eArgTypeSymbol,       "Lookup a symbol by name in the symbol tables in one or more target modules."},
3433     { LLDB_OPT_SET_3,   true,  "file",       'f', required_argument, NULL, 0, eArgTypeFilename,     "Lookup a file by fullpath or basename in one or more target modules."},
3434     { LLDB_OPT_SET_3,   false, "line",       'l', required_argument, NULL, 0, eArgTypeLineNum,      "Lookup a line number in a file (must be used in conjunction with --file)."},
3435     { LLDB_OPT_SET_3|
3436       LLDB_OPT_SET_4,   false, "no-inlines", 'i', no_argument,       NULL, 0, eArgTypeNone,         "Ignore inline entries (must be used in conjunction with --file or --function)."},
3437     { LLDB_OPT_SET_4,   true,  "function",   'n', required_argument, NULL, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules."},
3438     { LLDB_OPT_SET_5,   true,  "type",       't', required_argument, NULL, 0, eArgTypeName,         "Lookup a type by name in the debug symbols in one or more target modules."},
3439     { LLDB_OPT_SET_ALL, false, "verbose",    'v', no_argument,       NULL, 0, eArgTypeNone,         "Enable verbose lookup information."},
3440     { 0, false, NULL,           0, 0,                 NULL, 0, eArgTypeNone, NULL }
3441 };
3442 
3443 
3444 #pragma mark CommandObjectMultiwordImageSearchPaths
3445 
3446 //-------------------------------------------------------------------------
3447 // CommandObjectMultiwordImageSearchPaths
3448 //-------------------------------------------------------------------------
3449 
3450 class CommandObjectTargetModulesImageSearchPaths : public CommandObjectMultiword
3451 {
3452 public:
3453 
3454     CommandObjectTargetModulesImageSearchPaths (CommandInterpreter &interpreter) :
3455     CommandObjectMultiword (interpreter,
3456                             "target modules search-paths",
3457                             "A set of commands for operating on debugger target image search paths.",
3458                             "target modules search-paths <subcommand> [<subcommand-options>]")
3459     {
3460         LoadSubCommand ("add",     CommandObjectSP (new CommandObjectTargetModulesSearchPathsAdd (interpreter)));
3461         LoadSubCommand ("clear",   CommandObjectSP (new CommandObjectTargetModulesSearchPathsClear (interpreter)));
3462         LoadSubCommand ("insert",  CommandObjectSP (new CommandObjectTargetModulesSearchPathsInsert (interpreter)));
3463         LoadSubCommand ("list",    CommandObjectSP (new CommandObjectTargetModulesSearchPathsList (interpreter)));
3464         LoadSubCommand ("query",   CommandObjectSP (new CommandObjectTargetModulesSearchPathsQuery (interpreter)));
3465     }
3466 
3467     ~CommandObjectTargetModulesImageSearchPaths()
3468     {
3469     }
3470 };
3471 
3472 
3473 
3474 #pragma mark CommandObjectTargetModules
3475 
3476 //-------------------------------------------------------------------------
3477 // CommandObjectTargetModules
3478 //-------------------------------------------------------------------------
3479 
3480 class CommandObjectTargetModules : public CommandObjectMultiword
3481 {
3482 public:
3483     //------------------------------------------------------------------
3484     // Constructors and Destructors
3485     //------------------------------------------------------------------
3486     CommandObjectTargetModules(CommandInterpreter &interpreter) :
3487         CommandObjectMultiword (interpreter,
3488                                 "target modules",
3489                                 "A set of commands for accessing information for one or more target modules.",
3490                                 "target modules <sub-command> ...")
3491     {
3492         LoadSubCommand ("add",          CommandObjectSP (new CommandObjectTargetModulesAdd (interpreter)));
3493         LoadSubCommand ("load",         CommandObjectSP (new CommandObjectTargetModulesLoad (interpreter)));
3494         //LoadSubCommand ("unload",       CommandObjectSP (new CommandObjectTargetModulesUnload (interpreter)));
3495         LoadSubCommand ("dump",         CommandObjectSP (new CommandObjectTargetModulesDump (interpreter)));
3496         LoadSubCommand ("list",         CommandObjectSP (new CommandObjectTargetModulesList (interpreter)));
3497         LoadSubCommand ("lookup",       CommandObjectSP (new CommandObjectTargetModulesLookup (interpreter)));
3498         LoadSubCommand ("search-paths", CommandObjectSP (new CommandObjectTargetModulesImageSearchPaths (interpreter)));
3499 
3500     }
3501     virtual
3502     ~CommandObjectTargetModules()
3503     {
3504     }
3505 
3506 private:
3507     //------------------------------------------------------------------
3508     // For CommandObjectTargetModules only
3509     //------------------------------------------------------------------
3510     DISALLOW_COPY_AND_ASSIGN (CommandObjectTargetModules);
3511 };
3512 
3513 
3514 #pragma mark CommandObjectTargetStopHookAdd
3515 
3516 //-------------------------------------------------------------------------
3517 // CommandObjectTargetStopHookAdd
3518 //-------------------------------------------------------------------------
3519 
3520 class CommandObjectTargetStopHookAdd : public CommandObject
3521 {
3522 public:
3523 
3524     class CommandOptions : public Options
3525     {
3526     public:
3527         CommandOptions (CommandInterpreter &interpreter) :
3528             Options(interpreter),
3529             m_line_start(0),
3530             m_line_end (UINT_MAX),
3531             m_func_name_type_mask (eFunctionNameTypeAuto),
3532             m_sym_ctx_specified (false),
3533             m_thread_specified (false),
3534             m_use_one_liner (false),
3535             m_one_liner()
3536         {
3537         }
3538 
3539         ~CommandOptions () {}
3540 
3541         const OptionDefinition*
3542         GetDefinitions ()
3543         {
3544             return g_option_table;
3545         }
3546 
3547         virtual Error
3548         SetOptionValue (uint32_t option_idx, const char *option_arg)
3549         {
3550             Error error;
3551             char short_option = (char) m_getopt_table[option_idx].val;
3552             bool success;
3553 
3554             switch (short_option)
3555             {
3556                 case 'c':
3557                     m_class_name = option_arg;
3558                     m_sym_ctx_specified = true;
3559                 break;
3560 
3561                 case 'e':
3562                     m_line_end = Args::StringToUInt32 (option_arg, UINT_MAX, 0, &success);
3563                     if (!success)
3564                     {
3565                         error.SetErrorStringWithFormat ("invalid end line number: \"%s\"", option_arg);
3566                         break;
3567                     }
3568                     m_sym_ctx_specified = true;
3569                 break;
3570 
3571                 case 'l':
3572                     m_line_start = Args::StringToUInt32 (option_arg, 0, 0, &success);
3573                     if (!success)
3574                     {
3575                         error.SetErrorStringWithFormat ("invalid start line number: \"%s\"", option_arg);
3576                         break;
3577                     }
3578                     m_sym_ctx_specified = true;
3579                 break;
3580 
3581                 case 'i':
3582                     m_no_inlines = true;
3583                 break;
3584 
3585                 case 'n':
3586                     m_function_name = option_arg;
3587                     m_func_name_type_mask |= eFunctionNameTypeAuto;
3588                     m_sym_ctx_specified = true;
3589                 break;
3590 
3591                 case 'f':
3592                     m_file_name = option_arg;
3593                     m_sym_ctx_specified = true;
3594                 break;
3595                 case 's':
3596                     m_module_name = option_arg;
3597                     m_sym_ctx_specified = true;
3598                 break;
3599                 case 't' :
3600                 {
3601                     m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
3602                     if (m_thread_id == LLDB_INVALID_THREAD_ID)
3603                        error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg);
3604                     m_thread_specified = true;
3605                 }
3606                 break;
3607                 case 'T':
3608                     m_thread_name = option_arg;
3609                     m_thread_specified = true;
3610                 break;
3611                 case 'q':
3612                     m_queue_name = option_arg;
3613                     m_thread_specified = true;
3614                     break;
3615                 case 'x':
3616                 {
3617                     m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
3618                     if (m_thread_id == UINT32_MAX)
3619                        error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg);
3620                     m_thread_specified = true;
3621                 }
3622                 break;
3623                 case 'o':
3624                     m_use_one_liner = true;
3625                     m_one_liner = option_arg;
3626                 break;
3627                 default:
3628                     error.SetErrorStringWithFormat ("unrecognized option %c.", short_option);
3629                 break;
3630             }
3631             return error;
3632         }
3633 
3634         void
3635         OptionParsingStarting ()
3636         {
3637             m_class_name.clear();
3638             m_function_name.clear();
3639             m_line_start = 0;
3640             m_line_end = UINT_MAX;
3641             m_file_name.clear();
3642             m_module_name.clear();
3643             m_func_name_type_mask = eFunctionNameTypeAuto;
3644             m_thread_id = LLDB_INVALID_THREAD_ID;
3645             m_thread_index = UINT32_MAX;
3646             m_thread_name.clear();
3647             m_queue_name.clear();
3648 
3649             m_no_inlines = false;
3650             m_sym_ctx_specified = false;
3651             m_thread_specified = false;
3652 
3653             m_use_one_liner = false;
3654             m_one_liner.clear();
3655         }
3656 
3657 
3658         static OptionDefinition g_option_table[];
3659 
3660         std::string m_class_name;
3661         std::string m_function_name;
3662         uint32_t    m_line_start;
3663         uint32_t    m_line_end;
3664         std::string m_file_name;
3665         std::string m_module_name;
3666         uint32_t m_func_name_type_mask;  // A pick from lldb::FunctionNameType.
3667         lldb::tid_t m_thread_id;
3668         uint32_t m_thread_index;
3669         std::string m_thread_name;
3670         std::string m_queue_name;
3671         bool        m_sym_ctx_specified;
3672         bool        m_no_inlines;
3673         bool        m_thread_specified;
3674         // Instance variables to hold the values for one_liner options.
3675         bool m_use_one_liner;
3676         std::string m_one_liner;
3677     };
3678 
3679     Options *
3680     GetOptions ()
3681     {
3682         return &m_options;
3683     }
3684 
3685     CommandObjectTargetStopHookAdd (CommandInterpreter &interpreter) :
3686         CommandObject (interpreter,
3687                        "target stop-hook add ",
3688                        "Add a hook to be executed when the target stops.",
3689                        "target stop-hook add"),
3690         m_options (interpreter)
3691     {
3692     }
3693 
3694     ~CommandObjectTargetStopHookAdd ()
3695     {
3696     }
3697 
3698     static size_t
3699     ReadCommandsCallbackFunction (void *baton,
3700                                   InputReader &reader,
3701                                   lldb::InputReaderAction notification,
3702                                   const char *bytes,
3703                                   size_t bytes_len)
3704     {
3705         StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
3706         Target::StopHook *new_stop_hook = ((Target::StopHook *) baton);
3707         static bool got_interrupted;
3708         bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
3709 
3710         switch (notification)
3711         {
3712         case eInputReaderActivate:
3713             if (!batch_mode)
3714             {
3715                 out_stream->Printf ("%s\n", "Enter your stop hook command(s).  Type 'DONE' to end.");
3716                 if (reader.GetPrompt())
3717                     out_stream->Printf ("%s", reader.GetPrompt());
3718                 out_stream->Flush();
3719             }
3720             got_interrupted = false;
3721             break;
3722 
3723         case eInputReaderDeactivate:
3724             break;
3725 
3726         case eInputReaderReactivate:
3727             if (reader.GetPrompt() && !batch_mode)
3728             {
3729                 out_stream->Printf ("%s", reader.GetPrompt());
3730                 out_stream->Flush();
3731             }
3732             got_interrupted = false;
3733             break;
3734 
3735         case eInputReaderAsynchronousOutputWritten:
3736             break;
3737 
3738         case eInputReaderGotToken:
3739             if (bytes && bytes_len && baton)
3740             {
3741                 StringList *commands = new_stop_hook->GetCommandPointer();
3742                 if (commands)
3743                 {
3744                     commands->AppendString (bytes, bytes_len);
3745                 }
3746             }
3747             if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
3748             {
3749                 out_stream->Printf ("%s", reader.GetPrompt());
3750                 out_stream->Flush();
3751             }
3752             break;
3753 
3754         case eInputReaderInterrupt:
3755             {
3756                 // Finish, and cancel the stop hook.
3757                 new_stop_hook->GetTarget()->RemoveStopHookByID(new_stop_hook->GetID());
3758                 if (!batch_mode)
3759                 {
3760                     out_stream->Printf ("Stop hook cancelled.\n");
3761                     out_stream->Flush();
3762                 }
3763 
3764                 reader.SetIsDone (true);
3765             }
3766             got_interrupted = true;
3767             break;
3768 
3769         case eInputReaderEndOfFile:
3770             reader.SetIsDone (true);
3771             break;
3772 
3773         case eInputReaderDone:
3774             if (!got_interrupted && !batch_mode)
3775             {
3776                 out_stream->Printf ("Stop hook #%llu added.\n", new_stop_hook->GetID());
3777                 out_stream->Flush();
3778             }
3779             break;
3780         }
3781 
3782         return bytes_len;
3783     }
3784 
3785     bool
3786     Execute (Args& command,
3787              CommandReturnObject &result)
3788     {
3789         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
3790         if (target)
3791         {
3792             Target::StopHookSP new_hook_sp;
3793             target->AddStopHook (new_hook_sp);
3794 
3795             //  First step, make the specifier.
3796             std::auto_ptr<SymbolContextSpecifier> specifier_ap;
3797             if (m_options.m_sym_ctx_specified)
3798             {
3799                 specifier_ap.reset(new SymbolContextSpecifier(m_interpreter.GetDebugger().GetSelectedTarget()));
3800 
3801                 if (!m_options.m_module_name.empty())
3802                 {
3803                     specifier_ap->AddSpecification (m_options.m_module_name.c_str(), SymbolContextSpecifier::eModuleSpecified);
3804                 }
3805 
3806                 if (!m_options.m_class_name.empty())
3807                 {
3808                     specifier_ap->AddSpecification (m_options.m_class_name.c_str(), SymbolContextSpecifier::eClassOrNamespaceSpecified);
3809                 }
3810 
3811                 if (!m_options.m_file_name.empty())
3812                 {
3813                     specifier_ap->AddSpecification (m_options.m_file_name.c_str(), SymbolContextSpecifier::eFileSpecified);
3814                 }
3815 
3816                 if (m_options.m_line_start != 0)
3817                 {
3818                     specifier_ap->AddLineSpecification (m_options.m_line_start, SymbolContextSpecifier::eLineStartSpecified);
3819                 }
3820 
3821                 if (m_options.m_line_end != UINT_MAX)
3822                 {
3823                     specifier_ap->AddLineSpecification (m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
3824                 }
3825 
3826                 if (!m_options.m_function_name.empty())
3827                 {
3828                     specifier_ap->AddSpecification (m_options.m_function_name.c_str(), SymbolContextSpecifier::eFunctionSpecified);
3829                 }
3830             }
3831 
3832             if (specifier_ap.get())
3833                 new_hook_sp->SetSpecifier (specifier_ap.release());
3834 
3835             // Next see if any of the thread options have been entered:
3836 
3837             if (m_options.m_thread_specified)
3838             {
3839                 ThreadSpec *thread_spec = new ThreadSpec();
3840 
3841                 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
3842                 {
3843                     thread_spec->SetTID (m_options.m_thread_id);
3844                 }
3845 
3846                 if (m_options.m_thread_index != UINT32_MAX)
3847                     thread_spec->SetIndex (m_options.m_thread_index);
3848 
3849                 if (!m_options.m_thread_name.empty())
3850                     thread_spec->SetName (m_options.m_thread_name.c_str());
3851 
3852                 if (!m_options.m_queue_name.empty())
3853                     thread_spec->SetQueueName (m_options.m_queue_name.c_str());
3854 
3855                 new_hook_sp->SetThreadSpecifier (thread_spec);
3856 
3857             }
3858             if (m_options.m_use_one_liner)
3859             {
3860                 // Use one-liner.
3861                 new_hook_sp->GetCommandPointer()->AppendString (m_options.m_one_liner.c_str());
3862                 result.AppendMessageWithFormat("Stop hook #%llu added.\n", new_hook_sp->GetID());
3863             }
3864             else
3865             {
3866                 // Otherwise gather up the command list, we'll push an input reader and suck the data from that directly into
3867                 // the new stop hook's command string.
3868                 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
3869                 if (!reader_sp)
3870                 {
3871                     result.AppendError("out of memory\n");
3872                     result.SetStatus (eReturnStatusFailed);
3873                     target->RemoveStopHookByID (new_hook_sp->GetID());
3874                     return false;
3875                 }
3876 
3877                 Error err (reader_sp->Initialize (CommandObjectTargetStopHookAdd::ReadCommandsCallbackFunction,
3878                                                   new_hook_sp.get(), // baton
3879                                                   eInputReaderGranularityLine,  // token size, to pass to callback function
3880                                                   "DONE",                       // end token
3881                                                   "> ",                         // prompt
3882                                                   true));                       // echo input
3883                 if (!err.Success())
3884                 {
3885                     result.AppendError (err.AsCString());
3886                     result.SetStatus (eReturnStatusFailed);
3887                     target->RemoveStopHookByID (new_hook_sp->GetID());
3888                     return false;
3889                 }
3890                 m_interpreter.GetDebugger().PushInputReader (reader_sp);
3891             }
3892             result.SetStatus (eReturnStatusSuccessFinishNoResult);
3893         }
3894         else
3895         {
3896             result.AppendError ("invalid target\n");
3897             result.SetStatus (eReturnStatusFailed);
3898         }
3899 
3900         return result.Succeeded();
3901     }
3902 private:
3903     CommandOptions m_options;
3904 };
3905 
3906 OptionDefinition
3907 CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] =
3908 {
3909     { LLDB_OPT_SET_ALL, false, "one-liner", 'o', required_argument, NULL, NULL, eArgTypeOneLiner,
3910         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
3911     { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
3912         "Set the module within which the stop-hook is to be run."},
3913     { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, NULL, eArgTypeThreadIndex,
3914         "The stop hook is run only for the thread whose index matches this argument."},
3915     { LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, NULL, eArgTypeThreadID,
3916         "The stop hook is run only for the thread whose TID matches this argument."},
3917     { LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, NULL, eArgTypeThreadName,
3918         "The stop hook is run only for the thread whose thread name matches this argument."},
3919     { LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, NULL, eArgTypeQueueName,
3920         "The stop hook is run only for threads in the queue whose name is given by this argument."},
3921     { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
3922         "Specify the source file within which the stop-hook is to be run." },
3923     { LLDB_OPT_SET_1, false, "start-line", 'l', required_argument, NULL, 0, eArgTypeLineNum,
3924         "Set the start of the line range for which the stop-hook is to be run."},
3925     { LLDB_OPT_SET_1, false, "end-line", 'e', required_argument, NULL, 0, eArgTypeLineNum,
3926         "Set the end of the line range for which the stop-hook is to be run."},
3927     { LLDB_OPT_SET_2, false, "classname", 'c', required_argument, NULL, NULL, eArgTypeClassName,
3928         "Specify the class within which the stop-hook is to be run." },
3929     { LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
3930         "Set the function name within which the stop hook will be run." },
3931     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
3932 };
3933 
3934 #pragma mark CommandObjectTargetStopHookDelete
3935 
3936 //-------------------------------------------------------------------------
3937 // CommandObjectTargetStopHookDelete
3938 //-------------------------------------------------------------------------
3939 
3940 class CommandObjectTargetStopHookDelete : public CommandObject
3941 {
3942 public:
3943 
3944     CommandObjectTargetStopHookDelete (CommandInterpreter &interpreter) :
3945         CommandObject (interpreter,
3946                        "target stop-hook delete",
3947                        "Delete a stop-hook.",
3948                        "target stop-hook delete [<idx>]")
3949     {
3950     }
3951 
3952     ~CommandObjectTargetStopHookDelete ()
3953     {
3954     }
3955 
3956     bool
3957     Execute (Args& command,
3958              CommandReturnObject &result)
3959     {
3960         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
3961         if (target)
3962         {
3963             // FIXME: see if we can use the breakpoint id style parser?
3964             size_t num_args = command.GetArgumentCount();
3965             if (num_args == 0)
3966             {
3967                 if (!m_interpreter.Confirm ("Delete all stop hooks?", true))
3968                 {
3969                     result.SetStatus (eReturnStatusFailed);
3970                     return false;
3971                 }
3972                 else
3973                 {
3974                     target->RemoveAllStopHooks();
3975                 }
3976             }
3977             else
3978             {
3979                 bool success;
3980                 for (size_t i = 0; i < num_args; i++)
3981                 {
3982                     lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success);
3983                     if (!success)
3984                     {
3985                         result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i));
3986                         result.SetStatus(eReturnStatusFailed);
3987                         return false;
3988                     }
3989                     success = target->RemoveStopHookByID (user_id);
3990                     if (!success)
3991                     {
3992                         result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i));
3993                         result.SetStatus(eReturnStatusFailed);
3994                         return false;
3995                     }
3996                 }
3997             }
3998             result.SetStatus (eReturnStatusSuccessFinishNoResult);
3999         }
4000         else
4001         {
4002             result.AppendError ("invalid target\n");
4003             result.SetStatus (eReturnStatusFailed);
4004         }
4005 
4006         return result.Succeeded();
4007     }
4008 };
4009 #pragma mark CommandObjectTargetStopHookEnableDisable
4010 
4011 //-------------------------------------------------------------------------
4012 // CommandObjectTargetStopHookEnableDisable
4013 //-------------------------------------------------------------------------
4014 
4015 class CommandObjectTargetStopHookEnableDisable : public CommandObject
4016 {
4017 public:
4018 
4019     CommandObjectTargetStopHookEnableDisable (CommandInterpreter &interpreter, bool enable, const char *name, const char *help, const char *syntax) :
4020         CommandObject (interpreter,
4021                        name,
4022                        help,
4023                        syntax),
4024         m_enable (enable)
4025     {
4026     }
4027 
4028     ~CommandObjectTargetStopHookEnableDisable ()
4029     {
4030     }
4031 
4032     bool
4033     Execute (Args& command,
4034              CommandReturnObject &result)
4035     {
4036         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
4037         if (target)
4038         {
4039             // FIXME: see if we can use the breakpoint id style parser?
4040             size_t num_args = command.GetArgumentCount();
4041             bool success;
4042 
4043             if (num_args == 0)
4044             {
4045                 target->SetAllStopHooksActiveState (m_enable);
4046             }
4047             else
4048             {
4049                 for (size_t i = 0; i < num_args; i++)
4050                 {
4051                     lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success);
4052                     if (!success)
4053                     {
4054                         result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i));
4055                         result.SetStatus(eReturnStatusFailed);
4056                         return false;
4057                     }
4058                     success = target->SetStopHookActiveStateByID (user_id, m_enable);
4059                     if (!success)
4060                     {
4061                         result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i));
4062                         result.SetStatus(eReturnStatusFailed);
4063                         return false;
4064                     }
4065                 }
4066             }
4067             result.SetStatus (eReturnStatusSuccessFinishNoResult);
4068         }
4069         else
4070         {
4071             result.AppendError ("invalid target\n");
4072             result.SetStatus (eReturnStatusFailed);
4073         }
4074         return result.Succeeded();
4075     }
4076 private:
4077     bool m_enable;
4078 };
4079 
4080 #pragma mark CommandObjectTargetStopHookList
4081 
4082 //-------------------------------------------------------------------------
4083 // CommandObjectTargetStopHookList
4084 //-------------------------------------------------------------------------
4085 
4086 class CommandObjectTargetStopHookList : public CommandObject
4087 {
4088 public:
4089 
4090     CommandObjectTargetStopHookList (CommandInterpreter &interpreter) :
4091         CommandObject (interpreter,
4092                        "target stop-hook list",
4093                        "List all stop-hooks.",
4094                        "target stop-hook list [<type>]")
4095     {
4096     }
4097 
4098     ~CommandObjectTargetStopHookList ()
4099     {
4100     }
4101 
4102     bool
4103     Execute (Args& command,
4104              CommandReturnObject &result)
4105     {
4106         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
4107         if (!target)
4108         {
4109             result.AppendError ("invalid target\n");
4110             result.SetStatus (eReturnStatusFailed);
4111             return result.Succeeded();
4112         }
4113 
4114         size_t num_hooks = target->GetNumStopHooks ();
4115         if (num_hooks == 0)
4116         {
4117             result.GetOutputStream().PutCString ("No stop hooks.\n");
4118         }
4119         else
4120         {
4121             for (size_t i = 0; i < num_hooks; i++)
4122             {
4123                 Target::StopHookSP this_hook = target->GetStopHookAtIndex (i);
4124                 if (i > 0)
4125                     result.GetOutputStream().PutCString ("\n");
4126                 this_hook->GetDescription (&(result.GetOutputStream()), eDescriptionLevelFull);
4127             }
4128         }
4129         result.SetStatus (eReturnStatusSuccessFinishResult);
4130         return result.Succeeded();
4131     }
4132 };
4133 
4134 #pragma mark CommandObjectMultiwordTargetStopHooks
4135 //-------------------------------------------------------------------------
4136 // CommandObjectMultiwordTargetStopHooks
4137 //-------------------------------------------------------------------------
4138 
4139 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword
4140 {
4141 public:
4142 
4143     CommandObjectMultiwordTargetStopHooks (CommandInterpreter &interpreter) :
4144         CommandObjectMultiword (interpreter,
4145                                 "target stop-hook",
4146                                 "A set of commands for operating on debugger target stop-hooks.",
4147                                 "target stop-hook <subcommand> [<subcommand-options>]")
4148     {
4149         LoadSubCommand ("add",      CommandObjectSP (new CommandObjectTargetStopHookAdd (interpreter)));
4150         LoadSubCommand ("delete",   CommandObjectSP (new CommandObjectTargetStopHookDelete (interpreter)));
4151         LoadSubCommand ("disable",  CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter,
4152                                                                                                    false,
4153                                                                                                    "target stop-hook disable [<id>]",
4154                                                                                                    "Disable a stop-hook.",
4155                                                                                                    "target stop-hook disable")));
4156         LoadSubCommand ("enable",   CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter,
4157                                                                                                    true,
4158                                                                                                    "target stop-hook enable [<id>]",
4159                                                                                                    "Enable a stop-hook.",
4160                                                                                                    "target stop-hook enable")));
4161         LoadSubCommand ("list",     CommandObjectSP (new CommandObjectTargetStopHookList (interpreter)));
4162     }
4163 
4164     ~CommandObjectMultiwordTargetStopHooks()
4165     {
4166     }
4167 };
4168 
4169 
4170 
4171 #pragma mark CommandObjectMultiwordTarget
4172 
4173 //-------------------------------------------------------------------------
4174 // CommandObjectMultiwordTarget
4175 //-------------------------------------------------------------------------
4176 
4177 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter &interpreter) :
4178     CommandObjectMultiword (interpreter,
4179                             "target",
4180                             "A set of commands for operating on debugger targets.",
4181                             "target <subcommand> [<subcommand-options>]")
4182 {
4183 
4184     LoadSubCommand ("create",    CommandObjectSP (new CommandObjectTargetCreate (interpreter)));
4185     LoadSubCommand ("delete",    CommandObjectSP (new CommandObjectTargetDelete (interpreter)));
4186     LoadSubCommand ("list",      CommandObjectSP (new CommandObjectTargetList   (interpreter)));
4187     LoadSubCommand ("select",    CommandObjectSP (new CommandObjectTargetSelect (interpreter)));
4188     LoadSubCommand ("stop-hook", CommandObjectSP (new CommandObjectMultiwordTargetStopHooks (interpreter)));
4189     LoadSubCommand ("modules",   CommandObjectSP (new CommandObjectTargetModules (interpreter)));
4190     LoadSubCommand ("variable",  CommandObjectSP (new CommandObjectTargetVariable (interpreter)));
4191 }
4192 
4193 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget ()
4194 {
4195 }
4196 
4197 
4198