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