1 //===-- CommandObjectTarget.cpp ---------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "CommandObjectTarget.h"
10 
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/IOHandler.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/ModuleSpec.h"
15 #include "lldb/Core/Section.h"
16 #include "lldb/Core/ValueObjectVariable.h"
17 #include "lldb/DataFormatters/ValueObjectPrinter.h"
18 #include "lldb/Host/OptionParser.h"
19 #include "lldb/Host/StringConvert.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandReturnObject.h"
22 #include "lldb/Interpreter/OptionArgParser.h"
23 #include "lldb/Interpreter/OptionGroupArchitecture.h"
24 #include "lldb/Interpreter/OptionGroupBoolean.h"
25 #include "lldb/Interpreter/OptionGroupFile.h"
26 #include "lldb/Interpreter/OptionGroupFormat.h"
27 #include "lldb/Interpreter/OptionGroupPlatform.h"
28 #include "lldb/Interpreter/OptionGroupString.h"
29 #include "lldb/Interpreter/OptionGroupUInt64.h"
30 #include "lldb/Interpreter/OptionGroupUUID.h"
31 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
32 #include "lldb/Interpreter/OptionGroupVariable.h"
33 #include "lldb/Interpreter/Options.h"
34 #include "lldb/Symbol/CompileUnit.h"
35 #include "lldb/Symbol/FuncUnwinders.h"
36 #include "lldb/Symbol/LineTable.h"
37 #include "lldb/Symbol/LocateSymbolFile.h"
38 #include "lldb/Symbol/ObjectFile.h"
39 #include "lldb/Symbol/SymbolFile.h"
40 #include "lldb/Symbol/UnwindPlan.h"
41 #include "lldb/Symbol/VariableList.h"
42 #include "lldb/Target/ABI.h"
43 #include "lldb/Target/Process.h"
44 #include "lldb/Target/RegisterContext.h"
45 #include "lldb/Target/SectionLoadList.h"
46 #include "lldb/Target/StackFrame.h"
47 #include "lldb/Target/Thread.h"
48 #include "lldb/Target/ThreadSpec.h"
49 #include "lldb/Utility/Args.h"
50 #include "lldb/Utility/State.h"
51 #include "lldb/Utility/Timer.h"
52 
53 #include "llvm/Support/FileSystem.h"
54 #include "llvm/Support/FormatAdapters.h"
55 
56 #include <cerrno>
57 
58 using namespace lldb;
59 using namespace lldb_private;
60 
61 static void DumpTargetInfo(uint32_t target_idx, Target *target,
62                            const char *prefix_cstr,
63                            bool show_stopped_process_status, Stream &strm) {
64   const ArchSpec &target_arch = target->GetArchitecture();
65 
66   Module *exe_module = target->GetExecutableModulePointer();
67   char exe_path[PATH_MAX];
68   bool exe_valid = false;
69   if (exe_module)
70     exe_valid = exe_module->GetFileSpec().GetPath(exe_path, sizeof(exe_path));
71 
72   if (!exe_valid)
73     ::strcpy(exe_path, "<none>");
74 
75   strm.Printf("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx,
76               exe_path);
77 
78   uint32_t properties = 0;
79   if (target_arch.IsValid()) {
80     strm.Printf("%sarch=", properties++ > 0 ? ", " : " ( ");
81     target_arch.DumpTriple(strm);
82     properties++;
83   }
84   PlatformSP platform_sp(target->GetPlatform());
85   if (platform_sp)
86     strm.Printf("%splatform=%s", properties++ > 0 ? ", " : " ( ",
87                 platform_sp->GetName().GetCString());
88 
89   ProcessSP process_sp(target->GetProcessSP());
90   bool show_process_status = false;
91   if (process_sp) {
92     lldb::pid_t pid = process_sp->GetID();
93     StateType state = process_sp->GetState();
94     if (show_stopped_process_status)
95       show_process_status = StateIsStoppedState(state, true);
96     const char *state_cstr = StateAsCString(state);
97     if (pid != LLDB_INVALID_PROCESS_ID)
98       strm.Printf("%spid=%" PRIu64, properties++ > 0 ? ", " : " ( ", pid);
99     strm.Printf("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr);
100   }
101   if (properties > 0)
102     strm.PutCString(" )\n");
103   else
104     strm.EOL();
105   if (show_process_status) {
106     const bool only_threads_with_stop_reason = true;
107     const uint32_t start_frame = 0;
108     const uint32_t num_frames = 1;
109     const uint32_t num_frames_with_source = 1;
110     const bool     stop_format = false;
111     process_sp->GetStatus(strm);
112     process_sp->GetThreadStatus(strm, only_threads_with_stop_reason,
113                                 start_frame, num_frames,
114                                 num_frames_with_source, stop_format);
115   }
116 }
117 
118 static uint32_t DumpTargetList(TargetList &target_list,
119                                bool show_stopped_process_status, Stream &strm) {
120   const uint32_t num_targets = target_list.GetNumTargets();
121   if (num_targets) {
122     TargetSP selected_target_sp(target_list.GetSelectedTarget());
123     strm.PutCString("Current targets:\n");
124     for (uint32_t i = 0; i < num_targets; ++i) {
125       TargetSP target_sp(target_list.GetTargetAtIndex(i));
126       if (target_sp) {
127         bool is_selected = target_sp.get() == selected_target_sp.get();
128         DumpTargetInfo(i, target_sp.get(), is_selected ? "* " : "  ",
129                        show_stopped_process_status, strm);
130       }
131     }
132   }
133   return num_targets;
134 }
135 
136 // Note that the negation in the argument name causes a slightly confusing
137 // mapping of the enum values.
138 static constexpr OptionEnumValueElement g_dependents_enumaration[] = {
139     {
140         eLoadDependentsDefault,
141         "default",
142         "Only load dependents when the target is an executable.",
143     },
144     {
145         eLoadDependentsNo,
146         "true",
147         "Don't load dependents, even if the target is an executable.",
148     },
149     {
150         eLoadDependentsYes,
151         "false",
152         "Load dependents, even if the target is not an executable.",
153     },
154 };
155 
156 #define LLDB_OPTIONS_target_dependents
157 #include "CommandOptions.inc"
158 
159 class OptionGroupDependents : public OptionGroup {
160 public:
161   OptionGroupDependents() {}
162 
163   ~OptionGroupDependents() override {}
164 
165   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
166     return llvm::makeArrayRef(g_target_dependents_options);
167   }
168 
169   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
170                         ExecutionContext *execution_context) override {
171     Status error;
172 
173     // For compatibility no value means don't load dependents.
174     if (option_value.empty()) {
175       m_load_dependent_files = eLoadDependentsNo;
176       return error;
177     }
178 
179     const char short_option =
180         g_target_dependents_options[option_idx].short_option;
181     if (short_option == 'd') {
182       LoadDependentFiles tmp_load_dependents;
183       tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum(
184           option_value, g_target_dependents_options[option_idx].enum_values, 0,
185           error);
186       if (error.Success())
187         m_load_dependent_files = tmp_load_dependents;
188     } else {
189       error.SetErrorStringWithFormat("unrecognized short option '%c'",
190                                      short_option);
191     }
192 
193     return error;
194   }
195 
196   Status SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete;
197 
198   void OptionParsingStarting(ExecutionContext *execution_context) override {
199     m_load_dependent_files = eLoadDependentsDefault;
200   }
201 
202   LoadDependentFiles m_load_dependent_files;
203 
204 private:
205   DISALLOW_COPY_AND_ASSIGN(OptionGroupDependents);
206 };
207 
208 #pragma mark CommandObjectTargetCreate
209 
210 // "target create"
211 
212 class CommandObjectTargetCreate : public CommandObjectParsed {
213 public:
214   CommandObjectTargetCreate(CommandInterpreter &interpreter)
215       : CommandObjectParsed(
216             interpreter, "target create",
217             "Create a target using the argument as the main executable.",
218             nullptr),
219         m_option_group(), m_arch_option(),
220         m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename,
221                     "Fullpath to a core file to use for this target."),
222         m_platform_path(LLDB_OPT_SET_1, false, "platform-path", 'P', 0,
223                         eArgTypePath,
224                         "Path to the remote file to use for this target."),
225         m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
226                       eArgTypeFilename,
227                       "Fullpath to a stand alone debug "
228                       "symbols file for when debug symbols "
229                       "are not in the executable."),
230         m_remote_file(
231             LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename,
232             "Fullpath to the file on the remote host if debugging remotely."),
233         m_add_dependents() {
234     CommandArgumentEntry arg;
235     CommandArgumentData file_arg;
236 
237     // Define the first (and only) variant of this arg.
238     file_arg.arg_type = eArgTypeFilename;
239     file_arg.arg_repetition = eArgRepeatPlain;
240 
241     // There is only one variant this argument could be; put it into the
242     // argument entry.
243     arg.push_back(file_arg);
244 
245     // Push the data for the first argument into the m_arguments vector.
246     m_arguments.push_back(arg);
247 
248     m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
249     m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
250     m_option_group.Append(&m_platform_path, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
251     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
252     m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
253     m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
254     m_option_group.Finalize();
255   }
256 
257   ~CommandObjectTargetCreate() override = default;
258 
259   Options *GetOptions() override { return &m_option_group; }
260 
261   void
262   HandleArgumentCompletion(CompletionRequest &request,
263                            OptionElementVector &opt_element_vector) override {
264     CommandCompletions::InvokeCommonCompletionCallbacks(
265         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
266         request, nullptr);
267   }
268 
269 protected:
270   bool DoExecute(Args &command, CommandReturnObject &result) override {
271     const size_t argc = command.GetArgumentCount();
272     FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue());
273     FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());
274 
275     if (core_file) {
276       if (!FileSystem::Instance().Exists(core_file)) {
277         result.AppendErrorWithFormat("core file '%s' doesn't exist",
278                                      core_file.GetPath().c_str());
279         result.SetStatus(eReturnStatusFailed);
280         return false;
281       }
282       if (!FileSystem::Instance().Readable(core_file)) {
283         result.AppendErrorWithFormat("core file '%s' is not readable",
284                                      core_file.GetPath().c_str());
285         result.SetStatus(eReturnStatusFailed);
286         return false;
287       }
288     }
289 
290     if (argc == 1 || core_file || remote_file) {
291       FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
292       if (symfile) {
293         if (FileSystem::Instance().Exists(symfile)) {
294           if (!FileSystem::Instance().Readable(symfile)) {
295             result.AppendErrorWithFormat("symbol file '%s' is not readable",
296                                          symfile.GetPath().c_str());
297             result.SetStatus(eReturnStatusFailed);
298             return false;
299           }
300         } else {
301           char symfile_path[PATH_MAX];
302           symfile.GetPath(symfile_path, sizeof(symfile_path));
303           result.AppendErrorWithFormat("invalid symbol file path '%s'",
304                                        symfile_path);
305           result.SetStatus(eReturnStatusFailed);
306           return false;
307         }
308       }
309 
310       const char *file_path = command.GetArgumentAtIndex(0);
311       static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
312       Timer scoped_timer(func_cat, "(lldb) target create '%s'", file_path);
313       FileSpec file_spec;
314 
315       if (file_path) {
316         file_spec.SetFile(file_path, FileSpec::Style::native);
317         FileSystem::Instance().Resolve(file_spec);
318       }
319 
320       bool must_set_platform_path = false;
321 
322       Debugger &debugger = GetDebugger();
323 
324       TargetSP target_sp;
325       llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
326       Status error(debugger.GetTargetList().CreateTarget(
327           debugger, file_path, arch_cstr,
328           m_add_dependents.m_load_dependent_files, nullptr, target_sp));
329 
330       if (target_sp) {
331         // Only get the platform after we create the target because we might
332         // have switched platforms depending on what the arguments were to
333         // CreateTarget() we can't rely on the selected platform.
334 
335         PlatformSP platform_sp = target_sp->GetPlatform();
336 
337         if (remote_file) {
338           if (platform_sp) {
339             // I have a remote file.. two possible cases
340             if (file_spec && FileSystem::Instance().Exists(file_spec)) {
341               // if the remote file does not exist, push it there
342               if (!platform_sp->GetFileExists(remote_file)) {
343                 Status err = platform_sp->PutFile(file_spec, remote_file);
344                 if (err.Fail()) {
345                   result.AppendError(err.AsCString());
346                   result.SetStatus(eReturnStatusFailed);
347                   return false;
348                 }
349               }
350             } else {
351               // there is no local file and we need one
352               // in order to make the remote ---> local transfer we need a
353               // platform
354               // TODO: if the user has passed in a --platform argument, use it
355               // to fetch the right platform
356               if (!platform_sp) {
357                 result.AppendError(
358                     "unable to perform remote debugging without a platform");
359                 result.SetStatus(eReturnStatusFailed);
360                 return false;
361               }
362               if (file_path) {
363                 // copy the remote file to the local file
364                 Status err = platform_sp->GetFile(remote_file, file_spec);
365                 if (err.Fail()) {
366                   result.AppendError(err.AsCString());
367                   result.SetStatus(eReturnStatusFailed);
368                   return false;
369                 }
370               } else {
371                 // make up a local file
372                 result.AppendError("remote --> local transfer without local "
373                                    "path is not implemented yet");
374                 result.SetStatus(eReturnStatusFailed);
375                 return false;
376               }
377             }
378           } else {
379             result.AppendError("no platform found for target");
380             result.SetStatus(eReturnStatusFailed);
381             return false;
382           }
383         }
384 
385         if (symfile || remote_file) {
386           ModuleSP module_sp(target_sp->GetExecutableModule());
387           if (module_sp) {
388             if (symfile)
389               module_sp->SetSymbolFileFileSpec(symfile);
390             if (remote_file) {
391               std::string remote_path = remote_file.GetPath();
392               target_sp->SetArg0(remote_path.c_str());
393               module_sp->SetPlatformFileSpec(remote_file);
394             }
395           }
396         }
397 
398         debugger.GetTargetList().SetSelectedTarget(target_sp.get());
399         if (must_set_platform_path) {
400           ModuleSpec main_module_spec(file_spec);
401           ModuleSP module_sp = target_sp->GetOrCreateModule(main_module_spec,
402                                                           true /* notify */);
403           if (module_sp)
404             module_sp->SetPlatformFileSpec(remote_file);
405         }
406         if (core_file) {
407           char core_path[PATH_MAX];
408           core_file.GetPath(core_path, sizeof(core_path));
409           if (FileSystem::Instance().Exists(core_file)) {
410             if (!FileSystem::Instance().Readable(core_file)) {
411               result.AppendMessageWithFormat(
412                   "Core file '%s' is not readable.\n", core_path);
413               result.SetStatus(eReturnStatusFailed);
414               return false;
415             }
416             FileSpec core_file_dir;
417             core_file_dir.GetDirectory() = core_file.GetDirectory();
418             target_sp->AppendExecutableSearchPaths(core_file_dir);
419 
420             ProcessSP process_sp(target_sp->CreateProcess(
421                 GetDebugger().GetListener(), llvm::StringRef(), &core_file));
422 
423             if (process_sp) {
424               // Seems weird that we Launch a core file, but that is what we
425               // do!
426               error = process_sp->LoadCore();
427 
428               if (error.Fail()) {
429                 result.AppendError(
430                     error.AsCString("can't find plug-in for core file"));
431                 result.SetStatus(eReturnStatusFailed);
432                 return false;
433               } else {
434                 result.AppendMessageWithFormat(
435                     "Core file '%s' (%s) was loaded.\n", core_path,
436                     target_sp->GetArchitecture().GetArchitectureName());
437                 result.SetStatus(eReturnStatusSuccessFinishNoResult);
438               }
439             } else {
440               result.AppendErrorWithFormat(
441                   "Unable to find process plug-in for core file '%s'\n",
442                   core_path);
443               result.SetStatus(eReturnStatusFailed);
444             }
445           } else {
446             result.AppendErrorWithFormat("Core file '%s' does not exist\n",
447                                          core_path);
448             result.SetStatus(eReturnStatusFailed);
449           }
450         } else {
451           result.AppendMessageWithFormat(
452               "Current executable set to '%s' (%s).\n",
453               file_spec.GetPath().c_str(),
454               target_sp->GetArchitecture().GetArchitectureName());
455           result.SetStatus(eReturnStatusSuccessFinishNoResult);
456         }
457       } else {
458         result.AppendError(error.AsCString());
459         result.SetStatus(eReturnStatusFailed);
460       }
461     } else {
462       result.AppendErrorWithFormat("'%s' takes exactly one executable path "
463                                    "argument, or use the --core option.\n",
464                                    m_cmd_name.c_str());
465       result.SetStatus(eReturnStatusFailed);
466     }
467     return result.Succeeded();
468   }
469 
470 private:
471   OptionGroupOptions m_option_group;
472   OptionGroupArchitecture m_arch_option;
473   OptionGroupFile m_core_file;
474   OptionGroupFile m_platform_path;
475   OptionGroupFile m_symbol_file;
476   OptionGroupFile m_remote_file;
477   OptionGroupDependents m_add_dependents;
478 };
479 
480 #pragma mark CommandObjectTargetList
481 
482 // "target list"
483 
484 class CommandObjectTargetList : public CommandObjectParsed {
485 public:
486   CommandObjectTargetList(CommandInterpreter &interpreter)
487       : CommandObjectParsed(
488             interpreter, "target list",
489             "List all current targets in the current debug session.", nullptr) {
490   }
491 
492   ~CommandObjectTargetList() override = default;
493 
494 protected:
495   bool DoExecute(Args &args, CommandReturnObject &result) override {
496     if (args.GetArgumentCount() == 0) {
497       Stream &strm = result.GetOutputStream();
498 
499       bool show_stopped_process_status = false;
500       if (DumpTargetList(GetDebugger().GetTargetList(),
501                          show_stopped_process_status, strm) == 0) {
502         strm.PutCString("No targets.\n");
503       }
504       result.SetStatus(eReturnStatusSuccessFinishResult);
505     } else {
506       result.AppendError("the 'target list' command takes no arguments\n");
507       result.SetStatus(eReturnStatusFailed);
508     }
509     return result.Succeeded();
510   }
511 };
512 
513 #pragma mark CommandObjectTargetSelect
514 
515 // "target select"
516 
517 class CommandObjectTargetSelect : public CommandObjectParsed {
518 public:
519   CommandObjectTargetSelect(CommandInterpreter &interpreter)
520       : CommandObjectParsed(
521             interpreter, "target select",
522             "Select a target as the current target by target index.", nullptr) {
523   }
524 
525   ~CommandObjectTargetSelect() override = default;
526 
527 protected:
528   bool DoExecute(Args &args, CommandReturnObject &result) override {
529     if (args.GetArgumentCount() == 1) {
530       bool success = false;
531       const char *target_idx_arg = args.GetArgumentAtIndex(0);
532       uint32_t target_idx =
533           StringConvert::ToUInt32(target_idx_arg, UINT32_MAX, 0, &success);
534       if (success) {
535         TargetList &target_list = GetDebugger().GetTargetList();
536         const uint32_t num_targets = target_list.GetNumTargets();
537         if (target_idx < num_targets) {
538           TargetSP target_sp(target_list.GetTargetAtIndex(target_idx));
539           if (target_sp) {
540             Stream &strm = result.GetOutputStream();
541             target_list.SetSelectedTarget(target_sp.get());
542             bool show_stopped_process_status = false;
543             DumpTargetList(target_list, show_stopped_process_status, strm);
544             result.SetStatus(eReturnStatusSuccessFinishResult);
545           } else {
546             result.AppendErrorWithFormat("target #%u is NULL in target list\n",
547                                          target_idx);
548             result.SetStatus(eReturnStatusFailed);
549           }
550         } else {
551           if (num_targets > 0) {
552             result.AppendErrorWithFormat(
553                 "index %u is out of range, valid target indexes are 0 - %u\n",
554                 target_idx, num_targets - 1);
555           } else {
556             result.AppendErrorWithFormat(
557                 "index %u is out of range since there are no active targets\n",
558                 target_idx);
559           }
560           result.SetStatus(eReturnStatusFailed);
561         }
562       } else {
563         result.AppendErrorWithFormat("invalid index string value '%s'\n",
564                                      target_idx_arg);
565         result.SetStatus(eReturnStatusFailed);
566       }
567     } else {
568       result.AppendError(
569           "'target select' takes a single argument: a target index\n");
570       result.SetStatus(eReturnStatusFailed);
571     }
572     return result.Succeeded();
573   }
574 };
575 
576 #pragma mark CommandObjectTargetSelect
577 
578 // "target delete"
579 
580 class CommandObjectTargetDelete : public CommandObjectParsed {
581 public:
582   CommandObjectTargetDelete(CommandInterpreter &interpreter)
583       : CommandObjectParsed(interpreter, "target delete",
584                             "Delete one or more targets by target index.",
585                             nullptr),
586         m_option_group(), m_all_option(LLDB_OPT_SET_1, false, "all", 'a',
587                                        "Delete all targets.", false, true),
588         m_cleanup_option(
589             LLDB_OPT_SET_1, false, "clean", 'c',
590             "Perform extra cleanup to minimize memory consumption after "
591             "deleting the target.  "
592             "By default, LLDB will keep in memory any modules previously "
593             "loaded by the target as well "
594             "as all of its debug info.  Specifying --clean will unload all of "
595             "these shared modules and "
596             "cause them to be reparsed again the next time the target is run",
597             false, true) {
598     m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
599     m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
600     m_option_group.Finalize();
601   }
602 
603   ~CommandObjectTargetDelete() override = default;
604 
605   Options *GetOptions() override { return &m_option_group; }
606 
607 protected:
608   bool DoExecute(Args &args, CommandReturnObject &result) override {
609     const size_t argc = args.GetArgumentCount();
610     std::vector<TargetSP> delete_target_list;
611     TargetList &target_list = GetDebugger().GetTargetList();
612     TargetSP target_sp;
613 
614     if (m_all_option.GetOptionValue()) {
615       for (int i = 0; i < target_list.GetNumTargets(); ++i)
616         delete_target_list.push_back(target_list.GetTargetAtIndex(i));
617     } else if (argc > 0) {
618       const uint32_t num_targets = target_list.GetNumTargets();
619       // Bail out if don't have any targets.
620       if (num_targets == 0) {
621         result.AppendError("no targets to delete");
622         result.SetStatus(eReturnStatusFailed);
623         return false;
624       }
625 
626       for (auto &entry : args.entries()) {
627         uint32_t target_idx;
628         if (entry.ref.getAsInteger(0, target_idx)) {
629           result.AppendErrorWithFormat("invalid target index '%s'\n",
630                                        entry.c_str());
631           result.SetStatus(eReturnStatusFailed);
632           return false;
633         }
634         if (target_idx < num_targets) {
635           target_sp = target_list.GetTargetAtIndex(target_idx);
636           if (target_sp) {
637             delete_target_list.push_back(target_sp);
638             continue;
639           }
640         }
641         if (num_targets > 1)
642           result.AppendErrorWithFormat("target index %u is out of range, valid "
643                                        "target indexes are 0 - %u\n",
644                                        target_idx, num_targets - 1);
645         else
646           result.AppendErrorWithFormat(
647               "target index %u is out of range, the only valid index is 0\n",
648               target_idx);
649 
650         result.SetStatus(eReturnStatusFailed);
651         return false;
652       }
653     } else {
654       target_sp = target_list.GetSelectedTarget();
655       if (!target_sp) {
656         result.AppendErrorWithFormat("no target is currently selected\n");
657         result.SetStatus(eReturnStatusFailed);
658         return false;
659       }
660       delete_target_list.push_back(target_sp);
661     }
662 
663     const size_t num_targets_to_delete = delete_target_list.size();
664     for (size_t idx = 0; idx < num_targets_to_delete; ++idx) {
665       target_sp = delete_target_list[idx];
666       target_list.DeleteTarget(target_sp);
667       target_sp->Destroy();
668     }
669     // If "--clean" was specified, prune any orphaned shared modules from the
670     // global shared module list
671     if (m_cleanup_option.GetOptionValue()) {
672       const bool mandatory = true;
673       ModuleList::RemoveOrphanSharedModules(mandatory);
674     }
675     result.GetOutputStream().Printf("%u targets deleted.\n",
676                                     (uint32_t)num_targets_to_delete);
677     result.SetStatus(eReturnStatusSuccessFinishResult);
678 
679     return true;
680   }
681 
682   OptionGroupOptions m_option_group;
683   OptionGroupBoolean m_all_option;
684   OptionGroupBoolean m_cleanup_option;
685 };
686 
687 #pragma mark CommandObjectTargetVariable
688 
689 // "target variable"
690 
691 class CommandObjectTargetVariable : public CommandObjectParsed {
692   static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
693   static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'
694 
695 public:
696   CommandObjectTargetVariable(CommandInterpreter &interpreter)
697       : CommandObjectParsed(interpreter, "target variable",
698                             "Read global variables for the current target, "
699                             "before or while running a process.",
700                             nullptr, eCommandRequiresTarget),
701         m_option_group(),
702         m_option_variable(false), // Don't include frame options
703         m_option_format(eFormatDefault),
704         m_option_compile_units(LLDB_OPT_SET_1, false, "file", SHORT_OPTION_FILE,
705                                0, eArgTypeFilename,
706                                "A basename or fullpath to a file that contains "
707                                "global variables. This option can be "
708                                "specified multiple times."),
709         m_option_shared_libraries(
710             LLDB_OPT_SET_1, false, "shlib", SHORT_OPTION_SHLB, 0,
711             eArgTypeFilename,
712             "A basename or fullpath to a shared library to use in the search "
713             "for global "
714             "variables. This option can be specified multiple times."),
715         m_varobj_options() {
716     CommandArgumentEntry arg;
717     CommandArgumentData var_name_arg;
718 
719     // Define the first (and only) variant of this arg.
720     var_name_arg.arg_type = eArgTypeVarName;
721     var_name_arg.arg_repetition = eArgRepeatPlus;
722 
723     // There is only one variant this argument could be; put it into the
724     // argument entry.
725     arg.push_back(var_name_arg);
726 
727     // Push the data for the first argument into the m_arguments vector.
728     m_arguments.push_back(arg);
729 
730     m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
731     m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
732     m_option_group.Append(&m_option_format,
733                           OptionGroupFormat::OPTION_GROUP_FORMAT |
734                               OptionGroupFormat::OPTION_GROUP_GDB_FMT,
735                           LLDB_OPT_SET_1);
736     m_option_group.Append(&m_option_compile_units, LLDB_OPT_SET_ALL,
737                           LLDB_OPT_SET_1);
738     m_option_group.Append(&m_option_shared_libraries, LLDB_OPT_SET_ALL,
739                           LLDB_OPT_SET_1);
740     m_option_group.Finalize();
741   }
742 
743   ~CommandObjectTargetVariable() override = default;
744 
745   void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp,
746                        const char *root_name) {
747     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
748 
749     if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() &&
750         valobj_sp->IsRuntimeSupportValue())
751       return;
752 
753     switch (var_sp->GetScope()) {
754     case eValueTypeVariableGlobal:
755       if (m_option_variable.show_scope)
756         s.PutCString("GLOBAL: ");
757       break;
758 
759     case eValueTypeVariableStatic:
760       if (m_option_variable.show_scope)
761         s.PutCString("STATIC: ");
762       break;
763 
764     case eValueTypeVariableArgument:
765       if (m_option_variable.show_scope)
766         s.PutCString("   ARG: ");
767       break;
768 
769     case eValueTypeVariableLocal:
770       if (m_option_variable.show_scope)
771         s.PutCString(" LOCAL: ");
772       break;
773 
774     case eValueTypeVariableThreadLocal:
775       if (m_option_variable.show_scope)
776         s.PutCString("THREAD: ");
777       break;
778 
779     default:
780       break;
781     }
782 
783     if (m_option_variable.show_decl) {
784       bool show_fullpaths = false;
785       bool show_module = true;
786       if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
787         s.PutCString(": ");
788     }
789 
790     const Format format = m_option_format.GetFormat();
791     if (format != eFormatDefault)
792       options.SetFormat(format);
793 
794     options.SetRootValueObjectName(root_name);
795 
796     valobj_sp->Dump(s, options);
797   }
798 
799   static size_t GetVariableCallback(void *baton, const char *name,
800                                     VariableList &variable_list) {
801     Target *target = static_cast<Target *>(baton);
802     if (target) {
803       return target->GetImages().FindGlobalVariables(ConstString(name),
804                                                      UINT32_MAX, variable_list);
805     }
806     return 0;
807   }
808 
809   Options *GetOptions() override { return &m_option_group; }
810 
811 protected:
812   void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
813                               const SymbolContext &sc,
814                               const VariableList &variable_list, Stream &s) {
815     size_t count = variable_list.GetSize();
816     if (count > 0) {
817       if (sc.module_sp) {
818         if (sc.comp_unit) {
819           s.Printf("Global variables for %s in %s:\n",
820                    sc.comp_unit->GetPath().c_str(),
821                    sc.module_sp->GetFileSpec().GetPath().c_str());
822         } else {
823           s.Printf("Global variables for %s\n",
824                    sc.module_sp->GetFileSpec().GetPath().c_str());
825         }
826       } else if (sc.comp_unit) {
827         s.Printf("Global variables for %s\n", sc.comp_unit->GetPath().c_str());
828       }
829 
830       for (uint32_t i = 0; i < count; ++i) {
831         VariableSP var_sp(variable_list.GetVariableAtIndex(i));
832         if (var_sp) {
833           ValueObjectSP valobj_sp(ValueObjectVariable::Create(
834               exe_ctx.GetBestExecutionContextScope(), var_sp));
835 
836           if (valobj_sp)
837             DumpValueObject(s, var_sp, valobj_sp,
838                             var_sp->GetName().GetCString());
839         }
840       }
841     }
842   }
843 
844   bool DoExecute(Args &args, CommandReturnObject &result) override {
845     Target *target = m_exe_ctx.GetTargetPtr();
846     const size_t argc = args.GetArgumentCount();
847     Stream &s = result.GetOutputStream();
848 
849     if (argc > 0) {
850 
851       // TODO: Convert to entry-based iteration.  Requires converting
852       // DumpValueObject.
853       for (size_t idx = 0; idx < argc; ++idx) {
854         VariableList variable_list;
855         ValueObjectList valobj_list;
856 
857         const char *arg = args.GetArgumentAtIndex(idx);
858         size_t matches = 0;
859         bool use_var_name = false;
860         if (m_option_variable.use_regex) {
861           RegularExpression regex(llvm::StringRef::withNullAsEmpty(arg));
862           if (!regex.IsValid()) {
863             result.GetErrorStream().Printf(
864                 "error: invalid regular expression: '%s'\n", arg);
865             result.SetStatus(eReturnStatusFailed);
866             return false;
867           }
868           use_var_name = true;
869           matches = target->GetImages().FindGlobalVariables(regex, UINT32_MAX,
870                                                             variable_list);
871         } else {
872           Status error(Variable::GetValuesForVariableExpressionPath(
873               arg, m_exe_ctx.GetBestExecutionContextScope(),
874               GetVariableCallback, target, variable_list, valobj_list));
875           matches = variable_list.GetSize();
876         }
877 
878         if (matches == 0) {
879           result.GetErrorStream().Printf(
880               "error: can't find global variable '%s'\n", arg);
881           result.SetStatus(eReturnStatusFailed);
882           return false;
883         } else {
884           for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) {
885             VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx));
886             if (var_sp) {
887               ValueObjectSP valobj_sp(
888                   valobj_list.GetValueObjectAtIndex(global_idx));
889               if (!valobj_sp)
890                 valobj_sp = ValueObjectVariable::Create(
891                     m_exe_ctx.GetBestExecutionContextScope(), var_sp);
892 
893               if (valobj_sp)
894                 DumpValueObject(s, var_sp, valobj_sp,
895                                 use_var_name ? var_sp->GetName().GetCString()
896                                              : arg);
897             }
898           }
899         }
900       }
901     } else {
902       const FileSpecList &compile_units =
903           m_option_compile_units.GetOptionValue().GetCurrentValue();
904       const FileSpecList &shlibs =
905           m_option_shared_libraries.GetOptionValue().GetCurrentValue();
906       SymbolContextList sc_list;
907       const size_t num_compile_units = compile_units.GetSize();
908       const size_t num_shlibs = shlibs.GetSize();
909       if (num_compile_units == 0 && num_shlibs == 0) {
910         bool success = false;
911         StackFrame *frame = m_exe_ctx.GetFramePtr();
912         CompileUnit *comp_unit = nullptr;
913         if (frame) {
914           SymbolContext sc = frame->GetSymbolContext(eSymbolContextCompUnit);
915           if (sc.comp_unit) {
916             const bool can_create = true;
917             VariableListSP comp_unit_varlist_sp(
918                 sc.comp_unit->GetVariableList(can_create));
919             if (comp_unit_varlist_sp) {
920               size_t count = comp_unit_varlist_sp->GetSize();
921               if (count > 0) {
922                 DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
923                 success = true;
924               }
925             }
926           }
927         }
928         if (!success) {
929           if (frame) {
930             if (comp_unit)
931               result.AppendErrorWithFormat(
932                   "no global variables in current compile unit: %s\n",
933                   comp_unit->GetPath().c_str());
934             else
935               result.AppendErrorWithFormat(
936                   "no debug information for frame %u\n",
937                   frame->GetFrameIndex());
938           } else
939             result.AppendError("'target variable' takes one or more global "
940                                "variable names as arguments\n");
941           result.SetStatus(eReturnStatusFailed);
942         }
943       } else {
944         SymbolContextList sc_list;
945         const bool append = true;
946         // We have one or more compile unit or shlib
947         if (num_shlibs > 0) {
948           for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) {
949             const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
950             ModuleSpec module_spec(module_file);
951 
952             ModuleSP module_sp(
953                 target->GetImages().FindFirstModule(module_spec));
954             if (module_sp) {
955               if (num_compile_units > 0) {
956                 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
957                   module_sp->FindCompileUnits(
958                       compile_units.GetFileSpecAtIndex(cu_idx), append,
959                       sc_list);
960               } else {
961                 SymbolContext sc;
962                 sc.module_sp = module_sp;
963                 sc_list.Append(sc);
964               }
965             } else {
966               // Didn't find matching shlib/module in target...
967               result.AppendErrorWithFormat(
968                   "target doesn't contain the specified shared library: %s\n",
969                   module_file.GetPath().c_str());
970             }
971           }
972         } else {
973           // No shared libraries, we just want to find globals for the compile
974           // units files that were specified
975           for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
976             target->GetImages().FindCompileUnits(
977                 compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
978         }
979 
980         const uint32_t num_scs = sc_list.GetSize();
981         if (num_scs > 0) {
982           SymbolContext sc;
983           for (uint32_t sc_idx = 0; sc_idx < num_scs; ++sc_idx) {
984             if (sc_list.GetContextAtIndex(sc_idx, sc)) {
985               if (sc.comp_unit) {
986                 const bool can_create = true;
987                 VariableListSP comp_unit_varlist_sp(
988                     sc.comp_unit->GetVariableList(can_create));
989                 if (comp_unit_varlist_sp)
990                   DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
991                                          s);
992               } else if (sc.module_sp) {
993                 // Get all global variables for this module
994                 lldb_private::RegularExpression all_globals_regex(
995                     llvm::StringRef(
996                         ".")); // Any global with at least one character
997                 VariableList variable_list;
998                 sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX,
999                                                   variable_list);
1000                 DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
1001               }
1002             }
1003           }
1004         }
1005       }
1006     }
1007 
1008     if (m_interpreter.TruncationWarningNecessary()) {
1009       result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
1010                                       m_cmd_name.c_str());
1011       m_interpreter.TruncationWarningGiven();
1012     }
1013 
1014     return result.Succeeded();
1015   }
1016 
1017   OptionGroupOptions m_option_group;
1018   OptionGroupVariable m_option_variable;
1019   OptionGroupFormat m_option_format;
1020   OptionGroupFileList m_option_compile_units;
1021   OptionGroupFileList m_option_shared_libraries;
1022   OptionGroupValueObjectDisplay m_varobj_options;
1023 };
1024 
1025 #pragma mark CommandObjectTargetModulesSearchPathsAdd
1026 
1027 class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed {
1028 public:
1029   CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter &interpreter)
1030       : CommandObjectParsed(interpreter, "target modules search-paths add",
1031                             "Add new image search paths substitution pairs to "
1032                             "the current target.",
1033                             nullptr) {
1034     CommandArgumentEntry arg;
1035     CommandArgumentData old_prefix_arg;
1036     CommandArgumentData new_prefix_arg;
1037 
1038     // Define the first variant of this arg pair.
1039     old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1040     old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1041 
1042     // Define the first variant of this arg pair.
1043     new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1044     new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1045 
1046     // There are two required arguments that must always occur together, i.e.
1047     // an argument "pair".  Because they must always occur together, they are
1048     // treated as two variants of one argument rather than two independent
1049     // arguments.  Push them both into the first argument position for
1050     // m_arguments...
1051 
1052     arg.push_back(old_prefix_arg);
1053     arg.push_back(new_prefix_arg);
1054 
1055     m_arguments.push_back(arg);
1056   }
1057 
1058   ~CommandObjectTargetModulesSearchPathsAdd() override = default;
1059 
1060 protected:
1061   bool DoExecute(Args &command, CommandReturnObject &result) override {
1062     Target *target = GetDebugger().GetSelectedTarget().get();
1063     if (target) {
1064       const size_t argc = command.GetArgumentCount();
1065       if (argc & 1) {
1066         result.AppendError("add requires an even number of arguments\n");
1067         result.SetStatus(eReturnStatusFailed);
1068       } else {
1069         for (size_t i = 0; i < argc; i += 2) {
1070           const char *from = command.GetArgumentAtIndex(i);
1071           const char *to = command.GetArgumentAtIndex(i + 1);
1072 
1073           if (from[0] && to[0]) {
1074             Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
1075             if (log) {
1076               LLDB_LOGF(log,
1077                         "target modules search path adding ImageSearchPath "
1078                         "pair: '%s' -> '%s'",
1079                         from, to);
1080             }
1081             bool last_pair = ((argc - i) == 2);
1082             target->GetImageSearchPathList().Append(
1083                 ConstString(from), ConstString(to),
1084                 last_pair); // Notify if this is the last pair
1085             result.SetStatus(eReturnStatusSuccessFinishNoResult);
1086           } else {
1087             if (from[0])
1088               result.AppendError("<path-prefix> can't be empty\n");
1089             else
1090               result.AppendError("<new-path-prefix> can't be empty\n");
1091             result.SetStatus(eReturnStatusFailed);
1092           }
1093         }
1094       }
1095     } else {
1096       result.AppendError("invalid target\n");
1097       result.SetStatus(eReturnStatusFailed);
1098     }
1099     return result.Succeeded();
1100   }
1101 };
1102 
1103 #pragma mark CommandObjectTargetModulesSearchPathsClear
1104 
1105 class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed {
1106 public:
1107   CommandObjectTargetModulesSearchPathsClear(CommandInterpreter &interpreter)
1108       : CommandObjectParsed(interpreter, "target modules search-paths clear",
1109                             "Clear all current image search path substitution "
1110                             "pairs from the current target.",
1111                             "target modules search-paths clear") {}
1112 
1113   ~CommandObjectTargetModulesSearchPathsClear() override = default;
1114 
1115 protected:
1116   bool DoExecute(Args &command, CommandReturnObject &result) override {
1117     Target *target = GetDebugger().GetSelectedTarget().get();
1118     if (target) {
1119       bool notify = true;
1120       target->GetImageSearchPathList().Clear(notify);
1121       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1122     } else {
1123       result.AppendError("invalid target\n");
1124       result.SetStatus(eReturnStatusFailed);
1125     }
1126     return result.Succeeded();
1127   }
1128 };
1129 
1130 #pragma mark CommandObjectTargetModulesSearchPathsInsert
1131 
1132 class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed {
1133 public:
1134   CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter &interpreter)
1135       : CommandObjectParsed(interpreter, "target modules search-paths insert",
1136                             "Insert a new image search path substitution pair "
1137                             "into the current target at the specified index.",
1138                             nullptr) {
1139     CommandArgumentEntry arg1;
1140     CommandArgumentEntry arg2;
1141     CommandArgumentData index_arg;
1142     CommandArgumentData old_prefix_arg;
1143     CommandArgumentData new_prefix_arg;
1144 
1145     // Define the first and only variant of this arg.
1146     index_arg.arg_type = eArgTypeIndex;
1147     index_arg.arg_repetition = eArgRepeatPlain;
1148 
1149     // Put the one and only variant into the first arg for m_arguments:
1150     arg1.push_back(index_arg);
1151 
1152     // Define the first variant of this arg pair.
1153     old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1154     old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1155 
1156     // Define the first variant of this arg pair.
1157     new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1158     new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1159 
1160     // There are two required arguments that must always occur together, i.e.
1161     // an argument "pair".  Because they must always occur together, they are
1162     // treated as two variants of one argument rather than two independent
1163     // arguments.  Push them both into the same argument position for
1164     // m_arguments...
1165 
1166     arg2.push_back(old_prefix_arg);
1167     arg2.push_back(new_prefix_arg);
1168 
1169     // Add arguments to m_arguments.
1170     m_arguments.push_back(arg1);
1171     m_arguments.push_back(arg2);
1172   }
1173 
1174   ~CommandObjectTargetModulesSearchPathsInsert() override = default;
1175 
1176 protected:
1177   bool DoExecute(Args &command, CommandReturnObject &result) override {
1178     Target *target = GetDebugger().GetSelectedTarget().get();
1179     if (target) {
1180       size_t argc = command.GetArgumentCount();
1181       // check for at least 3 arguments and an odd number of parameters
1182       if (argc >= 3 && argc & 1) {
1183         bool success = false;
1184 
1185         uint32_t insert_idx = StringConvert::ToUInt32(
1186             command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
1187 
1188         if (!success) {
1189           result.AppendErrorWithFormat(
1190               "<index> parameter is not an integer: '%s'.\n",
1191               command.GetArgumentAtIndex(0));
1192           result.SetStatus(eReturnStatusFailed);
1193           return result.Succeeded();
1194         }
1195 
1196         // shift off the index
1197         command.Shift();
1198         argc = command.GetArgumentCount();
1199 
1200         for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) {
1201           const char *from = command.GetArgumentAtIndex(i);
1202           const char *to = command.GetArgumentAtIndex(i + 1);
1203 
1204           if (from[0] && to[0]) {
1205             bool last_pair = ((argc - i) == 2);
1206             target->GetImageSearchPathList().Insert(
1207                 ConstString(from), ConstString(to), insert_idx, last_pair);
1208             result.SetStatus(eReturnStatusSuccessFinishNoResult);
1209           } else {
1210             if (from[0])
1211               result.AppendError("<path-prefix> can't be empty\n");
1212             else
1213               result.AppendError("<new-path-prefix> can't be empty\n");
1214             result.SetStatus(eReturnStatusFailed);
1215             return false;
1216           }
1217         }
1218       } else {
1219         result.AppendError("insert requires at least three arguments\n");
1220         result.SetStatus(eReturnStatusFailed);
1221         return result.Succeeded();
1222       }
1223 
1224     } else {
1225       result.AppendError("invalid target\n");
1226       result.SetStatus(eReturnStatusFailed);
1227     }
1228     return result.Succeeded();
1229   }
1230 };
1231 
1232 #pragma mark CommandObjectTargetModulesSearchPathsList
1233 
1234 class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed {
1235 public:
1236   CommandObjectTargetModulesSearchPathsList(CommandInterpreter &interpreter)
1237       : CommandObjectParsed(interpreter, "target modules search-paths list",
1238                             "List all current image search path substitution "
1239                             "pairs in the current target.",
1240                             "target modules search-paths list") {}
1241 
1242   ~CommandObjectTargetModulesSearchPathsList() override = default;
1243 
1244 protected:
1245   bool DoExecute(Args &command, CommandReturnObject &result) override {
1246     Target *target = GetDebugger().GetSelectedTarget().get();
1247     if (target) {
1248       if (command.GetArgumentCount() != 0) {
1249         result.AppendError("list takes no arguments\n");
1250         result.SetStatus(eReturnStatusFailed);
1251         return result.Succeeded();
1252       }
1253 
1254       target->GetImageSearchPathList().Dump(&result.GetOutputStream());
1255       result.SetStatus(eReturnStatusSuccessFinishResult);
1256     } else {
1257       result.AppendError("invalid target\n");
1258       result.SetStatus(eReturnStatusFailed);
1259     }
1260     return result.Succeeded();
1261   }
1262 };
1263 
1264 #pragma mark CommandObjectTargetModulesSearchPathsQuery
1265 
1266 class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed {
1267 public:
1268   CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter &interpreter)
1269       : CommandObjectParsed(
1270             interpreter, "target modules search-paths query",
1271             "Transform a path using the first applicable image search path.",
1272             nullptr) {
1273     CommandArgumentEntry arg;
1274     CommandArgumentData path_arg;
1275 
1276     // Define the first (and only) variant of this arg.
1277     path_arg.arg_type = eArgTypeDirectoryName;
1278     path_arg.arg_repetition = eArgRepeatPlain;
1279 
1280     // There is only one variant this argument could be; put it into the
1281     // argument entry.
1282     arg.push_back(path_arg);
1283 
1284     // Push the data for the first argument into the m_arguments vector.
1285     m_arguments.push_back(arg);
1286   }
1287 
1288   ~CommandObjectTargetModulesSearchPathsQuery() override = default;
1289 
1290 protected:
1291   bool DoExecute(Args &command, CommandReturnObject &result) override {
1292     Target *target = GetDebugger().GetSelectedTarget().get();
1293     if (target) {
1294       if (command.GetArgumentCount() != 1) {
1295         result.AppendError("query requires one argument\n");
1296         result.SetStatus(eReturnStatusFailed);
1297         return result.Succeeded();
1298       }
1299 
1300       ConstString orig(command.GetArgumentAtIndex(0));
1301       ConstString transformed;
1302       if (target->GetImageSearchPathList().RemapPath(orig, transformed))
1303         result.GetOutputStream().Printf("%s\n", transformed.GetCString());
1304       else
1305         result.GetOutputStream().Printf("%s\n", orig.GetCString());
1306 
1307       result.SetStatus(eReturnStatusSuccessFinishResult);
1308     } else {
1309       result.AppendError("invalid target\n");
1310       result.SetStatus(eReturnStatusFailed);
1311     }
1312     return result.Succeeded();
1313   }
1314 };
1315 
1316 // Static Helper functions
1317 static void DumpModuleArchitecture(Stream &strm, Module *module,
1318                                    bool full_triple, uint32_t width) {
1319   if (module) {
1320     StreamString arch_strm;
1321 
1322     if (full_triple)
1323       module->GetArchitecture().DumpTriple(arch_strm);
1324     else
1325       arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
1326     std::string arch_str = arch_strm.GetString();
1327 
1328     if (width)
1329       strm.Printf("%-*s", width, arch_str.c_str());
1330     else
1331       strm.PutCString(arch_str);
1332   }
1333 }
1334 
1335 static void DumpModuleUUID(Stream &strm, Module *module) {
1336   if (module && module->GetUUID().IsValid())
1337     module->GetUUID().Dump(&strm);
1338   else
1339     strm.PutCString("                                    ");
1340 }
1341 
1342 static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
1343                                          Stream &strm, Module *module,
1344                                          const FileSpec &file_spec,
1345                                          lldb::DescriptionLevel desc_level) {
1346   uint32_t num_matches = 0;
1347   if (module) {
1348     SymbolContextList sc_list;
1349     num_matches = module->ResolveSymbolContextsForFileSpec(
1350         file_spec, 0, false, eSymbolContextCompUnit, sc_list);
1351 
1352     for (uint32_t i = 0; i < num_matches; ++i) {
1353       SymbolContext sc;
1354       if (sc_list.GetContextAtIndex(i, sc)) {
1355         if (i > 0)
1356           strm << "\n\n";
1357 
1358         strm << "Line table for " << *static_cast<FileSpec *>(sc.comp_unit)
1359              << " in `" << module->GetFileSpec().GetFilename() << "\n";
1360         LineTable *line_table = sc.comp_unit->GetLineTable();
1361         if (line_table)
1362           line_table->GetDescription(
1363               &strm, interpreter.GetExecutionContext().GetTargetPtr(),
1364               desc_level);
1365         else
1366           strm << "No line table";
1367       }
1368     }
1369   }
1370   return num_matches;
1371 }
1372 
1373 static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr,
1374                          uint32_t width) {
1375   if (file_spec_ptr) {
1376     if (width > 0) {
1377       std::string fullpath = file_spec_ptr->GetPath();
1378       strm.Printf("%-*s", width, fullpath.c_str());
1379       return;
1380     } else {
1381       file_spec_ptr->Dump(&strm);
1382       return;
1383     }
1384   }
1385   // Keep the width spacing correct if things go wrong...
1386   if (width > 0)
1387     strm.Printf("%-*s", width, "");
1388 }
1389 
1390 static void DumpDirectory(Stream &strm, const FileSpec *file_spec_ptr,
1391                           uint32_t width) {
1392   if (file_spec_ptr) {
1393     if (width > 0)
1394       strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
1395     else
1396       file_spec_ptr->GetDirectory().Dump(&strm);
1397     return;
1398   }
1399   // Keep the width spacing correct if things go wrong...
1400   if (width > 0)
1401     strm.Printf("%-*s", width, "");
1402 }
1403 
1404 static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr,
1405                          uint32_t width) {
1406   if (file_spec_ptr) {
1407     if (width > 0)
1408       strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
1409     else
1410       file_spec_ptr->GetFilename().Dump(&strm);
1411     return;
1412   }
1413   // Keep the width spacing correct if things go wrong...
1414   if (width > 0)
1415     strm.Printf("%-*s", width, "");
1416 }
1417 
1418 static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
1419   size_t num_dumped = 0;
1420   std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
1421   const size_t num_modules = module_list.GetSize();
1422   if (num_modules > 0) {
1423     strm.Printf("Dumping headers for %" PRIu64 " module(s).\n",
1424                 static_cast<uint64_t>(num_modules));
1425     strm.IndentMore();
1426     for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1427       Module *module = module_list.GetModulePointerAtIndexUnlocked(image_idx);
1428       if (module) {
1429         if (num_dumped++ > 0) {
1430           strm.EOL();
1431           strm.EOL();
1432         }
1433         ObjectFile *objfile = module->GetObjectFile();
1434         if (objfile)
1435           objfile->Dump(&strm);
1436         else {
1437           strm.Format("No object file for module: {0:F}\n",
1438                       module->GetFileSpec());
1439         }
1440       }
1441     }
1442     strm.IndentLess();
1443   }
1444   return num_dumped;
1445 }
1446 
1447 static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
1448                              Module *module, SortOrder sort_order) {
1449   if (!module)
1450     return;
1451   if (Symtab *symtab = module->GetSymtab())
1452     symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
1453                  sort_order);
1454 }
1455 
1456 static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,
1457                                Module *module) {
1458   if (module) {
1459     SectionList *section_list = module->GetSectionList();
1460     if (section_list) {
1461       strm.Printf("Sections for '%s' (%s):\n",
1462                   module->GetSpecificationDescription().c_str(),
1463                   module->GetArchitecture().GetArchitectureName());
1464       strm.IndentMore();
1465       section_list->Dump(&strm,
1466                          interpreter.GetExecutionContext().GetTargetPtr(), true,
1467                          UINT32_MAX);
1468       strm.IndentLess();
1469     }
1470   }
1471 }
1472 
1473 static bool DumpModuleSymbolFile(Stream &strm, Module *module) {
1474   if (module) {
1475     if (SymbolFile *symbol_file = module->GetSymbolFile(true)) {
1476       symbol_file->Dump(strm);
1477       return true;
1478     }
1479   }
1480   return false;
1481 }
1482 
1483 static void DumpAddress(ExecutionContextScope *exe_scope,
1484                         const Address &so_addr, bool verbose, Stream &strm) {
1485   strm.IndentMore();
1486   strm.Indent("    Address: ");
1487   so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
1488   strm.PutCString(" (");
1489   so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset);
1490   strm.PutCString(")\n");
1491   strm.Indent("    Summary: ");
1492   const uint32_t save_indent = strm.GetIndentLevel();
1493   strm.SetIndentLevel(save_indent + 13);
1494   so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription);
1495   strm.SetIndentLevel(save_indent);
1496   // Print out detailed address information when verbose is enabled
1497   if (verbose) {
1498     strm.EOL();
1499     so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext);
1500   }
1501   strm.IndentLess();
1502 }
1503 
1504 static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
1505                                   Module *module, uint32_t resolve_mask,
1506                                   lldb::addr_t raw_addr, lldb::addr_t offset,
1507                                   bool verbose) {
1508   if (module) {
1509     lldb::addr_t addr = raw_addr - offset;
1510     Address so_addr;
1511     SymbolContext sc;
1512     Target *target = interpreter.GetExecutionContext().GetTargetPtr();
1513     if (target && !target->GetSectionLoadList().IsEmpty()) {
1514       if (!target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
1515         return false;
1516       else if (so_addr.GetModule().get() != module)
1517         return false;
1518     } else {
1519       if (!module->ResolveFileAddress(addr, so_addr))
1520         return false;
1521     }
1522 
1523     ExecutionContextScope *exe_scope =
1524         interpreter.GetExecutionContext().GetBestExecutionContextScope();
1525     DumpAddress(exe_scope, so_addr, verbose, strm);
1526     //        strm.IndentMore();
1527     //        strm.Indent ("    Address: ");
1528     //        so_addr.Dump (&strm, exe_scope,
1529     //        Address::DumpStyleModuleWithFileAddress);
1530     //        strm.PutCString (" (");
1531     //        so_addr.Dump (&strm, exe_scope,
1532     //        Address::DumpStyleSectionNameOffset);
1533     //        strm.PutCString (")\n");
1534     //        strm.Indent ("    Summary: ");
1535     //        const uint32_t save_indent = strm.GetIndentLevel ();
1536     //        strm.SetIndentLevel (save_indent + 13);
1537     //        so_addr.Dump (&strm, exe_scope,
1538     //        Address::DumpStyleResolvedDescription);
1539     //        strm.SetIndentLevel (save_indent);
1540     //        // Print out detailed address information when verbose is enabled
1541     //        if (verbose)
1542     //        {
1543     //            strm.EOL();
1544     //            so_addr.Dump (&strm, exe_scope,
1545     //            Address::DumpStyleDetailedSymbolContext);
1546     //        }
1547     //        strm.IndentLess();
1548     return true;
1549   }
1550 
1551   return false;
1552 }
1553 
1554 static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
1555                                      Stream &strm, Module *module,
1556                                      const char *name, bool name_is_regex,
1557                                      bool verbose) {
1558   if (!module)
1559     return 0;
1560 
1561   Symtab *symtab = module->GetSymtab();
1562   if (!symtab)
1563     return 0;
1564 
1565   SymbolContext sc;
1566   std::vector<uint32_t> match_indexes;
1567   ConstString symbol_name(name);
1568   uint32_t num_matches = 0;
1569   if (name_is_regex) {
1570     RegularExpression name_regexp(symbol_name.GetStringRef());
1571     num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType(
1572         name_regexp, eSymbolTypeAny, match_indexes);
1573   } else {
1574     num_matches =
1575         symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes);
1576   }
1577 
1578   if (num_matches > 0) {
1579     strm.Indent();
1580     strm.Printf("%u symbols match %s'%s' in ", num_matches,
1581                 name_is_regex ? "the regular expression " : "", name);
1582     DumpFullpath(strm, &module->GetFileSpec(), 0);
1583     strm.PutCString(":\n");
1584     strm.IndentMore();
1585     for (uint32_t i = 0; i < num_matches; ++i) {
1586       Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
1587       if (symbol && symbol->ValueIsAddress()) {
1588         DumpAddress(
1589             interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1590             symbol->GetAddressRef(), verbose, strm);
1591       }
1592     }
1593     strm.IndentLess();
1594   }
1595   return num_matches;
1596 }
1597 
1598 static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
1599                                   Stream &strm, SymbolContextList &sc_list,
1600                                   bool verbose) {
1601   strm.IndentMore();
1602 
1603   const uint32_t num_matches = sc_list.GetSize();
1604 
1605   for (uint32_t i = 0; i < num_matches; ++i) {
1606     SymbolContext sc;
1607     if (sc_list.GetContextAtIndex(i, sc)) {
1608       AddressRange range;
1609 
1610       sc.GetAddressRange(eSymbolContextEverything, 0, true, range);
1611 
1612       DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm);
1613     }
1614   }
1615   strm.IndentLess();
1616 }
1617 
1618 static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
1619                                      Stream &strm, Module *module,
1620                                      const char *name, bool name_is_regex,
1621                                      bool include_inlines, bool include_symbols,
1622                                      bool verbose) {
1623   if (module && name && name[0]) {
1624     SymbolContextList sc_list;
1625     const bool append = true;
1626     size_t num_matches = 0;
1627     if (name_is_regex) {
1628       RegularExpression function_name_regex((llvm::StringRef(name)));
1629       num_matches = module->FindFunctions(function_name_regex, include_symbols,
1630                                           include_inlines, append, sc_list);
1631     } else {
1632       ConstString function_name(name);
1633       num_matches = module->FindFunctions(
1634           function_name, nullptr, eFunctionNameTypeAuto, include_symbols,
1635           include_inlines, append, sc_list);
1636     }
1637 
1638     if (num_matches) {
1639       strm.Indent();
1640       strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1641                   num_matches > 1 ? "es" : "");
1642       DumpFullpath(strm, &module->GetFileSpec(), 0);
1643       strm.PutCString(":\n");
1644       DumpSymbolContextList(
1645           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1646           strm, sc_list, verbose);
1647     }
1648     return num_matches;
1649   }
1650   return 0;
1651 }
1652 
1653 static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
1654                                  Module *module, const char *name_cstr,
1655                                  bool name_is_regex) {
1656   if (module && name_cstr && name_cstr[0]) {
1657     TypeList type_list;
1658     const uint32_t max_num_matches = UINT32_MAX;
1659     size_t num_matches = 0;
1660     bool name_is_fully_qualified = false;
1661 
1662     ConstString name(name_cstr);
1663     llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
1664     num_matches =
1665         module->FindTypes(name, name_is_fully_qualified, max_num_matches,
1666                           searched_symbol_files, type_list);
1667 
1668     if (num_matches) {
1669       strm.Indent();
1670       strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1671                   num_matches > 1 ? "es" : "");
1672       DumpFullpath(strm, &module->GetFileSpec(), 0);
1673       strm.PutCString(":\n");
1674       for (TypeSP type_sp : type_list.Types()) {
1675         if (type_sp) {
1676           // Resolve the clang type so that any forward references to types
1677           // that haven't yet been parsed will get parsed.
1678           type_sp->GetFullCompilerType();
1679           type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1680           // Print all typedef chains
1681           TypeSP typedef_type_sp(type_sp);
1682           TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1683           while (typedefed_type_sp) {
1684             strm.EOL();
1685             strm.Printf("     typedef '%s': ",
1686                         typedef_type_sp->GetName().GetCString());
1687             typedefed_type_sp->GetFullCompilerType();
1688             typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull,
1689                                               true);
1690             typedef_type_sp = typedefed_type_sp;
1691             typedefed_type_sp = typedef_type_sp->GetTypedefType();
1692           }
1693         }
1694         strm.EOL();
1695       }
1696     }
1697     return num_matches;
1698   }
1699   return 0;
1700 }
1701 
1702 static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
1703                              Module &module, const char *name_cstr,
1704                              bool name_is_regex) {
1705   TypeList type_list;
1706   const uint32_t max_num_matches = UINT32_MAX;
1707   size_t num_matches = 1;
1708   bool name_is_fully_qualified = false;
1709 
1710   ConstString name(name_cstr);
1711   llvm::DenseSet<SymbolFile *> searched_symbol_files;
1712   num_matches = module.FindTypes(name, name_is_fully_qualified, max_num_matches,
1713                                  searched_symbol_files, type_list);
1714 
1715   if (num_matches) {
1716     strm.Indent();
1717     strm.PutCString("Best match found in ");
1718     DumpFullpath(strm, &module.GetFileSpec(), 0);
1719     strm.PutCString(":\n");
1720 
1721     TypeSP type_sp(type_list.GetTypeAtIndex(0));
1722     if (type_sp) {
1723       // Resolve the clang type so that any forward references to types that
1724       // haven't yet been parsed will get parsed.
1725       type_sp->GetFullCompilerType();
1726       type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1727       // Print all typedef chains
1728       TypeSP typedef_type_sp(type_sp);
1729       TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1730       while (typedefed_type_sp) {
1731         strm.EOL();
1732         strm.Printf("     typedef '%s': ",
1733                     typedef_type_sp->GetName().GetCString());
1734         typedefed_type_sp->GetFullCompilerType();
1735         typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1736         typedef_type_sp = typedefed_type_sp;
1737         typedefed_type_sp = typedef_type_sp->GetTypedefType();
1738       }
1739     }
1740     strm.EOL();
1741   }
1742   return num_matches;
1743 }
1744 
1745 static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
1746                                           Stream &strm, Module *module,
1747                                           const FileSpec &file_spec,
1748                                           uint32_t line, bool check_inlines,
1749                                           bool verbose) {
1750   if (module && file_spec) {
1751     SymbolContextList sc_list;
1752     const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
1753         file_spec, line, check_inlines, eSymbolContextEverything, sc_list);
1754     if (num_matches > 0) {
1755       strm.Indent();
1756       strm.Printf("%u match%s found in ", num_matches,
1757                   num_matches > 1 ? "es" : "");
1758       strm << file_spec;
1759       if (line > 0)
1760         strm.Printf(":%u", line);
1761       strm << " in ";
1762       DumpFullpath(strm, &module->GetFileSpec(), 0);
1763       strm.PutCString(":\n");
1764       DumpSymbolContextList(
1765           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1766           strm, sc_list, verbose);
1767       return num_matches;
1768     }
1769   }
1770   return 0;
1771 }
1772 
1773 static size_t FindModulesByName(Target *target, const char *module_name,
1774                                 ModuleList &module_list,
1775                                 bool check_global_list) {
1776   FileSpec module_file_spec(module_name);
1777   ModuleSpec module_spec(module_file_spec);
1778 
1779   const size_t initial_size = module_list.GetSize();
1780 
1781   if (check_global_list) {
1782     // Check the global list
1783     std::lock_guard<std::recursive_mutex> guard(
1784         Module::GetAllocationModuleCollectionMutex());
1785     const size_t num_modules = Module::GetNumberAllocatedModules();
1786     ModuleSP module_sp;
1787     for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1788       Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
1789 
1790       if (module) {
1791         if (module->MatchesModuleSpec(module_spec)) {
1792           module_sp = module->shared_from_this();
1793           module_list.AppendIfNeeded(module_sp);
1794         }
1795       }
1796     }
1797   } else {
1798     if (target) {
1799       const size_t num_matches =
1800           target->GetImages().FindModules(module_spec, module_list);
1801 
1802       // Not found in our module list for our target, check the main shared
1803       // module list in case it is a extra file used somewhere else
1804       if (num_matches == 0) {
1805         module_spec.GetArchitecture() = target->GetArchitecture();
1806         ModuleList::FindSharedModules(module_spec, module_list);
1807       }
1808     } else {
1809       ModuleList::FindSharedModules(module_spec, module_list);
1810     }
1811   }
1812 
1813   return module_list.GetSize() - initial_size;
1814 }
1815 
1816 #pragma mark CommandObjectTargetModulesModuleAutoComplete
1817 
1818 // A base command object class that can auto complete with module file
1819 // paths
1820 
1821 class CommandObjectTargetModulesModuleAutoComplete
1822     : public CommandObjectParsed {
1823 public:
1824   CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
1825                                                const char *name,
1826                                                const char *help,
1827                                                const char *syntax)
1828       : CommandObjectParsed(interpreter, name, help, syntax) {
1829     CommandArgumentEntry arg;
1830     CommandArgumentData file_arg;
1831 
1832     // Define the first (and only) variant of this arg.
1833     file_arg.arg_type = eArgTypeFilename;
1834     file_arg.arg_repetition = eArgRepeatStar;
1835 
1836     // There is only one variant this argument could be; put it into the
1837     // argument entry.
1838     arg.push_back(file_arg);
1839 
1840     // Push the data for the first argument into the m_arguments vector.
1841     m_arguments.push_back(arg);
1842   }
1843 
1844   ~CommandObjectTargetModulesModuleAutoComplete() override = default;
1845 
1846   void
1847   HandleArgumentCompletion(CompletionRequest &request,
1848                            OptionElementVector &opt_element_vector) override {
1849     CommandCompletions::InvokeCommonCompletionCallbacks(
1850         GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request,
1851         nullptr);
1852   }
1853 };
1854 
1855 #pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1856 
1857 // A base command object class that can auto complete with module source
1858 // file paths
1859 
1860 class CommandObjectTargetModulesSourceFileAutoComplete
1861     : public CommandObjectParsed {
1862 public:
1863   CommandObjectTargetModulesSourceFileAutoComplete(
1864       CommandInterpreter &interpreter, const char *name, const char *help,
1865       const char *syntax, uint32_t flags)
1866       : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1867     CommandArgumentEntry arg;
1868     CommandArgumentData source_file_arg;
1869 
1870     // Define the first (and only) variant of this arg.
1871     source_file_arg.arg_type = eArgTypeSourceFile;
1872     source_file_arg.arg_repetition = eArgRepeatPlus;
1873 
1874     // There is only one variant this argument could be; put it into the
1875     // argument entry.
1876     arg.push_back(source_file_arg);
1877 
1878     // Push the data for the first argument into the m_arguments vector.
1879     m_arguments.push_back(arg);
1880   }
1881 
1882   ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
1883 
1884   void
1885   HandleArgumentCompletion(CompletionRequest &request,
1886                            OptionElementVector &opt_element_vector) override {
1887     CommandCompletions::InvokeCommonCompletionCallbacks(
1888         GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
1889         request, nullptr);
1890   }
1891 };
1892 
1893 #pragma mark CommandObjectTargetModulesDumpObjfile
1894 
1895 class CommandObjectTargetModulesDumpObjfile
1896     : public CommandObjectTargetModulesModuleAutoComplete {
1897 public:
1898   CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
1899       : CommandObjectTargetModulesModuleAutoComplete(
1900             interpreter, "target modules dump objfile",
1901             "Dump the object file headers from one or more target modules.",
1902             nullptr) {}
1903 
1904   ~CommandObjectTargetModulesDumpObjfile() override = default;
1905 
1906 protected:
1907   bool DoExecute(Args &command, CommandReturnObject &result) override {
1908     Target *target = GetDebugger().GetSelectedTarget().get();
1909     if (target == nullptr) {
1910       result.AppendError("invalid target, create a debug target using the "
1911                          "'target create' command");
1912       result.SetStatus(eReturnStatusFailed);
1913       return false;
1914     }
1915 
1916     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1917     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1918     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1919 
1920     size_t num_dumped = 0;
1921     if (command.GetArgumentCount() == 0) {
1922       // Dump all headers for all modules images
1923       num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(),
1924                                             target->GetImages());
1925       if (num_dumped == 0) {
1926         result.AppendError("the target has no associated executable images");
1927         result.SetStatus(eReturnStatusFailed);
1928       }
1929     } else {
1930       // Find the modules that match the basename or full path.
1931       ModuleList module_list;
1932       const char *arg_cstr;
1933       for (int arg_idx = 0;
1934            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
1935            ++arg_idx) {
1936         size_t num_matched =
1937             FindModulesByName(target, arg_cstr, module_list, true);
1938         if (num_matched == 0) {
1939           result.AppendWarningWithFormat(
1940               "Unable to find an image that matches '%s'.\n", arg_cstr);
1941         }
1942       }
1943       // Dump all the modules we found.
1944       num_dumped =
1945           DumpModuleObjfileHeaders(result.GetOutputStream(), module_list);
1946     }
1947 
1948     if (num_dumped > 0) {
1949       result.SetStatus(eReturnStatusSuccessFinishResult);
1950     } else {
1951       result.AppendError("no matching executable images found");
1952       result.SetStatus(eReturnStatusFailed);
1953     }
1954     return result.Succeeded();
1955   }
1956 };
1957 
1958 #pragma mark CommandObjectTargetModulesDumpSymtab
1959 
1960 static constexpr OptionEnumValueElement g_sort_option_enumeration[] = {
1961     {
1962         eSortOrderNone,
1963         "none",
1964         "No sorting, use the original symbol table order.",
1965     },
1966     {
1967         eSortOrderByAddress,
1968         "address",
1969         "Sort output by symbol address.",
1970     },
1971     {
1972         eSortOrderByName,
1973         "name",
1974         "Sort output by symbol name.",
1975     },
1976 };
1977 
1978 #define LLDB_OPTIONS_target_modules_dump_symtab
1979 #include "CommandOptions.inc"
1980 
1981 class CommandObjectTargetModulesDumpSymtab
1982     : public CommandObjectTargetModulesModuleAutoComplete {
1983 public:
1984   CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
1985       : CommandObjectTargetModulesModuleAutoComplete(
1986             interpreter, "target modules dump symtab",
1987             "Dump the symbol table from one or more target modules.", nullptr),
1988         m_options() {}
1989 
1990   ~CommandObjectTargetModulesDumpSymtab() override = default;
1991 
1992   Options *GetOptions() override { return &m_options; }
1993 
1994   class CommandOptions : public Options {
1995   public:
1996     CommandOptions() : Options(), m_sort_order(eSortOrderNone) {}
1997 
1998     ~CommandOptions() override = default;
1999 
2000     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2001                           ExecutionContext *execution_context) override {
2002       Status error;
2003       const int short_option = m_getopt_table[option_idx].val;
2004 
2005       switch (short_option) {
2006       case 's':
2007         m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
2008             option_arg, GetDefinitions()[option_idx].enum_values,
2009             eSortOrderNone, error);
2010         break;
2011 
2012       default:
2013         error.SetErrorStringWithFormat("invalid short option character '%c'",
2014                                        short_option);
2015         break;
2016       }
2017       return error;
2018     }
2019 
2020     void OptionParsingStarting(ExecutionContext *execution_context) override {
2021       m_sort_order = eSortOrderNone;
2022     }
2023 
2024     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2025       return llvm::makeArrayRef(g_target_modules_dump_symtab_options);
2026     }
2027 
2028     SortOrder m_sort_order;
2029   };
2030 
2031 protected:
2032   bool DoExecute(Args &command, CommandReturnObject &result) override {
2033     Target *target = GetDebugger().GetSelectedTarget().get();
2034     if (target == nullptr) {
2035       result.AppendError("invalid target, create a debug target using the "
2036                          "'target create' command");
2037       result.SetStatus(eReturnStatusFailed);
2038       return false;
2039     } else {
2040       uint32_t num_dumped = 0;
2041 
2042       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2043       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2044       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2045 
2046       if (command.GetArgumentCount() == 0) {
2047         // Dump all sections for all modules images
2048         std::lock_guard<std::recursive_mutex> guard(
2049             target->GetImages().GetMutex());
2050         const size_t num_modules = target->GetImages().GetSize();
2051         if (num_modules > 0) {
2052           result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64
2053                                           " modules.\n",
2054                                           (uint64_t)num_modules);
2055           for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2056             if (num_dumped > 0) {
2057               result.GetOutputStream().EOL();
2058               result.GetOutputStream().EOL();
2059             }
2060             if (m_interpreter.WasInterrupted())
2061               break;
2062             num_dumped++;
2063             DumpModuleSymtab(
2064                 m_interpreter, result.GetOutputStream(),
2065                 target->GetImages().GetModulePointerAtIndexUnlocked(image_idx),
2066                 m_options.m_sort_order);
2067           }
2068         } else {
2069           result.AppendError("the target has no associated executable images");
2070           result.SetStatus(eReturnStatusFailed);
2071           return false;
2072         }
2073       } else {
2074         // Dump specified images (by basename or fullpath)
2075         const char *arg_cstr;
2076         for (int arg_idx = 0;
2077              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2078              ++arg_idx) {
2079           ModuleList module_list;
2080           const size_t num_matches =
2081               FindModulesByName(target, arg_cstr, module_list, true);
2082           if (num_matches > 0) {
2083             for (size_t i = 0; i < num_matches; ++i) {
2084               Module *module = module_list.GetModulePointerAtIndex(i);
2085               if (module) {
2086                 if (num_dumped > 0) {
2087                   result.GetOutputStream().EOL();
2088                   result.GetOutputStream().EOL();
2089                 }
2090                 if (m_interpreter.WasInterrupted())
2091                   break;
2092                 num_dumped++;
2093                 DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
2094                                  module, m_options.m_sort_order);
2095               }
2096             }
2097           } else
2098             result.AppendWarningWithFormat(
2099                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2100         }
2101       }
2102 
2103       if (num_dumped > 0)
2104         result.SetStatus(eReturnStatusSuccessFinishResult);
2105       else {
2106         result.AppendError("no matching executable images found");
2107         result.SetStatus(eReturnStatusFailed);
2108       }
2109     }
2110     return result.Succeeded();
2111   }
2112 
2113   CommandOptions m_options;
2114 };
2115 
2116 #pragma mark CommandObjectTargetModulesDumpSections
2117 
2118 // Image section dumping command
2119 
2120 class CommandObjectTargetModulesDumpSections
2121     : public CommandObjectTargetModulesModuleAutoComplete {
2122 public:
2123   CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter)
2124       : CommandObjectTargetModulesModuleAutoComplete(
2125             interpreter, "target modules dump sections",
2126             "Dump the sections from one or more target modules.",
2127             //"target modules dump sections [<file1> ...]")
2128             nullptr) {}
2129 
2130   ~CommandObjectTargetModulesDumpSections() override = default;
2131 
2132 protected:
2133   bool DoExecute(Args &command, CommandReturnObject &result) override {
2134     Target *target = GetDebugger().GetSelectedTarget().get();
2135     if (target == nullptr) {
2136       result.AppendError("invalid target, create a debug target using the "
2137                          "'target create' command");
2138       result.SetStatus(eReturnStatusFailed);
2139       return false;
2140     } else {
2141       uint32_t num_dumped = 0;
2142 
2143       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2144       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2145       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2146 
2147       if (command.GetArgumentCount() == 0) {
2148         // Dump all sections for all modules images
2149         const size_t num_modules = target->GetImages().GetSize();
2150         if (num_modules > 0) {
2151           result.GetOutputStream().Printf("Dumping sections for %" PRIu64
2152                                           " modules.\n",
2153                                           (uint64_t)num_modules);
2154           for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2155             if (m_interpreter.WasInterrupted())
2156               break;
2157             num_dumped++;
2158             DumpModuleSections(
2159                 m_interpreter, result.GetOutputStream(),
2160                 target->GetImages().GetModulePointerAtIndex(image_idx));
2161           }
2162         } else {
2163           result.AppendError("the target has no associated executable images");
2164           result.SetStatus(eReturnStatusFailed);
2165           return false;
2166         }
2167       } else {
2168         // Dump specified images (by basename or fullpath)
2169         const char *arg_cstr;
2170         for (int arg_idx = 0;
2171              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2172              ++arg_idx) {
2173           ModuleList module_list;
2174           const size_t num_matches =
2175               FindModulesByName(target, arg_cstr, module_list, true);
2176           if (num_matches > 0) {
2177             for (size_t i = 0; i < num_matches; ++i) {
2178               if (m_interpreter.WasInterrupted())
2179                 break;
2180               Module *module = module_list.GetModulePointerAtIndex(i);
2181               if (module) {
2182                 num_dumped++;
2183                 DumpModuleSections(m_interpreter, result.GetOutputStream(),
2184                                    module);
2185               }
2186             }
2187           } else {
2188             // Check the global list
2189             std::lock_guard<std::recursive_mutex> guard(
2190                 Module::GetAllocationModuleCollectionMutex());
2191 
2192             result.AppendWarningWithFormat(
2193                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2194           }
2195         }
2196       }
2197 
2198       if (num_dumped > 0)
2199         result.SetStatus(eReturnStatusSuccessFinishResult);
2200       else {
2201         result.AppendError("no matching executable images found");
2202         result.SetStatus(eReturnStatusFailed);
2203       }
2204     }
2205     return result.Succeeded();
2206   }
2207 };
2208 
2209 #pragma mark CommandObjectTargetModulesDumpSections
2210 
2211 // Clang AST dumping command
2212 
2213 class CommandObjectTargetModulesDumpClangAST
2214     : public CommandObjectTargetModulesModuleAutoComplete {
2215 public:
2216   CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter)
2217       : CommandObjectTargetModulesModuleAutoComplete(
2218             interpreter, "target modules dump ast",
2219             "Dump the clang ast for a given module's symbol file.",
2220             //"target modules dump ast [<file1> ...]")
2221             nullptr) {}
2222 
2223   ~CommandObjectTargetModulesDumpClangAST() override = default;
2224 
2225 protected:
2226   bool DoExecute(Args &command, CommandReturnObject &result) override {
2227     Target *target = GetDebugger().GetSelectedTarget().get();
2228     if (target == nullptr) {
2229       result.AppendError("invalid target, create a debug target using the "
2230                          "'target create' command");
2231       result.SetStatus(eReturnStatusFailed);
2232       return false;
2233     }
2234 
2235     const size_t num_modules = target->GetImages().GetSize();
2236     if (num_modules == 0) {
2237       result.AppendError("the target has no associated executable images");
2238       result.SetStatus(eReturnStatusFailed);
2239       return false;
2240     }
2241 
2242     if (command.GetArgumentCount() == 0) {
2243       // Dump all ASTs for all modules images
2244       result.GetOutputStream().Printf("Dumping clang ast for %" PRIu64
2245                                       " modules.\n",
2246                                       (uint64_t)num_modules);
2247       for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2248         if (m_interpreter.WasInterrupted())
2249           break;
2250         Module *m = target->GetImages().GetModulePointerAtIndex(image_idx);
2251         if (SymbolFile *sf = m->GetSymbolFile())
2252           sf->DumpClangAST(result.GetOutputStream());
2253       }
2254       result.SetStatus(eReturnStatusSuccessFinishResult);
2255       return true;
2256     }
2257 
2258     // Dump specified ASTs (by basename or fullpath)
2259     for (const Args::ArgEntry &arg : command.entries()) {
2260       ModuleList module_list;
2261       const size_t num_matches =
2262           FindModulesByName(target, arg.c_str(), module_list, true);
2263       if (num_matches == 0) {
2264         // Check the global list
2265         std::lock_guard<std::recursive_mutex> guard(
2266             Module::GetAllocationModuleCollectionMutex());
2267 
2268         result.AppendWarningWithFormat(
2269             "Unable to find an image that matches '%s'.\n", arg.c_str());
2270         continue;
2271       }
2272 
2273       for (size_t i = 0; i < num_matches; ++i) {
2274         if (m_interpreter.WasInterrupted())
2275           break;
2276         Module *m = module_list.GetModulePointerAtIndex(i);
2277         if (SymbolFile *sf = m->GetSymbolFile())
2278           sf->DumpClangAST(result.GetOutputStream());
2279       }
2280     }
2281     result.SetStatus(eReturnStatusSuccessFinishResult);
2282     return true;
2283   }
2284 };
2285 
2286 #pragma mark CommandObjectTargetModulesDumpSymfile
2287 
2288 // Image debug symbol dumping command
2289 
2290 class CommandObjectTargetModulesDumpSymfile
2291     : public CommandObjectTargetModulesModuleAutoComplete {
2292 public:
2293   CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter)
2294       : CommandObjectTargetModulesModuleAutoComplete(
2295             interpreter, "target modules dump symfile",
2296             "Dump the debug symbol file for one or more target modules.",
2297             //"target modules dump symfile [<file1> ...]")
2298             nullptr) {}
2299 
2300   ~CommandObjectTargetModulesDumpSymfile() override = default;
2301 
2302 protected:
2303   bool DoExecute(Args &command, CommandReturnObject &result) override {
2304     Target *target = GetDebugger().GetSelectedTarget().get();
2305     if (target == nullptr) {
2306       result.AppendError("invalid target, create a debug target using the "
2307                          "'target create' command");
2308       result.SetStatus(eReturnStatusFailed);
2309       return false;
2310     } else {
2311       uint32_t num_dumped = 0;
2312 
2313       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2314       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2315       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2316 
2317       if (command.GetArgumentCount() == 0) {
2318         // Dump all sections for all modules images
2319         const ModuleList &target_modules = target->GetImages();
2320         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2321         const size_t num_modules = target_modules.GetSize();
2322         if (num_modules > 0) {
2323           result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64
2324                                           " modules.\n",
2325                                           (uint64_t)num_modules);
2326           for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2327             if (m_interpreter.WasInterrupted())
2328               break;
2329             if (DumpModuleSymbolFile(
2330                     result.GetOutputStream(),
2331                     target_modules.GetModulePointerAtIndexUnlocked(image_idx)))
2332               num_dumped++;
2333           }
2334         } else {
2335           result.AppendError("the target has no associated executable images");
2336           result.SetStatus(eReturnStatusFailed);
2337           return false;
2338         }
2339       } else {
2340         // Dump specified images (by basename or fullpath)
2341         const char *arg_cstr;
2342         for (int arg_idx = 0;
2343              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2344              ++arg_idx) {
2345           ModuleList module_list;
2346           const size_t num_matches =
2347               FindModulesByName(target, arg_cstr, module_list, true);
2348           if (num_matches > 0) {
2349             for (size_t i = 0; i < num_matches; ++i) {
2350               if (m_interpreter.WasInterrupted())
2351                 break;
2352               Module *module = module_list.GetModulePointerAtIndex(i);
2353               if (module) {
2354                 if (DumpModuleSymbolFile(result.GetOutputStream(), module))
2355                   num_dumped++;
2356               }
2357             }
2358           } else
2359             result.AppendWarningWithFormat(
2360                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2361         }
2362       }
2363 
2364       if (num_dumped > 0)
2365         result.SetStatus(eReturnStatusSuccessFinishResult);
2366       else {
2367         result.AppendError("no matching executable images found");
2368         result.SetStatus(eReturnStatusFailed);
2369       }
2370     }
2371     return result.Succeeded();
2372   }
2373 };
2374 
2375 #pragma mark CommandObjectTargetModulesDumpLineTable
2376 #define LLDB_OPTIONS_target_modules_dump
2377 #include "CommandOptions.inc"
2378 
2379 // Image debug line table dumping command
2380 
2381 class CommandObjectTargetModulesDumpLineTable
2382     : public CommandObjectTargetModulesSourceFileAutoComplete {
2383 public:
2384   CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter)
2385       : CommandObjectTargetModulesSourceFileAutoComplete(
2386             interpreter, "target modules dump line-table",
2387             "Dump the line table for one or more compilation units.", nullptr,
2388             eCommandRequiresTarget) {}
2389 
2390   ~CommandObjectTargetModulesDumpLineTable() override = default;
2391 
2392   Options *GetOptions() override { return &m_options; }
2393 
2394 protected:
2395   bool DoExecute(Args &command, CommandReturnObject &result) override {
2396     Target *target = m_exe_ctx.GetTargetPtr();
2397     uint32_t total_num_dumped = 0;
2398 
2399     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2400     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2401     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2402 
2403     if (command.GetArgumentCount() == 0) {
2404       result.AppendError("file option must be specified.");
2405       result.SetStatus(eReturnStatusFailed);
2406       return result.Succeeded();
2407     } else {
2408       // Dump specified images (by basename or fullpath)
2409       const char *arg_cstr;
2410       for (int arg_idx = 0;
2411            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2412            ++arg_idx) {
2413         FileSpec file_spec(arg_cstr);
2414 
2415         const ModuleList &target_modules = target->GetImages();
2416         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2417         const size_t num_modules = target_modules.GetSize();
2418         if (num_modules > 0) {
2419           uint32_t num_dumped = 0;
2420           for (uint32_t i = 0; i < num_modules; ++i) {
2421             if (m_interpreter.WasInterrupted())
2422               break;
2423             if (DumpCompileUnitLineTable(
2424                     m_interpreter, result.GetOutputStream(),
2425                     target_modules.GetModulePointerAtIndexUnlocked(i),
2426                     file_spec,
2427                     m_options.m_verbose ? eDescriptionLevelFull
2428                                         : eDescriptionLevelBrief))
2429               num_dumped++;
2430           }
2431           if (num_dumped == 0)
2432             result.AppendWarningWithFormat(
2433                 "No source filenames matched '%s'.\n", arg_cstr);
2434           else
2435             total_num_dumped += num_dumped;
2436         }
2437       }
2438     }
2439 
2440     if (total_num_dumped > 0)
2441       result.SetStatus(eReturnStatusSuccessFinishResult);
2442     else {
2443       result.AppendError("no source filenames matched any command arguments");
2444       result.SetStatus(eReturnStatusFailed);
2445     }
2446     return result.Succeeded();
2447   }
2448 
2449   class CommandOptions : public Options {
2450   public:
2451     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
2452 
2453     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2454                           ExecutionContext *execution_context) override {
2455       assert(option_idx == 0 && "We only have one option.");
2456       m_verbose = true;
2457 
2458       return Status();
2459     }
2460 
2461     void OptionParsingStarting(ExecutionContext *execution_context) override {
2462       m_verbose = false;
2463     }
2464 
2465     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2466       return llvm::makeArrayRef(g_target_modules_dump_options);
2467     }
2468 
2469     bool m_verbose;
2470   };
2471 
2472   CommandOptions m_options;
2473 };
2474 
2475 #pragma mark CommandObjectTargetModulesDump
2476 
2477 // Dump multi-word command for target modules
2478 
2479 class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2480 public:
2481   // Constructors and Destructors
2482   CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
2483       : CommandObjectMultiword(
2484             interpreter, "target modules dump",
2485             "Commands for dumping information about one or "
2486             "more target modules.",
2487             "target modules dump "
2488             "[headers|symtab|sections|ast|symfile|line-table] "
2489             "[<file1> <file2> ...]") {
2490     LoadSubCommand("objfile",
2491                    CommandObjectSP(
2492                        new CommandObjectTargetModulesDumpObjfile(interpreter)));
2493     LoadSubCommand(
2494         "symtab",
2495         CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter)));
2496     LoadSubCommand("sections",
2497                    CommandObjectSP(new CommandObjectTargetModulesDumpSections(
2498                        interpreter)));
2499     LoadSubCommand("symfile",
2500                    CommandObjectSP(
2501                        new CommandObjectTargetModulesDumpSymfile(interpreter)));
2502     LoadSubCommand(
2503         "ast", CommandObjectSP(
2504                    new CommandObjectTargetModulesDumpClangAST(interpreter)));
2505     LoadSubCommand("line-table",
2506                    CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
2507                        interpreter)));
2508   }
2509 
2510   ~CommandObjectTargetModulesDump() override = default;
2511 };
2512 
2513 class CommandObjectTargetModulesAdd : public CommandObjectParsed {
2514 public:
2515   CommandObjectTargetModulesAdd(CommandInterpreter &interpreter)
2516       : CommandObjectParsed(interpreter, "target modules add",
2517                             "Add a new module to the current target's modules.",
2518                             "target modules add [<module>]"),
2519         m_option_group(),
2520         m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
2521                       eArgTypeFilename, "Fullpath to a stand alone debug "
2522                                         "symbols file for when debug symbols "
2523                                         "are not in the executable.") {
2524     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2525                           LLDB_OPT_SET_1);
2526     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2527     m_option_group.Finalize();
2528   }
2529 
2530   ~CommandObjectTargetModulesAdd() override = default;
2531 
2532   Options *GetOptions() override { return &m_option_group; }
2533 
2534   void
2535   HandleArgumentCompletion(CompletionRequest &request,
2536                            OptionElementVector &opt_element_vector) override {
2537     CommandCompletions::InvokeCommonCompletionCallbacks(
2538         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
2539         request, nullptr);
2540   }
2541 
2542 protected:
2543   OptionGroupOptions m_option_group;
2544   OptionGroupUUID m_uuid_option_group;
2545   OptionGroupFile m_symbol_file;
2546 
2547   bool DoExecute(Args &args, CommandReturnObject &result) override {
2548     Target *target = GetDebugger().GetSelectedTarget().get();
2549     if (target == nullptr) {
2550       result.AppendError("invalid target, create a debug target using the "
2551                          "'target create' command");
2552       result.SetStatus(eReturnStatusFailed);
2553       return false;
2554     } else {
2555       bool flush = false;
2556 
2557       const size_t argc = args.GetArgumentCount();
2558       if (argc == 0) {
2559         if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2560           // We are given a UUID only, go locate the file
2561           ModuleSpec module_spec;
2562           module_spec.GetUUID() =
2563               m_uuid_option_group.GetOptionValue().GetCurrentValue();
2564           if (m_symbol_file.GetOptionValue().OptionWasSet())
2565             module_spec.GetSymbolFileSpec() =
2566                 m_symbol_file.GetOptionValue().GetCurrentValue();
2567           if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
2568             ModuleSP module_sp(target->GetOrCreateModule(module_spec,
2569                                                  true /* notify */));
2570             if (module_sp) {
2571               result.SetStatus(eReturnStatusSuccessFinishResult);
2572               return true;
2573             } else {
2574               StreamString strm;
2575               module_spec.GetUUID().Dump(&strm);
2576               if (module_spec.GetFileSpec()) {
2577                 if (module_spec.GetSymbolFileSpec()) {
2578                   result.AppendErrorWithFormat(
2579                       "Unable to create the executable or symbol file with "
2580                       "UUID %s with path %s and symbol file %s",
2581                       strm.GetData(),
2582                       module_spec.GetFileSpec().GetPath().c_str(),
2583                       module_spec.GetSymbolFileSpec().GetPath().c_str());
2584                 } else {
2585                   result.AppendErrorWithFormat(
2586                       "Unable to create the executable or symbol file with "
2587                       "UUID %s with path %s",
2588                       strm.GetData(),
2589                       module_spec.GetFileSpec().GetPath().c_str());
2590                 }
2591               } else {
2592                 result.AppendErrorWithFormat("Unable to create the executable "
2593                                              "or symbol file with UUID %s",
2594                                              strm.GetData());
2595               }
2596               result.SetStatus(eReturnStatusFailed);
2597               return false;
2598             }
2599           } else {
2600             StreamString strm;
2601             module_spec.GetUUID().Dump(&strm);
2602             result.AppendErrorWithFormat(
2603                 "Unable to locate the executable or symbol file with UUID %s",
2604                 strm.GetData());
2605             result.SetStatus(eReturnStatusFailed);
2606             return false;
2607           }
2608         } else {
2609           result.AppendError(
2610               "one or more executable image paths must be specified");
2611           result.SetStatus(eReturnStatusFailed);
2612           return false;
2613         }
2614       } else {
2615         for (auto &entry : args.entries()) {
2616           if (entry.ref.empty())
2617             continue;
2618 
2619           FileSpec file_spec(entry.ref);
2620           if (FileSystem::Instance().Exists(file_spec)) {
2621             ModuleSpec module_spec(file_spec);
2622             if (m_uuid_option_group.GetOptionValue().OptionWasSet())
2623               module_spec.GetUUID() =
2624                   m_uuid_option_group.GetOptionValue().GetCurrentValue();
2625             if (m_symbol_file.GetOptionValue().OptionWasSet())
2626               module_spec.GetSymbolFileSpec() =
2627                   m_symbol_file.GetOptionValue().GetCurrentValue();
2628             if (!module_spec.GetArchitecture().IsValid())
2629               module_spec.GetArchitecture() = target->GetArchitecture();
2630             Status error;
2631             ModuleSP module_sp(target->GetOrCreateModule(module_spec,
2632                                             true /* notify */, &error));
2633             if (!module_sp) {
2634               const char *error_cstr = error.AsCString();
2635               if (error_cstr)
2636                 result.AppendError(error_cstr);
2637               else
2638                 result.AppendErrorWithFormat("unsupported module: %s",
2639                                              entry.c_str());
2640               result.SetStatus(eReturnStatusFailed);
2641               return false;
2642             } else {
2643               flush = true;
2644             }
2645             result.SetStatus(eReturnStatusSuccessFinishResult);
2646           } else {
2647             std::string resolved_path = file_spec.GetPath();
2648             result.SetStatus(eReturnStatusFailed);
2649             if (resolved_path != entry.ref) {
2650               result.AppendErrorWithFormat(
2651                   "invalid module path '%s' with resolved path '%s'\n",
2652                   entry.ref.str().c_str(), resolved_path.c_str());
2653               break;
2654             }
2655             result.AppendErrorWithFormat("invalid module path '%s'\n",
2656                                          entry.c_str());
2657             break;
2658           }
2659         }
2660       }
2661 
2662       if (flush) {
2663         ProcessSP process = target->GetProcessSP();
2664         if (process)
2665           process->Flush();
2666       }
2667     }
2668 
2669     return result.Succeeded();
2670   }
2671 };
2672 
2673 class CommandObjectTargetModulesLoad
2674     : public CommandObjectTargetModulesModuleAutoComplete {
2675 public:
2676   CommandObjectTargetModulesLoad(CommandInterpreter &interpreter)
2677       : CommandObjectTargetModulesModuleAutoComplete(
2678             interpreter, "target modules load", "Set the load addresses for "
2679                                                 "one or more sections in a "
2680                                                 "target module.",
2681             "target modules load [--file <module> --uuid <uuid>] <sect-name> "
2682             "<address> [<sect-name> <address> ....]"),
2683         m_option_group(),
2684         m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName,
2685                       "Fullpath or basename for module to load.", ""),
2686         m_load_option(LLDB_OPT_SET_1, false, "load", 'l',
2687                       "Write file contents to the memory.", false, true),
2688         m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p',
2689                     "Set PC to the entry point."
2690                     " Only applicable with '--load' option.",
2691                     false, true),
2692         m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset,
2693                        "Set the load address for all sections to be the "
2694                        "virtual address in the file plus the offset.",
2695                        0) {
2696     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2697                           LLDB_OPT_SET_1);
2698     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2699     m_option_group.Append(&m_load_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2700     m_option_group.Append(&m_pc_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2701     m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2702     m_option_group.Finalize();
2703   }
2704 
2705   ~CommandObjectTargetModulesLoad() override = default;
2706 
2707   Options *GetOptions() override { return &m_option_group; }
2708 
2709 protected:
2710   bool DoExecute(Args &args, CommandReturnObject &result) override {
2711     Target *target = GetDebugger().GetSelectedTarget().get();
2712     const bool load = m_load_option.GetOptionValue().GetCurrentValue();
2713     const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();
2714     if (target == nullptr) {
2715       result.AppendError("invalid target, create a debug target using the "
2716                          "'target create' command");
2717       result.SetStatus(eReturnStatusFailed);
2718       return false;
2719     } else {
2720       const size_t argc = args.GetArgumentCount();
2721       ModuleSpec module_spec;
2722       bool search_using_module_spec = false;
2723 
2724       // Allow "load" option to work without --file or --uuid option.
2725       if (load) {
2726         if (!m_file_option.GetOptionValue().OptionWasSet() &&
2727             !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2728           ModuleList &module_list = target->GetImages();
2729           if (module_list.GetSize() == 1) {
2730             search_using_module_spec = true;
2731             module_spec.GetFileSpec() =
2732                 module_list.GetModuleAtIndex(0)->GetFileSpec();
2733           }
2734         }
2735       }
2736 
2737       if (m_file_option.GetOptionValue().OptionWasSet()) {
2738         search_using_module_spec = true;
2739         const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
2740         const bool use_global_module_list = true;
2741         ModuleList module_list;
2742         const size_t num_matches = FindModulesByName(
2743             target, arg_cstr, module_list, use_global_module_list);
2744         if (num_matches == 1) {
2745           module_spec.GetFileSpec() =
2746               module_list.GetModuleAtIndex(0)->GetFileSpec();
2747         } else if (num_matches > 1) {
2748           search_using_module_spec = false;
2749           result.AppendErrorWithFormat(
2750               "more than 1 module matched by name '%s'\n", arg_cstr);
2751           result.SetStatus(eReturnStatusFailed);
2752         } else {
2753           search_using_module_spec = false;
2754           result.AppendErrorWithFormat("no object file for module '%s'\n",
2755                                        arg_cstr);
2756           result.SetStatus(eReturnStatusFailed);
2757         }
2758       }
2759 
2760       if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2761         search_using_module_spec = true;
2762         module_spec.GetUUID() =
2763             m_uuid_option_group.GetOptionValue().GetCurrentValue();
2764       }
2765 
2766       if (search_using_module_spec) {
2767         ModuleList matching_modules;
2768         const size_t num_matches =
2769             target->GetImages().FindModules(module_spec, matching_modules);
2770 
2771         char path[PATH_MAX];
2772         if (num_matches == 1) {
2773           Module *module = matching_modules.GetModulePointerAtIndex(0);
2774           if (module) {
2775             ObjectFile *objfile = module->GetObjectFile();
2776             if (objfile) {
2777               SectionList *section_list = module->GetSectionList();
2778               if (section_list) {
2779                 bool changed = false;
2780                 if (argc == 0) {
2781                   if (m_slide_option.GetOptionValue().OptionWasSet()) {
2782                     const addr_t slide =
2783                         m_slide_option.GetOptionValue().GetCurrentValue();
2784                     const bool slide_is_offset = true;
2785                     module->SetLoadAddress(*target, slide, slide_is_offset,
2786                                            changed);
2787                   } else {
2788                     result.AppendError("one or more section name + load "
2789                                        "address pair must be specified");
2790                     result.SetStatus(eReturnStatusFailed);
2791                     return false;
2792                   }
2793                 } else {
2794                   if (m_slide_option.GetOptionValue().OptionWasSet()) {
2795                     result.AppendError("The \"--slide <offset>\" option can't "
2796                                        "be used in conjunction with setting "
2797                                        "section load addresses.\n");
2798                     result.SetStatus(eReturnStatusFailed);
2799                     return false;
2800                   }
2801 
2802                   for (size_t i = 0; i < argc; i += 2) {
2803                     const char *sect_name = args.GetArgumentAtIndex(i);
2804                     const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1);
2805                     if (sect_name && load_addr_cstr) {
2806                       ConstString const_sect_name(sect_name);
2807                       bool success = false;
2808                       addr_t load_addr = StringConvert::ToUInt64(
2809                           load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success);
2810                       if (success) {
2811                         SectionSP section_sp(
2812                             section_list->FindSectionByName(const_sect_name));
2813                         if (section_sp) {
2814                           if (section_sp->IsThreadSpecific()) {
2815                             result.AppendErrorWithFormat(
2816                                 "thread specific sections are not yet "
2817                                 "supported (section '%s')\n",
2818                                 sect_name);
2819                             result.SetStatus(eReturnStatusFailed);
2820                             break;
2821                           } else {
2822                             if (target->GetSectionLoadList()
2823                                     .SetSectionLoadAddress(section_sp,
2824                                                            load_addr))
2825                               changed = true;
2826                             result.AppendMessageWithFormat(
2827                                 "section '%s' loaded at 0x%" PRIx64 "\n",
2828                                 sect_name, load_addr);
2829                           }
2830                         } else {
2831                           result.AppendErrorWithFormat("no section found that "
2832                                                        "matches the section "
2833                                                        "name '%s'\n",
2834                                                        sect_name);
2835                           result.SetStatus(eReturnStatusFailed);
2836                           break;
2837                         }
2838                       } else {
2839                         result.AppendErrorWithFormat(
2840                             "invalid load address string '%s'\n",
2841                             load_addr_cstr);
2842                         result.SetStatus(eReturnStatusFailed);
2843                         break;
2844                       }
2845                     } else {
2846                       if (sect_name)
2847                         result.AppendError("section names must be followed by "
2848                                            "a load address.\n");
2849                       else
2850                         result.AppendError("one or more section name + load "
2851                                            "address pair must be specified.\n");
2852                       result.SetStatus(eReturnStatusFailed);
2853                       break;
2854                     }
2855                   }
2856                 }
2857 
2858                 if (changed) {
2859                   target->ModulesDidLoad(matching_modules);
2860                   Process *process = m_exe_ctx.GetProcessPtr();
2861                   if (process)
2862                     process->Flush();
2863                 }
2864                 if (load) {
2865                   ProcessSP process = target->CalculateProcess();
2866                   Address file_entry = objfile->GetEntryPointAddress();
2867                   if (!process) {
2868                     result.AppendError("No process");
2869                     return false;
2870                   }
2871                   if (set_pc && !file_entry.IsValid()) {
2872                     result.AppendError("No entry address in object file");
2873                     return false;
2874                   }
2875                   std::vector<ObjectFile::LoadableData> loadables(
2876                       objfile->GetLoadableData(*target));
2877                   if (loadables.size() == 0) {
2878                     result.AppendError("No loadable sections");
2879                     return false;
2880                   }
2881                   Status error = process->WriteObjectFile(std::move(loadables));
2882                   if (error.Fail()) {
2883                     result.AppendError(error.AsCString());
2884                     return false;
2885                   }
2886                   if (set_pc) {
2887                     ThreadList &thread_list = process->GetThreadList();
2888                     RegisterContextSP reg_context(
2889                         thread_list.GetSelectedThread()->GetRegisterContext());
2890                     addr_t file_entry_addr = file_entry.GetLoadAddress(target);
2891                     if (!reg_context->SetPC(file_entry_addr)) {
2892                       result.AppendErrorWithFormat("failed to set PC value to "
2893                                                    "0x%" PRIx64 "\n",
2894                                                    file_entry_addr);
2895                       result.SetStatus(eReturnStatusFailed);
2896                     }
2897                   }
2898                 }
2899               } else {
2900                 module->GetFileSpec().GetPath(path, sizeof(path));
2901                 result.AppendErrorWithFormat(
2902                     "no sections in object file '%s'\n", path);
2903                 result.SetStatus(eReturnStatusFailed);
2904               }
2905             } else {
2906               module->GetFileSpec().GetPath(path, sizeof(path));
2907               result.AppendErrorWithFormat("no object file for module '%s'\n",
2908                                            path);
2909               result.SetStatus(eReturnStatusFailed);
2910             }
2911           } else {
2912             FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
2913             if (module_spec_file) {
2914               module_spec_file->GetPath(path, sizeof(path));
2915               result.AppendErrorWithFormat("invalid module '%s'.\n", path);
2916             } else
2917               result.AppendError("no module spec");
2918             result.SetStatus(eReturnStatusFailed);
2919           }
2920         } else {
2921           std::string uuid_str;
2922 
2923           if (module_spec.GetFileSpec())
2924             module_spec.GetFileSpec().GetPath(path, sizeof(path));
2925           else
2926             path[0] = '\0';
2927 
2928           if (module_spec.GetUUIDPtr())
2929             uuid_str = module_spec.GetUUID().GetAsString();
2930           if (num_matches > 1) {
2931             result.AppendErrorWithFormat(
2932                 "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "",
2933                 path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2934             for (size_t i = 0; i < num_matches; ++i) {
2935               if (matching_modules.GetModulePointerAtIndex(i)
2936                       ->GetFileSpec()
2937                       .GetPath(path, sizeof(path)))
2938                 result.AppendMessageWithFormat("%s\n", path);
2939             }
2940           } else {
2941             result.AppendErrorWithFormat(
2942                 "no modules were found  that match%s%s%s%s.\n",
2943                 path[0] ? " file=" : "", path,
2944                 !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2945           }
2946           result.SetStatus(eReturnStatusFailed);
2947         }
2948       } else {
2949         result.AppendError("either the \"--file <module>\" or the \"--uuid "
2950                            "<uuid>\" option must be specified.\n");
2951         result.SetStatus(eReturnStatusFailed);
2952         return false;
2953       }
2954     }
2955     return result.Succeeded();
2956   }
2957 
2958   OptionGroupOptions m_option_group;
2959   OptionGroupUUID m_uuid_option_group;
2960   OptionGroupString m_file_option;
2961   OptionGroupBoolean m_load_option;
2962   OptionGroupBoolean m_pc_option;
2963   OptionGroupUInt64 m_slide_option;
2964 };
2965 
2966 // List images with associated information
2967 #define LLDB_OPTIONS_target_modules_list
2968 #include "CommandOptions.inc"
2969 
2970 class CommandObjectTargetModulesList : public CommandObjectParsed {
2971 public:
2972   class CommandOptions : public Options {
2973   public:
2974     CommandOptions()
2975         : Options(), m_format_array(), m_use_global_module_list(false),
2976           m_module_addr(LLDB_INVALID_ADDRESS) {}
2977 
2978     ~CommandOptions() override = default;
2979 
2980     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2981                           ExecutionContext *execution_context) override {
2982       Status error;
2983 
2984       const int short_option = m_getopt_table[option_idx].val;
2985       if (short_option == 'g') {
2986         m_use_global_module_list = true;
2987       } else if (short_option == 'a') {
2988         m_module_addr = OptionArgParser::ToAddress(
2989             execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
2990       } else {
2991         unsigned long width = 0;
2992         option_arg.getAsInteger(0, width);
2993         m_format_array.push_back(std::make_pair(short_option, width));
2994       }
2995       return error;
2996     }
2997 
2998     void OptionParsingStarting(ExecutionContext *execution_context) override {
2999       m_format_array.clear();
3000       m_use_global_module_list = false;
3001       m_module_addr = LLDB_INVALID_ADDRESS;
3002     }
3003 
3004     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3005       return llvm::makeArrayRef(g_target_modules_list_options);
3006     }
3007 
3008     // Instance variables to hold the values for command options.
3009     typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
3010     FormatWidthCollection m_format_array;
3011     bool m_use_global_module_list;
3012     lldb::addr_t m_module_addr;
3013   };
3014 
3015   CommandObjectTargetModulesList(CommandInterpreter &interpreter)
3016       : CommandObjectParsed(
3017             interpreter, "target modules list",
3018             "List current executable and dependent shared library images.",
3019             "target modules list [<cmd-options>]"),
3020         m_options() {}
3021 
3022   ~CommandObjectTargetModulesList() override = default;
3023 
3024   Options *GetOptions() override { return &m_options; }
3025 
3026 protected:
3027   bool DoExecute(Args &command, CommandReturnObject &result) override {
3028     Target *target = GetDebugger().GetSelectedTarget().get();
3029     const bool use_global_module_list = m_options.m_use_global_module_list;
3030     // Define a local module list here to ensure it lives longer than any
3031     // "locker" object which might lock its contents below (through the
3032     // "module_list_ptr" variable).
3033     ModuleList module_list;
3034     if (target == nullptr && !use_global_module_list) {
3035       result.AppendError("invalid target, create a debug target using the "
3036                          "'target create' command");
3037       result.SetStatus(eReturnStatusFailed);
3038       return false;
3039     } else {
3040       if (target) {
3041         uint32_t addr_byte_size =
3042             target->GetArchitecture().GetAddressByteSize();
3043         result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3044         result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3045       }
3046       // Dump all sections for all modules images
3047       Stream &strm = result.GetOutputStream();
3048 
3049       if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) {
3050         if (target) {
3051           Address module_address;
3052           if (module_address.SetLoadAddress(m_options.m_module_addr, target)) {
3053             ModuleSP module_sp(module_address.GetModule());
3054             if (module_sp) {
3055               PrintModule(target, module_sp.get(), 0, strm);
3056               result.SetStatus(eReturnStatusSuccessFinishResult);
3057             } else {
3058               result.AppendErrorWithFormat(
3059                   "Couldn't find module matching address: 0x%" PRIx64 ".",
3060                   m_options.m_module_addr);
3061               result.SetStatus(eReturnStatusFailed);
3062             }
3063           } else {
3064             result.AppendErrorWithFormat(
3065                 "Couldn't find module containing address: 0x%" PRIx64 ".",
3066                 m_options.m_module_addr);
3067             result.SetStatus(eReturnStatusFailed);
3068           }
3069         } else {
3070           result.AppendError(
3071               "Can only look up modules by address with a valid target.");
3072           result.SetStatus(eReturnStatusFailed);
3073         }
3074         return result.Succeeded();
3075       }
3076 
3077       size_t num_modules = 0;
3078 
3079       // This locker will be locked on the mutex in module_list_ptr if it is
3080       // non-nullptr. Otherwise it will lock the
3081       // AllocationModuleCollectionMutex when accessing the global module list
3082       // directly.
3083       std::unique_lock<std::recursive_mutex> guard(
3084           Module::GetAllocationModuleCollectionMutex(), std::defer_lock);
3085 
3086       const ModuleList *module_list_ptr = nullptr;
3087       const size_t argc = command.GetArgumentCount();
3088       if (argc == 0) {
3089         if (use_global_module_list) {
3090           guard.lock();
3091           num_modules = Module::GetNumberAllocatedModules();
3092         } else {
3093           module_list_ptr = &target->GetImages();
3094         }
3095       } else {
3096         // TODO: Convert to entry based iteration.  Requires converting
3097         // FindModulesByName.
3098         for (size_t i = 0; i < argc; ++i) {
3099           // Dump specified images (by basename or fullpath)
3100           const char *arg_cstr = command.GetArgumentAtIndex(i);
3101           const size_t num_matches = FindModulesByName(
3102               target, arg_cstr, module_list, use_global_module_list);
3103           if (num_matches == 0) {
3104             if (argc == 1) {
3105               result.AppendErrorWithFormat("no modules found that match '%s'",
3106                                            arg_cstr);
3107               result.SetStatus(eReturnStatusFailed);
3108               return false;
3109             }
3110           }
3111         }
3112 
3113         module_list_ptr = &module_list;
3114       }
3115 
3116       std::unique_lock<std::recursive_mutex> lock;
3117       if (module_list_ptr != nullptr) {
3118         lock =
3119             std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex());
3120 
3121         num_modules = module_list_ptr->GetSize();
3122       }
3123 
3124       if (num_modules > 0) {
3125         for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
3126           ModuleSP module_sp;
3127           Module *module;
3128           if (module_list_ptr) {
3129             module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx);
3130             module = module_sp.get();
3131           } else {
3132             module = Module::GetAllocatedModuleAtIndex(image_idx);
3133             module_sp = module->shared_from_this();
3134           }
3135 
3136           const size_t indent = strm.Printf("[%3u] ", image_idx);
3137           PrintModule(target, module, indent, strm);
3138         }
3139         result.SetStatus(eReturnStatusSuccessFinishResult);
3140       } else {
3141         if (argc) {
3142           if (use_global_module_list)
3143             result.AppendError(
3144                 "the global module list has no matching modules");
3145           else
3146             result.AppendError("the target has no matching modules");
3147         } else {
3148           if (use_global_module_list)
3149             result.AppendError("the global module list is empty");
3150           else
3151             result.AppendError(
3152                 "the target has no associated executable images");
3153         }
3154         result.SetStatus(eReturnStatusFailed);
3155         return false;
3156       }
3157     }
3158     return result.Succeeded();
3159   }
3160 
3161   void PrintModule(Target *target, Module *module, int indent, Stream &strm) {
3162     if (module == nullptr) {
3163       strm.PutCString("Null module");
3164       return;
3165     }
3166 
3167     bool dump_object_name = false;
3168     if (m_options.m_format_array.empty()) {
3169       m_options.m_format_array.push_back(std::make_pair('u', 0));
3170       m_options.m_format_array.push_back(std::make_pair('h', 0));
3171       m_options.m_format_array.push_back(std::make_pair('f', 0));
3172       m_options.m_format_array.push_back(std::make_pair('S', 0));
3173     }
3174     const size_t num_entries = m_options.m_format_array.size();
3175     bool print_space = false;
3176     for (size_t i = 0; i < num_entries; ++i) {
3177       if (print_space)
3178         strm.PutChar(' ');
3179       print_space = true;
3180       const char format_char = m_options.m_format_array[i].first;
3181       uint32_t width = m_options.m_format_array[i].second;
3182       switch (format_char) {
3183       case 'A':
3184         DumpModuleArchitecture(strm, module, false, width);
3185         break;
3186 
3187       case 't':
3188         DumpModuleArchitecture(strm, module, true, width);
3189         break;
3190 
3191       case 'f':
3192         DumpFullpath(strm, &module->GetFileSpec(), width);
3193         dump_object_name = true;
3194         break;
3195 
3196       case 'd':
3197         DumpDirectory(strm, &module->GetFileSpec(), width);
3198         break;
3199 
3200       case 'b':
3201         DumpBasename(strm, &module->GetFileSpec(), width);
3202         dump_object_name = true;
3203         break;
3204 
3205       case 'h':
3206       case 'o':
3207         // Image header address
3208         {
3209           uint32_t addr_nibble_width =
3210               target ? (target->GetArchitecture().GetAddressByteSize() * 2)
3211                      : 16;
3212 
3213           ObjectFile *objfile = module->GetObjectFile();
3214           if (objfile) {
3215             Address base_addr(objfile->GetBaseAddress());
3216             if (base_addr.IsValid()) {
3217               if (target && !target->GetSectionLoadList().IsEmpty()) {
3218                 lldb::addr_t load_addr =
3219                     base_addr.GetLoadAddress(target);
3220                 if (load_addr == LLDB_INVALID_ADDRESS) {
3221                   base_addr.Dump(&strm, target,
3222                                    Address::DumpStyleModuleWithFileAddress,
3223                                    Address::DumpStyleFileAddress);
3224                 } else {
3225                   if (format_char == 'o') {
3226                     // Show the offset of slide for the image
3227                     strm.Printf(
3228                         "0x%*.*" PRIx64, addr_nibble_width, addr_nibble_width,
3229                         load_addr - base_addr.GetFileAddress());
3230                   } else {
3231                     // Show the load address of the image
3232                     strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
3233                                 addr_nibble_width, load_addr);
3234                   }
3235                 }
3236                 break;
3237               }
3238               // The address was valid, but the image isn't loaded, output the
3239               // address in an appropriate format
3240               base_addr.Dump(&strm, target, Address::DumpStyleFileAddress);
3241               break;
3242             }
3243           }
3244           strm.Printf("%*s", addr_nibble_width + 2, "");
3245         }
3246         break;
3247 
3248       case 'r': {
3249         size_t ref_count = 0;
3250         ModuleSP module_sp(module->shared_from_this());
3251         if (module_sp) {
3252           // Take one away to make sure we don't count our local "module_sp"
3253           ref_count = module_sp.use_count() - 1;
3254         }
3255         if (width)
3256           strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count);
3257         else
3258           strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count);
3259       } break;
3260 
3261       case 's':
3262       case 'S': {
3263         if (const SymbolFile *symbol_file = module->GetSymbolFile()) {
3264           const FileSpec symfile_spec =
3265               symbol_file->GetObjectFile()->GetFileSpec();
3266           if (format_char == 'S') {
3267             // Dump symbol file only if different from module file
3268             if (!symfile_spec || symfile_spec == module->GetFileSpec()) {
3269               print_space = false;
3270               break;
3271             }
3272             // Add a newline and indent past the index
3273             strm.Printf("\n%*s", indent, "");
3274           }
3275           DumpFullpath(strm, &symfile_spec, width);
3276           dump_object_name = true;
3277           break;
3278         }
3279         strm.Printf("%.*s", width, "<NONE>");
3280       } break;
3281 
3282       case 'm':
3283         strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(),
3284                                               llvm::AlignStyle::Left, width));
3285         break;
3286 
3287       case 'p':
3288         strm.Printf("%p", static_cast<void *>(module));
3289         break;
3290 
3291       case 'u':
3292         DumpModuleUUID(strm, module);
3293         break;
3294 
3295       default:
3296         break;
3297       }
3298     }
3299     if (dump_object_name) {
3300       const char *object_name = module->GetObjectName().GetCString();
3301       if (object_name)
3302         strm.Printf("(%s)", object_name);
3303     }
3304     strm.EOL();
3305   }
3306 
3307   CommandOptions m_options;
3308 };
3309 
3310 #pragma mark CommandObjectTargetModulesShowUnwind
3311 
3312 // Lookup unwind information in images
3313 #define LLDB_OPTIONS_target_modules_show_unwind
3314 #include "CommandOptions.inc"
3315 
3316 class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
3317 public:
3318   enum {
3319     eLookupTypeInvalid = -1,
3320     eLookupTypeAddress = 0,
3321     eLookupTypeSymbol,
3322     eLookupTypeFunction,
3323     eLookupTypeFunctionOrSymbol,
3324     kNumLookupTypes
3325   };
3326 
3327   class CommandOptions : public Options {
3328   public:
3329     CommandOptions()
3330         : Options(), m_type(eLookupTypeInvalid), m_str(),
3331           m_addr(LLDB_INVALID_ADDRESS) {}
3332 
3333     ~CommandOptions() override = default;
3334 
3335     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3336                           ExecutionContext *execution_context) override {
3337       Status error;
3338 
3339       const int short_option = m_getopt_table[option_idx].val;
3340 
3341       switch (short_option) {
3342       case 'a': {
3343         m_str = option_arg;
3344         m_type = eLookupTypeAddress;
3345         m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3346                                             LLDB_INVALID_ADDRESS, &error);
3347         if (m_addr == LLDB_INVALID_ADDRESS)
3348           error.SetErrorStringWithFormat("invalid address string '%s'",
3349                                          option_arg.str().c_str());
3350         break;
3351       }
3352 
3353       case 'n':
3354         m_str = option_arg;
3355         m_type = eLookupTypeFunctionOrSymbol;
3356         break;
3357 
3358       default:
3359         error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
3360         break;
3361       }
3362 
3363       return error;
3364     }
3365 
3366     void OptionParsingStarting(ExecutionContext *execution_context) override {
3367       m_type = eLookupTypeInvalid;
3368       m_str.clear();
3369       m_addr = LLDB_INVALID_ADDRESS;
3370     }
3371 
3372     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3373       return llvm::makeArrayRef(g_target_modules_show_unwind_options);
3374     }
3375 
3376     // Instance variables to hold the values for command options.
3377 
3378     int m_type;        // Should be a eLookupTypeXXX enum after parsing options
3379     std::string m_str; // Holds name lookup
3380     lldb::addr_t m_addr; // Holds the address to lookup
3381   };
3382 
3383   CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
3384       : CommandObjectParsed(
3385             interpreter, "target modules show-unwind",
3386             "Show synthesized unwind instructions for a function.", nullptr,
3387             eCommandRequiresTarget | eCommandRequiresProcess |
3388                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
3389         m_options() {}
3390 
3391   ~CommandObjectTargetModulesShowUnwind() override = default;
3392 
3393   Options *GetOptions() override { return &m_options; }
3394 
3395 protected:
3396   bool DoExecute(Args &command, CommandReturnObject &result) override {
3397     Target *target = m_exe_ctx.GetTargetPtr();
3398     Process *process = m_exe_ctx.GetProcessPtr();
3399     ABI *abi = nullptr;
3400     if (process)
3401       abi = process->GetABI().get();
3402 
3403     if (process == nullptr) {
3404       result.AppendError(
3405           "You must have a process running to use this command.");
3406       result.SetStatus(eReturnStatusFailed);
3407       return false;
3408     }
3409 
3410     ThreadList threads(process->GetThreadList());
3411     if (threads.GetSize() == 0) {
3412       result.AppendError("The process must be paused to use this command.");
3413       result.SetStatus(eReturnStatusFailed);
3414       return false;
3415     }
3416 
3417     ThreadSP thread(threads.GetThreadAtIndex(0));
3418     if (!thread) {
3419       result.AppendError("The process must be paused to use this command.");
3420       result.SetStatus(eReturnStatusFailed);
3421       return false;
3422     }
3423 
3424     SymbolContextList sc_list;
3425 
3426     if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
3427       ConstString function_name(m_options.m_str.c_str());
3428       target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto,
3429                                         true, false, true, sc_list);
3430     } else if (m_options.m_type == eLookupTypeAddress && target) {
3431       Address addr;
3432       if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr,
3433                                                           addr)) {
3434         SymbolContext sc;
3435         ModuleSP module_sp(addr.GetModule());
3436         module_sp->ResolveSymbolContextForAddress(addr,
3437                                                   eSymbolContextEverything, sc);
3438         if (sc.function || sc.symbol) {
3439           sc_list.Append(sc);
3440         }
3441       }
3442     } else {
3443       result.AppendError(
3444           "address-expression or function name option must be specified.");
3445       result.SetStatus(eReturnStatusFailed);
3446       return false;
3447     }
3448 
3449     size_t num_matches = sc_list.GetSize();
3450     if (num_matches == 0) {
3451       result.AppendErrorWithFormat("no unwind data found that matches '%s'.",
3452                                    m_options.m_str.c_str());
3453       result.SetStatus(eReturnStatusFailed);
3454       return false;
3455     }
3456 
3457     for (uint32_t idx = 0; idx < num_matches; idx++) {
3458       SymbolContext sc;
3459       sc_list.GetContextAtIndex(idx, sc);
3460       if (sc.symbol == nullptr && sc.function == nullptr)
3461         continue;
3462       if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr)
3463         continue;
3464       AddressRange range;
3465       if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
3466                               false, range))
3467         continue;
3468       if (!range.GetBaseAddress().IsValid())
3469         continue;
3470       ConstString funcname(sc.GetFunctionName());
3471       if (funcname.IsEmpty())
3472         continue;
3473       addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target);
3474       if (abi)
3475         start_addr = abi->FixCodeAddress(start_addr);
3476 
3477       FuncUnwindersSP func_unwinders_sp(
3478           sc.module_sp->GetUnwindTable()
3479               .GetUncachedFuncUnwindersContainingAddress(start_addr, sc));
3480       if (!func_unwinders_sp)
3481         continue;
3482 
3483       result.GetOutputStream().Printf(
3484           "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n",
3485           sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
3486           funcname.AsCString(), start_addr);
3487 
3488       UnwindPlanSP non_callsite_unwind_plan =
3489           func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread);
3490       if (non_callsite_unwind_plan) {
3491         result.GetOutputStream().Printf(
3492             "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
3493             non_callsite_unwind_plan->GetSourceName().AsCString());
3494       }
3495       UnwindPlanSP callsite_unwind_plan =
3496           func_unwinders_sp->GetUnwindPlanAtCallSite(*target, *thread);
3497       if (callsite_unwind_plan) {
3498         result.GetOutputStream().Printf(
3499             "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
3500             callsite_unwind_plan->GetSourceName().AsCString());
3501       }
3502       UnwindPlanSP fast_unwind_plan =
3503           func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
3504       if (fast_unwind_plan) {
3505         result.GetOutputStream().Printf(
3506             "Fast UnwindPlan is '%s'\n",
3507             fast_unwind_plan->GetSourceName().AsCString());
3508       }
3509 
3510       result.GetOutputStream().Printf("\n");
3511 
3512       UnwindPlanSP assembly_sp =
3513           func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread);
3514       if (assembly_sp) {
3515         result.GetOutputStream().Printf(
3516             "Assembly language inspection UnwindPlan:\n");
3517         assembly_sp->Dump(result.GetOutputStream(), thread.get(),
3518                           LLDB_INVALID_ADDRESS);
3519         result.GetOutputStream().Printf("\n");
3520       }
3521 
3522       UnwindPlanSP ehframe_sp =
3523           func_unwinders_sp->GetEHFrameUnwindPlan(*target);
3524       if (ehframe_sp) {
3525         result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
3526         ehframe_sp->Dump(result.GetOutputStream(), thread.get(),
3527                          LLDB_INVALID_ADDRESS);
3528         result.GetOutputStream().Printf("\n");
3529       }
3530 
3531       UnwindPlanSP ehframe_augmented_sp =
3532           func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread);
3533       if (ehframe_augmented_sp) {
3534         result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
3535         ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3536                                    LLDB_INVALID_ADDRESS);
3537         result.GetOutputStream().Printf("\n");
3538       }
3539 
3540       if (UnwindPlanSP plan_sp =
3541               func_unwinders_sp->GetDebugFrameUnwindPlan(*target)) {
3542         result.GetOutputStream().Printf("debug_frame UnwindPlan:\n");
3543         plan_sp->Dump(result.GetOutputStream(), thread.get(),
3544                       LLDB_INVALID_ADDRESS);
3545         result.GetOutputStream().Printf("\n");
3546       }
3547 
3548       if (UnwindPlanSP plan_sp =
3549               func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target,
3550                                                                   *thread)) {
3551         result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n");
3552         plan_sp->Dump(result.GetOutputStream(), thread.get(),
3553                       LLDB_INVALID_ADDRESS);
3554         result.GetOutputStream().Printf("\n");
3555       }
3556 
3557       UnwindPlanSP arm_unwind_sp =
3558           func_unwinders_sp->GetArmUnwindUnwindPlan(*target);
3559       if (arm_unwind_sp) {
3560         result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
3561         arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3562                             LLDB_INVALID_ADDRESS);
3563         result.GetOutputStream().Printf("\n");
3564       }
3565 
3566       if (UnwindPlanSP symfile_plan_sp =
3567               func_unwinders_sp->GetSymbolFileUnwindPlan(*thread)) {
3568         result.GetOutputStream().Printf("Symbol file UnwindPlan:\n");
3569         symfile_plan_sp->Dump(result.GetOutputStream(), thread.get(),
3570                               LLDB_INVALID_ADDRESS);
3571         result.GetOutputStream().Printf("\n");
3572       }
3573 
3574       UnwindPlanSP compact_unwind_sp =
3575           func_unwinders_sp->GetCompactUnwindUnwindPlan(*target);
3576       if (compact_unwind_sp) {
3577         result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
3578         compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3579                                 LLDB_INVALID_ADDRESS);
3580         result.GetOutputStream().Printf("\n");
3581       }
3582 
3583       if (fast_unwind_plan) {
3584         result.GetOutputStream().Printf("Fast UnwindPlan:\n");
3585         fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(),
3586                                LLDB_INVALID_ADDRESS);
3587         result.GetOutputStream().Printf("\n");
3588       }
3589 
3590       ABISP abi_sp = process->GetABI();
3591       if (abi_sp) {
3592         UnwindPlan arch_default(lldb::eRegisterKindGeneric);
3593         if (abi_sp->CreateDefaultUnwindPlan(arch_default)) {
3594           result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
3595           arch_default.Dump(result.GetOutputStream(), thread.get(),
3596                             LLDB_INVALID_ADDRESS);
3597           result.GetOutputStream().Printf("\n");
3598         }
3599 
3600         UnwindPlan arch_entry(lldb::eRegisterKindGeneric);
3601         if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) {
3602           result.GetOutputStream().Printf(
3603               "Arch default at entry point UnwindPlan:\n");
3604           arch_entry.Dump(result.GetOutputStream(), thread.get(),
3605                           LLDB_INVALID_ADDRESS);
3606           result.GetOutputStream().Printf("\n");
3607         }
3608       }
3609 
3610       result.GetOutputStream().Printf("\n");
3611     }
3612     return result.Succeeded();
3613   }
3614 
3615   CommandOptions m_options;
3616 };
3617 
3618 // Lookup information in images
3619 #define LLDB_OPTIONS_target_modules_lookup
3620 #include "CommandOptions.inc"
3621 
3622 class CommandObjectTargetModulesLookup : public CommandObjectParsed {
3623 public:
3624   enum {
3625     eLookupTypeInvalid = -1,
3626     eLookupTypeAddress = 0,
3627     eLookupTypeSymbol,
3628     eLookupTypeFileLine, // Line is optional
3629     eLookupTypeFunction,
3630     eLookupTypeFunctionOrSymbol,
3631     eLookupTypeType,
3632     kNumLookupTypes
3633   };
3634 
3635   class CommandOptions : public Options {
3636   public:
3637     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
3638 
3639     ~CommandOptions() override = default;
3640 
3641     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3642                           ExecutionContext *execution_context) override {
3643       Status error;
3644 
3645       const int short_option = m_getopt_table[option_idx].val;
3646 
3647       switch (short_option) {
3648       case 'a': {
3649         m_type = eLookupTypeAddress;
3650         m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3651                                             LLDB_INVALID_ADDRESS, &error);
3652       } break;
3653 
3654       case 'o':
3655         if (option_arg.getAsInteger(0, m_offset))
3656           error.SetErrorStringWithFormat("invalid offset string '%s'",
3657                                          option_arg.str().c_str());
3658         break;
3659 
3660       case 's':
3661         m_str = option_arg;
3662         m_type = eLookupTypeSymbol;
3663         break;
3664 
3665       case 'f':
3666         m_file.SetFile(option_arg, FileSpec::Style::native);
3667         m_type = eLookupTypeFileLine;
3668         break;
3669 
3670       case 'i':
3671         m_include_inlines = false;
3672         break;
3673 
3674       case 'l':
3675         if (option_arg.getAsInteger(0, m_line_number))
3676           error.SetErrorStringWithFormat("invalid line number string '%s'",
3677                                          option_arg.str().c_str());
3678         else if (m_line_number == 0)
3679           error.SetErrorString("zero is an invalid line number");
3680         m_type = eLookupTypeFileLine;
3681         break;
3682 
3683       case 'F':
3684         m_str = option_arg;
3685         m_type = eLookupTypeFunction;
3686         break;
3687 
3688       case 'n':
3689         m_str = option_arg;
3690         m_type = eLookupTypeFunctionOrSymbol;
3691         break;
3692 
3693       case 't':
3694         m_str = option_arg;
3695         m_type = eLookupTypeType;
3696         break;
3697 
3698       case 'v':
3699         m_verbose = true;
3700         break;
3701 
3702       case 'A':
3703         m_print_all = true;
3704         break;
3705 
3706       case 'r':
3707         m_use_regex = true;
3708         break;
3709       }
3710 
3711       return error;
3712     }
3713 
3714     void OptionParsingStarting(ExecutionContext *execution_context) override {
3715       m_type = eLookupTypeInvalid;
3716       m_str.clear();
3717       m_file.Clear();
3718       m_addr = LLDB_INVALID_ADDRESS;
3719       m_offset = 0;
3720       m_line_number = 0;
3721       m_use_regex = false;
3722       m_include_inlines = true;
3723       m_verbose = false;
3724       m_print_all = false;
3725     }
3726 
3727     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3728       return llvm::makeArrayRef(g_target_modules_lookup_options);
3729     }
3730 
3731     int m_type;        // Should be a eLookupTypeXXX enum after parsing options
3732     std::string m_str; // Holds name lookup
3733     FileSpec m_file;   // Files for file lookups
3734     lldb::addr_t m_addr; // Holds the address to lookup
3735     lldb::addr_t
3736         m_offset; // Subtract this offset from m_addr before doing lookups.
3737     uint32_t m_line_number; // Line number for file+line lookups
3738     bool m_use_regex;       // Name lookups in m_str are regular expressions.
3739     bool m_include_inlines; // Check for inline entries when looking up by
3740                             // file/line.
3741     bool m_verbose;         // Enable verbose lookup info
3742     bool m_print_all; // Print all matches, even in cases where there's a best
3743                       // match.
3744   };
3745 
3746   CommandObjectTargetModulesLookup(CommandInterpreter &interpreter)
3747       : CommandObjectParsed(interpreter, "target modules lookup",
3748                             "Look up information within executable and "
3749                             "dependent shared library images.",
3750                             nullptr, eCommandRequiresTarget),
3751         m_options() {
3752     CommandArgumentEntry arg;
3753     CommandArgumentData file_arg;
3754 
3755     // Define the first (and only) variant of this arg.
3756     file_arg.arg_type = eArgTypeFilename;
3757     file_arg.arg_repetition = eArgRepeatStar;
3758 
3759     // There is only one variant this argument could be; put it into the
3760     // argument entry.
3761     arg.push_back(file_arg);
3762 
3763     // Push the data for the first argument into the m_arguments vector.
3764     m_arguments.push_back(arg);
3765   }
3766 
3767   ~CommandObjectTargetModulesLookup() override = default;
3768 
3769   Options *GetOptions() override { return &m_options; }
3770 
3771   bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result,
3772                   bool &syntax_error) {
3773     switch (m_options.m_type) {
3774     case eLookupTypeAddress:
3775     case eLookupTypeFileLine:
3776     case eLookupTypeFunction:
3777     case eLookupTypeFunctionOrSymbol:
3778     case eLookupTypeSymbol:
3779     default:
3780       return false;
3781     case eLookupTypeType:
3782       break;
3783     }
3784 
3785     StackFrameSP frame = m_exe_ctx.GetFrameSP();
3786 
3787     if (!frame)
3788       return false;
3789 
3790     const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule));
3791 
3792     if (!sym_ctx.module_sp)
3793       return false;
3794 
3795     switch (m_options.m_type) {
3796     default:
3797       return false;
3798     case eLookupTypeType:
3799       if (!m_options.m_str.empty()) {
3800         if (LookupTypeHere(m_interpreter, result.GetOutputStream(),
3801                            *sym_ctx.module_sp, m_options.m_str.c_str(),
3802                            m_options.m_use_regex)) {
3803           result.SetStatus(eReturnStatusSuccessFinishResult);
3804           return true;
3805         }
3806       }
3807       break;
3808     }
3809 
3810     return true;
3811   }
3812 
3813   bool LookupInModule(CommandInterpreter &interpreter, Module *module,
3814                       CommandReturnObject &result, bool &syntax_error) {
3815     switch (m_options.m_type) {
3816     case eLookupTypeAddress:
3817       if (m_options.m_addr != LLDB_INVALID_ADDRESS) {
3818         if (LookupAddressInModule(
3819                 m_interpreter, result.GetOutputStream(), module,
3820                 eSymbolContextEverything |
3821                     (m_options.m_verbose
3822                          ? static_cast<int>(eSymbolContextVariable)
3823                          : 0),
3824                 m_options.m_addr, m_options.m_offset, m_options.m_verbose)) {
3825           result.SetStatus(eReturnStatusSuccessFinishResult);
3826           return true;
3827         }
3828       }
3829       break;
3830 
3831     case eLookupTypeSymbol:
3832       if (!m_options.m_str.empty()) {
3833         if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(),
3834                                  module, m_options.m_str.c_str(),
3835                                  m_options.m_use_regex, m_options.m_verbose)) {
3836           result.SetStatus(eReturnStatusSuccessFinishResult);
3837           return true;
3838         }
3839       }
3840       break;
3841 
3842     case eLookupTypeFileLine:
3843       if (m_options.m_file) {
3844         if (LookupFileAndLineInModule(
3845                 m_interpreter, result.GetOutputStream(), module,
3846                 m_options.m_file, m_options.m_line_number,
3847                 m_options.m_include_inlines, m_options.m_verbose)) {
3848           result.SetStatus(eReturnStatusSuccessFinishResult);
3849           return true;
3850         }
3851       }
3852       break;
3853 
3854     case eLookupTypeFunctionOrSymbol:
3855     case eLookupTypeFunction:
3856       if (!m_options.m_str.empty()) {
3857         if (LookupFunctionInModule(
3858                 m_interpreter, result.GetOutputStream(), module,
3859                 m_options.m_str.c_str(), m_options.m_use_regex,
3860                 m_options.m_include_inlines,
3861                 m_options.m_type ==
3862                     eLookupTypeFunctionOrSymbol, // include symbols
3863                 m_options.m_verbose)) {
3864           result.SetStatus(eReturnStatusSuccessFinishResult);
3865           return true;
3866         }
3867       }
3868       break;
3869 
3870     case eLookupTypeType:
3871       if (!m_options.m_str.empty()) {
3872         if (LookupTypeInModule(m_interpreter, result.GetOutputStream(), module,
3873                                m_options.m_str.c_str(),
3874                                m_options.m_use_regex)) {
3875           result.SetStatus(eReturnStatusSuccessFinishResult);
3876           return true;
3877         }
3878       }
3879       break;
3880 
3881     default:
3882       m_options.GenerateOptionUsage(
3883           result.GetErrorStream(), this,
3884           GetCommandInterpreter().GetDebugger().GetTerminalWidth());
3885       syntax_error = true;
3886       break;
3887     }
3888 
3889     result.SetStatus(eReturnStatusFailed);
3890     return false;
3891   }
3892 
3893 protected:
3894   bool DoExecute(Args &command, CommandReturnObject &result) override {
3895     Target *target = GetDebugger().GetSelectedTarget().get();
3896     if (target == nullptr) {
3897       result.AppendError("invalid target, create a debug target using the "
3898                          "'target create' command");
3899       result.SetStatus(eReturnStatusFailed);
3900       return false;
3901     } else {
3902       bool syntax_error = false;
3903       uint32_t i;
3904       uint32_t num_successful_lookups = 0;
3905       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
3906       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3907       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3908       // Dump all sections for all modules images
3909 
3910       if (command.GetArgumentCount() == 0) {
3911         ModuleSP current_module;
3912 
3913         // Where it is possible to look in the current symbol context first,
3914         // try that.  If this search was successful and --all was not passed,
3915         // don't print anything else.
3916         if (LookupHere(m_interpreter, result, syntax_error)) {
3917           result.GetOutputStream().EOL();
3918           num_successful_lookups++;
3919           if (!m_options.m_print_all) {
3920             result.SetStatus(eReturnStatusSuccessFinishResult);
3921             return result.Succeeded();
3922           }
3923         }
3924 
3925         // Dump all sections for all other modules
3926 
3927         const ModuleList &target_modules = target->GetImages();
3928         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
3929         const size_t num_modules = target_modules.GetSize();
3930         if (num_modules > 0) {
3931           for (i = 0; i < num_modules && !syntax_error; ++i) {
3932             Module *module_pointer =
3933                 target_modules.GetModulePointerAtIndexUnlocked(i);
3934 
3935             if (module_pointer != current_module.get() &&
3936                 LookupInModule(
3937                     m_interpreter,
3938                     target_modules.GetModulePointerAtIndexUnlocked(i), result,
3939                     syntax_error)) {
3940               result.GetOutputStream().EOL();
3941               num_successful_lookups++;
3942             }
3943           }
3944         } else {
3945           result.AppendError("the target has no associated executable images");
3946           result.SetStatus(eReturnStatusFailed);
3947           return false;
3948         }
3949       } else {
3950         // Dump specified images (by basename or fullpath)
3951         const char *arg_cstr;
3952         for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr &&
3953                     !syntax_error;
3954              ++i) {
3955           ModuleList module_list;
3956           const size_t num_matches =
3957               FindModulesByName(target, arg_cstr, module_list, false);
3958           if (num_matches > 0) {
3959             for (size_t j = 0; j < num_matches; ++j) {
3960               Module *module = module_list.GetModulePointerAtIndex(j);
3961               if (module) {
3962                 if (LookupInModule(m_interpreter, module, result,
3963                                    syntax_error)) {
3964                   result.GetOutputStream().EOL();
3965                   num_successful_lookups++;
3966                 }
3967               }
3968             }
3969           } else
3970             result.AppendWarningWithFormat(
3971                 "Unable to find an image that matches '%s'.\n", arg_cstr);
3972         }
3973       }
3974 
3975       if (num_successful_lookups > 0)
3976         result.SetStatus(eReturnStatusSuccessFinishResult);
3977       else
3978         result.SetStatus(eReturnStatusFailed);
3979     }
3980     return result.Succeeded();
3981   }
3982 
3983   CommandOptions m_options;
3984 };
3985 
3986 #pragma mark CommandObjectMultiwordImageSearchPaths
3987 
3988 // CommandObjectMultiwordImageSearchPaths
3989 
3990 class CommandObjectTargetModulesImageSearchPaths
3991     : public CommandObjectMultiword {
3992 public:
3993   CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter)
3994       : CommandObjectMultiword(
3995             interpreter, "target modules search-paths",
3996             "Commands for managing module search paths for a target.",
3997             "target modules search-paths <subcommand> [<subcommand-options>]") {
3998     LoadSubCommand(
3999         "add", CommandObjectSP(
4000                    new CommandObjectTargetModulesSearchPathsAdd(interpreter)));
4001     LoadSubCommand(
4002         "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear(
4003                      interpreter)));
4004     LoadSubCommand(
4005         "insert",
4006         CommandObjectSP(
4007             new CommandObjectTargetModulesSearchPathsInsert(interpreter)));
4008     LoadSubCommand(
4009         "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList(
4010                     interpreter)));
4011     LoadSubCommand(
4012         "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery(
4013                      interpreter)));
4014   }
4015 
4016   ~CommandObjectTargetModulesImageSearchPaths() override = default;
4017 };
4018 
4019 #pragma mark CommandObjectTargetModules
4020 
4021 // CommandObjectTargetModules
4022 
4023 class CommandObjectTargetModules : public CommandObjectMultiword {
4024 public:
4025   // Constructors and Destructors
4026   CommandObjectTargetModules(CommandInterpreter &interpreter)
4027       : CommandObjectMultiword(interpreter, "target modules",
4028                                "Commands for accessing information for one or "
4029                                "more target modules.",
4030                                "target modules <sub-command> ...") {
4031     LoadSubCommand(
4032         "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter)));
4033     LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad(
4034                                interpreter)));
4035     LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump(
4036                                interpreter)));
4037     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList(
4038                                interpreter)));
4039     LoadSubCommand(
4040         "lookup",
4041         CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter)));
4042     LoadSubCommand(
4043         "search-paths",
4044         CommandObjectSP(
4045             new CommandObjectTargetModulesImageSearchPaths(interpreter)));
4046     LoadSubCommand(
4047         "show-unwind",
4048         CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter)));
4049   }
4050 
4051   ~CommandObjectTargetModules() override = default;
4052 
4053 private:
4054   // For CommandObjectTargetModules only
4055   DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetModules);
4056 };
4057 
4058 class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
4059 public:
4060   CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter)
4061       : CommandObjectParsed(
4062             interpreter, "target symbols add",
4063             "Add a debug symbol file to one of the target's current modules by "
4064             "specifying a path to a debug symbols file, or using the options "
4065             "to specify a module to download symbols for.",
4066             "target symbols add <cmd-options> [<symfile>]",
4067             eCommandRequiresTarget),
4068         m_option_group(),
4069         m_file_option(
4070             LLDB_OPT_SET_1, false, "shlib", 's',
4071             CommandCompletions::eModuleCompletion, eArgTypeShlibName,
4072             "Fullpath or basename for module to find debug symbols for."),
4073         m_current_frame_option(
4074             LLDB_OPT_SET_2, false, "frame", 'F',
4075             "Locate the debug symbols the currently selected frame.", false,
4076             true)
4077 
4078   {
4079     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
4080                           LLDB_OPT_SET_1);
4081     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
4082     m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2,
4083                           LLDB_OPT_SET_2);
4084     m_option_group.Finalize();
4085   }
4086 
4087   ~CommandObjectTargetSymbolsAdd() override = default;
4088 
4089   void
4090   HandleArgumentCompletion(CompletionRequest &request,
4091                            OptionElementVector &opt_element_vector) override {
4092     CommandCompletions::InvokeCommonCompletionCallbacks(
4093         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
4094         request, nullptr);
4095   }
4096 
4097   Options *GetOptions() override { return &m_option_group; }
4098 
4099 protected:
4100   bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
4101                         CommandReturnObject &result) {
4102     const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
4103     if (symbol_fspec) {
4104       char symfile_path[PATH_MAX];
4105       symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));
4106 
4107       if (!module_spec.GetUUID().IsValid()) {
4108         if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
4109           module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename();
4110       }
4111       // We now have a module that represents a symbol file that can be used
4112       // for a module that might exist in the current target, so we need to
4113       // find that module in the target
4114       ModuleList matching_module_list;
4115 
4116       size_t num_matches = 0;
4117       // First extract all module specs from the symbol file
4118       lldb_private::ModuleSpecList symfile_module_specs;
4119       if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
4120                                               0, 0, symfile_module_specs)) {
4121         // Now extract the module spec that matches the target architecture
4122         ModuleSpec target_arch_module_spec;
4123         ModuleSpec symfile_module_spec;
4124         target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
4125         if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
4126                                                         symfile_module_spec)) {
4127           // See if it has a UUID?
4128           if (symfile_module_spec.GetUUID().IsValid()) {
4129             // It has a UUID, look for this UUID in the target modules
4130             ModuleSpec symfile_uuid_module_spec;
4131             symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
4132             num_matches = target->GetImages().FindModules(
4133                 symfile_uuid_module_spec, matching_module_list);
4134           }
4135         }
4136 
4137         if (num_matches == 0) {
4138           // No matches yet, iterate through the module specs to find a UUID
4139           // value that we can match up to an image in our target
4140           const size_t num_symfile_module_specs =
4141               symfile_module_specs.GetSize();
4142           for (size_t i = 0; i < num_symfile_module_specs && num_matches == 0;
4143                ++i) {
4144             if (symfile_module_specs.GetModuleSpecAtIndex(
4145                     i, symfile_module_spec)) {
4146               if (symfile_module_spec.GetUUID().IsValid()) {
4147                 // It has a UUID, look for this UUID in the target modules
4148                 ModuleSpec symfile_uuid_module_spec;
4149                 symfile_uuid_module_spec.GetUUID() =
4150                     symfile_module_spec.GetUUID();
4151                 num_matches = target->GetImages().FindModules(
4152                     symfile_uuid_module_spec, matching_module_list);
4153               }
4154             }
4155           }
4156         }
4157       }
4158 
4159       // Just try to match up the file by basename if we have no matches at
4160       // this point
4161       if (num_matches == 0)
4162         num_matches =
4163             target->GetImages().FindModules(module_spec, matching_module_list);
4164 
4165       while (num_matches == 0) {
4166         ConstString filename_no_extension(
4167             module_spec.GetFileSpec().GetFileNameStrippingExtension());
4168         // Empty string returned, lets bail
4169         if (!filename_no_extension)
4170           break;
4171 
4172         // Check if there was no extension to strip and the basename is the
4173         // same
4174         if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
4175           break;
4176 
4177         // Replace basename with one less extension
4178         module_spec.GetFileSpec().GetFilename() = filename_no_extension;
4179 
4180         num_matches =
4181             target->GetImages().FindModules(module_spec, matching_module_list);
4182       }
4183 
4184       if (num_matches > 1) {
4185         result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
4186                                      "use the --uuid option to resolve the "
4187                                      "ambiguity.\n",
4188                                      symfile_path);
4189       } else if (num_matches == 1) {
4190         ModuleSP module_sp(matching_module_list.GetModuleAtIndex(0));
4191 
4192         // The module has not yet created its symbol vendor, we can just give
4193         // the existing target module the symfile path to use for when it
4194         // decides to create it!
4195         module_sp->SetSymbolFileFileSpec(symbol_fspec);
4196 
4197         SymbolFile *symbol_file =
4198             module_sp->GetSymbolFile(true, &result.GetErrorStream());
4199         if (symbol_file) {
4200           ObjectFile *object_file = symbol_file->GetObjectFile();
4201 
4202           if (object_file && object_file->GetFileSpec() == symbol_fspec) {
4203             // Provide feedback that the symfile has been successfully added.
4204             const FileSpec &module_fs = module_sp->GetFileSpec();
4205             result.AppendMessageWithFormat(
4206                 "symbol file '%s' has been added to '%s'\n", symfile_path,
4207                 module_fs.GetPath().c_str());
4208 
4209             // Let clients know something changed in the module if it is
4210             // currently loaded
4211             ModuleList module_list;
4212             module_list.Append(module_sp);
4213             target->SymbolsDidLoad(module_list);
4214 
4215             // Make sure we load any scripting resources that may be embedded
4216             // in the debug info files in case the platform supports that.
4217             Status error;
4218             StreamString feedback_stream;
4219             module_sp->LoadScriptingResourceInTarget(target, error,
4220                                                      &feedback_stream);
4221             if (error.Fail() && error.AsCString())
4222               result.AppendWarningWithFormat(
4223                   "unable to load scripting data for module %s - error "
4224                   "reported was %s",
4225                   module_sp->GetFileSpec()
4226                       .GetFileNameStrippingExtension()
4227                       .GetCString(),
4228                   error.AsCString());
4229             else if (feedback_stream.GetSize())
4230               result.AppendWarningWithFormat("%s", feedback_stream.GetData());
4231 
4232             flush = true;
4233             result.SetStatus(eReturnStatusSuccessFinishResult);
4234             return true;
4235           }
4236         }
4237         // Clear the symbol file spec if anything went wrong
4238         module_sp->SetSymbolFileFileSpec(FileSpec());
4239       }
4240 
4241       namespace fs = llvm::sys::fs;
4242       if (module_spec.GetUUID().IsValid()) {
4243         StreamString ss_symfile_uuid;
4244         module_spec.GetUUID().Dump(&ss_symfile_uuid);
4245         result.AppendErrorWithFormat(
4246             "symbol file '%s' (%s) does not match any existing module%s\n",
4247             symfile_path, ss_symfile_uuid.GetData(),
4248             !fs::is_regular_file(symbol_fspec.GetPath())
4249                 ? "\n       please specify the full path to the symbol file"
4250                 : "");
4251       } else {
4252         result.AppendErrorWithFormat(
4253             "symbol file '%s' does not match any existing module%s\n",
4254             symfile_path,
4255             !fs::is_regular_file(symbol_fspec.GetPath())
4256                 ? "\n       please specify the full path to the symbol file"
4257                 : "");
4258       }
4259     } else {
4260       result.AppendError(
4261           "one or more executable image paths must be specified");
4262     }
4263     result.SetStatus(eReturnStatusFailed);
4264     return false;
4265   }
4266 
4267   bool DoExecute(Args &args, CommandReturnObject &result) override {
4268     Target *target = m_exe_ctx.GetTargetPtr();
4269     result.SetStatus(eReturnStatusFailed);
4270     bool flush = false;
4271     ModuleSpec module_spec;
4272     const bool uuid_option_set =
4273         m_uuid_option_group.GetOptionValue().OptionWasSet();
4274     const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
4275     const bool frame_option_set =
4276         m_current_frame_option.GetOptionValue().OptionWasSet();
4277     const size_t argc = args.GetArgumentCount();
4278 
4279     if (argc == 0) {
4280       if (uuid_option_set || file_option_set || frame_option_set) {
4281         bool success = false;
4282         bool error_set = false;
4283         if (frame_option_set) {
4284           Process *process = m_exe_ctx.GetProcessPtr();
4285           if (process) {
4286             const StateType process_state = process->GetState();
4287             if (StateIsStoppedState(process_state, true)) {
4288               StackFrame *frame = m_exe_ctx.GetFramePtr();
4289               if (frame) {
4290                 ModuleSP frame_module_sp(
4291                     frame->GetSymbolContext(eSymbolContextModule).module_sp);
4292                 if (frame_module_sp) {
4293                   if (FileSystem::Instance().Exists(
4294                           frame_module_sp->GetPlatformFileSpec())) {
4295                     module_spec.GetArchitecture() =
4296                         frame_module_sp->GetArchitecture();
4297                     module_spec.GetFileSpec() =
4298                         frame_module_sp->GetPlatformFileSpec();
4299                   }
4300                   module_spec.GetUUID() = frame_module_sp->GetUUID();
4301                   success = module_spec.GetUUID().IsValid() ||
4302                             module_spec.GetFileSpec();
4303                 } else {
4304                   result.AppendError("frame has no module");
4305                   error_set = true;
4306                 }
4307               } else {
4308                 result.AppendError("invalid current frame");
4309                 error_set = true;
4310               }
4311             } else {
4312               result.AppendErrorWithFormat("process is not stopped: %s",
4313                                            StateAsCString(process_state));
4314               error_set = true;
4315             }
4316           } else {
4317             result.AppendError(
4318                 "a process must exist in order to use the --frame option");
4319             error_set = true;
4320           }
4321         } else {
4322           if (uuid_option_set) {
4323             module_spec.GetUUID() =
4324                 m_uuid_option_group.GetOptionValue().GetCurrentValue();
4325             success |= module_spec.GetUUID().IsValid();
4326           } else if (file_option_set) {
4327             module_spec.GetFileSpec() =
4328                 m_file_option.GetOptionValue().GetCurrentValue();
4329             ModuleSP module_sp(
4330                 target->GetImages().FindFirstModule(module_spec));
4331             if (module_sp) {
4332               module_spec.GetFileSpec() = module_sp->GetFileSpec();
4333               module_spec.GetPlatformFileSpec() =
4334                   module_sp->GetPlatformFileSpec();
4335               module_spec.GetUUID() = module_sp->GetUUID();
4336               module_spec.GetArchitecture() = module_sp->GetArchitecture();
4337             } else {
4338               module_spec.GetArchitecture() = target->GetArchitecture();
4339             }
4340             success |= module_spec.GetUUID().IsValid() ||
4341                        FileSystem::Instance().Exists(module_spec.GetFileSpec());
4342           }
4343         }
4344 
4345         if (success) {
4346           if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
4347             if (module_spec.GetSymbolFileSpec())
4348               success = AddModuleSymbols(target, module_spec, flush, result);
4349           }
4350         }
4351 
4352         if (!success && !error_set) {
4353           StreamString error_strm;
4354           if (uuid_option_set) {
4355             error_strm.PutCString("unable to find debug symbols for UUID ");
4356             module_spec.GetUUID().Dump(&error_strm);
4357           } else if (file_option_set) {
4358             error_strm.PutCString(
4359                 "unable to find debug symbols for the executable file ");
4360             error_strm << module_spec.GetFileSpec();
4361           } else if (frame_option_set) {
4362             error_strm.PutCString(
4363                 "unable to find debug symbols for the current frame");
4364           }
4365           result.AppendError(error_strm.GetString());
4366         }
4367       } else {
4368         result.AppendError("one or more symbol file paths must be specified, "
4369                            "or options must be specified");
4370       }
4371     } else {
4372       if (uuid_option_set) {
4373         result.AppendError("specify either one or more paths to symbol files "
4374                            "or use the --uuid option without arguments");
4375       } else if (frame_option_set) {
4376         result.AppendError("specify either one or more paths to symbol files "
4377                            "or use the --frame option without arguments");
4378       } else if (file_option_set && argc > 1) {
4379         result.AppendError("specify at most one symbol file path when "
4380                            "--shlib option is set");
4381       } else {
4382         PlatformSP platform_sp(target->GetPlatform());
4383 
4384         for (auto &entry : args.entries()) {
4385           if (!entry.ref.empty()) {
4386             auto &symbol_file_spec = module_spec.GetSymbolFileSpec();
4387             symbol_file_spec.SetFile(entry.ref, FileSpec::Style::native);
4388             FileSystem::Instance().Resolve(symbol_file_spec);
4389             if (file_option_set) {
4390               module_spec.GetFileSpec() =
4391                   m_file_option.GetOptionValue().GetCurrentValue();
4392             }
4393             if (platform_sp) {
4394               FileSpec symfile_spec;
4395               if (platform_sp
4396                       ->ResolveSymbolFile(*target, module_spec, symfile_spec)
4397                       .Success())
4398                 module_spec.GetSymbolFileSpec() = symfile_spec;
4399             }
4400 
4401             ArchSpec arch;
4402             bool symfile_exists =
4403                 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec());
4404 
4405             if (symfile_exists) {
4406               if (!AddModuleSymbols(target, module_spec, flush, result))
4407                 break;
4408             } else {
4409               std::string resolved_symfile_path =
4410                   module_spec.GetSymbolFileSpec().GetPath();
4411               if (resolved_symfile_path != entry.ref) {
4412                 result.AppendErrorWithFormat(
4413                     "invalid module path '%s' with resolved path '%s'\n",
4414                     entry.c_str(), resolved_symfile_path.c_str());
4415                 break;
4416               }
4417               result.AppendErrorWithFormat("invalid module path '%s'\n",
4418                                            entry.c_str());
4419               break;
4420             }
4421           }
4422         }
4423       }
4424     }
4425 
4426     if (flush) {
4427       Process *process = m_exe_ctx.GetProcessPtr();
4428       if (process)
4429         process->Flush();
4430     }
4431     return result.Succeeded();
4432   }
4433 
4434   OptionGroupOptions m_option_group;
4435   OptionGroupUUID m_uuid_option_group;
4436   OptionGroupFile m_file_option;
4437   OptionGroupBoolean m_current_frame_option;
4438 };
4439 
4440 #pragma mark CommandObjectTargetSymbols
4441 
4442 // CommandObjectTargetSymbols
4443 
4444 class CommandObjectTargetSymbols : public CommandObjectMultiword {
4445 public:
4446   // Constructors and Destructors
4447   CommandObjectTargetSymbols(CommandInterpreter &interpreter)
4448       : CommandObjectMultiword(
4449             interpreter, "target symbols",
4450             "Commands for adding and managing debug symbol files.",
4451             "target symbols <sub-command> ...") {
4452     LoadSubCommand(
4453         "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
4454   }
4455 
4456   ~CommandObjectTargetSymbols() override = default;
4457 
4458 private:
4459   // For CommandObjectTargetModules only
4460   DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetSymbols);
4461 };
4462 
4463 #pragma mark CommandObjectTargetStopHookAdd
4464 
4465 // CommandObjectTargetStopHookAdd
4466 #define LLDB_OPTIONS_target_stop_hook_add
4467 #include "CommandOptions.inc"
4468 
4469 class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
4470                                        public IOHandlerDelegateMultiline {
4471 public:
4472   class CommandOptions : public Options {
4473   public:
4474     CommandOptions()
4475         : Options(), m_line_start(0), m_line_end(UINT_MAX),
4476           m_func_name_type_mask(eFunctionNameTypeAuto),
4477           m_sym_ctx_specified(false), m_thread_specified(false),
4478           m_use_one_liner(false), m_one_liner() {}
4479 
4480     ~CommandOptions() override = default;
4481 
4482     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4483       return llvm::makeArrayRef(g_target_stop_hook_add_options);
4484     }
4485 
4486     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4487                           ExecutionContext *execution_context) override {
4488       Status error;
4489       const int short_option = m_getopt_table[option_idx].val;
4490 
4491       switch (short_option) {
4492       case 'c':
4493         m_class_name = option_arg;
4494         m_sym_ctx_specified = true;
4495         break;
4496 
4497       case 'e':
4498         if (option_arg.getAsInteger(0, m_line_end)) {
4499           error.SetErrorStringWithFormat("invalid end line number: \"%s\"",
4500                                          option_arg.str().c_str());
4501           break;
4502         }
4503         m_sym_ctx_specified = true;
4504         break;
4505 
4506       case 'G': {
4507         bool value, success;
4508         value = OptionArgParser::ToBoolean(option_arg, false, &success);
4509         if (success) {
4510           m_auto_continue = value;
4511         } else
4512           error.SetErrorStringWithFormat(
4513               "invalid boolean value '%s' passed for -G option",
4514               option_arg.str().c_str());
4515       }
4516       break;
4517       case 'l':
4518         if (option_arg.getAsInteger(0, m_line_start)) {
4519           error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
4520                                          option_arg.str().c_str());
4521           break;
4522         }
4523         m_sym_ctx_specified = true;
4524         break;
4525 
4526       case 'i':
4527         m_no_inlines = true;
4528         break;
4529 
4530       case 'n':
4531         m_function_name = option_arg;
4532         m_func_name_type_mask |= eFunctionNameTypeAuto;
4533         m_sym_ctx_specified = true;
4534         break;
4535 
4536       case 'f':
4537         m_file_name = option_arg;
4538         m_sym_ctx_specified = true;
4539         break;
4540 
4541       case 's':
4542         m_module_name = option_arg;
4543         m_sym_ctx_specified = true;
4544         break;
4545 
4546       case 't':
4547         if (option_arg.getAsInteger(0, m_thread_id))
4548           error.SetErrorStringWithFormat("invalid thread id string '%s'",
4549                                          option_arg.str().c_str());
4550         m_thread_specified = true;
4551         break;
4552 
4553       case 'T':
4554         m_thread_name = option_arg;
4555         m_thread_specified = true;
4556         break;
4557 
4558       case 'q':
4559         m_queue_name = option_arg;
4560         m_thread_specified = true;
4561         break;
4562 
4563       case 'x':
4564         if (option_arg.getAsInteger(0, m_thread_index))
4565           error.SetErrorStringWithFormat("invalid thread index string '%s'",
4566                                          option_arg.str().c_str());
4567         m_thread_specified = true;
4568         break;
4569 
4570       case 'o':
4571         m_use_one_liner = true;
4572         m_one_liner.push_back(option_arg);
4573         break;
4574 
4575       default:
4576         error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
4577         break;
4578       }
4579       return error;
4580     }
4581 
4582     void OptionParsingStarting(ExecutionContext *execution_context) override {
4583       m_class_name.clear();
4584       m_function_name.clear();
4585       m_line_start = 0;
4586       m_line_end = UINT_MAX;
4587       m_file_name.clear();
4588       m_module_name.clear();
4589       m_func_name_type_mask = eFunctionNameTypeAuto;
4590       m_thread_id = LLDB_INVALID_THREAD_ID;
4591       m_thread_index = UINT32_MAX;
4592       m_thread_name.clear();
4593       m_queue_name.clear();
4594 
4595       m_no_inlines = false;
4596       m_sym_ctx_specified = false;
4597       m_thread_specified = false;
4598 
4599       m_use_one_liner = false;
4600       m_one_liner.clear();
4601       m_auto_continue = false;
4602     }
4603 
4604     std::string m_class_name;
4605     std::string m_function_name;
4606     uint32_t m_line_start;
4607     uint32_t m_line_end;
4608     std::string m_file_name;
4609     std::string m_module_name;
4610     uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType.
4611     lldb::tid_t m_thread_id;
4612     uint32_t m_thread_index;
4613     std::string m_thread_name;
4614     std::string m_queue_name;
4615     bool m_sym_ctx_specified;
4616     bool m_no_inlines;
4617     bool m_thread_specified;
4618     // Instance variables to hold the values for one_liner options.
4619     bool m_use_one_liner;
4620     std::vector<std::string> m_one_liner;
4621     bool m_auto_continue;
4622   };
4623 
4624   CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
4625       : CommandObjectParsed(interpreter, "target stop-hook add",
4626                             "Add a hook to be executed when the target stops.",
4627                             "target stop-hook add"),
4628         IOHandlerDelegateMultiline("DONE",
4629                                    IOHandlerDelegate::Completion::LLDBCommand),
4630         m_options() {}
4631 
4632   ~CommandObjectTargetStopHookAdd() override = default;
4633 
4634   Options *GetOptions() override { return &m_options; }
4635 
4636 protected:
4637   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
4638     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4639     if (output_sp && interactive) {
4640       output_sp->PutCString(
4641           "Enter your stop hook command(s).  Type 'DONE' to end.\n");
4642       output_sp->Flush();
4643     }
4644   }
4645 
4646   void IOHandlerInputComplete(IOHandler &io_handler,
4647                               std::string &line) override {
4648     if (m_stop_hook_sp) {
4649       if (line.empty()) {
4650         StreamFileSP error_sp(io_handler.GetErrorStreamFile());
4651         if (error_sp) {
4652           error_sp->Printf("error: stop hook #%" PRIu64
4653                            " aborted, no commands.\n",
4654                            m_stop_hook_sp->GetID());
4655           error_sp->Flush();
4656         }
4657         Target *target = GetDebugger().GetSelectedTarget().get();
4658         if (target)
4659           target->RemoveStopHookByID(m_stop_hook_sp->GetID());
4660       } else {
4661         m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
4662         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4663         if (output_sp) {
4664           output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
4665                             m_stop_hook_sp->GetID());
4666           output_sp->Flush();
4667         }
4668       }
4669       m_stop_hook_sp.reset();
4670     }
4671     io_handler.SetIsDone(true);
4672   }
4673 
4674   bool DoExecute(Args &command, CommandReturnObject &result) override {
4675     m_stop_hook_sp.reset();
4676 
4677     Target *target = GetSelectedOrDummyTarget();
4678     if (target) {
4679       Target::StopHookSP new_hook_sp = target->CreateStopHook();
4680 
4681       //  First step, make the specifier.
4682       std::unique_ptr<SymbolContextSpecifier> specifier_up;
4683       if (m_options.m_sym_ctx_specified) {
4684         specifier_up.reset(
4685             new SymbolContextSpecifier(GetDebugger().GetSelectedTarget()));
4686 
4687         if (!m_options.m_module_name.empty()) {
4688           specifier_up->AddSpecification(
4689               m_options.m_module_name.c_str(),
4690               SymbolContextSpecifier::eModuleSpecified);
4691         }
4692 
4693         if (!m_options.m_class_name.empty()) {
4694           specifier_up->AddSpecification(
4695               m_options.m_class_name.c_str(),
4696               SymbolContextSpecifier::eClassOrNamespaceSpecified);
4697         }
4698 
4699         if (!m_options.m_file_name.empty()) {
4700           specifier_up->AddSpecification(
4701               m_options.m_file_name.c_str(),
4702               SymbolContextSpecifier::eFileSpecified);
4703         }
4704 
4705         if (m_options.m_line_start != 0) {
4706           specifier_up->AddLineSpecification(
4707               m_options.m_line_start,
4708               SymbolContextSpecifier::eLineStartSpecified);
4709         }
4710 
4711         if (m_options.m_line_end != UINT_MAX) {
4712           specifier_up->AddLineSpecification(
4713               m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
4714         }
4715 
4716         if (!m_options.m_function_name.empty()) {
4717           specifier_up->AddSpecification(
4718               m_options.m_function_name.c_str(),
4719               SymbolContextSpecifier::eFunctionSpecified);
4720         }
4721       }
4722 
4723       if (specifier_up)
4724         new_hook_sp->SetSpecifier(specifier_up.release());
4725 
4726       // Next see if any of the thread options have been entered:
4727 
4728       if (m_options.m_thread_specified) {
4729         ThreadSpec *thread_spec = new ThreadSpec();
4730 
4731         if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
4732           thread_spec->SetTID(m_options.m_thread_id);
4733         }
4734 
4735         if (m_options.m_thread_index != UINT32_MAX)
4736           thread_spec->SetIndex(m_options.m_thread_index);
4737 
4738         if (!m_options.m_thread_name.empty())
4739           thread_spec->SetName(m_options.m_thread_name.c_str());
4740 
4741         if (!m_options.m_queue_name.empty())
4742           thread_spec->SetQueueName(m_options.m_queue_name.c_str());
4743 
4744         new_hook_sp->SetThreadSpecifier(thread_spec);
4745       }
4746 
4747       new_hook_sp->SetAutoContinue(m_options.m_auto_continue);
4748       if (m_options.m_use_one_liner) {
4749         // Use one-liners.
4750         for (auto cmd : m_options.m_one_liner)
4751           new_hook_sp->GetCommandPointer()->AppendString(
4752             cmd.c_str());
4753         result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
4754                                        new_hook_sp->GetID());
4755       } else {
4756         m_stop_hook_sp = new_hook_sp;
4757         m_interpreter.GetLLDBCommandsFromIOHandler(
4758             "> ",     // Prompt
4759             *this,    // IOHandlerDelegate
4760             true,     // Run IOHandler in async mode
4761             nullptr); // Baton for the "io_handler" that will be passed back
4762                       // into our IOHandlerDelegate functions
4763       }
4764       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4765     } else {
4766       result.AppendError("invalid target\n");
4767       result.SetStatus(eReturnStatusFailed);
4768     }
4769 
4770     return result.Succeeded();
4771   }
4772 
4773 private:
4774   CommandOptions m_options;
4775   Target::StopHookSP m_stop_hook_sp;
4776 };
4777 
4778 #pragma mark CommandObjectTargetStopHookDelete
4779 
4780 // CommandObjectTargetStopHookDelete
4781 
4782 class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
4783 public:
4784   CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
4785       : CommandObjectParsed(interpreter, "target stop-hook delete",
4786                             "Delete a stop-hook.",
4787                             "target stop-hook delete [<idx>]") {}
4788 
4789   ~CommandObjectTargetStopHookDelete() override = default;
4790 
4791 protected:
4792   bool DoExecute(Args &command, CommandReturnObject &result) override {
4793     Target *target = GetSelectedOrDummyTarget();
4794     if (target) {
4795       // FIXME: see if we can use the breakpoint id style parser?
4796       size_t num_args = command.GetArgumentCount();
4797       if (num_args == 0) {
4798         if (!m_interpreter.Confirm("Delete all stop hooks?", true)) {
4799           result.SetStatus(eReturnStatusFailed);
4800           return false;
4801         } else {
4802           target->RemoveAllStopHooks();
4803         }
4804       } else {
4805         bool success;
4806         for (size_t i = 0; i < num_args; i++) {
4807           lldb::user_id_t user_id = StringConvert::ToUInt32(
4808               command.GetArgumentAtIndex(i), 0, 0, &success);
4809           if (!success) {
4810             result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4811                                          command.GetArgumentAtIndex(i));
4812             result.SetStatus(eReturnStatusFailed);
4813             return false;
4814           }
4815           success = target->RemoveStopHookByID(user_id);
4816           if (!success) {
4817             result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4818                                          command.GetArgumentAtIndex(i));
4819             result.SetStatus(eReturnStatusFailed);
4820             return false;
4821           }
4822         }
4823       }
4824       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4825     } else {
4826       result.AppendError("invalid target\n");
4827       result.SetStatus(eReturnStatusFailed);
4828     }
4829 
4830     return result.Succeeded();
4831   }
4832 };
4833 
4834 #pragma mark CommandObjectTargetStopHookEnableDisable
4835 
4836 // CommandObjectTargetStopHookEnableDisable
4837 
4838 class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
4839 public:
4840   CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
4841                                            bool enable, const char *name,
4842                                            const char *help, const char *syntax)
4843       : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
4844   }
4845 
4846   ~CommandObjectTargetStopHookEnableDisable() override = default;
4847 
4848 protected:
4849   bool DoExecute(Args &command, CommandReturnObject &result) override {
4850     Target *target = GetSelectedOrDummyTarget();
4851     if (target) {
4852       // FIXME: see if we can use the breakpoint id style parser?
4853       size_t num_args = command.GetArgumentCount();
4854       bool success;
4855 
4856       if (num_args == 0) {
4857         target->SetAllStopHooksActiveState(m_enable);
4858       } else {
4859         for (size_t i = 0; i < num_args; i++) {
4860           lldb::user_id_t user_id = StringConvert::ToUInt32(
4861               command.GetArgumentAtIndex(i), 0, 0, &success);
4862           if (!success) {
4863             result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4864                                          command.GetArgumentAtIndex(i));
4865             result.SetStatus(eReturnStatusFailed);
4866             return false;
4867           }
4868           success = target->SetStopHookActiveStateByID(user_id, m_enable);
4869           if (!success) {
4870             result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4871                                          command.GetArgumentAtIndex(i));
4872             result.SetStatus(eReturnStatusFailed);
4873             return false;
4874           }
4875         }
4876       }
4877       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4878     } else {
4879       result.AppendError("invalid target\n");
4880       result.SetStatus(eReturnStatusFailed);
4881     }
4882     return result.Succeeded();
4883   }
4884 
4885 private:
4886   bool m_enable;
4887 };
4888 
4889 #pragma mark CommandObjectTargetStopHookList
4890 
4891 // CommandObjectTargetStopHookList
4892 
4893 class CommandObjectTargetStopHookList : public CommandObjectParsed {
4894 public:
4895   CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
4896       : CommandObjectParsed(interpreter, "target stop-hook list",
4897                             "List all stop-hooks.",
4898                             "target stop-hook list [<type>]") {}
4899 
4900   ~CommandObjectTargetStopHookList() override = default;
4901 
4902 protected:
4903   bool DoExecute(Args &command, CommandReturnObject &result) override {
4904     Target *target = GetSelectedOrDummyTarget();
4905     if (!target) {
4906       result.AppendError("invalid target\n");
4907       result.SetStatus(eReturnStatusFailed);
4908       return result.Succeeded();
4909     }
4910 
4911     size_t num_hooks = target->GetNumStopHooks();
4912     if (num_hooks == 0) {
4913       result.GetOutputStream().PutCString("No stop hooks.\n");
4914     } else {
4915       for (size_t i = 0; i < num_hooks; i++) {
4916         Target::StopHookSP this_hook = target->GetStopHookAtIndex(i);
4917         if (i > 0)
4918           result.GetOutputStream().PutCString("\n");
4919         this_hook->GetDescription(&(result.GetOutputStream()),
4920                                   eDescriptionLevelFull);
4921       }
4922     }
4923     result.SetStatus(eReturnStatusSuccessFinishResult);
4924     return result.Succeeded();
4925   }
4926 };
4927 
4928 #pragma mark CommandObjectMultiwordTargetStopHooks
4929 
4930 // CommandObjectMultiwordTargetStopHooks
4931 
4932 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
4933 public:
4934   CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
4935       : CommandObjectMultiword(
4936             interpreter, "target stop-hook",
4937             "Commands for operating on debugger target stop-hooks.",
4938             "target stop-hook <subcommand> [<subcommand-options>]") {
4939     LoadSubCommand("add", CommandObjectSP(
4940                               new CommandObjectTargetStopHookAdd(interpreter)));
4941     LoadSubCommand(
4942         "delete",
4943         CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
4944     LoadSubCommand("disable",
4945                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
4946                        interpreter, false, "target stop-hook disable [<id>]",
4947                        "Disable a stop-hook.", "target stop-hook disable")));
4948     LoadSubCommand("enable",
4949                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
4950                        interpreter, true, "target stop-hook enable [<id>]",
4951                        "Enable a stop-hook.", "target stop-hook enable")));
4952     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList(
4953                                interpreter)));
4954   }
4955 
4956   ~CommandObjectMultiwordTargetStopHooks() override = default;
4957 };
4958 
4959 #pragma mark CommandObjectMultiwordTarget
4960 
4961 // CommandObjectMultiwordTarget
4962 
4963 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
4964     CommandInterpreter &interpreter)
4965     : CommandObjectMultiword(interpreter, "target",
4966                              "Commands for operating on debugger targets.",
4967                              "target <subcommand> [<subcommand-options>]") {
4968   LoadSubCommand("create",
4969                  CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
4970   LoadSubCommand("delete",
4971                  CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
4972   LoadSubCommand("list",
4973                  CommandObjectSP(new CommandObjectTargetList(interpreter)));
4974   LoadSubCommand("select",
4975                  CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
4976   LoadSubCommand(
4977       "stop-hook",
4978       CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
4979   LoadSubCommand("modules",
4980                  CommandObjectSP(new CommandObjectTargetModules(interpreter)));
4981   LoadSubCommand("symbols",
4982                  CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
4983   LoadSubCommand("variable",
4984                  CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
4985 }
4986 
4987 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;
4988