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 constexpr OptionEnumValueElement g_dependents_enumaration[] = {
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 
151 static constexpr OptionDefinition g_dependents_options[] = {
152     {LLDB_OPT_SET_1, false, "no-dependents", 'd',
153      OptionParser::eOptionalArgument, nullptr,
154      OptionEnumValues(g_dependents_enumaration), 0, eArgTypeValue,
155      "Whether or not to load dependents when creating a target. If the option "
156      "is not specified, the value is implicitly 'default'. If the option is "
157      "specified but without a value, the value is implicitly 'true'."}};
158 
159 class OptionGroupDependents : public OptionGroup {
160 public:
161   OptionGroupDependents() {}
162 
163   ~OptionGroupDependents() override {}
164 
165   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
166     return llvm::makeArrayRef(g_dependents_options);
167   }
168 
169   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
170                         ExecutionContext *execution_context) override {
171     Status error;
172 
173     // For compatibility no value means don't load dependents.
174     if (option_value.empty()) {
175       m_load_dependent_files = eLoadDependentsNo;
176       return error;
177     }
178 
179     const char short_option = g_dependents_options[option_idx].short_option;
180     if (short_option == 'd') {
181       LoadDependentFiles tmp_load_dependents;
182       tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum(
183           option_value, g_dependents_options[option_idx].enum_values, 0, error);
184       if (error.Success())
185         m_load_dependent_files = tmp_load_dependents;
186     } else {
187       error.SetErrorStringWithFormat("unrecognized short option '%c'",
188                                      short_option);
189     }
190 
191     return error;
192   }
193 
194   Status SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete;
195 
196   void OptionParsingStarting(ExecutionContext *execution_context) override {
197     m_load_dependent_files = eLoadDependentsDefault;
198   }
199 
200   LoadDependentFiles m_load_dependent_files;
201 
202 private:
203   DISALLOW_COPY_AND_ASSIGN(OptionGroupDependents);
204 };
205 
206 #pragma mark CommandObjectTargetCreate
207 
208 //-------------------------------------------------------------------------
209 // "target create"
210 //-------------------------------------------------------------------------
211 
212 class CommandObjectTargetCreate : public CommandObjectParsed {
213 public:
214   CommandObjectTargetCreate(CommandInterpreter &interpreter)
215       : CommandObjectParsed(
216             interpreter, "target create",
217             "Create a target using the argument as the main executable.",
218             nullptr),
219         m_option_group(), m_arch_option(),
220         m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename,
221                     "Fullpath to a core file to use for this target."),
222         m_platform_path(LLDB_OPT_SET_1, false, "platform-path", 'P', 0,
223                         eArgTypePath,
224                         "Path to the remote file to use for this target."),
225         m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
226                       eArgTypeFilename,
227                       "Fullpath to a stand alone debug "
228                       "symbols file for when debug symbols "
229                       "are not in the executable."),
230         m_remote_file(
231             LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename,
232             "Fullpath to the file on the remote host if debugging remotely."),
233         m_add_dependents() {
234     CommandArgumentEntry arg;
235     CommandArgumentData file_arg;
236 
237     // Define the first (and only) variant of this arg.
238     file_arg.arg_type = eArgTypeFilename;
239     file_arg.arg_repetition = eArgRepeatPlain;
240 
241     // There is only one variant this argument could be; put it into the
242     // argument entry.
243     arg.push_back(file_arg);
244 
245     // Push the data for the first argument into the m_arguments vector.
246     m_arguments.push_back(arg);
247 
248     m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
249     m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
250     m_option_group.Append(&m_platform_path, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
251     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
252     m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
253     m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
254     m_option_group.Finalize();
255   }
256 
257   ~CommandObjectTargetCreate() override = default;
258 
259   Options *GetOptions() override { return &m_option_group; }
260 
261   int HandleArgumentCompletion(
262       CompletionRequest &request,
263       OptionElementVector &opt_element_vector) override {
264     CommandCompletions::InvokeCommonCompletionCallbacks(
265         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
266         request, nullptr);
267     return request.GetNumberOfMatches();
268   }
269 
270 protected:
271   bool DoExecute(Args &command, CommandReturnObject &result) override {
272     const size_t argc = command.GetArgumentCount();
273     FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue());
274     FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());
275 
276     if (core_file) {
277       if (!FileSystem::Instance().Exists(core_file)) {
278         result.AppendErrorWithFormat("core file '%s' doesn't exist",
279                                      core_file.GetPath().c_str());
280         result.SetStatus(eReturnStatusFailed);
281         return false;
282       }
283       if (!FileSystem::Instance().Readable(core_file)) {
284         result.AppendErrorWithFormat("core file '%s' is not readable",
285                                      core_file.GetPath().c_str());
286         result.SetStatus(eReturnStatusFailed);
287         return false;
288       }
289     }
290 
291     if (argc == 1 || core_file || remote_file) {
292       FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
293       if (symfile) {
294         if (FileSystem::Instance().Exists(symfile)) {
295           if (!FileSystem::Instance().Readable(symfile)) {
296             result.AppendErrorWithFormat("symbol file '%s' is not readable",
297                                          symfile.GetPath().c_str());
298             result.SetStatus(eReturnStatusFailed);
299             return false;
300           }
301         } else {
302           char symfile_path[PATH_MAX];
303           symfile.GetPath(symfile_path, sizeof(symfile_path));
304           result.AppendErrorWithFormat("invalid symbol file path '%s'",
305                                        symfile_path);
306           result.SetStatus(eReturnStatusFailed);
307           return false;
308         }
309       }
310 
311       const char *file_path = command.GetArgumentAtIndex(0);
312       static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
313       Timer scoped_timer(func_cat, "(lldb) target create '%s'", file_path);
314       FileSpec file_spec;
315 
316       if (file_path) {
317         file_spec.SetFile(file_path, FileSpec::Style::native);
318         FileSystem::Instance().Resolve(file_spec);
319       }
320 
321       bool must_set_platform_path = false;
322 
323       Debugger &debugger = m_interpreter.GetDebugger();
324 
325       TargetSP target_sp;
326       llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
327       Status error(debugger.GetTargetList().CreateTarget(
328           debugger, file_path, arch_cstr,
329           m_add_dependents.m_load_dependent_files, nullptr, target_sp));
330 
331       if (target_sp) {
332         // Only get the platform after we create the target because we might
333         // have switched platforms depending on what the arguments were to
334         // CreateTarget() we can't rely on the selected platform.
335 
336         PlatformSP platform_sp = target_sp->GetPlatform();
337 
338         if (remote_file) {
339           if (platform_sp) {
340             // I have a remote file.. two possible cases
341             if (file_spec && FileSystem::Instance().Exists(file_spec)) {
342               // if the remote file does not exist, push it there
343               if (!platform_sp->GetFileExists(remote_file)) {
344                 Status err = platform_sp->PutFile(file_spec, remote_file);
345                 if (err.Fail()) {
346                   result.AppendError(err.AsCString());
347                   result.SetStatus(eReturnStatusFailed);
348                   return false;
349                 }
350               }
351             } else {
352               // there is no local file and we need one
353               // in order to make the remote ---> local transfer we need a
354               // platform
355               // TODO: if the user has passed in a --platform argument, use it
356               // to fetch the right platform
357               if (!platform_sp) {
358                 result.AppendError(
359                     "unable to perform remote debugging without a platform");
360                 result.SetStatus(eReturnStatusFailed);
361                 return false;
362               }
363               if (file_path) {
364                 // copy the remote file to the local file
365                 Status err = platform_sp->GetFile(remote_file, file_spec);
366                 if (err.Fail()) {
367                   result.AppendError(err.AsCString());
368                   result.SetStatus(eReturnStatusFailed);
369                   return false;
370                 }
371               } else {
372                 // make up a local file
373                 result.AppendError("remote --> local transfer without local "
374                                    "path is not implemented yet");
375                 result.SetStatus(eReturnStatusFailed);
376                 return false;
377               }
378             }
379           } else {
380             result.AppendError("no platform found for target");
381             result.SetStatus(eReturnStatusFailed);
382             return false;
383           }
384         }
385 
386         if (symfile || remote_file) {
387           ModuleSP module_sp(target_sp->GetExecutableModule());
388           if (module_sp) {
389             if (symfile)
390               module_sp->SetSymbolFileFileSpec(symfile);
391             if (remote_file) {
392               std::string remote_path = remote_file.GetPath();
393               target_sp->SetArg0(remote_path.c_str());
394               module_sp->SetPlatformFileSpec(remote_file);
395             }
396           }
397         }
398 
399         debugger.GetTargetList().SetSelectedTarget(target_sp.get());
400         if (must_set_platform_path) {
401           ModuleSpec main_module_spec(file_spec);
402           ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec);
403           if (module_sp)
404             module_sp->SetPlatformFileSpec(remote_file);
405         }
406         if (core_file) {
407           char core_path[PATH_MAX];
408           core_file.GetPath(core_path, sizeof(core_path));
409           if (FileSystem::Instance().Exists(core_file)) {
410             if (!FileSystem::Instance().Readable(core_file)) {
411               result.AppendMessageWithFormat(
412                   "Core file '%s' is not readable.\n", core_path);
413               result.SetStatus(eReturnStatusFailed);
414               return false;
415             }
416             FileSpec core_file_dir;
417             core_file_dir.GetDirectory() = core_file.GetDirectory();
418             target_sp->GetExecutableSearchPaths().Append(core_file_dir);
419 
420             ProcessSP process_sp(target_sp->CreateProcess(
421                 m_interpreter.GetDebugger().GetListener(), llvm::StringRef(),
422                 &core_file));
423 
424             if (process_sp) {
425               // Seems weird that we Launch a core file, but that is what we
426               // do!
427               error = process_sp->LoadCore();
428 
429               if (error.Fail()) {
430                 result.AppendError(
431                     error.AsCString("can't find plug-in for core file"));
432                 result.SetStatus(eReturnStatusFailed);
433                 return false;
434               } else {
435                 result.AppendMessageWithFormat(
436                     "Core file '%s' (%s) was loaded.\n", core_path,
437                     target_sp->GetArchitecture().GetArchitectureName());
438                 result.SetStatus(eReturnStatusSuccessFinishNoResult);
439               }
440             } else {
441               result.AppendErrorWithFormat(
442                   "Unable to find process plug-in for core file '%s'\n",
443                   core_path);
444               result.SetStatus(eReturnStatusFailed);
445             }
446           } else {
447             result.AppendErrorWithFormat("Core file '%s' does not exist\n",
448                                          core_path);
449             result.SetStatus(eReturnStatusFailed);
450           }
451         } else {
452           result.AppendMessageWithFormat(
453               "Current executable set to '%s' (%s).\n", file_path,
454               target_sp->GetArchitecture().GetArchitectureName());
455           result.SetStatus(eReturnStatusSuccessFinishNoResult);
456         }
457       } else {
458         result.AppendError(error.AsCString());
459         result.SetStatus(eReturnStatusFailed);
460       }
461     } else {
462       result.AppendErrorWithFormat("'%s' takes exactly one executable path "
463                                    "argument, or use the --core option.\n",
464                                    m_cmd_name.c_str());
465       result.SetStatus(eReturnStatusFailed);
466     }
467     return result.Succeeded();
468   }
469 
470 private:
471   OptionGroupOptions m_option_group;
472   OptionGroupArchitecture m_arch_option;
473   OptionGroupFile m_core_file;
474   OptionGroupFile m_platform_path;
475   OptionGroupFile m_symbol_file;
476   OptionGroupFile m_remote_file;
477   OptionGroupDependents m_add_dependents;
478 };
479 
480 #pragma mark CommandObjectTargetList
481 
482 //----------------------------------------------------------------------
483 // "target list"
484 //----------------------------------------------------------------------
485 
486 class CommandObjectTargetList : public CommandObjectParsed {
487 public:
488   CommandObjectTargetList(CommandInterpreter &interpreter)
489       : CommandObjectParsed(
490             interpreter, "target list",
491             "List all current targets in the current debug session.", nullptr) {
492   }
493 
494   ~CommandObjectTargetList() override = default;
495 
496 protected:
497   bool DoExecute(Args &args, CommandReturnObject &result) override {
498     if (args.GetArgumentCount() == 0) {
499       Stream &strm = result.GetOutputStream();
500 
501       bool show_stopped_process_status = false;
502       if (DumpTargetList(m_interpreter.GetDebugger().GetTargetList(),
503                          show_stopped_process_status, strm) == 0) {
504         strm.PutCString("No targets.\n");
505       }
506       result.SetStatus(eReturnStatusSuccessFinishResult);
507     } else {
508       result.AppendError("the 'target list' command takes no arguments\n");
509       result.SetStatus(eReturnStatusFailed);
510     }
511     return result.Succeeded();
512   }
513 };
514 
515 #pragma mark CommandObjectTargetSelect
516 
517 //----------------------------------------------------------------------
518 // "target select"
519 //----------------------------------------------------------------------
520 
521 class CommandObjectTargetSelect : public CommandObjectParsed {
522 public:
523   CommandObjectTargetSelect(CommandInterpreter &interpreter)
524       : CommandObjectParsed(
525             interpreter, "target select",
526             "Select a target as the current target by target index.", nullptr) {
527   }
528 
529   ~CommandObjectTargetSelect() override = default;
530 
531 protected:
532   bool DoExecute(Args &args, CommandReturnObject &result) override {
533     if (args.GetArgumentCount() == 1) {
534       bool success = false;
535       const char *target_idx_arg = args.GetArgumentAtIndex(0);
536       uint32_t target_idx =
537           StringConvert::ToUInt32(target_idx_arg, UINT32_MAX, 0, &success);
538       if (success) {
539         TargetList &target_list = m_interpreter.GetDebugger().GetTargetList();
540         const uint32_t num_targets = target_list.GetNumTargets();
541         if (target_idx < num_targets) {
542           TargetSP target_sp(target_list.GetTargetAtIndex(target_idx));
543           if (target_sp) {
544             Stream &strm = result.GetOutputStream();
545             target_list.SetSelectedTarget(target_sp.get());
546             bool show_stopped_process_status = false;
547             DumpTargetList(target_list, show_stopped_process_status, strm);
548             result.SetStatus(eReturnStatusSuccessFinishResult);
549           } else {
550             result.AppendErrorWithFormat("target #%u is NULL in target list\n",
551                                          target_idx);
552             result.SetStatus(eReturnStatusFailed);
553           }
554         } else {
555           if (num_targets > 0) {
556             result.AppendErrorWithFormat(
557                 "index %u is out of range, valid target indexes are 0 - %u\n",
558                 target_idx, num_targets - 1);
559           } else {
560             result.AppendErrorWithFormat(
561                 "index %u is out of range since there are no active targets\n",
562                 target_idx);
563           }
564           result.SetStatus(eReturnStatusFailed);
565         }
566       } else {
567         result.AppendErrorWithFormat("invalid index string value '%s'\n",
568                                      target_idx_arg);
569         result.SetStatus(eReturnStatusFailed);
570       }
571     } else {
572       result.AppendError(
573           "'target select' takes a single argument: a target index\n");
574       result.SetStatus(eReturnStatusFailed);
575     }
576     return result.Succeeded();
577   }
578 };
579 
580 #pragma mark CommandObjectTargetSelect
581 
582 //----------------------------------------------------------------------
583 // "target delete"
584 //----------------------------------------------------------------------
585 
586 class CommandObjectTargetDelete : public CommandObjectParsed {
587 public:
588   CommandObjectTargetDelete(CommandInterpreter &interpreter)
589       : CommandObjectParsed(interpreter, "target delete",
590                             "Delete one or more targets by target index.",
591                             nullptr),
592         m_option_group(), m_all_option(LLDB_OPT_SET_1, false, "all", 'a',
593                                        "Delete all targets.", false, true),
594         m_cleanup_option(
595             LLDB_OPT_SET_1, false, "clean", 'c',
596             "Perform extra cleanup to minimize memory consumption after "
597             "deleting the target.  "
598             "By default, LLDB will keep in memory any modules previously "
599             "loaded by the target as well "
600             "as all of its debug info.  Specifying --clean will unload all of "
601             "these shared modules and "
602             "cause them to be reparsed again the next time the target is run",
603             false, true) {
604     m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
605     m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
606     m_option_group.Finalize();
607   }
608 
609   ~CommandObjectTargetDelete() override = default;
610 
611   Options *GetOptions() override { return &m_option_group; }
612 
613 protected:
614   bool DoExecute(Args &args, CommandReturnObject &result) override {
615     const size_t argc = args.GetArgumentCount();
616     std::vector<TargetSP> delete_target_list;
617     TargetList &target_list = m_interpreter.GetDebugger().GetTargetList();
618     TargetSP target_sp;
619 
620     if (m_all_option.GetOptionValue()) {
621       for (int i = 0; i < target_list.GetNumTargets(); ++i)
622         delete_target_list.push_back(target_list.GetTargetAtIndex(i));
623     } else if (argc > 0) {
624       const uint32_t num_targets = target_list.GetNumTargets();
625       // Bail out if don't have any targets.
626       if (num_targets == 0) {
627         result.AppendError("no targets to delete");
628         result.SetStatus(eReturnStatusFailed);
629         return false;
630       }
631 
632       for (auto &entry : args.entries()) {
633         uint32_t target_idx;
634         if (entry.ref.getAsInteger(0, target_idx)) {
635           result.AppendErrorWithFormat("invalid target index '%s'\n",
636                                        entry.c_str());
637           result.SetStatus(eReturnStatusFailed);
638           return false;
639         }
640         if (target_idx < num_targets) {
641           target_sp = target_list.GetTargetAtIndex(target_idx);
642           if (target_sp) {
643             delete_target_list.push_back(target_sp);
644             continue;
645           }
646         }
647         if (num_targets > 1)
648           result.AppendErrorWithFormat("target index %u is out of range, valid "
649                                        "target indexes are 0 - %u\n",
650                                        target_idx, num_targets - 1);
651         else
652           result.AppendErrorWithFormat(
653               "target index %u is out of range, the only valid index is 0\n",
654               target_idx);
655 
656         result.SetStatus(eReturnStatusFailed);
657         return false;
658       }
659     } else {
660       target_sp = target_list.GetSelectedTarget();
661       if (!target_sp) {
662         result.AppendErrorWithFormat("no target is currently selected\n");
663         result.SetStatus(eReturnStatusFailed);
664         return false;
665       }
666       delete_target_list.push_back(target_sp);
667     }
668 
669     const size_t num_targets_to_delete = delete_target_list.size();
670     for (size_t idx = 0; idx < num_targets_to_delete; ++idx) {
671       target_sp = delete_target_list[idx];
672       target_list.DeleteTarget(target_sp);
673       target_sp->Destroy();
674     }
675     // If "--clean" was specified, prune any orphaned shared modules from the
676     // global shared module list
677     if (m_cleanup_option.GetOptionValue()) {
678       const bool mandatory = true;
679       ModuleList::RemoveOrphanSharedModules(mandatory);
680     }
681     result.GetOutputStream().Printf("%u targets deleted.\n",
682                                     (uint32_t)num_targets_to_delete);
683     result.SetStatus(eReturnStatusSuccessFinishResult);
684 
685     return true;
686   }
687 
688   OptionGroupOptions m_option_group;
689   OptionGroupBoolean m_all_option;
690   OptionGroupBoolean m_cleanup_option;
691 };
692 
693 #pragma mark CommandObjectTargetVariable
694 
695 //----------------------------------------------------------------------
696 // "target variable"
697 //----------------------------------------------------------------------
698 
699 class CommandObjectTargetVariable : public CommandObjectParsed {
700   static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
701   static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'
702 
703 public:
704   CommandObjectTargetVariable(CommandInterpreter &interpreter)
705       : CommandObjectParsed(interpreter, "target variable",
706                             "Read global variables for the current target, "
707                             "before or while running a process.",
708                             nullptr, eCommandRequiresTarget),
709         m_option_group(),
710         m_option_variable(false), // Don't include frame options
711         m_option_format(eFormatDefault),
712         m_option_compile_units(LLDB_OPT_SET_1, false, "file", SHORT_OPTION_FILE,
713                                0, eArgTypeFilename,
714                                "A basename or fullpath to a file that contains "
715                                "global variables. This option can be "
716                                "specified multiple times."),
717         m_option_shared_libraries(
718             LLDB_OPT_SET_1, false, "shlib", SHORT_OPTION_SHLB, 0,
719             eArgTypeFilename,
720             "A basename or fullpath to a shared library to use in the search "
721             "for global "
722             "variables. This option can be specified multiple times."),
723         m_varobj_options() {
724     CommandArgumentEntry arg;
725     CommandArgumentData var_name_arg;
726 
727     // Define the first (and only) variant of this arg.
728     var_name_arg.arg_type = eArgTypeVarName;
729     var_name_arg.arg_repetition = eArgRepeatPlus;
730 
731     // There is only one variant this argument could be; put it into the
732     // argument entry.
733     arg.push_back(var_name_arg);
734 
735     // Push the data for the first argument into the m_arguments vector.
736     m_arguments.push_back(arg);
737 
738     m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
739     m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
740     m_option_group.Append(&m_option_format,
741                           OptionGroupFormat::OPTION_GROUP_FORMAT |
742                               OptionGroupFormat::OPTION_GROUP_GDB_FMT,
743                           LLDB_OPT_SET_1);
744     m_option_group.Append(&m_option_compile_units, LLDB_OPT_SET_ALL,
745                           LLDB_OPT_SET_1);
746     m_option_group.Append(&m_option_shared_libraries, LLDB_OPT_SET_ALL,
747                           LLDB_OPT_SET_1);
748     m_option_group.Finalize();
749   }
750 
751   ~CommandObjectTargetVariable() override = default;
752 
753   void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp,
754                        const char *root_name) {
755     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
756 
757     if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() &&
758         valobj_sp->IsRuntimeSupportValue())
759       return;
760 
761     switch (var_sp->GetScope()) {
762     case eValueTypeVariableGlobal:
763       if (m_option_variable.show_scope)
764         s.PutCString("GLOBAL: ");
765       break;
766 
767     case eValueTypeVariableStatic:
768       if (m_option_variable.show_scope)
769         s.PutCString("STATIC: ");
770       break;
771 
772     case eValueTypeVariableArgument:
773       if (m_option_variable.show_scope)
774         s.PutCString("   ARG: ");
775       break;
776 
777     case eValueTypeVariableLocal:
778       if (m_option_variable.show_scope)
779         s.PutCString(" LOCAL: ");
780       break;
781 
782     case eValueTypeVariableThreadLocal:
783       if (m_option_variable.show_scope)
784         s.PutCString("THREAD: ");
785       break;
786 
787     default:
788       break;
789     }
790 
791     if (m_option_variable.show_decl) {
792       bool show_fullpaths = false;
793       bool show_module = true;
794       if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
795         s.PutCString(": ");
796     }
797 
798     const Format format = m_option_format.GetFormat();
799     if (format != eFormatDefault)
800       options.SetFormat(format);
801 
802     options.SetRootValueObjectName(root_name);
803 
804     valobj_sp->Dump(s, options);
805   }
806 
807   static size_t GetVariableCallback(void *baton, const char *name,
808                                     VariableList &variable_list) {
809     Target *target = static_cast<Target *>(baton);
810     if (target) {
811       return target->GetImages().FindGlobalVariables(ConstString(name),
812                                                      UINT32_MAX, variable_list);
813     }
814     return 0;
815   }
816 
817   Options *GetOptions() override { return &m_option_group; }
818 
819 protected:
820   void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
821                               const SymbolContext &sc,
822                               const VariableList &variable_list, Stream &s) {
823     size_t count = variable_list.GetSize();
824     if (count > 0) {
825       if (sc.module_sp) {
826         if (sc.comp_unit) {
827           s.Printf("Global variables for %s in %s:\n",
828                    sc.comp_unit->GetPath().c_str(),
829                    sc.module_sp->GetFileSpec().GetPath().c_str());
830         } else {
831           s.Printf("Global variables for %s\n",
832                    sc.module_sp->GetFileSpec().GetPath().c_str());
833         }
834       } else if (sc.comp_unit) {
835         s.Printf("Global variables for %s\n", sc.comp_unit->GetPath().c_str());
836       }
837 
838       for (uint32_t i = 0; i < count; ++i) {
839         VariableSP var_sp(variable_list.GetVariableAtIndex(i));
840         if (var_sp) {
841           ValueObjectSP valobj_sp(ValueObjectVariable::Create(
842               exe_ctx.GetBestExecutionContextScope(), var_sp));
843 
844           if (valobj_sp)
845             DumpValueObject(s, var_sp, valobj_sp,
846                             var_sp->GetName().GetCString());
847         }
848       }
849     }
850   }
851 
852   bool DoExecute(Args &args, CommandReturnObject &result) override {
853     Target *target = m_exe_ctx.GetTargetPtr();
854     const size_t argc = args.GetArgumentCount();
855     Stream &s = result.GetOutputStream();
856 
857     if (argc > 0) {
858 
859       // TODO: Convert to entry-based iteration.  Requires converting
860       // DumpValueObject.
861       for (size_t idx = 0; idx < argc; ++idx) {
862         VariableList variable_list;
863         ValueObjectList valobj_list;
864 
865         const char *arg = args.GetArgumentAtIndex(idx);
866         size_t matches = 0;
867         bool use_var_name = false;
868         if (m_option_variable.use_regex) {
869           RegularExpression regex(llvm::StringRef::withNullAsEmpty(arg));
870           if (!regex.IsValid()) {
871             result.GetErrorStream().Printf(
872                 "error: invalid regular expression: '%s'\n", arg);
873             result.SetStatus(eReturnStatusFailed);
874             return false;
875           }
876           use_var_name = true;
877           matches = target->GetImages().FindGlobalVariables(regex, UINT32_MAX,
878                                                             variable_list);
879         } else {
880           Status error(Variable::GetValuesForVariableExpressionPath(
881               arg, m_exe_ctx.GetBestExecutionContextScope(),
882               GetVariableCallback, target, variable_list, valobj_list));
883           matches = variable_list.GetSize();
884         }
885 
886         if (matches == 0) {
887           result.GetErrorStream().Printf(
888               "error: can't find global variable '%s'\n", arg);
889           result.SetStatus(eReturnStatusFailed);
890           return false;
891         } else {
892           for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) {
893             VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx));
894             if (var_sp) {
895               ValueObjectSP valobj_sp(
896                   valobj_list.GetValueObjectAtIndex(global_idx));
897               if (!valobj_sp)
898                 valobj_sp = ValueObjectVariable::Create(
899                     m_exe_ctx.GetBestExecutionContextScope(), var_sp);
900 
901               if (valobj_sp)
902                 DumpValueObject(s, var_sp, valobj_sp,
903                                 use_var_name ? var_sp->GetName().GetCString()
904                                              : arg);
905             }
906           }
907         }
908       }
909     } else {
910       const FileSpecList &compile_units =
911           m_option_compile_units.GetOptionValue().GetCurrentValue();
912       const FileSpecList &shlibs =
913           m_option_shared_libraries.GetOptionValue().GetCurrentValue();
914       SymbolContextList sc_list;
915       const size_t num_compile_units = compile_units.GetSize();
916       const size_t num_shlibs = shlibs.GetSize();
917       if (num_compile_units == 0 && num_shlibs == 0) {
918         bool success = false;
919         StackFrame *frame = m_exe_ctx.GetFramePtr();
920         CompileUnit *comp_unit = nullptr;
921         if (frame) {
922           SymbolContext sc = frame->GetSymbolContext(eSymbolContextCompUnit);
923           if (sc.comp_unit) {
924             const bool can_create = true;
925             VariableListSP comp_unit_varlist_sp(
926                 sc.comp_unit->GetVariableList(can_create));
927             if (comp_unit_varlist_sp) {
928               size_t count = comp_unit_varlist_sp->GetSize();
929               if (count > 0) {
930                 DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
931                 success = true;
932               }
933             }
934           }
935         }
936         if (!success) {
937           if (frame) {
938             if (comp_unit)
939               result.AppendErrorWithFormat(
940                   "no global variables in current compile unit: %s\n",
941                   comp_unit->GetPath().c_str());
942             else
943               result.AppendErrorWithFormat(
944                   "no debug information for frame %u\n",
945                   frame->GetFrameIndex());
946           } else
947             result.AppendError("'target variable' takes one or more global "
948                                "variable names as arguments\n");
949           result.SetStatus(eReturnStatusFailed);
950         }
951       } else {
952         SymbolContextList sc_list;
953         const bool append = true;
954         // We have one or more compile unit or shlib
955         if (num_shlibs > 0) {
956           for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) {
957             const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
958             ModuleSpec module_spec(module_file);
959 
960             ModuleSP module_sp(
961                 target->GetImages().FindFirstModule(module_spec));
962             if (module_sp) {
963               if (num_compile_units > 0) {
964                 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
965                   module_sp->FindCompileUnits(
966                       compile_units.GetFileSpecAtIndex(cu_idx), append,
967                       sc_list);
968               } else {
969                 SymbolContext sc;
970                 sc.module_sp = module_sp;
971                 sc_list.Append(sc);
972               }
973             } else {
974               // Didn't find matching shlib/module in target...
975               result.AppendErrorWithFormat(
976                   "target doesn't contain the specified shared library: %s\n",
977                   module_file.GetPath().c_str());
978             }
979           }
980         } else {
981           // No shared libraries, we just want to find globals for the compile
982           // units files that were specified
983           for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
984             target->GetImages().FindCompileUnits(
985                 compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
986         }
987 
988         const uint32_t num_scs = sc_list.GetSize();
989         if (num_scs > 0) {
990           SymbolContext sc;
991           for (uint32_t sc_idx = 0; sc_idx < num_scs; ++sc_idx) {
992             if (sc_list.GetContextAtIndex(sc_idx, sc)) {
993               if (sc.comp_unit) {
994                 const bool can_create = true;
995                 VariableListSP comp_unit_varlist_sp(
996                     sc.comp_unit->GetVariableList(can_create));
997                 if (comp_unit_varlist_sp)
998                   DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
999                                          s);
1000               } else if (sc.module_sp) {
1001                 // Get all global variables for this module
1002                 lldb_private::RegularExpression all_globals_regex(
1003                     llvm::StringRef(
1004                         ".")); // Any global with at least one character
1005                 VariableList variable_list;
1006                 sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX,
1007                                                   variable_list);
1008                 DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
1009               }
1010             }
1011           }
1012         }
1013       }
1014     }
1015 
1016     if (m_interpreter.TruncationWarningNecessary()) {
1017       result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
1018                                       m_cmd_name.c_str());
1019       m_interpreter.TruncationWarningGiven();
1020     }
1021 
1022     return result.Succeeded();
1023   }
1024 
1025   OptionGroupOptions m_option_group;
1026   OptionGroupVariable m_option_variable;
1027   OptionGroupFormat m_option_format;
1028   OptionGroupFileList m_option_compile_units;
1029   OptionGroupFileList m_option_shared_libraries;
1030   OptionGroupValueObjectDisplay m_varobj_options;
1031 };
1032 
1033 #pragma mark CommandObjectTargetModulesSearchPathsAdd
1034 
1035 class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed {
1036 public:
1037   CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter &interpreter)
1038       : CommandObjectParsed(interpreter, "target modules search-paths add",
1039                             "Add new image search paths substitution pairs to "
1040                             "the current target.",
1041                             nullptr) {
1042     CommandArgumentEntry arg;
1043     CommandArgumentData old_prefix_arg;
1044     CommandArgumentData new_prefix_arg;
1045 
1046     // Define the first variant of this arg pair.
1047     old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1048     old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1049 
1050     // Define the first variant of this arg pair.
1051     new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1052     new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1053 
1054     // There are two required arguments that must always occur together, i.e.
1055     // an argument "pair".  Because they must always occur together, they are
1056     // treated as two variants of one argument rather than two independent
1057     // arguments.  Push them both into the first argument position for
1058     // m_arguments...
1059 
1060     arg.push_back(old_prefix_arg);
1061     arg.push_back(new_prefix_arg);
1062 
1063     m_arguments.push_back(arg);
1064   }
1065 
1066   ~CommandObjectTargetModulesSearchPathsAdd() override = default;
1067 
1068 protected:
1069   bool DoExecute(Args &command, CommandReturnObject &result) override {
1070     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1071     if (target) {
1072       const size_t argc = command.GetArgumentCount();
1073       if (argc & 1) {
1074         result.AppendError("add requires an even number of arguments\n");
1075         result.SetStatus(eReturnStatusFailed);
1076       } else {
1077         for (size_t i = 0; i < argc; i += 2) {
1078           const char *from = command.GetArgumentAtIndex(i);
1079           const char *to = command.GetArgumentAtIndex(i + 1);
1080 
1081           if (from[0] && to[0]) {
1082             Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
1083             if (log) {
1084               log->Printf("target modules search path adding ImageSearchPath "
1085                           "pair: '%s' -> '%s'",
1086                           from, to);
1087             }
1088             bool last_pair = ((argc - i) == 2);
1089             target->GetImageSearchPathList().Append(
1090                 ConstString(from), ConstString(to),
1091                 last_pair); // Notify if this is the last pair
1092             result.SetStatus(eReturnStatusSuccessFinishNoResult);
1093           } else {
1094             if (from[0])
1095               result.AppendError("<path-prefix> can't be empty\n");
1096             else
1097               result.AppendError("<new-path-prefix> can't be empty\n");
1098             result.SetStatus(eReturnStatusFailed);
1099           }
1100         }
1101       }
1102     } else {
1103       result.AppendError("invalid target\n");
1104       result.SetStatus(eReturnStatusFailed);
1105     }
1106     return result.Succeeded();
1107   }
1108 };
1109 
1110 #pragma mark CommandObjectTargetModulesSearchPathsClear
1111 
1112 class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed {
1113 public:
1114   CommandObjectTargetModulesSearchPathsClear(CommandInterpreter &interpreter)
1115       : CommandObjectParsed(interpreter, "target modules search-paths clear",
1116                             "Clear all current image search path substitution "
1117                             "pairs from the current target.",
1118                             "target modules search-paths clear") {}
1119 
1120   ~CommandObjectTargetModulesSearchPathsClear() override = default;
1121 
1122 protected:
1123   bool DoExecute(Args &command, CommandReturnObject &result) override {
1124     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1125     if (target) {
1126       bool notify = true;
1127       target->GetImageSearchPathList().Clear(notify);
1128       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1129     } else {
1130       result.AppendError("invalid target\n");
1131       result.SetStatus(eReturnStatusFailed);
1132     }
1133     return result.Succeeded();
1134   }
1135 };
1136 
1137 #pragma mark CommandObjectTargetModulesSearchPathsInsert
1138 
1139 class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed {
1140 public:
1141   CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter &interpreter)
1142       : CommandObjectParsed(interpreter, "target modules search-paths insert",
1143                             "Insert a new image search path substitution pair "
1144                             "into the current target at the specified index.",
1145                             nullptr) {
1146     CommandArgumentEntry arg1;
1147     CommandArgumentEntry arg2;
1148     CommandArgumentData index_arg;
1149     CommandArgumentData old_prefix_arg;
1150     CommandArgumentData new_prefix_arg;
1151 
1152     // Define the first and only variant of this arg.
1153     index_arg.arg_type = eArgTypeIndex;
1154     index_arg.arg_repetition = eArgRepeatPlain;
1155 
1156     // Put the one and only variant into the first arg for m_arguments:
1157     arg1.push_back(index_arg);
1158 
1159     // Define the first variant of this arg pair.
1160     old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1161     old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1162 
1163     // Define the first variant of this arg pair.
1164     new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1165     new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1166 
1167     // There are two required arguments that must always occur together, i.e.
1168     // an argument "pair".  Because they must always occur together, they are
1169     // treated as two variants of one argument rather than two independent
1170     // arguments.  Push them both into the same argument position for
1171     // m_arguments...
1172 
1173     arg2.push_back(old_prefix_arg);
1174     arg2.push_back(new_prefix_arg);
1175 
1176     // Add arguments to m_arguments.
1177     m_arguments.push_back(arg1);
1178     m_arguments.push_back(arg2);
1179   }
1180 
1181   ~CommandObjectTargetModulesSearchPathsInsert() override = default;
1182 
1183 protected:
1184   bool DoExecute(Args &command, CommandReturnObject &result) override {
1185     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1186     if (target) {
1187       size_t argc = command.GetArgumentCount();
1188       // check for at least 3 arguments and an odd number of parameters
1189       if (argc >= 3 && argc & 1) {
1190         bool success = false;
1191 
1192         uint32_t insert_idx = StringConvert::ToUInt32(
1193             command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
1194 
1195         if (!success) {
1196           result.AppendErrorWithFormat(
1197               "<index> parameter is not an integer: '%s'.\n",
1198               command.GetArgumentAtIndex(0));
1199           result.SetStatus(eReturnStatusFailed);
1200           return result.Succeeded();
1201         }
1202 
1203         // shift off the index
1204         command.Shift();
1205         argc = command.GetArgumentCount();
1206 
1207         for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) {
1208           const char *from = command.GetArgumentAtIndex(i);
1209           const char *to = command.GetArgumentAtIndex(i + 1);
1210 
1211           if (from[0] && to[0]) {
1212             bool last_pair = ((argc - i) == 2);
1213             target->GetImageSearchPathList().Insert(
1214                 ConstString(from), ConstString(to), insert_idx, last_pair);
1215             result.SetStatus(eReturnStatusSuccessFinishNoResult);
1216           } else {
1217             if (from[0])
1218               result.AppendError("<path-prefix> can't be empty\n");
1219             else
1220               result.AppendError("<new-path-prefix> can't be empty\n");
1221             result.SetStatus(eReturnStatusFailed);
1222             return false;
1223           }
1224         }
1225       } else {
1226         result.AppendError("insert requires at least three arguments\n");
1227         result.SetStatus(eReturnStatusFailed);
1228         return result.Succeeded();
1229       }
1230 
1231     } else {
1232       result.AppendError("invalid target\n");
1233       result.SetStatus(eReturnStatusFailed);
1234     }
1235     return result.Succeeded();
1236   }
1237 };
1238 
1239 #pragma mark CommandObjectTargetModulesSearchPathsList
1240 
1241 class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed {
1242 public:
1243   CommandObjectTargetModulesSearchPathsList(CommandInterpreter &interpreter)
1244       : CommandObjectParsed(interpreter, "target modules search-paths list",
1245                             "List all current image search path substitution "
1246                             "pairs in the current target.",
1247                             "target modules search-paths list") {}
1248 
1249   ~CommandObjectTargetModulesSearchPathsList() override = default;
1250 
1251 protected:
1252   bool DoExecute(Args &command, CommandReturnObject &result) override {
1253     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1254     if (target) {
1255       if (command.GetArgumentCount() != 0) {
1256         result.AppendError("list takes no arguments\n");
1257         result.SetStatus(eReturnStatusFailed);
1258         return result.Succeeded();
1259       }
1260 
1261       target->GetImageSearchPathList().Dump(&result.GetOutputStream());
1262       result.SetStatus(eReturnStatusSuccessFinishResult);
1263     } else {
1264       result.AppendError("invalid target\n");
1265       result.SetStatus(eReturnStatusFailed);
1266     }
1267     return result.Succeeded();
1268   }
1269 };
1270 
1271 #pragma mark CommandObjectTargetModulesSearchPathsQuery
1272 
1273 class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed {
1274 public:
1275   CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter &interpreter)
1276       : CommandObjectParsed(
1277             interpreter, "target modules search-paths query",
1278             "Transform a path using the first applicable image search path.",
1279             nullptr) {
1280     CommandArgumentEntry arg;
1281     CommandArgumentData path_arg;
1282 
1283     // Define the first (and only) variant of this arg.
1284     path_arg.arg_type = eArgTypeDirectoryName;
1285     path_arg.arg_repetition = eArgRepeatPlain;
1286 
1287     // There is only one variant this argument could be; put it into the
1288     // argument entry.
1289     arg.push_back(path_arg);
1290 
1291     // Push the data for the first argument into the m_arguments vector.
1292     m_arguments.push_back(arg);
1293   }
1294 
1295   ~CommandObjectTargetModulesSearchPathsQuery() override = default;
1296 
1297 protected:
1298   bool DoExecute(Args &command, CommandReturnObject &result) override {
1299     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1300     if (target) {
1301       if (command.GetArgumentCount() != 1) {
1302         result.AppendError("query requires one argument\n");
1303         result.SetStatus(eReturnStatusFailed);
1304         return result.Succeeded();
1305       }
1306 
1307       ConstString orig(command.GetArgumentAtIndex(0));
1308       ConstString transformed;
1309       if (target->GetImageSearchPathList().RemapPath(orig, transformed))
1310         result.GetOutputStream().Printf("%s\n", transformed.GetCString());
1311       else
1312         result.GetOutputStream().Printf("%s\n", orig.GetCString());
1313 
1314       result.SetStatus(eReturnStatusSuccessFinishResult);
1315     } else {
1316       result.AppendError("invalid target\n");
1317       result.SetStatus(eReturnStatusFailed);
1318     }
1319     return result.Succeeded();
1320   }
1321 };
1322 
1323 //----------------------------------------------------------------------
1324 // Static Helper functions
1325 //----------------------------------------------------------------------
1326 static void DumpModuleArchitecture(Stream &strm, Module *module,
1327                                    bool full_triple, uint32_t width) {
1328   if (module) {
1329     StreamString arch_strm;
1330 
1331     if (full_triple)
1332       module->GetArchitecture().DumpTriple(arch_strm);
1333     else
1334       arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
1335     std::string arch_str = arch_strm.GetString();
1336 
1337     if (width)
1338       strm.Printf("%-*s", width, arch_str.c_str());
1339     else
1340       strm.PutCString(arch_str);
1341   }
1342 }
1343 
1344 static void DumpModuleUUID(Stream &strm, Module *module) {
1345   if (module && module->GetUUID().IsValid())
1346     module->GetUUID().Dump(&strm);
1347   else
1348     strm.PutCString("                                    ");
1349 }
1350 
1351 static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
1352                                          Stream &strm, Module *module,
1353                                          const FileSpec &file_spec,
1354                                          bool load_addresses) {
1355   uint32_t num_matches = 0;
1356   if (module) {
1357     SymbolContextList sc_list;
1358     num_matches = module->ResolveSymbolContextsForFileSpec(
1359         file_spec, 0, false, eSymbolContextCompUnit, sc_list);
1360 
1361     for (uint32_t i = 0; i < num_matches; ++i) {
1362       SymbolContext sc;
1363       if (sc_list.GetContextAtIndex(i, sc)) {
1364         if (i > 0)
1365           strm << "\n\n";
1366 
1367         strm << "Line table for " << *static_cast<FileSpec *>(sc.comp_unit)
1368              << " in `" << module->GetFileSpec().GetFilename() << "\n";
1369         LineTable *line_table = sc.comp_unit->GetLineTable();
1370         if (line_table)
1371           line_table->GetDescription(
1372               &strm, interpreter.GetExecutionContext().GetTargetPtr(),
1373               lldb::eDescriptionLevelBrief);
1374         else
1375           strm << "No line table";
1376       }
1377     }
1378   }
1379   return num_matches;
1380 }
1381 
1382 static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr,
1383                          uint32_t width) {
1384   if (file_spec_ptr) {
1385     if (width > 0) {
1386       std::string fullpath = file_spec_ptr->GetPath();
1387       strm.Printf("%-*s", width, fullpath.c_str());
1388       return;
1389     } else {
1390       file_spec_ptr->Dump(&strm);
1391       return;
1392     }
1393   }
1394   // Keep the width spacing correct if things go wrong...
1395   if (width > 0)
1396     strm.Printf("%-*s", width, "");
1397 }
1398 
1399 static void DumpDirectory(Stream &strm, const FileSpec *file_spec_ptr,
1400                           uint32_t width) {
1401   if (file_spec_ptr) {
1402     if (width > 0)
1403       strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
1404     else
1405       file_spec_ptr->GetDirectory().Dump(&strm);
1406     return;
1407   }
1408   // Keep the width spacing correct if things go wrong...
1409   if (width > 0)
1410     strm.Printf("%-*s", width, "");
1411 }
1412 
1413 static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr,
1414                          uint32_t width) {
1415   if (file_spec_ptr) {
1416     if (width > 0)
1417       strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
1418     else
1419       file_spec_ptr->GetFilename().Dump(&strm);
1420     return;
1421   }
1422   // Keep the width spacing correct if things go wrong...
1423   if (width > 0)
1424     strm.Printf("%-*s", width, "");
1425 }
1426 
1427 static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
1428   size_t num_dumped = 0;
1429   std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
1430   const size_t num_modules = module_list.GetSize();
1431   if (num_modules > 0) {
1432     strm.Printf("Dumping headers for %" PRIu64 " module(s).\n",
1433                 static_cast<uint64_t>(num_modules));
1434     strm.IndentMore();
1435     for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1436       Module *module = module_list.GetModulePointerAtIndexUnlocked(image_idx);
1437       if (module) {
1438         if (num_dumped++ > 0) {
1439           strm.EOL();
1440           strm.EOL();
1441         }
1442         ObjectFile *objfile = module->GetObjectFile();
1443         if (objfile)
1444           objfile->Dump(&strm);
1445         else {
1446           strm.Format("No object file for module: {0:F}\n",
1447                       module->GetFileSpec());
1448         }
1449       }
1450     }
1451     strm.IndentLess();
1452   }
1453   return num_dumped;
1454 }
1455 
1456 static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
1457                              Module *module, SortOrder sort_order) {
1458   if (module) {
1459     SymbolVendor *sym_vendor = module->GetSymbolVendor();
1460     if (sym_vendor) {
1461       Symtab *symtab = sym_vendor->GetSymtab();
1462       if (symtab)
1463         symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
1464                      sort_order);
1465     }
1466   }
1467 }
1468 
1469 static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,
1470                                Module *module) {
1471   if (module) {
1472     SectionList *section_list = module->GetSectionList();
1473     if (section_list) {
1474       strm.Printf("Sections for '%s' (%s):\n",
1475                   module->GetSpecificationDescription().c_str(),
1476                   module->GetArchitecture().GetArchitectureName());
1477       strm.IndentMore();
1478       section_list->Dump(&strm,
1479                          interpreter.GetExecutionContext().GetTargetPtr(), true,
1480                          UINT32_MAX);
1481       strm.IndentLess();
1482     }
1483   }
1484 }
1485 
1486 static bool DumpModuleSymbolVendor(Stream &strm, Module *module) {
1487   if (module) {
1488     SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
1489     if (symbol_vendor) {
1490       symbol_vendor->Dump(&strm);
1491       return true;
1492     }
1493   }
1494   return false;
1495 }
1496 
1497 static void DumpAddress(ExecutionContextScope *exe_scope,
1498                         const Address &so_addr, bool verbose, Stream &strm) {
1499   strm.IndentMore();
1500   strm.Indent("    Address: ");
1501   so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
1502   strm.PutCString(" (");
1503   so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset);
1504   strm.PutCString(")\n");
1505   strm.Indent("    Summary: ");
1506   const uint32_t save_indent = strm.GetIndentLevel();
1507   strm.SetIndentLevel(save_indent + 13);
1508   so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription);
1509   strm.SetIndentLevel(save_indent);
1510   // Print out detailed address information when verbose is enabled
1511   if (verbose) {
1512     strm.EOL();
1513     so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext);
1514   }
1515   strm.IndentLess();
1516 }
1517 
1518 static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
1519                                   Module *module, uint32_t resolve_mask,
1520                                   lldb::addr_t raw_addr, lldb::addr_t offset,
1521                                   bool verbose) {
1522   if (module) {
1523     lldb::addr_t addr = raw_addr - offset;
1524     Address so_addr;
1525     SymbolContext sc;
1526     Target *target = interpreter.GetExecutionContext().GetTargetPtr();
1527     if (target && !target->GetSectionLoadList().IsEmpty()) {
1528       if (!target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
1529         return false;
1530       else if (so_addr.GetModule().get() != module)
1531         return false;
1532     } else {
1533       if (!module->ResolveFileAddress(addr, so_addr))
1534         return false;
1535     }
1536 
1537     ExecutionContextScope *exe_scope =
1538         interpreter.GetExecutionContext().GetBestExecutionContextScope();
1539     DumpAddress(exe_scope, so_addr, verbose, strm);
1540     //        strm.IndentMore();
1541     //        strm.Indent ("    Address: ");
1542     //        so_addr.Dump (&strm, exe_scope,
1543     //        Address::DumpStyleModuleWithFileAddress);
1544     //        strm.PutCString (" (");
1545     //        so_addr.Dump (&strm, exe_scope,
1546     //        Address::DumpStyleSectionNameOffset);
1547     //        strm.PutCString (")\n");
1548     //        strm.Indent ("    Summary: ");
1549     //        const uint32_t save_indent = strm.GetIndentLevel ();
1550     //        strm.SetIndentLevel (save_indent + 13);
1551     //        so_addr.Dump (&strm, exe_scope,
1552     //        Address::DumpStyleResolvedDescription);
1553     //        strm.SetIndentLevel (save_indent);
1554     //        // Print out detailed address information when verbose is enabled
1555     //        if (verbose)
1556     //        {
1557     //            strm.EOL();
1558     //            so_addr.Dump (&strm, exe_scope,
1559     //            Address::DumpStyleDetailedSymbolContext);
1560     //        }
1561     //        strm.IndentLess();
1562     return true;
1563   }
1564 
1565   return false;
1566 }
1567 
1568 static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
1569                                      Stream &strm, Module *module,
1570                                      const char *name, bool name_is_regex,
1571                                      bool verbose) {
1572   if (module) {
1573     SymbolContext sc;
1574 
1575     SymbolVendor *sym_vendor = module->GetSymbolVendor();
1576     if (sym_vendor) {
1577       Symtab *symtab = sym_vendor->GetSymtab();
1578       if (symtab) {
1579         std::vector<uint32_t> match_indexes;
1580         ConstString symbol_name(name);
1581         uint32_t num_matches = 0;
1582         if (name_is_regex) {
1583           RegularExpression name_regexp(symbol_name.GetStringRef());
1584           num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType(
1585               name_regexp, eSymbolTypeAny, match_indexes);
1586         } else {
1587           num_matches =
1588               symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes);
1589         }
1590 
1591         if (num_matches > 0) {
1592           strm.Indent();
1593           strm.Printf("%u symbols match %s'%s' in ", num_matches,
1594                       name_is_regex ? "the regular expression " : "", name);
1595           DumpFullpath(strm, &module->GetFileSpec(), 0);
1596           strm.PutCString(":\n");
1597           strm.IndentMore();
1598           for (uint32_t i = 0; i < num_matches; ++i) {
1599             Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
1600             if (symbol && symbol->ValueIsAddress()) {
1601               DumpAddress(interpreter.GetExecutionContext()
1602                               .GetBestExecutionContextScope(),
1603                           symbol->GetAddressRef(), verbose, strm);
1604             }
1605           }
1606           strm.IndentLess();
1607           return num_matches;
1608         }
1609       }
1610     }
1611   }
1612   return 0;
1613 }
1614 
1615 static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
1616                                   Stream &strm, SymbolContextList &sc_list,
1617                                   bool verbose) {
1618   strm.IndentMore();
1619 
1620   const uint32_t num_matches = sc_list.GetSize();
1621 
1622   for (uint32_t i = 0; i < num_matches; ++i) {
1623     SymbolContext sc;
1624     if (sc_list.GetContextAtIndex(i, sc)) {
1625       AddressRange range;
1626 
1627       sc.GetAddressRange(eSymbolContextEverything, 0, true, range);
1628 
1629       DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm);
1630     }
1631   }
1632   strm.IndentLess();
1633 }
1634 
1635 static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
1636                                      Stream &strm, Module *module,
1637                                      const char *name, bool name_is_regex,
1638                                      bool include_inlines, bool include_symbols,
1639                                      bool verbose) {
1640   if (module && name && name[0]) {
1641     SymbolContextList sc_list;
1642     const bool append = true;
1643     size_t num_matches = 0;
1644     if (name_is_regex) {
1645       RegularExpression function_name_regex((llvm::StringRef(name)));
1646       num_matches = module->FindFunctions(function_name_regex, include_symbols,
1647                                           include_inlines, append, sc_list);
1648     } else {
1649       ConstString function_name(name);
1650       num_matches = module->FindFunctions(
1651           function_name, nullptr, eFunctionNameTypeAuto, include_symbols,
1652           include_inlines, append, sc_list);
1653     }
1654 
1655     if (num_matches) {
1656       strm.Indent();
1657       strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1658                   num_matches > 1 ? "es" : "");
1659       DumpFullpath(strm, &module->GetFileSpec(), 0);
1660       strm.PutCString(":\n");
1661       DumpSymbolContextList(
1662           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1663           strm, sc_list, verbose);
1664     }
1665     return num_matches;
1666   }
1667   return 0;
1668 }
1669 
1670 static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
1671                                  Module *module, const char *name_cstr,
1672                                  bool name_is_regex) {
1673   if (module && name_cstr && name_cstr[0]) {
1674     TypeList type_list;
1675     const uint32_t max_num_matches = UINT32_MAX;
1676     size_t num_matches = 0;
1677     bool name_is_fully_qualified = false;
1678     SymbolContext sc;
1679 
1680     ConstString name(name_cstr);
1681     llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
1682     num_matches =
1683         module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches,
1684                           searched_symbol_files, type_list);
1685 
1686     if (num_matches) {
1687       strm.Indent();
1688       strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1689                   num_matches > 1 ? "es" : "");
1690       DumpFullpath(strm, &module->GetFileSpec(), 0);
1691       strm.PutCString(":\n");
1692       for (TypeSP type_sp : type_list.Types()) {
1693         if (type_sp) {
1694           // Resolve the clang type so that any forward references to types
1695           // that haven't yet been parsed will get parsed.
1696           type_sp->GetFullCompilerType();
1697           type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1698           // Print all typedef chains
1699           TypeSP typedef_type_sp(type_sp);
1700           TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1701           while (typedefed_type_sp) {
1702             strm.EOL();
1703             strm.Printf("     typedef '%s': ",
1704                         typedef_type_sp->GetName().GetCString());
1705             typedefed_type_sp->GetFullCompilerType();
1706             typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull,
1707                                               true);
1708             typedef_type_sp = typedefed_type_sp;
1709             typedefed_type_sp = typedef_type_sp->GetTypedefType();
1710           }
1711         }
1712         strm.EOL();
1713       }
1714     }
1715     return num_matches;
1716   }
1717   return 0;
1718 }
1719 
1720 static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
1721                              const SymbolContext &sym_ctx,
1722                              const char *name_cstr, bool name_is_regex) {
1723   if (!sym_ctx.module_sp)
1724     return 0;
1725 
1726   TypeList type_list;
1727   const uint32_t max_num_matches = UINT32_MAX;
1728   size_t num_matches = 1;
1729   bool name_is_fully_qualified = false;
1730 
1731   ConstString name(name_cstr);
1732   llvm::DenseSet<SymbolFile *> searched_symbol_files;
1733   num_matches = sym_ctx.module_sp->FindTypes(
1734       sym_ctx, name, name_is_fully_qualified, max_num_matches,
1735       searched_symbol_files, type_list);
1736 
1737   if (num_matches) {
1738     strm.Indent();
1739     strm.PutCString("Best match found in ");
1740     DumpFullpath(strm, &sym_ctx.module_sp->GetFileSpec(), 0);
1741     strm.PutCString(":\n");
1742 
1743     TypeSP type_sp(type_list.GetTypeAtIndex(0));
1744     if (type_sp) {
1745       // Resolve the clang type so that any forward references to types that
1746       // haven't yet been parsed will get parsed.
1747       type_sp->GetFullCompilerType();
1748       type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1749       // Print all typedef chains
1750       TypeSP typedef_type_sp(type_sp);
1751       TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1752       while (typedefed_type_sp) {
1753         strm.EOL();
1754         strm.Printf("     typedef '%s': ",
1755                     typedef_type_sp->GetName().GetCString());
1756         typedefed_type_sp->GetFullCompilerType();
1757         typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1758         typedef_type_sp = typedefed_type_sp;
1759         typedefed_type_sp = typedef_type_sp->GetTypedefType();
1760       }
1761     }
1762     strm.EOL();
1763   }
1764   return num_matches;
1765 }
1766 
1767 static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
1768                                           Stream &strm, Module *module,
1769                                           const FileSpec &file_spec,
1770                                           uint32_t line, bool check_inlines,
1771                                           bool verbose) {
1772   if (module && file_spec) {
1773     SymbolContextList sc_list;
1774     const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
1775         file_spec, line, check_inlines, eSymbolContextEverything, sc_list);
1776     if (num_matches > 0) {
1777       strm.Indent();
1778       strm.Printf("%u match%s found in ", num_matches,
1779                   num_matches > 1 ? "es" : "");
1780       strm << file_spec;
1781       if (line > 0)
1782         strm.Printf(":%u", line);
1783       strm << " in ";
1784       DumpFullpath(strm, &module->GetFileSpec(), 0);
1785       strm.PutCString(":\n");
1786       DumpSymbolContextList(
1787           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1788           strm, sc_list, verbose);
1789       return num_matches;
1790     }
1791   }
1792   return 0;
1793 }
1794 
1795 static size_t FindModulesByName(Target *target, const char *module_name,
1796                                 ModuleList &module_list,
1797                                 bool check_global_list) {
1798   FileSpec module_file_spec(module_name);
1799   ModuleSpec module_spec(module_file_spec);
1800 
1801   const size_t initial_size = module_list.GetSize();
1802 
1803   if (check_global_list) {
1804     // Check the global list
1805     std::lock_guard<std::recursive_mutex> guard(
1806         Module::GetAllocationModuleCollectionMutex());
1807     const size_t num_modules = Module::GetNumberAllocatedModules();
1808     ModuleSP module_sp;
1809     for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1810       Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
1811 
1812       if (module) {
1813         if (module->MatchesModuleSpec(module_spec)) {
1814           module_sp = module->shared_from_this();
1815           module_list.AppendIfNeeded(module_sp);
1816         }
1817       }
1818     }
1819   } else {
1820     if (target) {
1821       const size_t num_matches =
1822           target->GetImages().FindModules(module_spec, module_list);
1823 
1824       // Not found in our module list for our target, check the main shared
1825       // module list in case it is a extra file used somewhere else
1826       if (num_matches == 0) {
1827         module_spec.GetArchitecture() = target->GetArchitecture();
1828         ModuleList::FindSharedModules(module_spec, module_list);
1829       }
1830     } else {
1831       ModuleList::FindSharedModules(module_spec, module_list);
1832     }
1833   }
1834 
1835   return module_list.GetSize() - initial_size;
1836 }
1837 
1838 #pragma mark CommandObjectTargetModulesModuleAutoComplete
1839 
1840 //----------------------------------------------------------------------
1841 // A base command object class that can auto complete with module file
1842 // paths
1843 //----------------------------------------------------------------------
1844 
1845 class CommandObjectTargetModulesModuleAutoComplete
1846     : public CommandObjectParsed {
1847 public:
1848   CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
1849                                                const char *name,
1850                                                const char *help,
1851                                                const char *syntax)
1852       : CommandObjectParsed(interpreter, name, help, syntax) {
1853     CommandArgumentEntry arg;
1854     CommandArgumentData file_arg;
1855 
1856     // Define the first (and only) variant of this arg.
1857     file_arg.arg_type = eArgTypeFilename;
1858     file_arg.arg_repetition = eArgRepeatStar;
1859 
1860     // There is only one variant this argument could be; put it into the
1861     // argument entry.
1862     arg.push_back(file_arg);
1863 
1864     // Push the data for the first argument into the m_arguments vector.
1865     m_arguments.push_back(arg);
1866   }
1867 
1868   ~CommandObjectTargetModulesModuleAutoComplete() override = default;
1869 
1870   int HandleArgumentCompletion(
1871       CompletionRequest &request,
1872       OptionElementVector &opt_element_vector) override {
1873     CommandCompletions::InvokeCommonCompletionCallbacks(
1874         GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request,
1875         nullptr);
1876     return request.GetNumberOfMatches();
1877   }
1878 };
1879 
1880 #pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1881 
1882 //----------------------------------------------------------------------
1883 // A base command object class that can auto complete with module source
1884 // file paths
1885 //----------------------------------------------------------------------
1886 
1887 class CommandObjectTargetModulesSourceFileAutoComplete
1888     : public CommandObjectParsed {
1889 public:
1890   CommandObjectTargetModulesSourceFileAutoComplete(
1891       CommandInterpreter &interpreter, const char *name, const char *help,
1892       const char *syntax, uint32_t flags)
1893       : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1894     CommandArgumentEntry arg;
1895     CommandArgumentData source_file_arg;
1896 
1897     // Define the first (and only) variant of this arg.
1898     source_file_arg.arg_type = eArgTypeSourceFile;
1899     source_file_arg.arg_repetition = eArgRepeatPlus;
1900 
1901     // There is only one variant this argument could be; put it into the
1902     // argument entry.
1903     arg.push_back(source_file_arg);
1904 
1905     // Push the data for the first argument into the m_arguments vector.
1906     m_arguments.push_back(arg);
1907   }
1908 
1909   ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
1910 
1911   int HandleArgumentCompletion(
1912       CompletionRequest &request,
1913       OptionElementVector &opt_element_vector) override {
1914     CommandCompletions::InvokeCommonCompletionCallbacks(
1915         GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
1916         request, nullptr);
1917     return request.GetNumberOfMatches();
1918   }
1919 };
1920 
1921 #pragma mark CommandObjectTargetModulesDumpObjfile
1922 
1923 class CommandObjectTargetModulesDumpObjfile
1924     : public CommandObjectTargetModulesModuleAutoComplete {
1925 public:
1926   CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
1927       : CommandObjectTargetModulesModuleAutoComplete(
1928             interpreter, "target modules dump objfile",
1929             "Dump the object file headers from one or more target modules.",
1930             nullptr) {}
1931 
1932   ~CommandObjectTargetModulesDumpObjfile() override = default;
1933 
1934 protected:
1935   bool DoExecute(Args &command, CommandReturnObject &result) override {
1936     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1937     if (target == nullptr) {
1938       result.AppendError("invalid target, create a debug target using the "
1939                          "'target create' command");
1940       result.SetStatus(eReturnStatusFailed);
1941       return false;
1942     }
1943 
1944     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1945     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1946     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1947 
1948     size_t num_dumped = 0;
1949     if (command.GetArgumentCount() == 0) {
1950       // Dump all headers for all modules images
1951       num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(),
1952                                             target->GetImages());
1953       if (num_dumped == 0) {
1954         result.AppendError("the target has no associated executable images");
1955         result.SetStatus(eReturnStatusFailed);
1956       }
1957     } else {
1958       // Find the modules that match the basename or full path.
1959       ModuleList module_list;
1960       const char *arg_cstr;
1961       for (int arg_idx = 0;
1962            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
1963            ++arg_idx) {
1964         size_t num_matched =
1965             FindModulesByName(target, arg_cstr, module_list, true);
1966         if (num_matched == 0) {
1967           result.AppendWarningWithFormat(
1968               "Unable to find an image that matches '%s'.\n", arg_cstr);
1969         }
1970       }
1971       // Dump all the modules we found.
1972       num_dumped =
1973           DumpModuleObjfileHeaders(result.GetOutputStream(), module_list);
1974     }
1975 
1976     if (num_dumped > 0) {
1977       result.SetStatus(eReturnStatusSuccessFinishResult);
1978     } else {
1979       result.AppendError("no matching executable images found");
1980       result.SetStatus(eReturnStatusFailed);
1981     }
1982     return result.Succeeded();
1983   }
1984 };
1985 
1986 #pragma mark CommandObjectTargetModulesDumpSymtab
1987 
1988 static constexpr OptionEnumValueElement g_sort_option_enumeration[] = {
1989     {eSortOrderNone, "none",
1990      "No sorting, use the original symbol table order."},
1991     {eSortOrderByAddress, "address", "Sort output by symbol address."},
1992     {eSortOrderByName, "name", "Sort output by symbol name."} };
1993 
1994 static constexpr OptionDefinition g_target_modules_dump_symtab_options[] = {
1995     // clang-format off
1996   { LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, nullptr, OptionEnumValues(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);
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);
2538           if (FileSystem::Instance().Exists(file_spec)) {
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 constexpr OptionDefinition g_target_modules_list_options[] = {
2888     // clang-format off
2889   { LLDB_OPT_SET_1, false, "address",        'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Display the image at this address." },
2890   { LLDB_OPT_SET_1, false, "arch",           'A', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the architecture when listing images." },
2891   { LLDB_OPT_SET_1, false, "triple",         't', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the triple when listing images." },
2892   { LLDB_OPT_SET_1, false, "header",         'h', OptionParser::eNoArgument,       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, {}, 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, {}, 0, eArgTypeNone,                "Display the UUID when listing images." },
2895   { LLDB_OPT_SET_1, false, "fullpath",       'f', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the fullpath to the image object file." },
2896   { LLDB_OPT_SET_1, false, "directory",      'd', OptionParser::eOptionalArgument, 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, {}, 0, eArgTypeWidth,               "Display the basename with optional width for the image object file." },
2898   { LLDB_OPT_SET_1, false, "symfile",        's', OptionParser::eOptionalArgument, 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, {}, 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, {}, 0, eArgTypeWidth,               "Display the modification time with optional width of the module." },
2901   { LLDB_OPT_SET_1, false, "ref-count",      'r', OptionParser::eOptionalArgument, 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, {}, 0, eArgTypeNone,                "Display the module pointer." },
2903   { LLDB_OPT_SET_1, false, "global",         'g', OptionParser::eNoArgument,       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 constexpr OptionDefinition g_target_modules_show_unwind_options[] = {
3254     // clang-format off
3255   { LLDB_OPT_SET_1, false, "name",    'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName,        "Show unwind instructions for a function or symbol name." },
3256   { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, 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 constexpr OptionDefinition g_target_modules_lookup_options[] = {
3560     // clang-format off
3561   { LLDB_OPT_SET_1,                                  true,  "address",    'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." },
3562   { LLDB_OPT_SET_1,                                  false, "offset",     'o', OptionParser::eRequiredArgument, 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, {}, 0, eArgTypeNone,                "The <name> argument for name lookups are regular expressions." },
3565   { LLDB_OPT_SET_2,                                  true,  "symbol",     's', OptionParser::eRequiredArgument, 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, {}, 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, {}, 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, {}, 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, {}, 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, {}, 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, {}, 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, {}, 0, eArgTypeNone,                "Enable verbose lookup information." },
3573   { LLDB_OPT_SET_ALL,                                false, "all",        'A', OptionParser::eNoArgument,       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, 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 (FileSystem::Instance().Exists(
4261                           frame_module_sp->GetPlatformFileSpec())) {
4262                     module_spec.GetArchitecture() =
4263                         frame_module_sp->GetArchitecture();
4264                     module_spec.GetFileSpec() =
4265                         frame_module_sp->GetPlatformFileSpec();
4266                   }
4267                   module_spec.GetUUID() = frame_module_sp->GetUUID();
4268                   success = module_spec.GetUUID().IsValid() ||
4269                             module_spec.GetFileSpec();
4270                 } else {
4271                   result.AppendError("frame has no module");
4272                   error_set = true;
4273                 }
4274               } else {
4275                 result.AppendError("invalid current frame");
4276                 error_set = true;
4277               }
4278             } else {
4279               result.AppendErrorWithFormat("process is not stopped: %s",
4280                                            StateAsCString(process_state));
4281               error_set = true;
4282             }
4283           } else {
4284             result.AppendError(
4285                 "a process must exist in order to use the --frame option");
4286             error_set = true;
4287           }
4288         } else {
4289           if (uuid_option_set) {
4290             module_spec.GetUUID() =
4291                 m_uuid_option_group.GetOptionValue().GetCurrentValue();
4292             success |= module_spec.GetUUID().IsValid();
4293           } else if (file_option_set) {
4294             module_spec.GetFileSpec() =
4295                 m_file_option.GetOptionValue().GetCurrentValue();
4296             ModuleSP module_sp(
4297                 target->GetImages().FindFirstModule(module_spec));
4298             if (module_sp) {
4299               module_spec.GetFileSpec() = module_sp->GetFileSpec();
4300               module_spec.GetPlatformFileSpec() =
4301                   module_sp->GetPlatformFileSpec();
4302               module_spec.GetUUID() = module_sp->GetUUID();
4303               module_spec.GetArchitecture() = module_sp->GetArchitecture();
4304             } else {
4305               module_spec.GetArchitecture() = target->GetArchitecture();
4306             }
4307             success |= module_spec.GetUUID().IsValid() ||
4308                        FileSystem::Instance().Exists(module_spec.GetFileSpec());
4309           }
4310         }
4311 
4312         if (success) {
4313           if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
4314             if (module_spec.GetSymbolFileSpec())
4315               success = AddModuleSymbols(target, module_spec, flush, result);
4316           }
4317         }
4318 
4319         if (!success && !error_set) {
4320           StreamString error_strm;
4321           if (uuid_option_set) {
4322             error_strm.PutCString("unable to find debug symbols for UUID ");
4323             module_spec.GetUUID().Dump(&error_strm);
4324           } else if (file_option_set) {
4325             error_strm.PutCString(
4326                 "unable to find debug symbols for the executable file ");
4327             error_strm << module_spec.GetFileSpec();
4328           } else if (frame_option_set) {
4329             error_strm.PutCString(
4330                 "unable to find debug symbols for the current frame");
4331           }
4332           result.AppendError(error_strm.GetString());
4333         }
4334       } else {
4335         result.AppendError("one or more symbol file paths must be specified, "
4336                            "or options must be specified");
4337       }
4338     } else {
4339       if (uuid_option_set) {
4340         result.AppendError("specify either one or more paths to symbol files "
4341                            "or use the --uuid option without arguments");
4342       } else if (frame_option_set) {
4343         result.AppendError("specify either one or more paths to symbol files "
4344                            "or use the --frame option without arguments");
4345       } else if (file_option_set && argc > 1) {
4346         result.AppendError("specify at most one symbol file path when "
4347                            "--shlib option is set");
4348       } else {
4349         PlatformSP platform_sp(target->GetPlatform());
4350 
4351         for (auto &entry : args.entries()) {
4352           if (!entry.ref.empty()) {
4353             auto &symbol_file_spec = module_spec.GetSymbolFileSpec();
4354             symbol_file_spec.SetFile(entry.ref, FileSpec::Style::native);
4355             FileSystem::Instance().Resolve(symbol_file_spec);
4356             if (file_option_set) {
4357               module_spec.GetFileSpec() =
4358                   m_file_option.GetOptionValue().GetCurrentValue();
4359             }
4360             if (platform_sp) {
4361               FileSpec symfile_spec;
4362               if (platform_sp
4363                       ->ResolveSymbolFile(*target, module_spec, symfile_spec)
4364                       .Success())
4365                 module_spec.GetSymbolFileSpec() = symfile_spec;
4366             }
4367 
4368             ArchSpec arch;
4369             bool symfile_exists =
4370                 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec());
4371 
4372             if (symfile_exists) {
4373               if (!AddModuleSymbols(target, module_spec, flush, result))
4374                 break;
4375             } else {
4376               std::string resolved_symfile_path =
4377                   module_spec.GetSymbolFileSpec().GetPath();
4378               if (resolved_symfile_path != entry.ref) {
4379                 result.AppendErrorWithFormat(
4380                     "invalid module path '%s' with resolved path '%s'\n",
4381                     entry.c_str(), resolved_symfile_path.c_str());
4382                 break;
4383               }
4384               result.AppendErrorWithFormat("invalid module path '%s'\n",
4385                                            entry.c_str());
4386               break;
4387             }
4388           }
4389         }
4390       }
4391     }
4392 
4393     if (flush) {
4394       Process *process = m_exe_ctx.GetProcessPtr();
4395       if (process)
4396         process->Flush();
4397     }
4398     return result.Succeeded();
4399   }
4400 
4401   OptionGroupOptions m_option_group;
4402   OptionGroupUUID m_uuid_option_group;
4403   OptionGroupFile m_file_option;
4404   OptionGroupBoolean m_current_frame_option;
4405 };
4406 
4407 #pragma mark CommandObjectTargetSymbols
4408 
4409 //-------------------------------------------------------------------------
4410 // CommandObjectTargetSymbols
4411 //-------------------------------------------------------------------------
4412 
4413 class CommandObjectTargetSymbols : public CommandObjectMultiword {
4414 public:
4415   //------------------------------------------------------------------
4416   // Constructors and Destructors
4417   //------------------------------------------------------------------
4418   CommandObjectTargetSymbols(CommandInterpreter &interpreter)
4419       : CommandObjectMultiword(
4420             interpreter, "target symbols",
4421             "Commands for adding and managing debug symbol files.",
4422             "target symbols <sub-command> ...") {
4423     LoadSubCommand(
4424         "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
4425   }
4426 
4427   ~CommandObjectTargetSymbols() override = default;
4428 
4429 private:
4430   //------------------------------------------------------------------
4431   // For CommandObjectTargetModules only
4432   //------------------------------------------------------------------
4433   DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetSymbols);
4434 };
4435 
4436 #pragma mark CommandObjectTargetStopHookAdd
4437 
4438 //-------------------------------------------------------------------------
4439 // CommandObjectTargetStopHookAdd
4440 //-------------------------------------------------------------------------
4441 
4442 static constexpr OptionDefinition g_target_stop_hook_add_options[] = {
4443     // clang-format off
4444   { LLDB_OPT_SET_ALL, false, "one-liner",    'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner,                                         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
4445   { LLDB_OPT_SET_ALL, false, "shlib",        's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName,    "Set the module within which the stop-hook is to be run." },
4446   { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex,                                      "The stop hook is run only for the thread whose index matches this argument." },
4447   { LLDB_OPT_SET_ALL, false, "thread-id",    't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID,                                         "The stop hook is run only for the thread whose TID matches this argument." },
4448   { LLDB_OPT_SET_ALL, false, "thread-name",  'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName,                                       "The stop hook is run only for the thread whose thread name matches this argument." },
4449   { LLDB_OPT_SET_ALL, false, "queue-name",   'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName,                                        "The stop hook is run only for threads in the queue whose name is given by this argument." },
4450   { LLDB_OPT_SET_1,   false, "file",         'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." },
4451   { LLDB_OPT_SET_1,   false, "start-line",   'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum,                                          "Set the start of the line range for which the stop-hook is to be run." },
4452   { LLDB_OPT_SET_1,   false, "end-line",     'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum,                                          "Set the end of the line range for which the stop-hook is to be run." },
4453   { LLDB_OPT_SET_2,   false, "classname",    'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeClassName,                                        "Specify the class within which the stop-hook is to be run." },
4454   { LLDB_OPT_SET_3,   false, "name",         'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." },
4455     // clang-format on
4456 };
4457 
4458 class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
4459                                        public IOHandlerDelegateMultiline {
4460 public:
4461   class CommandOptions : public Options {
4462   public:
4463     CommandOptions()
4464         : Options(), m_line_start(0), m_line_end(UINT_MAX),
4465           m_func_name_type_mask(eFunctionNameTypeAuto),
4466           m_sym_ctx_specified(false), m_thread_specified(false),
4467           m_use_one_liner(false), m_one_liner() {}
4468 
4469     ~CommandOptions() override = default;
4470 
4471     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4472       return llvm::makeArrayRef(g_target_stop_hook_add_options);
4473     }
4474 
4475     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4476                           ExecutionContext *execution_context) override {
4477       Status error;
4478       const int short_option = m_getopt_table[option_idx].val;
4479 
4480       switch (short_option) {
4481       case 'c':
4482         m_class_name = option_arg;
4483         m_sym_ctx_specified = true;
4484         break;
4485 
4486       case 'e':
4487         if (option_arg.getAsInteger(0, m_line_end)) {
4488           error.SetErrorStringWithFormat("invalid end line number: \"%s\"",
4489                                          option_arg.str().c_str());
4490           break;
4491         }
4492         m_sym_ctx_specified = true;
4493         break;
4494 
4495       case 'l':
4496         if (option_arg.getAsInteger(0, m_line_start)) {
4497           error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
4498                                          option_arg.str().c_str());
4499           break;
4500         }
4501         m_sym_ctx_specified = true;
4502         break;
4503 
4504       case 'i':
4505         m_no_inlines = true;
4506         break;
4507 
4508       case 'n':
4509         m_function_name = option_arg;
4510         m_func_name_type_mask |= eFunctionNameTypeAuto;
4511         m_sym_ctx_specified = true;
4512         break;
4513 
4514       case 'f':
4515         m_file_name = option_arg;
4516         m_sym_ctx_specified = true;
4517         break;
4518 
4519       case 's':
4520         m_module_name = option_arg;
4521         m_sym_ctx_specified = true;
4522         break;
4523 
4524       case 't':
4525         if (option_arg.getAsInteger(0, m_thread_id))
4526           error.SetErrorStringWithFormat("invalid thread id string '%s'",
4527                                          option_arg.str().c_str());
4528         m_thread_specified = true;
4529         break;
4530 
4531       case 'T':
4532         m_thread_name = option_arg;
4533         m_thread_specified = true;
4534         break;
4535 
4536       case 'q':
4537         m_queue_name = option_arg;
4538         m_thread_specified = true;
4539         break;
4540 
4541       case 'x':
4542         if (option_arg.getAsInteger(0, m_thread_index))
4543           error.SetErrorStringWithFormat("invalid thread index string '%s'",
4544                                          option_arg.str().c_str());
4545         m_thread_specified = true;
4546         break;
4547 
4548       case 'o':
4549         m_use_one_liner = true;
4550         m_one_liner = option_arg;
4551         break;
4552 
4553       default:
4554         error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
4555         break;
4556       }
4557       return error;
4558     }
4559 
4560     void OptionParsingStarting(ExecutionContext *execution_context) override {
4561       m_class_name.clear();
4562       m_function_name.clear();
4563       m_line_start = 0;
4564       m_line_end = UINT_MAX;
4565       m_file_name.clear();
4566       m_module_name.clear();
4567       m_func_name_type_mask = eFunctionNameTypeAuto;
4568       m_thread_id = LLDB_INVALID_THREAD_ID;
4569       m_thread_index = UINT32_MAX;
4570       m_thread_name.clear();
4571       m_queue_name.clear();
4572 
4573       m_no_inlines = false;
4574       m_sym_ctx_specified = false;
4575       m_thread_specified = false;
4576 
4577       m_use_one_liner = false;
4578       m_one_liner.clear();
4579     }
4580 
4581     std::string m_class_name;
4582     std::string m_function_name;
4583     uint32_t m_line_start;
4584     uint32_t m_line_end;
4585     std::string m_file_name;
4586     std::string m_module_name;
4587     uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType.
4588     lldb::tid_t m_thread_id;
4589     uint32_t m_thread_index;
4590     std::string m_thread_name;
4591     std::string m_queue_name;
4592     bool m_sym_ctx_specified;
4593     bool m_no_inlines;
4594     bool m_thread_specified;
4595     // Instance variables to hold the values for one_liner options.
4596     bool m_use_one_liner;
4597     std::string m_one_liner;
4598   };
4599 
4600   CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
4601       : CommandObjectParsed(interpreter, "target stop-hook add",
4602                             "Add a hook to be executed when the target stops.",
4603                             "target stop-hook add"),
4604         IOHandlerDelegateMultiline("DONE",
4605                                    IOHandlerDelegate::Completion::LLDBCommand),
4606         m_options() {}
4607 
4608   ~CommandObjectTargetStopHookAdd() override = default;
4609 
4610   Options *GetOptions() override { return &m_options; }
4611 
4612 protected:
4613   void IOHandlerActivated(IOHandler &io_handler) override {
4614     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4615     if (output_sp) {
4616       output_sp->PutCString(
4617           "Enter your stop hook command(s).  Type 'DONE' to end.\n");
4618       output_sp->Flush();
4619     }
4620   }
4621 
4622   void IOHandlerInputComplete(IOHandler &io_handler,
4623                               std::string &line) override {
4624     if (m_stop_hook_sp) {
4625       if (line.empty()) {
4626         StreamFileSP error_sp(io_handler.GetErrorStreamFile());
4627         if (error_sp) {
4628           error_sp->Printf("error: stop hook #%" PRIu64
4629                            " aborted, no commands.\n",
4630                            m_stop_hook_sp->GetID());
4631           error_sp->Flush();
4632         }
4633         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
4634         if (target)
4635           target->RemoveStopHookByID(m_stop_hook_sp->GetID());
4636       } else {
4637         m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
4638         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4639         if (output_sp) {
4640           output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
4641                             m_stop_hook_sp->GetID());
4642           output_sp->Flush();
4643         }
4644       }
4645       m_stop_hook_sp.reset();
4646     }
4647     io_handler.SetIsDone(true);
4648   }
4649 
4650   bool DoExecute(Args &command, CommandReturnObject &result) override {
4651     m_stop_hook_sp.reset();
4652 
4653     Target *target = GetSelectedOrDummyTarget();
4654     if (target) {
4655       Target::StopHookSP new_hook_sp = target->CreateStopHook();
4656 
4657       //  First step, make the specifier.
4658       std::unique_ptr<SymbolContextSpecifier> specifier_ap;
4659       if (m_options.m_sym_ctx_specified) {
4660         specifier_ap.reset(new SymbolContextSpecifier(
4661             m_interpreter.GetDebugger().GetSelectedTarget()));
4662 
4663         if (!m_options.m_module_name.empty()) {
4664           specifier_ap->AddSpecification(
4665               m_options.m_module_name.c_str(),
4666               SymbolContextSpecifier::eModuleSpecified);
4667         }
4668 
4669         if (!m_options.m_class_name.empty()) {
4670           specifier_ap->AddSpecification(
4671               m_options.m_class_name.c_str(),
4672               SymbolContextSpecifier::eClassOrNamespaceSpecified);
4673         }
4674 
4675         if (!m_options.m_file_name.empty()) {
4676           specifier_ap->AddSpecification(
4677               m_options.m_file_name.c_str(),
4678               SymbolContextSpecifier::eFileSpecified);
4679         }
4680 
4681         if (m_options.m_line_start != 0) {
4682           specifier_ap->AddLineSpecification(
4683               m_options.m_line_start,
4684               SymbolContextSpecifier::eLineStartSpecified);
4685         }
4686 
4687         if (m_options.m_line_end != UINT_MAX) {
4688           specifier_ap->AddLineSpecification(
4689               m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
4690         }
4691 
4692         if (!m_options.m_function_name.empty()) {
4693           specifier_ap->AddSpecification(
4694               m_options.m_function_name.c_str(),
4695               SymbolContextSpecifier::eFunctionSpecified);
4696         }
4697       }
4698 
4699       if (specifier_ap)
4700         new_hook_sp->SetSpecifier(specifier_ap.release());
4701 
4702       // Next see if any of the thread options have been entered:
4703 
4704       if (m_options.m_thread_specified) {
4705         ThreadSpec *thread_spec = new ThreadSpec();
4706 
4707         if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
4708           thread_spec->SetTID(m_options.m_thread_id);
4709         }
4710 
4711         if (m_options.m_thread_index != UINT32_MAX)
4712           thread_spec->SetIndex(m_options.m_thread_index);
4713 
4714         if (!m_options.m_thread_name.empty())
4715           thread_spec->SetName(m_options.m_thread_name.c_str());
4716 
4717         if (!m_options.m_queue_name.empty())
4718           thread_spec->SetQueueName(m_options.m_queue_name.c_str());
4719 
4720         new_hook_sp->SetThreadSpecifier(thread_spec);
4721       }
4722       if (m_options.m_use_one_liner) {
4723         // Use one-liner.
4724         new_hook_sp->GetCommandPointer()->AppendString(
4725             m_options.m_one_liner.c_str());
4726         result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
4727                                        new_hook_sp->GetID());
4728       } else {
4729         m_stop_hook_sp = new_hook_sp;
4730         m_interpreter.GetLLDBCommandsFromIOHandler(
4731             "> ",     // Prompt
4732             *this,    // IOHandlerDelegate
4733             true,     // Run IOHandler in async mode
4734             nullptr); // Baton for the "io_handler" that will be passed back
4735                       // into our IOHandlerDelegate functions
4736       }
4737       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4738     } else {
4739       result.AppendError("invalid target\n");
4740       result.SetStatus(eReturnStatusFailed);
4741     }
4742 
4743     return result.Succeeded();
4744   }
4745 
4746 private:
4747   CommandOptions m_options;
4748   Target::StopHookSP m_stop_hook_sp;
4749 };
4750 
4751 #pragma mark CommandObjectTargetStopHookDelete
4752 
4753 //-------------------------------------------------------------------------
4754 // CommandObjectTargetStopHookDelete
4755 //-------------------------------------------------------------------------
4756 
4757 class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
4758 public:
4759   CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
4760       : CommandObjectParsed(interpreter, "target stop-hook delete",
4761                             "Delete a stop-hook.",
4762                             "target stop-hook delete [<idx>]") {}
4763 
4764   ~CommandObjectTargetStopHookDelete() override = default;
4765 
4766 protected:
4767   bool DoExecute(Args &command, CommandReturnObject &result) override {
4768     Target *target = GetSelectedOrDummyTarget();
4769     if (target) {
4770       // FIXME: see if we can use the breakpoint id style parser?
4771       size_t num_args = command.GetArgumentCount();
4772       if (num_args == 0) {
4773         if (!m_interpreter.Confirm("Delete all stop hooks?", true)) {
4774           result.SetStatus(eReturnStatusFailed);
4775           return false;
4776         } else {
4777           target->RemoveAllStopHooks();
4778         }
4779       } else {
4780         bool success;
4781         for (size_t i = 0; i < num_args; i++) {
4782           lldb::user_id_t user_id = StringConvert::ToUInt32(
4783               command.GetArgumentAtIndex(i), 0, 0, &success);
4784           if (!success) {
4785             result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4786                                          command.GetArgumentAtIndex(i));
4787             result.SetStatus(eReturnStatusFailed);
4788             return false;
4789           }
4790           success = target->RemoveStopHookByID(user_id);
4791           if (!success) {
4792             result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4793                                          command.GetArgumentAtIndex(i));
4794             result.SetStatus(eReturnStatusFailed);
4795             return false;
4796           }
4797         }
4798       }
4799       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4800     } else {
4801       result.AppendError("invalid target\n");
4802       result.SetStatus(eReturnStatusFailed);
4803     }
4804 
4805     return result.Succeeded();
4806   }
4807 };
4808 
4809 #pragma mark CommandObjectTargetStopHookEnableDisable
4810 
4811 //-------------------------------------------------------------------------
4812 // CommandObjectTargetStopHookEnableDisable
4813 //-------------------------------------------------------------------------
4814 
4815 class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
4816 public:
4817   CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
4818                                            bool enable, const char *name,
4819                                            const char *help, const char *syntax)
4820       : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
4821   }
4822 
4823   ~CommandObjectTargetStopHookEnableDisable() override = default;
4824 
4825 protected:
4826   bool DoExecute(Args &command, CommandReturnObject &result) override {
4827     Target *target = GetSelectedOrDummyTarget();
4828     if (target) {
4829       // FIXME: see if we can use the breakpoint id style parser?
4830       size_t num_args = command.GetArgumentCount();
4831       bool success;
4832 
4833       if (num_args == 0) {
4834         target->SetAllStopHooksActiveState(m_enable);
4835       } else {
4836         for (size_t i = 0; i < num_args; i++) {
4837           lldb::user_id_t user_id = StringConvert::ToUInt32(
4838               command.GetArgumentAtIndex(i), 0, 0, &success);
4839           if (!success) {
4840             result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4841                                          command.GetArgumentAtIndex(i));
4842             result.SetStatus(eReturnStatusFailed);
4843             return false;
4844           }
4845           success = target->SetStopHookActiveStateByID(user_id, m_enable);
4846           if (!success) {
4847             result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4848                                          command.GetArgumentAtIndex(i));
4849             result.SetStatus(eReturnStatusFailed);
4850             return false;
4851           }
4852         }
4853       }
4854       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4855     } else {
4856       result.AppendError("invalid target\n");
4857       result.SetStatus(eReturnStatusFailed);
4858     }
4859     return result.Succeeded();
4860   }
4861 
4862 private:
4863   bool m_enable;
4864 };
4865 
4866 #pragma mark CommandObjectTargetStopHookList
4867 
4868 //-------------------------------------------------------------------------
4869 // CommandObjectTargetStopHookList
4870 //-------------------------------------------------------------------------
4871 
4872 class CommandObjectTargetStopHookList : public CommandObjectParsed {
4873 public:
4874   CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
4875       : CommandObjectParsed(interpreter, "target stop-hook list",
4876                             "List all stop-hooks.",
4877                             "target stop-hook list [<type>]") {}
4878 
4879   ~CommandObjectTargetStopHookList() override = default;
4880 
4881 protected:
4882   bool DoExecute(Args &command, CommandReturnObject &result) override {
4883     Target *target = GetSelectedOrDummyTarget();
4884     if (!target) {
4885       result.AppendError("invalid target\n");
4886       result.SetStatus(eReturnStatusFailed);
4887       return result.Succeeded();
4888     }
4889 
4890     size_t num_hooks = target->GetNumStopHooks();
4891     if (num_hooks == 0) {
4892       result.GetOutputStream().PutCString("No stop hooks.\n");
4893     } else {
4894       for (size_t i = 0; i < num_hooks; i++) {
4895         Target::StopHookSP this_hook = target->GetStopHookAtIndex(i);
4896         if (i > 0)
4897           result.GetOutputStream().PutCString("\n");
4898         this_hook->GetDescription(&(result.GetOutputStream()),
4899                                   eDescriptionLevelFull);
4900       }
4901     }
4902     result.SetStatus(eReturnStatusSuccessFinishResult);
4903     return result.Succeeded();
4904   }
4905 };
4906 
4907 #pragma mark CommandObjectMultiwordTargetStopHooks
4908 
4909 //-------------------------------------------------------------------------
4910 // CommandObjectMultiwordTargetStopHooks
4911 //-------------------------------------------------------------------------
4912 
4913 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
4914 public:
4915   CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
4916       : CommandObjectMultiword(
4917             interpreter, "target stop-hook",
4918             "Commands for operating on debugger target stop-hooks.",
4919             "target stop-hook <subcommand> [<subcommand-options>]") {
4920     LoadSubCommand("add", CommandObjectSP(
4921                               new CommandObjectTargetStopHookAdd(interpreter)));
4922     LoadSubCommand(
4923         "delete",
4924         CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
4925     LoadSubCommand("disable",
4926                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
4927                        interpreter, false, "target stop-hook disable [<id>]",
4928                        "Disable a stop-hook.", "target stop-hook disable")));
4929     LoadSubCommand("enable",
4930                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
4931                        interpreter, true, "target stop-hook enable [<id>]",
4932                        "Enable a stop-hook.", "target stop-hook enable")));
4933     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList(
4934                                interpreter)));
4935   }
4936 
4937   ~CommandObjectMultiwordTargetStopHooks() override = default;
4938 };
4939 
4940 #pragma mark CommandObjectMultiwordTarget
4941 
4942 //-------------------------------------------------------------------------
4943 // CommandObjectMultiwordTarget
4944 //-------------------------------------------------------------------------
4945 
4946 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
4947     CommandInterpreter &interpreter)
4948     : CommandObjectMultiword(interpreter, "target",
4949                              "Commands for operating on debugger targets.",
4950                              "target <subcommand> [<subcommand-options>]") {
4951   LoadSubCommand("create",
4952                  CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
4953   LoadSubCommand("delete",
4954                  CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
4955   LoadSubCommand("list",
4956                  CommandObjectSP(new CommandObjectTargetList(interpreter)));
4957   LoadSubCommand("select",
4958                  CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
4959   LoadSubCommand(
4960       "stop-hook",
4961       CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
4962   LoadSubCommand("modules",
4963                  CommandObjectSP(new CommandObjectTargetModules(interpreter)));
4964   LoadSubCommand("symbols",
4965                  CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
4966   LoadSubCommand("variable",
4967                  CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
4968 }
4969 
4970 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;
4971