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