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