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