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     SymbolContext sc;
1676 
1677     ConstString name(name_cstr);
1678     llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
1679     num_matches =
1680         module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches,
1681                           searched_symbol_files, type_list);
1682 
1683     if (num_matches) {
1684       strm.Indent();
1685       strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1686                   num_matches > 1 ? "es" : "");
1687       DumpFullpath(strm, &module->GetFileSpec(), 0);
1688       strm.PutCString(":\n");
1689       for (TypeSP type_sp : type_list.Types()) {
1690         if (type_sp) {
1691           // Resolve the clang type so that any forward references to types
1692           // that haven't yet been parsed will get parsed.
1693           type_sp->GetFullCompilerType();
1694           type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1695           // Print all typedef chains
1696           TypeSP typedef_type_sp(type_sp);
1697           TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1698           while (typedefed_type_sp) {
1699             strm.EOL();
1700             strm.Printf("     typedef '%s': ",
1701                         typedef_type_sp->GetName().GetCString());
1702             typedefed_type_sp->GetFullCompilerType();
1703             typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull,
1704                                               true);
1705             typedef_type_sp = typedefed_type_sp;
1706             typedefed_type_sp = typedef_type_sp->GetTypedefType();
1707           }
1708         }
1709         strm.EOL();
1710       }
1711     }
1712     return num_matches;
1713   }
1714   return 0;
1715 }
1716 
1717 static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
1718                              const SymbolContext &sym_ctx,
1719                              const char *name_cstr, bool name_is_regex) {
1720   if (!sym_ctx.module_sp)
1721     return 0;
1722 
1723   TypeList type_list;
1724   const uint32_t max_num_matches = UINT32_MAX;
1725   size_t num_matches = 1;
1726   bool name_is_fully_qualified = false;
1727 
1728   ConstString name(name_cstr);
1729   llvm::DenseSet<SymbolFile *> searched_symbol_files;
1730   num_matches = sym_ctx.module_sp->FindTypes(
1731       sym_ctx, name, name_is_fully_qualified, max_num_matches,
1732       searched_symbol_files, type_list);
1733 
1734   if (num_matches) {
1735     strm.Indent();
1736     strm.PutCString("Best match found in ");
1737     DumpFullpath(strm, &sym_ctx.module_sp->GetFileSpec(), 0);
1738     strm.PutCString(":\n");
1739 
1740     TypeSP type_sp(type_list.GetTypeAtIndex(0));
1741     if (type_sp) {
1742       // Resolve the clang type so that any forward references to types that
1743       // haven't yet been parsed will get parsed.
1744       type_sp->GetFullCompilerType();
1745       type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1746       // Print all typedef chains
1747       TypeSP typedef_type_sp(type_sp);
1748       TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1749       while (typedefed_type_sp) {
1750         strm.EOL();
1751         strm.Printf("     typedef '%s': ",
1752                     typedef_type_sp->GetName().GetCString());
1753         typedefed_type_sp->GetFullCompilerType();
1754         typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1755         typedef_type_sp = typedefed_type_sp;
1756         typedefed_type_sp = typedef_type_sp->GetTypedefType();
1757       }
1758     }
1759     strm.EOL();
1760   }
1761   return num_matches;
1762 }
1763 
1764 static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
1765                                           Stream &strm, Module *module,
1766                                           const FileSpec &file_spec,
1767                                           uint32_t line, bool check_inlines,
1768                                           bool verbose) {
1769   if (module && file_spec) {
1770     SymbolContextList sc_list;
1771     const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
1772         file_spec, line, check_inlines, eSymbolContextEverything, sc_list);
1773     if (num_matches > 0) {
1774       strm.Indent();
1775       strm.Printf("%u match%s found in ", num_matches,
1776                   num_matches > 1 ? "es" : "");
1777       strm << file_spec;
1778       if (line > 0)
1779         strm.Printf(":%u", line);
1780       strm << " in ";
1781       DumpFullpath(strm, &module->GetFileSpec(), 0);
1782       strm.PutCString(":\n");
1783       DumpSymbolContextList(
1784           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1785           strm, sc_list, verbose);
1786       return num_matches;
1787     }
1788   }
1789   return 0;
1790 }
1791 
1792 static size_t FindModulesByName(Target *target, const char *module_name,
1793                                 ModuleList &module_list,
1794                                 bool check_global_list) {
1795   FileSpec module_file_spec(module_name);
1796   ModuleSpec module_spec(module_file_spec);
1797 
1798   const size_t initial_size = module_list.GetSize();
1799 
1800   if (check_global_list) {
1801     // Check the global list
1802     std::lock_guard<std::recursive_mutex> guard(
1803         Module::GetAllocationModuleCollectionMutex());
1804     const size_t num_modules = Module::GetNumberAllocatedModules();
1805     ModuleSP module_sp;
1806     for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1807       Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
1808 
1809       if (module) {
1810         if (module->MatchesModuleSpec(module_spec)) {
1811           module_sp = module->shared_from_this();
1812           module_list.AppendIfNeeded(module_sp);
1813         }
1814       }
1815     }
1816   } else {
1817     if (target) {
1818       const size_t num_matches =
1819           target->GetImages().FindModules(module_spec, module_list);
1820 
1821       // Not found in our module list for our target, check the main shared
1822       // module list in case it is a extra file used somewhere else
1823       if (num_matches == 0) {
1824         module_spec.GetArchitecture() = target->GetArchitecture();
1825         ModuleList::FindSharedModules(module_spec, module_list);
1826       }
1827     } else {
1828       ModuleList::FindSharedModules(module_spec, module_list);
1829     }
1830   }
1831 
1832   return module_list.GetSize() - initial_size;
1833 }
1834 
1835 #pragma mark CommandObjectTargetModulesModuleAutoComplete
1836 
1837 //----------------------------------------------------------------------
1838 // A base command object class that can auto complete with module file
1839 // paths
1840 //----------------------------------------------------------------------
1841 
1842 class CommandObjectTargetModulesModuleAutoComplete
1843     : public CommandObjectParsed {
1844 public:
1845   CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
1846                                                const char *name,
1847                                                const char *help,
1848                                                const char *syntax)
1849       : CommandObjectParsed(interpreter, name, help, syntax) {
1850     CommandArgumentEntry arg;
1851     CommandArgumentData file_arg;
1852 
1853     // Define the first (and only) variant of this arg.
1854     file_arg.arg_type = eArgTypeFilename;
1855     file_arg.arg_repetition = eArgRepeatStar;
1856 
1857     // There is only one variant this argument could be; put it into the
1858     // argument entry.
1859     arg.push_back(file_arg);
1860 
1861     // Push the data for the first argument into the m_arguments vector.
1862     m_arguments.push_back(arg);
1863   }
1864 
1865   ~CommandObjectTargetModulesModuleAutoComplete() override = default;
1866 
1867   int HandleArgumentCompletion(
1868       CompletionRequest &request,
1869       OptionElementVector &opt_element_vector) override {
1870     CommandCompletions::InvokeCommonCompletionCallbacks(
1871         GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request,
1872         nullptr);
1873     return request.GetNumberOfMatches();
1874   }
1875 };
1876 
1877 #pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1878 
1879 //----------------------------------------------------------------------
1880 // A base command object class that can auto complete with module source
1881 // file paths
1882 //----------------------------------------------------------------------
1883 
1884 class CommandObjectTargetModulesSourceFileAutoComplete
1885     : public CommandObjectParsed {
1886 public:
1887   CommandObjectTargetModulesSourceFileAutoComplete(
1888       CommandInterpreter &interpreter, const char *name, const char *help,
1889       const char *syntax, uint32_t flags)
1890       : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1891     CommandArgumentEntry arg;
1892     CommandArgumentData source_file_arg;
1893 
1894     // Define the first (and only) variant of this arg.
1895     source_file_arg.arg_type = eArgTypeSourceFile;
1896     source_file_arg.arg_repetition = eArgRepeatPlus;
1897 
1898     // There is only one variant this argument could be; put it into the
1899     // argument entry.
1900     arg.push_back(source_file_arg);
1901 
1902     // Push the data for the first argument into the m_arguments vector.
1903     m_arguments.push_back(arg);
1904   }
1905 
1906   ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
1907 
1908   int HandleArgumentCompletion(
1909       CompletionRequest &request,
1910       OptionElementVector &opt_element_vector) override {
1911     CommandCompletions::InvokeCommonCompletionCallbacks(
1912         GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
1913         request, nullptr);
1914     return request.GetNumberOfMatches();
1915   }
1916 };
1917 
1918 #pragma mark CommandObjectTargetModulesDumpObjfile
1919 
1920 class CommandObjectTargetModulesDumpObjfile
1921     : public CommandObjectTargetModulesModuleAutoComplete {
1922 public:
1923   CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
1924       : CommandObjectTargetModulesModuleAutoComplete(
1925             interpreter, "target modules dump objfile",
1926             "Dump the object file headers from one or more target modules.",
1927             nullptr) {}
1928 
1929   ~CommandObjectTargetModulesDumpObjfile() override = default;
1930 
1931 protected:
1932   bool DoExecute(Args &command, CommandReturnObject &result) override {
1933     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1934     if (target == nullptr) {
1935       result.AppendError("invalid target, create a debug target using the "
1936                          "'target create' command");
1937       result.SetStatus(eReturnStatusFailed);
1938       return false;
1939     }
1940 
1941     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1942     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1943     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1944 
1945     size_t num_dumped = 0;
1946     if (command.GetArgumentCount() == 0) {
1947       // Dump all headers for all modules images
1948       num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(),
1949                                             target->GetImages());
1950       if (num_dumped == 0) {
1951         result.AppendError("the target has no associated executable images");
1952         result.SetStatus(eReturnStatusFailed);
1953       }
1954     } else {
1955       // Find the modules that match the basename or full path.
1956       ModuleList module_list;
1957       const char *arg_cstr;
1958       for (int arg_idx = 0;
1959            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
1960            ++arg_idx) {
1961         size_t num_matched =
1962             FindModulesByName(target, arg_cstr, module_list, true);
1963         if (num_matched == 0) {
1964           result.AppendWarningWithFormat(
1965               "Unable to find an image that matches '%s'.\n", arg_cstr);
1966         }
1967       }
1968       // Dump all the modules we found.
1969       num_dumped =
1970           DumpModuleObjfileHeaders(result.GetOutputStream(), module_list);
1971     }
1972 
1973     if (num_dumped > 0) {
1974       result.SetStatus(eReturnStatusSuccessFinishResult);
1975     } else {
1976       result.AppendError("no matching executable images found");
1977       result.SetStatus(eReturnStatusFailed);
1978     }
1979     return result.Succeeded();
1980   }
1981 };
1982 
1983 #pragma mark CommandObjectTargetModulesDumpSymtab
1984 
1985 static constexpr OptionEnumValueElement g_sort_option_enumeration[] = {
1986     {eSortOrderNone, "none",
1987      "No sorting, use the original symbol table order."},
1988     {eSortOrderByAddress, "address", "Sort output by symbol address."},
1989     {eSortOrderByName, "name", "Sort output by symbol name."} };
1990 
1991 static constexpr OptionDefinition g_target_modules_dump_symtab_options[] = {
1992     // clang-format off
1993   { 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." }
1994     // clang-format on
1995 };
1996 
1997 class CommandObjectTargetModulesDumpSymtab
1998     : public CommandObjectTargetModulesModuleAutoComplete {
1999 public:
2000   CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
2001       : CommandObjectTargetModulesModuleAutoComplete(
2002             interpreter, "target modules dump symtab",
2003             "Dump the symbol table from one or more target modules.", nullptr),
2004         m_options() {}
2005 
2006   ~CommandObjectTargetModulesDumpSymtab() override = default;
2007 
2008   Options *GetOptions() override { return &m_options; }
2009 
2010   class CommandOptions : public Options {
2011   public:
2012     CommandOptions() : Options(), m_sort_order(eSortOrderNone) {}
2013 
2014     ~CommandOptions() override = default;
2015 
2016     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2017                           ExecutionContext *execution_context) override {
2018       Status error;
2019       const int short_option = m_getopt_table[option_idx].val;
2020 
2021       switch (short_option) {
2022       case 's':
2023         m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
2024             option_arg, GetDefinitions()[option_idx].enum_values,
2025             eSortOrderNone, error);
2026         break;
2027 
2028       default:
2029         error.SetErrorStringWithFormat("invalid short option character '%c'",
2030                                        short_option);
2031         break;
2032       }
2033       return error;
2034     }
2035 
2036     void OptionParsingStarting(ExecutionContext *execution_context) override {
2037       m_sort_order = eSortOrderNone;
2038     }
2039 
2040     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2041       return llvm::makeArrayRef(g_target_modules_dump_symtab_options);
2042     }
2043 
2044     SortOrder m_sort_order;
2045   };
2046 
2047 protected:
2048   bool DoExecute(Args &command, CommandReturnObject &result) override {
2049     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2050     if (target == nullptr) {
2051       result.AppendError("invalid target, create a debug target using the "
2052                          "'target create' command");
2053       result.SetStatus(eReturnStatusFailed);
2054       return false;
2055     } else {
2056       uint32_t num_dumped = 0;
2057 
2058       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2059       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2060       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2061 
2062       if (command.GetArgumentCount() == 0) {
2063         // Dump all sections for all modules images
2064         std::lock_guard<std::recursive_mutex> guard(
2065             target->GetImages().GetMutex());
2066         const size_t num_modules = target->GetImages().GetSize();
2067         if (num_modules > 0) {
2068           result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64
2069                                           " modules.\n",
2070                                           (uint64_t)num_modules);
2071           for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2072             if (num_dumped > 0) {
2073               result.GetOutputStream().EOL();
2074               result.GetOutputStream().EOL();
2075             }
2076             if (m_interpreter.WasInterrupted())
2077               break;
2078             num_dumped++;
2079             DumpModuleSymtab(
2080                 m_interpreter, result.GetOutputStream(),
2081                 target->GetImages().GetModulePointerAtIndexUnlocked(image_idx),
2082                 m_options.m_sort_order);
2083           }
2084         } else {
2085           result.AppendError("the target has no associated executable images");
2086           result.SetStatus(eReturnStatusFailed);
2087           return false;
2088         }
2089       } else {
2090         // Dump specified images (by basename or fullpath)
2091         const char *arg_cstr;
2092         for (int arg_idx = 0;
2093              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2094              ++arg_idx) {
2095           ModuleList module_list;
2096           const size_t num_matches =
2097               FindModulesByName(target, arg_cstr, module_list, true);
2098           if (num_matches > 0) {
2099             for (size_t i = 0; i < num_matches; ++i) {
2100               Module *module = module_list.GetModulePointerAtIndex(i);
2101               if (module) {
2102                 if (num_dumped > 0) {
2103                   result.GetOutputStream().EOL();
2104                   result.GetOutputStream().EOL();
2105                 }
2106                 if (m_interpreter.WasInterrupted())
2107                   break;
2108                 num_dumped++;
2109                 DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
2110                                  module, m_options.m_sort_order);
2111               }
2112             }
2113           } else
2114             result.AppendWarningWithFormat(
2115                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2116         }
2117       }
2118 
2119       if (num_dumped > 0)
2120         result.SetStatus(eReturnStatusSuccessFinishResult);
2121       else {
2122         result.AppendError("no matching executable images found");
2123         result.SetStatus(eReturnStatusFailed);
2124       }
2125     }
2126     return result.Succeeded();
2127   }
2128 
2129   CommandOptions m_options;
2130 };
2131 
2132 #pragma mark CommandObjectTargetModulesDumpSections
2133 
2134 //----------------------------------------------------------------------
2135 // Image section dumping command
2136 //----------------------------------------------------------------------
2137 
2138 class CommandObjectTargetModulesDumpSections
2139     : public CommandObjectTargetModulesModuleAutoComplete {
2140 public:
2141   CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter)
2142       : CommandObjectTargetModulesModuleAutoComplete(
2143             interpreter, "target modules dump sections",
2144             "Dump the sections from one or more target modules.",
2145             //"target modules dump sections [<file1> ...]")
2146             nullptr) {}
2147 
2148   ~CommandObjectTargetModulesDumpSections() override = default;
2149 
2150 protected:
2151   bool DoExecute(Args &command, CommandReturnObject &result) override {
2152     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2153     if (target == nullptr) {
2154       result.AppendError("invalid target, create a debug target using the "
2155                          "'target create' command");
2156       result.SetStatus(eReturnStatusFailed);
2157       return false;
2158     } else {
2159       uint32_t num_dumped = 0;
2160 
2161       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2162       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2163       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2164 
2165       if (command.GetArgumentCount() == 0) {
2166         // Dump all sections for all modules images
2167         const size_t num_modules = target->GetImages().GetSize();
2168         if (num_modules > 0) {
2169           result.GetOutputStream().Printf("Dumping sections for %" PRIu64
2170                                           " modules.\n",
2171                                           (uint64_t)num_modules);
2172           for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2173             if (m_interpreter.WasInterrupted())
2174               break;
2175             num_dumped++;
2176             DumpModuleSections(
2177                 m_interpreter, result.GetOutputStream(),
2178                 target->GetImages().GetModulePointerAtIndex(image_idx));
2179           }
2180         } else {
2181           result.AppendError("the target has no associated executable images");
2182           result.SetStatus(eReturnStatusFailed);
2183           return false;
2184         }
2185       } else {
2186         // Dump specified images (by basename or fullpath)
2187         const char *arg_cstr;
2188         for (int arg_idx = 0;
2189              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2190              ++arg_idx) {
2191           ModuleList module_list;
2192           const size_t num_matches =
2193               FindModulesByName(target, arg_cstr, module_list, true);
2194           if (num_matches > 0) {
2195             for (size_t i = 0; i < num_matches; ++i) {
2196               if (m_interpreter.WasInterrupted())
2197                 break;
2198               Module *module = module_list.GetModulePointerAtIndex(i);
2199               if (module) {
2200                 num_dumped++;
2201                 DumpModuleSections(m_interpreter, result.GetOutputStream(),
2202                                    module);
2203               }
2204             }
2205           } else {
2206             // Check the global list
2207             std::lock_guard<std::recursive_mutex> guard(
2208                 Module::GetAllocationModuleCollectionMutex());
2209 
2210             result.AppendWarningWithFormat(
2211                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2212           }
2213         }
2214       }
2215 
2216       if (num_dumped > 0)
2217         result.SetStatus(eReturnStatusSuccessFinishResult);
2218       else {
2219         result.AppendError("no matching executable images found");
2220         result.SetStatus(eReturnStatusFailed);
2221       }
2222     }
2223     return result.Succeeded();
2224   }
2225 };
2226 
2227 #pragma mark CommandObjectTargetModulesDumpSections
2228 
2229 //----------------------------------------------------------------------
2230 // Clang AST dumping command
2231 //----------------------------------------------------------------------
2232 
2233 class CommandObjectTargetModulesDumpClangAST
2234     : public CommandObjectTargetModulesModuleAutoComplete {
2235 public:
2236   CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter)
2237       : CommandObjectTargetModulesModuleAutoComplete(
2238             interpreter, "target modules dump ast",
2239             "Dump the clang ast for a given module's symbol file.",
2240             //"target modules dump ast [<file1> ...]")
2241             nullptr) {}
2242 
2243   ~CommandObjectTargetModulesDumpClangAST() override = default;
2244 
2245 protected:
2246   bool DoExecute(Args &command, CommandReturnObject &result) override {
2247     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2248     if (target == nullptr) {
2249       result.AppendError("invalid target, create a debug target using the "
2250                          "'target create' command");
2251       result.SetStatus(eReturnStatusFailed);
2252       return false;
2253     }
2254 
2255     const size_t num_modules = target->GetImages().GetSize();
2256     if (num_modules == 0) {
2257       result.AppendError("the target has no associated executable images");
2258       result.SetStatus(eReturnStatusFailed);
2259       return false;
2260     }
2261 
2262     if (command.GetArgumentCount() == 0) {
2263       // Dump all ASTs for all modules images
2264       result.GetOutputStream().Printf("Dumping clang ast for %" PRIu64
2265                                       " modules.\n",
2266                                       (uint64_t)num_modules);
2267       for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2268         if (m_interpreter.WasInterrupted())
2269           break;
2270         Module *m = target->GetImages().GetModulePointerAtIndex(image_idx);
2271         SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile();
2272         sf->DumpClangAST(result.GetOutputStream());
2273       }
2274       result.SetStatus(eReturnStatusSuccessFinishResult);
2275       return true;
2276     }
2277 
2278     // Dump specified ASTs (by basename or fullpath)
2279     for (const Args::ArgEntry &arg : command.entries()) {
2280       ModuleList module_list;
2281       const size_t num_matches =
2282           FindModulesByName(target, arg.c_str(), module_list, true);
2283       if (num_matches == 0) {
2284         // Check the global list
2285         std::lock_guard<std::recursive_mutex> guard(
2286             Module::GetAllocationModuleCollectionMutex());
2287 
2288         result.AppendWarningWithFormat(
2289             "Unable to find an image that matches '%s'.\n", arg.c_str());
2290         continue;
2291       }
2292 
2293       for (size_t i = 0; i < num_matches; ++i) {
2294         if (m_interpreter.WasInterrupted())
2295           break;
2296         Module *m = module_list.GetModulePointerAtIndex(i);
2297         SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile();
2298         sf->DumpClangAST(result.GetOutputStream());
2299       }
2300     }
2301     result.SetStatus(eReturnStatusSuccessFinishResult);
2302     return true;
2303   }
2304 };
2305 
2306 #pragma mark CommandObjectTargetModulesDumpSymfile
2307 
2308 //----------------------------------------------------------------------
2309 // Image debug symbol dumping command
2310 //----------------------------------------------------------------------
2311 
2312 class CommandObjectTargetModulesDumpSymfile
2313     : public CommandObjectTargetModulesModuleAutoComplete {
2314 public:
2315   CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter)
2316       : CommandObjectTargetModulesModuleAutoComplete(
2317             interpreter, "target modules dump symfile",
2318             "Dump the debug symbol file for one or more target modules.",
2319             //"target modules dump symfile [<file1> ...]")
2320             nullptr) {}
2321 
2322   ~CommandObjectTargetModulesDumpSymfile() override = default;
2323 
2324 protected:
2325   bool DoExecute(Args &command, CommandReturnObject &result) override {
2326     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2327     if (target == nullptr) {
2328       result.AppendError("invalid target, create a debug target using the "
2329                          "'target create' command");
2330       result.SetStatus(eReturnStatusFailed);
2331       return false;
2332     } else {
2333       uint32_t num_dumped = 0;
2334 
2335       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2336       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2337       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2338 
2339       if (command.GetArgumentCount() == 0) {
2340         // Dump all sections for all modules images
2341         const ModuleList &target_modules = target->GetImages();
2342         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2343         const size_t num_modules = target_modules.GetSize();
2344         if (num_modules > 0) {
2345           result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64
2346                                           " modules.\n",
2347                                           (uint64_t)num_modules);
2348           for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2349             if (m_interpreter.WasInterrupted())
2350               break;
2351             if (DumpModuleSymbolVendor(
2352                     result.GetOutputStream(),
2353                     target_modules.GetModulePointerAtIndexUnlocked(image_idx)))
2354               num_dumped++;
2355           }
2356         } else {
2357           result.AppendError("the target has no associated executable images");
2358           result.SetStatus(eReturnStatusFailed);
2359           return false;
2360         }
2361       } else {
2362         // Dump specified images (by basename or fullpath)
2363         const char *arg_cstr;
2364         for (int arg_idx = 0;
2365              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2366              ++arg_idx) {
2367           ModuleList module_list;
2368           const size_t num_matches =
2369               FindModulesByName(target, arg_cstr, module_list, true);
2370           if (num_matches > 0) {
2371             for (size_t i = 0; i < num_matches; ++i) {
2372               if (m_interpreter.WasInterrupted())
2373                 break;
2374               Module *module = module_list.GetModulePointerAtIndex(i);
2375               if (module) {
2376                 if (DumpModuleSymbolVendor(result.GetOutputStream(), module))
2377                   num_dumped++;
2378               }
2379             }
2380           } else
2381             result.AppendWarningWithFormat(
2382                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2383         }
2384       }
2385 
2386       if (num_dumped > 0)
2387         result.SetStatus(eReturnStatusSuccessFinishResult);
2388       else {
2389         result.AppendError("no matching executable images found");
2390         result.SetStatus(eReturnStatusFailed);
2391       }
2392     }
2393     return result.Succeeded();
2394   }
2395 };
2396 
2397 #pragma mark CommandObjectTargetModulesDumpLineTable
2398 
2399 //----------------------------------------------------------------------
2400 // Image debug line table dumping command
2401 //----------------------------------------------------------------------
2402 
2403 class CommandObjectTargetModulesDumpLineTable
2404     : public CommandObjectTargetModulesSourceFileAutoComplete {
2405 public:
2406   CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter)
2407       : CommandObjectTargetModulesSourceFileAutoComplete(
2408             interpreter, "target modules dump line-table",
2409             "Dump the line table for one or more compilation units.", nullptr,
2410             eCommandRequiresTarget) {}
2411 
2412   ~CommandObjectTargetModulesDumpLineTable() override = default;
2413 
2414   Options *GetOptions() override { return &m_options; }
2415 
2416 protected:
2417   bool DoExecute(Args &command, CommandReturnObject &result) override {
2418     Target *target = m_exe_ctx.GetTargetPtr();
2419     uint32_t total_num_dumped = 0;
2420 
2421     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2422     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2423     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2424 
2425     if (command.GetArgumentCount() == 0) {
2426       result.AppendError("file option must be specified.");
2427       result.SetStatus(eReturnStatusFailed);
2428       return result.Succeeded();
2429     } else {
2430       // Dump specified images (by basename or fullpath)
2431       const char *arg_cstr;
2432       for (int arg_idx = 0;
2433            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2434            ++arg_idx) {
2435         FileSpec file_spec(arg_cstr);
2436 
2437         const ModuleList &target_modules = target->GetImages();
2438         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2439         const size_t num_modules = target_modules.GetSize();
2440         if (num_modules > 0) {
2441           uint32_t num_dumped = 0;
2442           for (uint32_t i = 0; i < num_modules; ++i) {
2443             if (m_interpreter.WasInterrupted())
2444               break;
2445             if (DumpCompileUnitLineTable(
2446                     m_interpreter, result.GetOutputStream(),
2447                     target_modules.GetModulePointerAtIndexUnlocked(i),
2448                     file_spec,
2449                     m_options.m_verbose ? eDescriptionLevelFull
2450                                         : eDescriptionLevelBrief))
2451               num_dumped++;
2452           }
2453           if (num_dumped == 0)
2454             result.AppendWarningWithFormat(
2455                 "No source filenames matched '%s'.\n", arg_cstr);
2456           else
2457             total_num_dumped += num_dumped;
2458         }
2459       }
2460     }
2461 
2462     if (total_num_dumped > 0)
2463       result.SetStatus(eReturnStatusSuccessFinishResult);
2464     else {
2465       result.AppendError("no source filenames matched any command arguments");
2466       result.SetStatus(eReturnStatusFailed);
2467     }
2468     return result.Succeeded();
2469   }
2470 
2471   class CommandOptions : public Options {
2472   public:
2473     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
2474 
2475     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2476                           ExecutionContext *execution_context) override {
2477       assert(option_idx == 0 && "We only have one option.");
2478       m_verbose = true;
2479 
2480       return Status();
2481     }
2482 
2483     void OptionParsingStarting(ExecutionContext *execution_context) override {
2484       m_verbose = false;
2485     }
2486 
2487     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2488       static constexpr OptionDefinition g_options[] = {
2489           {LLDB_OPT_SET_ALL,
2490            false,
2491            "verbose",
2492            'v',
2493            OptionParser::eNoArgument,
2494            nullptr,
2495            {},
2496            0,
2497            eArgTypeNone,
2498            "Enable verbose dump."},
2499       };
2500       return llvm::makeArrayRef(g_options);
2501     }
2502 
2503     bool m_verbose;
2504   };
2505 
2506   CommandOptions m_options;
2507 };
2508 
2509 #pragma mark CommandObjectTargetModulesDump
2510 
2511 //----------------------------------------------------------------------
2512 // Dump multi-word command for target modules
2513 //----------------------------------------------------------------------
2514 
2515 class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2516 public:
2517   //------------------------------------------------------------------
2518   // Constructors and Destructors
2519   //------------------------------------------------------------------
2520   CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
2521       : CommandObjectMultiword(
2522             interpreter, "target modules dump",
2523             "Commands for dumping information about one or "
2524             "more target modules.",
2525             "target modules dump "
2526             "[headers|symtab|sections|ast|symfile|line-table] "
2527             "[<file1> <file2> ...]") {
2528     LoadSubCommand("objfile",
2529                    CommandObjectSP(
2530                        new CommandObjectTargetModulesDumpObjfile(interpreter)));
2531     LoadSubCommand(
2532         "symtab",
2533         CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter)));
2534     LoadSubCommand("sections",
2535                    CommandObjectSP(new CommandObjectTargetModulesDumpSections(
2536                        interpreter)));
2537     LoadSubCommand("symfile",
2538                    CommandObjectSP(
2539                        new CommandObjectTargetModulesDumpSymfile(interpreter)));
2540     LoadSubCommand(
2541         "ast", CommandObjectSP(
2542                    new CommandObjectTargetModulesDumpClangAST(interpreter)));
2543     LoadSubCommand("line-table",
2544                    CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
2545                        interpreter)));
2546   }
2547 
2548   ~CommandObjectTargetModulesDump() override = default;
2549 };
2550 
2551 class CommandObjectTargetModulesAdd : public CommandObjectParsed {
2552 public:
2553   CommandObjectTargetModulesAdd(CommandInterpreter &interpreter)
2554       : CommandObjectParsed(interpreter, "target modules add",
2555                             "Add a new module to the current target's modules.",
2556                             "target modules add [<module>]"),
2557         m_option_group(),
2558         m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
2559                       eArgTypeFilename, "Fullpath to a stand alone debug "
2560                                         "symbols file for when debug symbols "
2561                                         "are not in the executable.") {
2562     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2563                           LLDB_OPT_SET_1);
2564     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2565     m_option_group.Finalize();
2566   }
2567 
2568   ~CommandObjectTargetModulesAdd() override = default;
2569 
2570   Options *GetOptions() override { return &m_option_group; }
2571 
2572   int HandleArgumentCompletion(
2573       CompletionRequest &request,
2574       OptionElementVector &opt_element_vector) override {
2575     CommandCompletions::InvokeCommonCompletionCallbacks(
2576         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
2577         request, nullptr);
2578     return request.GetNumberOfMatches();
2579   }
2580 
2581 protected:
2582   OptionGroupOptions m_option_group;
2583   OptionGroupUUID m_uuid_option_group;
2584   OptionGroupFile m_symbol_file;
2585 
2586   bool DoExecute(Args &args, CommandReturnObject &result) override {
2587     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2588     if (target == nullptr) {
2589       result.AppendError("invalid target, create a debug target using the "
2590                          "'target create' command");
2591       result.SetStatus(eReturnStatusFailed);
2592       return false;
2593     } else {
2594       bool flush = false;
2595 
2596       const size_t argc = args.GetArgumentCount();
2597       if (argc == 0) {
2598         if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2599           // We are given a UUID only, go locate the file
2600           ModuleSpec module_spec;
2601           module_spec.GetUUID() =
2602               m_uuid_option_group.GetOptionValue().GetCurrentValue();
2603           if (m_symbol_file.GetOptionValue().OptionWasSet())
2604             module_spec.GetSymbolFileSpec() =
2605                 m_symbol_file.GetOptionValue().GetCurrentValue();
2606           if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
2607             ModuleSP module_sp(target->GetSharedModule(module_spec));
2608             if (module_sp) {
2609               result.SetStatus(eReturnStatusSuccessFinishResult);
2610               return true;
2611             } else {
2612               StreamString strm;
2613               module_spec.GetUUID().Dump(&strm);
2614               if (module_spec.GetFileSpec()) {
2615                 if (module_spec.GetSymbolFileSpec()) {
2616                   result.AppendErrorWithFormat(
2617                       "Unable to create the executable or symbol file with "
2618                       "UUID %s with path %s and symbol file %s",
2619                       strm.GetData(),
2620                       module_spec.GetFileSpec().GetPath().c_str(),
2621                       module_spec.GetSymbolFileSpec().GetPath().c_str());
2622                 } else {
2623                   result.AppendErrorWithFormat(
2624                       "Unable to create the executable or symbol file with "
2625                       "UUID %s with path %s",
2626                       strm.GetData(),
2627                       module_spec.GetFileSpec().GetPath().c_str());
2628                 }
2629               } else {
2630                 result.AppendErrorWithFormat("Unable to create the executable "
2631                                              "or symbol file with UUID %s",
2632                                              strm.GetData());
2633               }
2634               result.SetStatus(eReturnStatusFailed);
2635               return false;
2636             }
2637           } else {
2638             StreamString strm;
2639             module_spec.GetUUID().Dump(&strm);
2640             result.AppendErrorWithFormat(
2641                 "Unable to locate the executable or symbol file with UUID %s",
2642                 strm.GetData());
2643             result.SetStatus(eReturnStatusFailed);
2644             return false;
2645           }
2646         } else {
2647           result.AppendError(
2648               "one or more executable image paths must be specified");
2649           result.SetStatus(eReturnStatusFailed);
2650           return false;
2651         }
2652       } else {
2653         for (auto &entry : args.entries()) {
2654           if (entry.ref.empty())
2655             continue;
2656 
2657           FileSpec file_spec(entry.ref);
2658           if (FileSystem::Instance().Exists(file_spec)) {
2659             ModuleSpec module_spec(file_spec);
2660             if (m_uuid_option_group.GetOptionValue().OptionWasSet())
2661               module_spec.GetUUID() =
2662                   m_uuid_option_group.GetOptionValue().GetCurrentValue();
2663             if (m_symbol_file.GetOptionValue().OptionWasSet())
2664               module_spec.GetSymbolFileSpec() =
2665                   m_symbol_file.GetOptionValue().GetCurrentValue();
2666             if (!module_spec.GetArchitecture().IsValid())
2667               module_spec.GetArchitecture() = target->GetArchitecture();
2668             Status error;
2669             ModuleSP module_sp(target->GetSharedModule(module_spec, &error));
2670             if (!module_sp) {
2671               const char *error_cstr = error.AsCString();
2672               if (error_cstr)
2673                 result.AppendError(error_cstr);
2674               else
2675                 result.AppendErrorWithFormat("unsupported module: %s",
2676                                              entry.c_str());
2677               result.SetStatus(eReturnStatusFailed);
2678               return false;
2679             } else {
2680               flush = true;
2681             }
2682             result.SetStatus(eReturnStatusSuccessFinishResult);
2683           } else {
2684             std::string resolved_path = file_spec.GetPath();
2685             result.SetStatus(eReturnStatusFailed);
2686             if (resolved_path != entry.ref) {
2687               result.AppendErrorWithFormat(
2688                   "invalid module path '%s' with resolved path '%s'\n",
2689                   entry.ref.str().c_str(), resolved_path.c_str());
2690               break;
2691             }
2692             result.AppendErrorWithFormat("invalid module path '%s'\n",
2693                                          entry.c_str());
2694             break;
2695           }
2696         }
2697       }
2698 
2699       if (flush) {
2700         ProcessSP process = target->GetProcessSP();
2701         if (process)
2702           process->Flush();
2703       }
2704     }
2705 
2706     return result.Succeeded();
2707   }
2708 };
2709 
2710 class CommandObjectTargetModulesLoad
2711     : public CommandObjectTargetModulesModuleAutoComplete {
2712 public:
2713   CommandObjectTargetModulesLoad(CommandInterpreter &interpreter)
2714       : CommandObjectTargetModulesModuleAutoComplete(
2715             interpreter, "target modules load", "Set the load addresses for "
2716                                                 "one or more sections in a "
2717                                                 "target module.",
2718             "target modules load [--file <module> --uuid <uuid>] <sect-name> "
2719             "<address> [<sect-name> <address> ....]"),
2720         m_option_group(),
2721         m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName,
2722                       "Fullpath or basename for module to load.", ""),
2723         m_load_option(LLDB_OPT_SET_1, false, "load", 'l',
2724                       "Write file contents to the memory.", false, true),
2725         m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p',
2726                     "Set PC to the entry point."
2727                     " Only applicable with '--load' option.",
2728                     false, true),
2729         m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset,
2730                        "Set the load address for all sections to be the "
2731                        "virtual address in the file plus the offset.",
2732                        0) {
2733     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2734                           LLDB_OPT_SET_1);
2735     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2736     m_option_group.Append(&m_load_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2737     m_option_group.Append(&m_pc_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2738     m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2739     m_option_group.Finalize();
2740   }
2741 
2742   ~CommandObjectTargetModulesLoad() override = default;
2743 
2744   Options *GetOptions() override { return &m_option_group; }
2745 
2746 protected:
2747   bool DoExecute(Args &args, CommandReturnObject &result) override {
2748     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2749     const bool load = m_load_option.GetOptionValue().GetCurrentValue();
2750     const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();
2751     if (target == nullptr) {
2752       result.AppendError("invalid target, create a debug target using the "
2753                          "'target create' command");
2754       result.SetStatus(eReturnStatusFailed);
2755       return false;
2756     } else {
2757       const size_t argc = args.GetArgumentCount();
2758       ModuleSpec module_spec;
2759       bool search_using_module_spec = false;
2760 
2761       // Allow "load" option to work without --file or --uuid option.
2762       if (load) {
2763         if (!m_file_option.GetOptionValue().OptionWasSet() &&
2764             !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2765           ModuleList &module_list = target->GetImages();
2766           if (module_list.GetSize() == 1) {
2767             search_using_module_spec = true;
2768             module_spec.GetFileSpec() =
2769                 module_list.GetModuleAtIndex(0)->GetFileSpec();
2770           }
2771         }
2772       }
2773 
2774       if (m_file_option.GetOptionValue().OptionWasSet()) {
2775         search_using_module_spec = true;
2776         const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
2777         const bool use_global_module_list = true;
2778         ModuleList module_list;
2779         const size_t num_matches = FindModulesByName(
2780             target, arg_cstr, module_list, use_global_module_list);
2781         if (num_matches == 1) {
2782           module_spec.GetFileSpec() =
2783               module_list.GetModuleAtIndex(0)->GetFileSpec();
2784         } else if (num_matches > 1) {
2785           search_using_module_spec = false;
2786           result.AppendErrorWithFormat(
2787               "more than 1 module matched by name '%s'\n", arg_cstr);
2788           result.SetStatus(eReturnStatusFailed);
2789         } else {
2790           search_using_module_spec = false;
2791           result.AppendErrorWithFormat("no object file for module '%s'\n",
2792                                        arg_cstr);
2793           result.SetStatus(eReturnStatusFailed);
2794         }
2795       }
2796 
2797       if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2798         search_using_module_spec = true;
2799         module_spec.GetUUID() =
2800             m_uuid_option_group.GetOptionValue().GetCurrentValue();
2801       }
2802 
2803       if (search_using_module_spec) {
2804         ModuleList matching_modules;
2805         const size_t num_matches =
2806             target->GetImages().FindModules(module_spec, matching_modules);
2807 
2808         char path[PATH_MAX];
2809         if (num_matches == 1) {
2810           Module *module = matching_modules.GetModulePointerAtIndex(0);
2811           if (module) {
2812             ObjectFile *objfile = module->GetObjectFile();
2813             if (objfile) {
2814               SectionList *section_list = module->GetSectionList();
2815               if (section_list) {
2816                 bool changed = false;
2817                 if (argc == 0) {
2818                   if (m_slide_option.GetOptionValue().OptionWasSet()) {
2819                     const addr_t slide =
2820                         m_slide_option.GetOptionValue().GetCurrentValue();
2821                     const bool slide_is_offset = true;
2822                     module->SetLoadAddress(*target, slide, slide_is_offset,
2823                                            changed);
2824                   } else {
2825                     result.AppendError("one or more section name + load "
2826                                        "address pair must be specified");
2827                     result.SetStatus(eReturnStatusFailed);
2828                     return false;
2829                   }
2830                 } else {
2831                   if (m_slide_option.GetOptionValue().OptionWasSet()) {
2832                     result.AppendError("The \"--slide <offset>\" option can't "
2833                                        "be used in conjunction with setting "
2834                                        "section load addresses.\n");
2835                     result.SetStatus(eReturnStatusFailed);
2836                     return false;
2837                   }
2838 
2839                   for (size_t i = 0; i < argc; i += 2) {
2840                     const char *sect_name = args.GetArgumentAtIndex(i);
2841                     const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1);
2842                     if (sect_name && load_addr_cstr) {
2843                       ConstString const_sect_name(sect_name);
2844                       bool success = false;
2845                       addr_t load_addr = StringConvert::ToUInt64(
2846                           load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success);
2847                       if (success) {
2848                         SectionSP section_sp(
2849                             section_list->FindSectionByName(const_sect_name));
2850                         if (section_sp) {
2851                           if (section_sp->IsThreadSpecific()) {
2852                             result.AppendErrorWithFormat(
2853                                 "thread specific sections are not yet "
2854                                 "supported (section '%s')\n",
2855                                 sect_name);
2856                             result.SetStatus(eReturnStatusFailed);
2857                             break;
2858                           } else {
2859                             if (target->GetSectionLoadList()
2860                                     .SetSectionLoadAddress(section_sp,
2861                                                            load_addr))
2862                               changed = true;
2863                             result.AppendMessageWithFormat(
2864                                 "section '%s' loaded at 0x%" PRIx64 "\n",
2865                                 sect_name, load_addr);
2866                           }
2867                         } else {
2868                           result.AppendErrorWithFormat("no section found that "
2869                                                        "matches the section "
2870                                                        "name '%s'\n",
2871                                                        sect_name);
2872                           result.SetStatus(eReturnStatusFailed);
2873                           break;
2874                         }
2875                       } else {
2876                         result.AppendErrorWithFormat(
2877                             "invalid load address string '%s'\n",
2878                             load_addr_cstr);
2879                         result.SetStatus(eReturnStatusFailed);
2880                         break;
2881                       }
2882                     } else {
2883                       if (sect_name)
2884                         result.AppendError("section names must be followed by "
2885                                            "a load address.\n");
2886                       else
2887                         result.AppendError("one or more section name + load "
2888                                            "address pair must be specified.\n");
2889                       result.SetStatus(eReturnStatusFailed);
2890                       break;
2891                     }
2892                   }
2893                 }
2894 
2895                 if (changed) {
2896                   target->ModulesDidLoad(matching_modules);
2897                   Process *process = m_exe_ctx.GetProcessPtr();
2898                   if (process)
2899                     process->Flush();
2900                 }
2901                 if (load) {
2902                   ProcessSP process = target->CalculateProcess();
2903                   Address file_entry = objfile->GetEntryPointAddress();
2904                   if (!process) {
2905                     result.AppendError("No process");
2906                     return false;
2907                   }
2908                   if (set_pc && !file_entry.IsValid()) {
2909                     result.AppendError("No entry address in object file");
2910                     return false;
2911                   }
2912                   std::vector<ObjectFile::LoadableData> loadables(
2913                       objfile->GetLoadableData(*target));
2914                   if (loadables.size() == 0) {
2915                     result.AppendError("No loadable sections");
2916                     return false;
2917                   }
2918                   Status error = process->WriteObjectFile(std::move(loadables));
2919                   if (error.Fail()) {
2920                     result.AppendError(error.AsCString());
2921                     return false;
2922                   }
2923                   if (set_pc) {
2924                     ThreadList &thread_list = process->GetThreadList();
2925                     RegisterContextSP reg_context(
2926                         thread_list.GetSelectedThread()->GetRegisterContext());
2927                     addr_t file_entry_addr = file_entry.GetLoadAddress(target);
2928                     if (!reg_context->SetPC(file_entry_addr)) {
2929                       result.AppendErrorWithFormat("failed to set PC value to "
2930                                                    "0x%" PRIx64 "\n",
2931                                                    file_entry_addr);
2932                       result.SetStatus(eReturnStatusFailed);
2933                     }
2934                   }
2935                 }
2936               } else {
2937                 module->GetFileSpec().GetPath(path, sizeof(path));
2938                 result.AppendErrorWithFormat(
2939                     "no sections in object file '%s'\n", path);
2940                 result.SetStatus(eReturnStatusFailed);
2941               }
2942             } else {
2943               module->GetFileSpec().GetPath(path, sizeof(path));
2944               result.AppendErrorWithFormat("no object file for module '%s'\n",
2945                                            path);
2946               result.SetStatus(eReturnStatusFailed);
2947             }
2948           } else {
2949             FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
2950             if (module_spec_file) {
2951               module_spec_file->GetPath(path, sizeof(path));
2952               result.AppendErrorWithFormat("invalid module '%s'.\n", path);
2953             } else
2954               result.AppendError("no module spec");
2955             result.SetStatus(eReturnStatusFailed);
2956           }
2957         } else {
2958           std::string uuid_str;
2959 
2960           if (module_spec.GetFileSpec())
2961             module_spec.GetFileSpec().GetPath(path, sizeof(path));
2962           else
2963             path[0] = '\0';
2964 
2965           if (module_spec.GetUUIDPtr())
2966             uuid_str = module_spec.GetUUID().GetAsString();
2967           if (num_matches > 1) {
2968             result.AppendErrorWithFormat(
2969                 "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "",
2970                 path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2971             for (size_t i = 0; i < num_matches; ++i) {
2972               if (matching_modules.GetModulePointerAtIndex(i)
2973                       ->GetFileSpec()
2974                       .GetPath(path, sizeof(path)))
2975                 result.AppendMessageWithFormat("%s\n", path);
2976             }
2977           } else {
2978             result.AppendErrorWithFormat(
2979                 "no modules were found  that match%s%s%s%s.\n",
2980                 path[0] ? " file=" : "", path,
2981                 !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2982           }
2983           result.SetStatus(eReturnStatusFailed);
2984         }
2985       } else {
2986         result.AppendError("either the \"--file <module>\" or the \"--uuid "
2987                            "<uuid>\" option must be specified.\n");
2988         result.SetStatus(eReturnStatusFailed);
2989         return false;
2990       }
2991     }
2992     return result.Succeeded();
2993   }
2994 
2995   OptionGroupOptions m_option_group;
2996   OptionGroupUUID m_uuid_option_group;
2997   OptionGroupString m_file_option;
2998   OptionGroupBoolean m_load_option;
2999   OptionGroupBoolean m_pc_option;
3000   OptionGroupUInt64 m_slide_option;
3001 };
3002 
3003 //----------------------------------------------------------------------
3004 // List images with associated information
3005 //----------------------------------------------------------------------
3006 
3007 static constexpr OptionDefinition g_target_modules_list_options[] = {
3008     // clang-format off
3009   { LLDB_OPT_SET_1, false, "address",        'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Display the image at this address." },
3010   { LLDB_OPT_SET_1, false, "arch",           'A', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the architecture when listing images." },
3011   { LLDB_OPT_SET_1, false, "triple",         't', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the triple when listing images." },
3012   { 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." },
3013   { 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)." },
3014   { LLDB_OPT_SET_1, false, "uuid",           'u', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Display the UUID when listing images." },
3015   { LLDB_OPT_SET_1, false, "fullpath",       'f', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the fullpath to the image object file." },
3016   { LLDB_OPT_SET_1, false, "directory",      'd', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the directory with optional width for the image object file." },
3017   { LLDB_OPT_SET_1, false, "basename",       'b', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the basename with optional width for the image object file." },
3018   { LLDB_OPT_SET_1, false, "symfile",        's', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the fullpath to the image symbol file with optional width." },
3019   { 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." },
3020   { LLDB_OPT_SET_1, false, "mod-time",       'm', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the modification time with optional width of the module." },
3021   { 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." },
3022   { LLDB_OPT_SET_1, false, "pointer",        'p', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeNone,                "Display the module pointer." },
3023   { 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." }
3024     // clang-format on
3025 };
3026 
3027 class CommandObjectTargetModulesList : public CommandObjectParsed {
3028 public:
3029   class CommandOptions : public Options {
3030   public:
3031     CommandOptions()
3032         : Options(), m_format_array(), m_use_global_module_list(false),
3033           m_module_addr(LLDB_INVALID_ADDRESS) {}
3034 
3035     ~CommandOptions() override = default;
3036 
3037     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3038                           ExecutionContext *execution_context) override {
3039       Status error;
3040 
3041       const int short_option = m_getopt_table[option_idx].val;
3042       if (short_option == 'g') {
3043         m_use_global_module_list = true;
3044       } else if (short_option == 'a') {
3045         m_module_addr = OptionArgParser::ToAddress(
3046             execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
3047       } else {
3048         unsigned long width = 0;
3049         option_arg.getAsInteger(0, width);
3050         m_format_array.push_back(std::make_pair(short_option, width));
3051       }
3052       return error;
3053     }
3054 
3055     void OptionParsingStarting(ExecutionContext *execution_context) override {
3056       m_format_array.clear();
3057       m_use_global_module_list = false;
3058       m_module_addr = LLDB_INVALID_ADDRESS;
3059     }
3060 
3061     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3062       return llvm::makeArrayRef(g_target_modules_list_options);
3063     }
3064 
3065     // Instance variables to hold the values for command options.
3066     typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
3067     FormatWidthCollection m_format_array;
3068     bool m_use_global_module_list;
3069     lldb::addr_t m_module_addr;
3070   };
3071 
3072   CommandObjectTargetModulesList(CommandInterpreter &interpreter)
3073       : CommandObjectParsed(
3074             interpreter, "target modules list",
3075             "List current executable and dependent shared library images.",
3076             "target modules list [<cmd-options>]"),
3077         m_options() {}
3078 
3079   ~CommandObjectTargetModulesList() override = default;
3080 
3081   Options *GetOptions() override { return &m_options; }
3082 
3083 protected:
3084   bool DoExecute(Args &command, CommandReturnObject &result) override {
3085     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
3086     const bool use_global_module_list = m_options.m_use_global_module_list;
3087     // Define a local module list here to ensure it lives longer than any
3088     // "locker" object which might lock its contents below (through the
3089     // "module_list_ptr" variable).
3090     ModuleList module_list;
3091     if (target == nullptr && !use_global_module_list) {
3092       result.AppendError("invalid target, create a debug target using the "
3093                          "'target create' command");
3094       result.SetStatus(eReturnStatusFailed);
3095       return false;
3096     } else {
3097       if (target) {
3098         uint32_t addr_byte_size =
3099             target->GetArchitecture().GetAddressByteSize();
3100         result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3101         result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3102       }
3103       // Dump all sections for all modules images
3104       Stream &strm = result.GetOutputStream();
3105 
3106       if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) {
3107         if (target) {
3108           Address module_address;
3109           if (module_address.SetLoadAddress(m_options.m_module_addr, target)) {
3110             ModuleSP module_sp(module_address.GetModule());
3111             if (module_sp) {
3112               PrintModule(target, module_sp.get(), 0, strm);
3113               result.SetStatus(eReturnStatusSuccessFinishResult);
3114             } else {
3115               result.AppendErrorWithFormat(
3116                   "Couldn't find module matching address: 0x%" PRIx64 ".",
3117                   m_options.m_module_addr);
3118               result.SetStatus(eReturnStatusFailed);
3119             }
3120           } else {
3121             result.AppendErrorWithFormat(
3122                 "Couldn't find module containing address: 0x%" PRIx64 ".",
3123                 m_options.m_module_addr);
3124             result.SetStatus(eReturnStatusFailed);
3125           }
3126         } else {
3127           result.AppendError(
3128               "Can only look up modules by address with a valid target.");
3129           result.SetStatus(eReturnStatusFailed);
3130         }
3131         return result.Succeeded();
3132       }
3133 
3134       size_t num_modules = 0;
3135 
3136       // This locker will be locked on the mutex in module_list_ptr if it is
3137       // non-nullptr. Otherwise it will lock the
3138       // AllocationModuleCollectionMutex when accessing the global module list
3139       // directly.
3140       std::unique_lock<std::recursive_mutex> guard(
3141           Module::GetAllocationModuleCollectionMutex(), std::defer_lock);
3142 
3143       const ModuleList *module_list_ptr = nullptr;
3144       const size_t argc = command.GetArgumentCount();
3145       if (argc == 0) {
3146         if (use_global_module_list) {
3147           guard.lock();
3148           num_modules = Module::GetNumberAllocatedModules();
3149         } else {
3150           module_list_ptr = &target->GetImages();
3151         }
3152       } else {
3153         // TODO: Convert to entry based iteration.  Requires converting
3154         // FindModulesByName.
3155         for (size_t i = 0; i < argc; ++i) {
3156           // Dump specified images (by basename or fullpath)
3157           const char *arg_cstr = command.GetArgumentAtIndex(i);
3158           const size_t num_matches = FindModulesByName(
3159               target, arg_cstr, module_list, use_global_module_list);
3160           if (num_matches == 0) {
3161             if (argc == 1) {
3162               result.AppendErrorWithFormat("no modules found that match '%s'",
3163                                            arg_cstr);
3164               result.SetStatus(eReturnStatusFailed);
3165               return false;
3166             }
3167           }
3168         }
3169 
3170         module_list_ptr = &module_list;
3171       }
3172 
3173       std::unique_lock<std::recursive_mutex> lock;
3174       if (module_list_ptr != nullptr) {
3175         lock =
3176             std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex());
3177 
3178         num_modules = module_list_ptr->GetSize();
3179       }
3180 
3181       if (num_modules > 0) {
3182         for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
3183           ModuleSP module_sp;
3184           Module *module;
3185           if (module_list_ptr) {
3186             module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx);
3187             module = module_sp.get();
3188           } else {
3189             module = Module::GetAllocatedModuleAtIndex(image_idx);
3190             module_sp = module->shared_from_this();
3191           }
3192 
3193           const size_t indent = strm.Printf("[%3u] ", image_idx);
3194           PrintModule(target, module, indent, strm);
3195         }
3196         result.SetStatus(eReturnStatusSuccessFinishResult);
3197       } else {
3198         if (argc) {
3199           if (use_global_module_list)
3200             result.AppendError(
3201                 "the global module list has no matching modules");
3202           else
3203             result.AppendError("the target has no matching modules");
3204         } else {
3205           if (use_global_module_list)
3206             result.AppendError("the global module list is empty");
3207           else
3208             result.AppendError(
3209                 "the target has no associated executable images");
3210         }
3211         result.SetStatus(eReturnStatusFailed);
3212         return false;
3213       }
3214     }
3215     return result.Succeeded();
3216   }
3217 
3218   void PrintModule(Target *target, Module *module, int indent, Stream &strm) {
3219     if (module == nullptr) {
3220       strm.PutCString("Null module");
3221       return;
3222     }
3223 
3224     bool dump_object_name = false;
3225     if (m_options.m_format_array.empty()) {
3226       m_options.m_format_array.push_back(std::make_pair('u', 0));
3227       m_options.m_format_array.push_back(std::make_pair('h', 0));
3228       m_options.m_format_array.push_back(std::make_pair('f', 0));
3229       m_options.m_format_array.push_back(std::make_pair('S', 0));
3230     }
3231     const size_t num_entries = m_options.m_format_array.size();
3232     bool print_space = false;
3233     for (size_t i = 0; i < num_entries; ++i) {
3234       if (print_space)
3235         strm.PutChar(' ');
3236       print_space = true;
3237       const char format_char = m_options.m_format_array[i].first;
3238       uint32_t width = m_options.m_format_array[i].second;
3239       switch (format_char) {
3240       case 'A':
3241         DumpModuleArchitecture(strm, module, false, width);
3242         break;
3243 
3244       case 't':
3245         DumpModuleArchitecture(strm, module, true, width);
3246         break;
3247 
3248       case 'f':
3249         DumpFullpath(strm, &module->GetFileSpec(), width);
3250         dump_object_name = true;
3251         break;
3252 
3253       case 'd':
3254         DumpDirectory(strm, &module->GetFileSpec(), width);
3255         break;
3256 
3257       case 'b':
3258         DumpBasename(strm, &module->GetFileSpec(), width);
3259         dump_object_name = true;
3260         break;
3261 
3262       case 'h':
3263       case 'o':
3264         // Image header address
3265         {
3266           uint32_t addr_nibble_width =
3267               target ? (target->GetArchitecture().GetAddressByteSize() * 2)
3268                      : 16;
3269 
3270           ObjectFile *objfile = module->GetObjectFile();
3271           if (objfile) {
3272             Address base_addr(objfile->GetBaseAddress());
3273             if (base_addr.IsValid()) {
3274               if (target && !target->GetSectionLoadList().IsEmpty()) {
3275                 lldb::addr_t load_addr =
3276                     base_addr.GetLoadAddress(target);
3277                 if (load_addr == LLDB_INVALID_ADDRESS) {
3278                   base_addr.Dump(&strm, target,
3279                                    Address::DumpStyleModuleWithFileAddress,
3280                                    Address::DumpStyleFileAddress);
3281                 } else {
3282                   if (format_char == 'o') {
3283                     // Show the offset of slide for the image
3284                     strm.Printf(
3285                         "0x%*.*" PRIx64, addr_nibble_width, addr_nibble_width,
3286                         load_addr - base_addr.GetFileAddress());
3287                   } else {
3288                     // Show the load address of the image
3289                     strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
3290                                 addr_nibble_width, load_addr);
3291                   }
3292                 }
3293                 break;
3294               }
3295               // The address was valid, but the image isn't loaded, output the
3296               // address in an appropriate format
3297               base_addr.Dump(&strm, target, Address::DumpStyleFileAddress);
3298               break;
3299             }
3300           }
3301           strm.Printf("%*s", addr_nibble_width + 2, "");
3302         }
3303         break;
3304 
3305       case 'r': {
3306         size_t ref_count = 0;
3307         ModuleSP module_sp(module->shared_from_this());
3308         if (module_sp) {
3309           // Take one away to make sure we don't count our local "module_sp"
3310           ref_count = module_sp.use_count() - 1;
3311         }
3312         if (width)
3313           strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count);
3314         else
3315           strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count);
3316       } break;
3317 
3318       case 's':
3319       case 'S': {
3320         const SymbolVendor *symbol_vendor = module->GetSymbolVendor();
3321         if (symbol_vendor) {
3322           const FileSpec symfile_spec = symbol_vendor->GetMainFileSpec();
3323           if (format_char == 'S') {
3324             // Dump symbol file only if different from module file
3325             if (!symfile_spec || symfile_spec == module->GetFileSpec()) {
3326               print_space = false;
3327               break;
3328             }
3329             // Add a newline and indent past the index
3330             strm.Printf("\n%*s", indent, "");
3331           }
3332           DumpFullpath(strm, &symfile_spec, width);
3333           dump_object_name = true;
3334           break;
3335         }
3336         strm.Printf("%.*s", width, "<NONE>");
3337       } break;
3338 
3339       case 'm':
3340         strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(),
3341                                               llvm::AlignStyle::Left, width));
3342         break;
3343 
3344       case 'p':
3345         strm.Printf("%p", static_cast<void *>(module));
3346         break;
3347 
3348       case 'u':
3349         DumpModuleUUID(strm, module);
3350         break;
3351 
3352       default:
3353         break;
3354       }
3355     }
3356     if (dump_object_name) {
3357       const char *object_name = module->GetObjectName().GetCString();
3358       if (object_name)
3359         strm.Printf("(%s)", object_name);
3360     }
3361     strm.EOL();
3362   }
3363 
3364   CommandOptions m_options;
3365 };
3366 
3367 #pragma mark CommandObjectTargetModulesShowUnwind
3368 
3369 //----------------------------------------------------------------------
3370 // Lookup unwind information in images
3371 //----------------------------------------------------------------------
3372 
3373 static constexpr OptionDefinition g_target_modules_show_unwind_options[] = {
3374     // clang-format off
3375   { LLDB_OPT_SET_1, false, "name",    'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName,        "Show unwind instructions for a function or symbol name." },
3376   { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" }
3377     // clang-format on
3378 };
3379 
3380 class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
3381 public:
3382   enum {
3383     eLookupTypeInvalid = -1,
3384     eLookupTypeAddress = 0,
3385     eLookupTypeSymbol,
3386     eLookupTypeFunction,
3387     eLookupTypeFunctionOrSymbol,
3388     kNumLookupTypes
3389   };
3390 
3391   class CommandOptions : public Options {
3392   public:
3393     CommandOptions()
3394         : Options(), m_type(eLookupTypeInvalid), m_str(),
3395           m_addr(LLDB_INVALID_ADDRESS) {}
3396 
3397     ~CommandOptions() override = default;
3398 
3399     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3400                           ExecutionContext *execution_context) override {
3401       Status error;
3402 
3403       const int short_option = m_getopt_table[option_idx].val;
3404 
3405       switch (short_option) {
3406       case 'a': {
3407         m_str = option_arg;
3408         m_type = eLookupTypeAddress;
3409         m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3410                                             LLDB_INVALID_ADDRESS, &error);
3411         if (m_addr == LLDB_INVALID_ADDRESS)
3412           error.SetErrorStringWithFormat("invalid address string '%s'",
3413                                          option_arg.str().c_str());
3414         break;
3415       }
3416 
3417       case 'n':
3418         m_str = option_arg;
3419         m_type = eLookupTypeFunctionOrSymbol;
3420         break;
3421 
3422       default:
3423         error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
3424         break;
3425       }
3426 
3427       return error;
3428     }
3429 
3430     void OptionParsingStarting(ExecutionContext *execution_context) override {
3431       m_type = eLookupTypeInvalid;
3432       m_str.clear();
3433       m_addr = LLDB_INVALID_ADDRESS;
3434     }
3435 
3436     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3437       return llvm::makeArrayRef(g_target_modules_show_unwind_options);
3438     }
3439 
3440     // Instance variables to hold the values for command options.
3441 
3442     int m_type;        // Should be a eLookupTypeXXX enum after parsing options
3443     std::string m_str; // Holds name lookup
3444     lldb::addr_t m_addr; // Holds the address to lookup
3445   };
3446 
3447   CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
3448       : CommandObjectParsed(
3449             interpreter, "target modules show-unwind",
3450             "Show synthesized unwind instructions for a function.", nullptr,
3451             eCommandRequiresTarget | eCommandRequiresProcess |
3452                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
3453         m_options() {}
3454 
3455   ~CommandObjectTargetModulesShowUnwind() override = default;
3456 
3457   Options *GetOptions() override { return &m_options; }
3458 
3459 protected:
3460   bool DoExecute(Args &command, CommandReturnObject &result) override {
3461     Target *target = m_exe_ctx.GetTargetPtr();
3462     Process *process = m_exe_ctx.GetProcessPtr();
3463     ABI *abi = nullptr;
3464     if (process)
3465       abi = process->GetABI().get();
3466 
3467     if (process == nullptr) {
3468       result.AppendError(
3469           "You must have a process running to use this command.");
3470       result.SetStatus(eReturnStatusFailed);
3471       return false;
3472     }
3473 
3474     ThreadList threads(process->GetThreadList());
3475     if (threads.GetSize() == 0) {
3476       result.AppendError("The process must be paused to use this command.");
3477       result.SetStatus(eReturnStatusFailed);
3478       return false;
3479     }
3480 
3481     ThreadSP thread(threads.GetThreadAtIndex(0));
3482     if (!thread) {
3483       result.AppendError("The process must be paused to use this command.");
3484       result.SetStatus(eReturnStatusFailed);
3485       return false;
3486     }
3487 
3488     SymbolContextList sc_list;
3489 
3490     if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
3491       ConstString function_name(m_options.m_str.c_str());
3492       target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto,
3493                                         true, false, true, sc_list);
3494     } else if (m_options.m_type == eLookupTypeAddress && target) {
3495       Address addr;
3496       if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr,
3497                                                           addr)) {
3498         SymbolContext sc;
3499         ModuleSP module_sp(addr.GetModule());
3500         module_sp->ResolveSymbolContextForAddress(addr,
3501                                                   eSymbolContextEverything, sc);
3502         if (sc.function || sc.symbol) {
3503           sc_list.Append(sc);
3504         }
3505       }
3506     } else {
3507       result.AppendError(
3508           "address-expression or function name option must be specified.");
3509       result.SetStatus(eReturnStatusFailed);
3510       return false;
3511     }
3512 
3513     size_t num_matches = sc_list.GetSize();
3514     if (num_matches == 0) {
3515       result.AppendErrorWithFormat("no unwind data found that matches '%s'.",
3516                                    m_options.m_str.c_str());
3517       result.SetStatus(eReturnStatusFailed);
3518       return false;
3519     }
3520 
3521     for (uint32_t idx = 0; idx < num_matches; idx++) {
3522       SymbolContext sc;
3523       sc_list.GetContextAtIndex(idx, sc);
3524       if (sc.symbol == nullptr && sc.function == nullptr)
3525         continue;
3526       if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr)
3527         continue;
3528       AddressRange range;
3529       if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
3530                               false, range))
3531         continue;
3532       if (!range.GetBaseAddress().IsValid())
3533         continue;
3534       ConstString funcname(sc.GetFunctionName());
3535       if (funcname.IsEmpty())
3536         continue;
3537       addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target);
3538       if (abi)
3539         start_addr = abi->FixCodeAddress(start_addr);
3540 
3541       FuncUnwindersSP func_unwinders_sp(
3542           sc.module_sp->GetObjectFile()
3543               ->GetUnwindTable()
3544               .GetUncachedFuncUnwindersContainingAddress(start_addr, sc));
3545       if (!func_unwinders_sp)
3546         continue;
3547 
3548       result.GetOutputStream().Printf(
3549           "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n",
3550           sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
3551           funcname.AsCString(), start_addr);
3552 
3553       UnwindPlanSP non_callsite_unwind_plan =
3554           func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread, -1);
3555       if (non_callsite_unwind_plan) {
3556         result.GetOutputStream().Printf(
3557             "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
3558             non_callsite_unwind_plan->GetSourceName().AsCString());
3559       }
3560       UnwindPlanSP callsite_unwind_plan =
3561           func_unwinders_sp->GetUnwindPlanAtCallSite(*target, -1);
3562       if (callsite_unwind_plan) {
3563         result.GetOutputStream().Printf(
3564             "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
3565             callsite_unwind_plan->GetSourceName().AsCString());
3566       }
3567       UnwindPlanSP fast_unwind_plan =
3568           func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
3569       if (fast_unwind_plan) {
3570         result.GetOutputStream().Printf(
3571             "Fast UnwindPlan is '%s'\n",
3572             fast_unwind_plan->GetSourceName().AsCString());
3573       }
3574 
3575       result.GetOutputStream().Printf("\n");
3576 
3577       UnwindPlanSP assembly_sp =
3578           func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread, 0);
3579       if (assembly_sp) {
3580         result.GetOutputStream().Printf(
3581             "Assembly language inspection UnwindPlan:\n");
3582         assembly_sp->Dump(result.GetOutputStream(), thread.get(),
3583                           LLDB_INVALID_ADDRESS);
3584         result.GetOutputStream().Printf("\n");
3585       }
3586 
3587       UnwindPlanSP ehframe_sp =
3588           func_unwinders_sp->GetEHFrameUnwindPlan(*target, 0);
3589       if (ehframe_sp) {
3590         result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
3591         ehframe_sp->Dump(result.GetOutputStream(), thread.get(),
3592                          LLDB_INVALID_ADDRESS);
3593         result.GetOutputStream().Printf("\n");
3594       }
3595 
3596       UnwindPlanSP ehframe_augmented_sp =
3597           func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread, 0);
3598       if (ehframe_augmented_sp) {
3599         result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
3600         ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3601                                    LLDB_INVALID_ADDRESS);
3602         result.GetOutputStream().Printf("\n");
3603       }
3604 
3605       if (UnwindPlanSP plan_sp =
3606               func_unwinders_sp->GetDebugFrameUnwindPlan(*target, 0)) {
3607         result.GetOutputStream().Printf("debug_frame UnwindPlan:\n");
3608         plan_sp->Dump(result.GetOutputStream(), thread.get(),
3609                       LLDB_INVALID_ADDRESS);
3610         result.GetOutputStream().Printf("\n");
3611       }
3612 
3613       if (UnwindPlanSP plan_sp =
3614               func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target,
3615                                                                   *thread, 0)) {
3616         result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n");
3617         plan_sp->Dump(result.GetOutputStream(), thread.get(),
3618                       LLDB_INVALID_ADDRESS);
3619         result.GetOutputStream().Printf("\n");
3620       }
3621 
3622       UnwindPlanSP arm_unwind_sp =
3623           func_unwinders_sp->GetArmUnwindUnwindPlan(*target, 0);
3624       if (arm_unwind_sp) {
3625         result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
3626         arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3627                             LLDB_INVALID_ADDRESS);
3628         result.GetOutputStream().Printf("\n");
3629       }
3630 
3631       UnwindPlanSP compact_unwind_sp =
3632           func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0);
3633       if (compact_unwind_sp) {
3634         result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
3635         compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3636                                 LLDB_INVALID_ADDRESS);
3637         result.GetOutputStream().Printf("\n");
3638       }
3639 
3640       if (fast_unwind_plan) {
3641         result.GetOutputStream().Printf("Fast UnwindPlan:\n");
3642         fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(),
3643                                LLDB_INVALID_ADDRESS);
3644         result.GetOutputStream().Printf("\n");
3645       }
3646 
3647       ABISP abi_sp = process->GetABI();
3648       if (abi_sp) {
3649         UnwindPlan arch_default(lldb::eRegisterKindGeneric);
3650         if (abi_sp->CreateDefaultUnwindPlan(arch_default)) {
3651           result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
3652           arch_default.Dump(result.GetOutputStream(), thread.get(),
3653                             LLDB_INVALID_ADDRESS);
3654           result.GetOutputStream().Printf("\n");
3655         }
3656 
3657         UnwindPlan arch_entry(lldb::eRegisterKindGeneric);
3658         if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) {
3659           result.GetOutputStream().Printf(
3660               "Arch default at entry point UnwindPlan:\n");
3661           arch_entry.Dump(result.GetOutputStream(), thread.get(),
3662                           LLDB_INVALID_ADDRESS);
3663           result.GetOutputStream().Printf("\n");
3664         }
3665       }
3666 
3667       result.GetOutputStream().Printf("\n");
3668     }
3669     return result.Succeeded();
3670   }
3671 
3672   CommandOptions m_options;
3673 };
3674 
3675 //----------------------------------------------------------------------
3676 // Lookup information in images
3677 //----------------------------------------------------------------------
3678 
3679 static constexpr OptionDefinition g_target_modules_lookup_options[] = {
3680     // clang-format off
3681   { LLDB_OPT_SET_1,                                  true,  "address",    'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." },
3682   { 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." },
3683   /* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */
3684   { 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." },
3685   { 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." },
3686   { 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." },
3687   { 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)." },
3688   { 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)." },
3689   { 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." },
3690   { 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." },
3691   { 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." },
3692   { LLDB_OPT_SET_ALL,                                false, "verbose",    'v', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Enable verbose lookup information." },
3693   { 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." },
3694     // clang-format on
3695 };
3696 
3697 class CommandObjectTargetModulesLookup : public CommandObjectParsed {
3698 public:
3699   enum {
3700     eLookupTypeInvalid = -1,
3701     eLookupTypeAddress = 0,
3702     eLookupTypeSymbol,
3703     eLookupTypeFileLine, // Line is optional
3704     eLookupTypeFunction,
3705     eLookupTypeFunctionOrSymbol,
3706     eLookupTypeType,
3707     kNumLookupTypes
3708   };
3709 
3710   class CommandOptions : public Options {
3711   public:
3712     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
3713 
3714     ~CommandOptions() override = default;
3715 
3716     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3717                           ExecutionContext *execution_context) override {
3718       Status error;
3719 
3720       const int short_option = m_getopt_table[option_idx].val;
3721 
3722       switch (short_option) {
3723       case 'a': {
3724         m_type = eLookupTypeAddress;
3725         m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3726                                             LLDB_INVALID_ADDRESS, &error);
3727       } break;
3728 
3729       case 'o':
3730         if (option_arg.getAsInteger(0, m_offset))
3731           error.SetErrorStringWithFormat("invalid offset string '%s'",
3732                                          option_arg.str().c_str());
3733         break;
3734 
3735       case 's':
3736         m_str = option_arg;
3737         m_type = eLookupTypeSymbol;
3738         break;
3739 
3740       case 'f':
3741         m_file.SetFile(option_arg, FileSpec::Style::native);
3742         m_type = eLookupTypeFileLine;
3743         break;
3744 
3745       case 'i':
3746         m_include_inlines = false;
3747         break;
3748 
3749       case 'l':
3750         if (option_arg.getAsInteger(0, m_line_number))
3751           error.SetErrorStringWithFormat("invalid line number string '%s'",
3752                                          option_arg.str().c_str());
3753         else if (m_line_number == 0)
3754           error.SetErrorString("zero is an invalid line number");
3755         m_type = eLookupTypeFileLine;
3756         break;
3757 
3758       case 'F':
3759         m_str = option_arg;
3760         m_type = eLookupTypeFunction;
3761         break;
3762 
3763       case 'n':
3764         m_str = option_arg;
3765         m_type = eLookupTypeFunctionOrSymbol;
3766         break;
3767 
3768       case 't':
3769         m_str = option_arg;
3770         m_type = eLookupTypeType;
3771         break;
3772 
3773       case 'v':
3774         m_verbose = 1;
3775         break;
3776 
3777       case 'A':
3778         m_print_all = true;
3779         break;
3780 
3781       case 'r':
3782         m_use_regex = true;
3783         break;
3784       }
3785 
3786       return error;
3787     }
3788 
3789     void OptionParsingStarting(ExecutionContext *execution_context) override {
3790       m_type = eLookupTypeInvalid;
3791       m_str.clear();
3792       m_file.Clear();
3793       m_addr = LLDB_INVALID_ADDRESS;
3794       m_offset = 0;
3795       m_line_number = 0;
3796       m_use_regex = false;
3797       m_include_inlines = true;
3798       m_verbose = false;
3799       m_print_all = false;
3800     }
3801 
3802     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3803       return llvm::makeArrayRef(g_target_modules_lookup_options);
3804     }
3805 
3806     int m_type;        // Should be a eLookupTypeXXX enum after parsing options
3807     std::string m_str; // Holds name lookup
3808     FileSpec m_file;   // Files for file lookups
3809     lldb::addr_t m_addr; // Holds the address to lookup
3810     lldb::addr_t
3811         m_offset; // Subtract this offset from m_addr before doing lookups.
3812     uint32_t m_line_number; // Line number for file+line lookups
3813     bool m_use_regex;       // Name lookups in m_str are regular expressions.
3814     bool m_include_inlines; // Check for inline entries when looking up by
3815                             // file/line.
3816     bool m_verbose;         // Enable verbose lookup info
3817     bool m_print_all; // Print all matches, even in cases where there's a best
3818                       // match.
3819   };
3820 
3821   CommandObjectTargetModulesLookup(CommandInterpreter &interpreter)
3822       : CommandObjectParsed(interpreter, "target modules lookup",
3823                             "Look up information within executable and "
3824                             "dependent shared library images.",
3825                             nullptr, eCommandRequiresTarget),
3826         m_options() {
3827     CommandArgumentEntry arg;
3828     CommandArgumentData file_arg;
3829 
3830     // Define the first (and only) variant of this arg.
3831     file_arg.arg_type = eArgTypeFilename;
3832     file_arg.arg_repetition = eArgRepeatStar;
3833 
3834     // There is only one variant this argument could be; put it into the
3835     // argument entry.
3836     arg.push_back(file_arg);
3837 
3838     // Push the data for the first argument into the m_arguments vector.
3839     m_arguments.push_back(arg);
3840   }
3841 
3842   ~CommandObjectTargetModulesLookup() override = default;
3843 
3844   Options *GetOptions() override { return &m_options; }
3845 
3846   bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result,
3847                   bool &syntax_error) {
3848     switch (m_options.m_type) {
3849     case eLookupTypeAddress:
3850     case eLookupTypeFileLine:
3851     case eLookupTypeFunction:
3852     case eLookupTypeFunctionOrSymbol:
3853     case eLookupTypeSymbol:
3854     default:
3855       return false;
3856     case eLookupTypeType:
3857       break;
3858     }
3859 
3860     StackFrameSP frame = m_exe_ctx.GetFrameSP();
3861 
3862     if (!frame)
3863       return false;
3864 
3865     const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule));
3866 
3867     if (!sym_ctx.module_sp)
3868       return false;
3869 
3870     switch (m_options.m_type) {
3871     default:
3872       return false;
3873     case eLookupTypeType:
3874       if (!m_options.m_str.empty()) {
3875         if (LookupTypeHere(m_interpreter, result.GetOutputStream(), sym_ctx,
3876                            m_options.m_str.c_str(), m_options.m_use_regex)) {
3877           result.SetStatus(eReturnStatusSuccessFinishResult);
3878           return true;
3879         }
3880       }
3881       break;
3882     }
3883 
3884     return true;
3885   }
3886 
3887   bool LookupInModule(CommandInterpreter &interpreter, Module *module,
3888                       CommandReturnObject &result, bool &syntax_error) {
3889     switch (m_options.m_type) {
3890     case eLookupTypeAddress:
3891       if (m_options.m_addr != LLDB_INVALID_ADDRESS) {
3892         if (LookupAddressInModule(
3893                 m_interpreter, result.GetOutputStream(), module,
3894                 eSymbolContextEverything |
3895                     (m_options.m_verbose
3896                          ? static_cast<int>(eSymbolContextVariable)
3897                          : 0),
3898                 m_options.m_addr, m_options.m_offset, m_options.m_verbose)) {
3899           result.SetStatus(eReturnStatusSuccessFinishResult);
3900           return true;
3901         }
3902       }
3903       break;
3904 
3905     case eLookupTypeSymbol:
3906       if (!m_options.m_str.empty()) {
3907         if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(),
3908                                  module, m_options.m_str.c_str(),
3909                                  m_options.m_use_regex, m_options.m_verbose)) {
3910           result.SetStatus(eReturnStatusSuccessFinishResult);
3911           return true;
3912         }
3913       }
3914       break;
3915 
3916     case eLookupTypeFileLine:
3917       if (m_options.m_file) {
3918         if (LookupFileAndLineInModule(
3919                 m_interpreter, result.GetOutputStream(), module,
3920                 m_options.m_file, m_options.m_line_number,
3921                 m_options.m_include_inlines, m_options.m_verbose)) {
3922           result.SetStatus(eReturnStatusSuccessFinishResult);
3923           return true;
3924         }
3925       }
3926       break;
3927 
3928     case eLookupTypeFunctionOrSymbol:
3929     case eLookupTypeFunction:
3930       if (!m_options.m_str.empty()) {
3931         if (LookupFunctionInModule(
3932                 m_interpreter, result.GetOutputStream(), module,
3933                 m_options.m_str.c_str(), m_options.m_use_regex,
3934                 m_options.m_include_inlines,
3935                 m_options.m_type ==
3936                     eLookupTypeFunctionOrSymbol, // include symbols
3937                 m_options.m_verbose)) {
3938           result.SetStatus(eReturnStatusSuccessFinishResult);
3939           return true;
3940         }
3941       }
3942       break;
3943 
3944     case eLookupTypeType:
3945       if (!m_options.m_str.empty()) {
3946         if (LookupTypeInModule(m_interpreter, result.GetOutputStream(), module,
3947                                m_options.m_str.c_str(),
3948                                m_options.m_use_regex)) {
3949           result.SetStatus(eReturnStatusSuccessFinishResult);
3950           return true;
3951         }
3952       }
3953       break;
3954 
3955     default:
3956       m_options.GenerateOptionUsage(
3957           result.GetErrorStream(), this,
3958           GetCommandInterpreter().GetDebugger().GetTerminalWidth());
3959       syntax_error = true;
3960       break;
3961     }
3962 
3963     result.SetStatus(eReturnStatusFailed);
3964     return false;
3965   }
3966 
3967 protected:
3968   bool DoExecute(Args &command, CommandReturnObject &result) override {
3969     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
3970     if (target == nullptr) {
3971       result.AppendError("invalid target, create a debug target using the "
3972                          "'target create' command");
3973       result.SetStatus(eReturnStatusFailed);
3974       return false;
3975     } else {
3976       bool syntax_error = false;
3977       uint32_t i;
3978       uint32_t num_successful_lookups = 0;
3979       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
3980       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3981       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3982       // Dump all sections for all modules images
3983 
3984       if (command.GetArgumentCount() == 0) {
3985         ModuleSP current_module;
3986 
3987         // Where it is possible to look in the current symbol context first,
3988         // try that.  If this search was successful and --all was not passed,
3989         // don't print anything else.
3990         if (LookupHere(m_interpreter, result, syntax_error)) {
3991           result.GetOutputStream().EOL();
3992           num_successful_lookups++;
3993           if (!m_options.m_print_all) {
3994             result.SetStatus(eReturnStatusSuccessFinishResult);
3995             return result.Succeeded();
3996           }
3997         }
3998 
3999         // Dump all sections for all other modules
4000 
4001         const ModuleList &target_modules = target->GetImages();
4002         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
4003         const size_t num_modules = target_modules.GetSize();
4004         if (num_modules > 0) {
4005           for (i = 0; i < num_modules && !syntax_error; ++i) {
4006             Module *module_pointer =
4007                 target_modules.GetModulePointerAtIndexUnlocked(i);
4008 
4009             if (module_pointer != current_module.get() &&
4010                 LookupInModule(
4011                     m_interpreter,
4012                     target_modules.GetModulePointerAtIndexUnlocked(i), result,
4013                     syntax_error)) {
4014               result.GetOutputStream().EOL();
4015               num_successful_lookups++;
4016             }
4017           }
4018         } else {
4019           result.AppendError("the target has no associated executable images");
4020           result.SetStatus(eReturnStatusFailed);
4021           return false;
4022         }
4023       } else {
4024         // Dump specified images (by basename or fullpath)
4025         const char *arg_cstr;
4026         for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr &&
4027                     !syntax_error;
4028              ++i) {
4029           ModuleList module_list;
4030           const size_t num_matches =
4031               FindModulesByName(target, arg_cstr, module_list, false);
4032           if (num_matches > 0) {
4033             for (size_t j = 0; j < num_matches; ++j) {
4034               Module *module = module_list.GetModulePointerAtIndex(j);
4035               if (module) {
4036                 if (LookupInModule(m_interpreter, module, result,
4037                                    syntax_error)) {
4038                   result.GetOutputStream().EOL();
4039                   num_successful_lookups++;
4040                 }
4041               }
4042             }
4043           } else
4044             result.AppendWarningWithFormat(
4045                 "Unable to find an image that matches '%s'.\n", arg_cstr);
4046         }
4047       }
4048 
4049       if (num_successful_lookups > 0)
4050         result.SetStatus(eReturnStatusSuccessFinishResult);
4051       else
4052         result.SetStatus(eReturnStatusFailed);
4053     }
4054     return result.Succeeded();
4055   }
4056 
4057   CommandOptions m_options;
4058 };
4059 
4060 #pragma mark CommandObjectMultiwordImageSearchPaths
4061 
4062 //-------------------------------------------------------------------------
4063 // CommandObjectMultiwordImageSearchPaths
4064 //-------------------------------------------------------------------------
4065 
4066 class CommandObjectTargetModulesImageSearchPaths
4067     : public CommandObjectMultiword {
4068 public:
4069   CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter)
4070       : CommandObjectMultiword(
4071             interpreter, "target modules search-paths",
4072             "Commands for managing module search paths for a target.",
4073             "target modules search-paths <subcommand> [<subcommand-options>]") {
4074     LoadSubCommand(
4075         "add", CommandObjectSP(
4076                    new CommandObjectTargetModulesSearchPathsAdd(interpreter)));
4077     LoadSubCommand(
4078         "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear(
4079                      interpreter)));
4080     LoadSubCommand(
4081         "insert",
4082         CommandObjectSP(
4083             new CommandObjectTargetModulesSearchPathsInsert(interpreter)));
4084     LoadSubCommand(
4085         "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList(
4086                     interpreter)));
4087     LoadSubCommand(
4088         "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery(
4089                      interpreter)));
4090   }
4091 
4092   ~CommandObjectTargetModulesImageSearchPaths() override = default;
4093 };
4094 
4095 #pragma mark CommandObjectTargetModules
4096 
4097 //-------------------------------------------------------------------------
4098 // CommandObjectTargetModules
4099 //-------------------------------------------------------------------------
4100 
4101 class CommandObjectTargetModules : public CommandObjectMultiword {
4102 public:
4103   //------------------------------------------------------------------
4104   // Constructors and Destructors
4105   //------------------------------------------------------------------
4106   CommandObjectTargetModules(CommandInterpreter &interpreter)
4107       : CommandObjectMultiword(interpreter, "target modules",
4108                                "Commands for accessing information for one or "
4109                                "more target modules.",
4110                                "target modules <sub-command> ...") {
4111     LoadSubCommand(
4112         "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter)));
4113     LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad(
4114                                interpreter)));
4115     LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump(
4116                                interpreter)));
4117     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList(
4118                                interpreter)));
4119     LoadSubCommand(
4120         "lookup",
4121         CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter)));
4122     LoadSubCommand(
4123         "search-paths",
4124         CommandObjectSP(
4125             new CommandObjectTargetModulesImageSearchPaths(interpreter)));
4126     LoadSubCommand(
4127         "show-unwind",
4128         CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter)));
4129   }
4130 
4131   ~CommandObjectTargetModules() override = default;
4132 
4133 private:
4134   //------------------------------------------------------------------
4135   // For CommandObjectTargetModules only
4136   //------------------------------------------------------------------
4137   DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetModules);
4138 };
4139 
4140 class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
4141 public:
4142   CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter)
4143       : CommandObjectParsed(
4144             interpreter, "target symbols add",
4145             "Add a debug symbol file to one of the target's current modules by "
4146             "specifying a path to a debug symbols file, or using the options "
4147             "to specify a module to download symbols for.",
4148             "target symbols add <cmd-options> [<symfile>]",
4149             eCommandRequiresTarget),
4150         m_option_group(),
4151         m_file_option(
4152             LLDB_OPT_SET_1, false, "shlib", 's',
4153             CommandCompletions::eModuleCompletion, eArgTypeShlibName,
4154             "Fullpath or basename for module to find debug symbols for."),
4155         m_current_frame_option(
4156             LLDB_OPT_SET_2, false, "frame", 'F',
4157             "Locate the debug symbols the currently selected frame.", false,
4158             true)
4159 
4160   {
4161     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
4162                           LLDB_OPT_SET_1);
4163     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
4164     m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2,
4165                           LLDB_OPT_SET_2);
4166     m_option_group.Finalize();
4167   }
4168 
4169   ~CommandObjectTargetSymbolsAdd() override = default;
4170 
4171   int HandleArgumentCompletion(
4172       CompletionRequest &request,
4173       OptionElementVector &opt_element_vector) override {
4174     CommandCompletions::InvokeCommonCompletionCallbacks(
4175         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
4176         request, nullptr);
4177     return request.GetNumberOfMatches();
4178   }
4179 
4180   Options *GetOptions() override { return &m_option_group; }
4181 
4182 protected:
4183   bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
4184                         CommandReturnObject &result) {
4185     const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
4186     if (symbol_fspec) {
4187       char symfile_path[PATH_MAX];
4188       symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));
4189 
4190       if (!module_spec.GetUUID().IsValid()) {
4191         if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
4192           module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename();
4193       }
4194       // We now have a module that represents a symbol file that can be used
4195       // for a module that might exist in the current target, so we need to
4196       // find that module in the target
4197       ModuleList matching_module_list;
4198 
4199       size_t num_matches = 0;
4200       // First extract all module specs from the symbol file
4201       lldb_private::ModuleSpecList symfile_module_specs;
4202       if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
4203                                               0, 0, symfile_module_specs)) {
4204         // Now extract the module spec that matches the target architecture
4205         ModuleSpec target_arch_module_spec;
4206         ModuleSpec symfile_module_spec;
4207         target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
4208         if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
4209                                                         symfile_module_spec)) {
4210           // See if it has a UUID?
4211           if (symfile_module_spec.GetUUID().IsValid()) {
4212             // It has a UUID, look for this UUID in the target modules
4213             ModuleSpec symfile_uuid_module_spec;
4214             symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
4215             num_matches = target->GetImages().FindModules(
4216                 symfile_uuid_module_spec, matching_module_list);
4217           }
4218         }
4219 
4220         if (num_matches == 0) {
4221           // No matches yet, iterate through the module specs to find a UUID
4222           // value that we can match up to an image in our target
4223           const size_t num_symfile_module_specs =
4224               symfile_module_specs.GetSize();
4225           for (size_t i = 0; i < num_symfile_module_specs && num_matches == 0;
4226                ++i) {
4227             if (symfile_module_specs.GetModuleSpecAtIndex(
4228                     i, symfile_module_spec)) {
4229               if (symfile_module_spec.GetUUID().IsValid()) {
4230                 // It has a UUID, look for this UUID in the target modules
4231                 ModuleSpec symfile_uuid_module_spec;
4232                 symfile_uuid_module_spec.GetUUID() =
4233                     symfile_module_spec.GetUUID();
4234                 num_matches = target->GetImages().FindModules(
4235                     symfile_uuid_module_spec, matching_module_list);
4236               }
4237             }
4238           }
4239         }
4240       }
4241 
4242       // Just try to match up the file by basename if we have no matches at
4243       // this point
4244       if (num_matches == 0)
4245         num_matches =
4246             target->GetImages().FindModules(module_spec, matching_module_list);
4247 
4248       while (num_matches == 0) {
4249         ConstString filename_no_extension(
4250             module_spec.GetFileSpec().GetFileNameStrippingExtension());
4251         // Empty string returned, lets bail
4252         if (!filename_no_extension)
4253           break;
4254 
4255         // Check if there was no extension to strip and the basename is the
4256         // same
4257         if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
4258           break;
4259 
4260         // Replace basename with one less extension
4261         module_spec.GetFileSpec().GetFilename() = filename_no_extension;
4262 
4263         num_matches =
4264             target->GetImages().FindModules(module_spec, matching_module_list);
4265       }
4266 
4267       if (num_matches > 1) {
4268         result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
4269                                      "use the --uuid option to resolve the "
4270                                      "ambiguity.\n",
4271                                      symfile_path);
4272       } else if (num_matches == 1) {
4273         ModuleSP module_sp(matching_module_list.GetModuleAtIndex(0));
4274 
4275         // The module has not yet created its symbol vendor, we can just give
4276         // the existing target module the symfile path to use for when it
4277         // decides to create it!
4278         module_sp->SetSymbolFileFileSpec(symbol_fspec);
4279 
4280         SymbolVendor *symbol_vendor =
4281             module_sp->GetSymbolVendor(true, &result.GetErrorStream());
4282         if (symbol_vendor) {
4283           SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
4284 
4285           if (symbol_file) {
4286             ObjectFile *object_file = symbol_file->GetObjectFile();
4287 
4288             if (object_file && object_file->GetFileSpec() == symbol_fspec) {
4289               // Provide feedback that the symfile has been successfully added.
4290               const FileSpec &module_fs = module_sp->GetFileSpec();
4291               result.AppendMessageWithFormat(
4292                   "symbol file '%s' has been added to '%s'\n", symfile_path,
4293                   module_fs.GetPath().c_str());
4294 
4295               // Let clients know something changed in the module if it is
4296               // currently loaded
4297               ModuleList module_list;
4298               module_list.Append(module_sp);
4299               target->SymbolsDidLoad(module_list);
4300 
4301               // Make sure we load any scripting resources that may be embedded
4302               // in the debug info files in case the platform supports that.
4303               Status error;
4304               StreamString feedback_stream;
4305               module_sp->LoadScriptingResourceInTarget(target, error,
4306                                                        &feedback_stream);
4307               if (error.Fail() && error.AsCString())
4308                 result.AppendWarningWithFormat(
4309                     "unable to load scripting data for module %s - error "
4310                     "reported was %s",
4311                     module_sp->GetFileSpec()
4312                         .GetFileNameStrippingExtension()
4313                         .GetCString(),
4314                     error.AsCString());
4315               else if (feedback_stream.GetSize())
4316                 result.AppendWarningWithFormat("%s", feedback_stream.GetData());
4317 
4318               flush = true;
4319               result.SetStatus(eReturnStatusSuccessFinishResult);
4320               return true;
4321             }
4322           }
4323         }
4324         // Clear the symbol file spec if anything went wrong
4325         module_sp->SetSymbolFileFileSpec(FileSpec());
4326       }
4327 
4328       namespace fs = llvm::sys::fs;
4329       if (module_spec.GetUUID().IsValid()) {
4330         StreamString ss_symfile_uuid;
4331         module_spec.GetUUID().Dump(&ss_symfile_uuid);
4332         result.AppendErrorWithFormat(
4333             "symbol file '%s' (%s) does not match any existing module%s\n",
4334             symfile_path, ss_symfile_uuid.GetData(),
4335             !fs::is_regular_file(symbol_fspec.GetPath())
4336                 ? "\n       please specify the full path to the symbol file"
4337                 : "");
4338       } else {
4339         result.AppendErrorWithFormat(
4340             "symbol file '%s' does not match any existing module%s\n",
4341             symfile_path,
4342             !fs::is_regular_file(symbol_fspec.GetPath())
4343                 ? "\n       please specify the full path to the symbol file"
4344                 : "");
4345       }
4346     } else {
4347       result.AppendError(
4348           "one or more executable image paths must be specified");
4349     }
4350     result.SetStatus(eReturnStatusFailed);
4351     return false;
4352   }
4353 
4354   bool DoExecute(Args &args, CommandReturnObject &result) override {
4355     Target *target = m_exe_ctx.GetTargetPtr();
4356     result.SetStatus(eReturnStatusFailed);
4357     bool flush = false;
4358     ModuleSpec module_spec;
4359     const bool uuid_option_set =
4360         m_uuid_option_group.GetOptionValue().OptionWasSet();
4361     const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
4362     const bool frame_option_set =
4363         m_current_frame_option.GetOptionValue().OptionWasSet();
4364     const size_t argc = args.GetArgumentCount();
4365 
4366     if (argc == 0) {
4367       if (uuid_option_set || file_option_set || frame_option_set) {
4368         bool success = false;
4369         bool error_set = false;
4370         if (frame_option_set) {
4371           Process *process = m_exe_ctx.GetProcessPtr();
4372           if (process) {
4373             const StateType process_state = process->GetState();
4374             if (StateIsStoppedState(process_state, true)) {
4375               StackFrame *frame = m_exe_ctx.GetFramePtr();
4376               if (frame) {
4377                 ModuleSP frame_module_sp(
4378                     frame->GetSymbolContext(eSymbolContextModule).module_sp);
4379                 if (frame_module_sp) {
4380                   if (FileSystem::Instance().Exists(
4381                           frame_module_sp->GetPlatformFileSpec())) {
4382                     module_spec.GetArchitecture() =
4383                         frame_module_sp->GetArchitecture();
4384                     module_spec.GetFileSpec() =
4385                         frame_module_sp->GetPlatformFileSpec();
4386                   }
4387                   module_spec.GetUUID() = frame_module_sp->GetUUID();
4388                   success = module_spec.GetUUID().IsValid() ||
4389                             module_spec.GetFileSpec();
4390                 } else {
4391                   result.AppendError("frame has no module");
4392                   error_set = true;
4393                 }
4394               } else {
4395                 result.AppendError("invalid current frame");
4396                 error_set = true;
4397               }
4398             } else {
4399               result.AppendErrorWithFormat("process is not stopped: %s",
4400                                            StateAsCString(process_state));
4401               error_set = true;
4402             }
4403           } else {
4404             result.AppendError(
4405                 "a process must exist in order to use the --frame option");
4406             error_set = true;
4407           }
4408         } else {
4409           if (uuid_option_set) {
4410             module_spec.GetUUID() =
4411                 m_uuid_option_group.GetOptionValue().GetCurrentValue();
4412             success |= module_spec.GetUUID().IsValid();
4413           } else if (file_option_set) {
4414             module_spec.GetFileSpec() =
4415                 m_file_option.GetOptionValue().GetCurrentValue();
4416             ModuleSP module_sp(
4417                 target->GetImages().FindFirstModule(module_spec));
4418             if (module_sp) {
4419               module_spec.GetFileSpec() = module_sp->GetFileSpec();
4420               module_spec.GetPlatformFileSpec() =
4421                   module_sp->GetPlatformFileSpec();
4422               module_spec.GetUUID() = module_sp->GetUUID();
4423               module_spec.GetArchitecture() = module_sp->GetArchitecture();
4424             } else {
4425               module_spec.GetArchitecture() = target->GetArchitecture();
4426             }
4427             success |= module_spec.GetUUID().IsValid() ||
4428                        FileSystem::Instance().Exists(module_spec.GetFileSpec());
4429           }
4430         }
4431 
4432         if (success) {
4433           if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
4434             if (module_spec.GetSymbolFileSpec())
4435               success = AddModuleSymbols(target, module_spec, flush, result);
4436           }
4437         }
4438 
4439         if (!success && !error_set) {
4440           StreamString error_strm;
4441           if (uuid_option_set) {
4442             error_strm.PutCString("unable to find debug symbols for UUID ");
4443             module_spec.GetUUID().Dump(&error_strm);
4444           } else if (file_option_set) {
4445             error_strm.PutCString(
4446                 "unable to find debug symbols for the executable file ");
4447             error_strm << module_spec.GetFileSpec();
4448           } else if (frame_option_set) {
4449             error_strm.PutCString(
4450                 "unable to find debug symbols for the current frame");
4451           }
4452           result.AppendError(error_strm.GetString());
4453         }
4454       } else {
4455         result.AppendError("one or more symbol file paths must be specified, "
4456                            "or options must be specified");
4457       }
4458     } else {
4459       if (uuid_option_set) {
4460         result.AppendError("specify either one or more paths to symbol files "
4461                            "or use the --uuid option without arguments");
4462       } else if (frame_option_set) {
4463         result.AppendError("specify either one or more paths to symbol files "
4464                            "or use the --frame option without arguments");
4465       } else if (file_option_set && argc > 1) {
4466         result.AppendError("specify at most one symbol file path when "
4467                            "--shlib option is set");
4468       } else {
4469         PlatformSP platform_sp(target->GetPlatform());
4470 
4471         for (auto &entry : args.entries()) {
4472           if (!entry.ref.empty()) {
4473             auto &symbol_file_spec = module_spec.GetSymbolFileSpec();
4474             symbol_file_spec.SetFile(entry.ref, FileSpec::Style::native);
4475             FileSystem::Instance().Resolve(symbol_file_spec);
4476             if (file_option_set) {
4477               module_spec.GetFileSpec() =
4478                   m_file_option.GetOptionValue().GetCurrentValue();
4479             }
4480             if (platform_sp) {
4481               FileSpec symfile_spec;
4482               if (platform_sp
4483                       ->ResolveSymbolFile(*target, module_spec, symfile_spec)
4484                       .Success())
4485                 module_spec.GetSymbolFileSpec() = symfile_spec;
4486             }
4487 
4488             ArchSpec arch;
4489             bool symfile_exists =
4490                 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec());
4491 
4492             if (symfile_exists) {
4493               if (!AddModuleSymbols(target, module_spec, flush, result))
4494                 break;
4495             } else {
4496               std::string resolved_symfile_path =
4497                   module_spec.GetSymbolFileSpec().GetPath();
4498               if (resolved_symfile_path != entry.ref) {
4499                 result.AppendErrorWithFormat(
4500                     "invalid module path '%s' with resolved path '%s'\n",
4501                     entry.c_str(), resolved_symfile_path.c_str());
4502                 break;
4503               }
4504               result.AppendErrorWithFormat("invalid module path '%s'\n",
4505                                            entry.c_str());
4506               break;
4507             }
4508           }
4509         }
4510       }
4511     }
4512 
4513     if (flush) {
4514       Process *process = m_exe_ctx.GetProcessPtr();
4515       if (process)
4516         process->Flush();
4517     }
4518     return result.Succeeded();
4519   }
4520 
4521   OptionGroupOptions m_option_group;
4522   OptionGroupUUID m_uuid_option_group;
4523   OptionGroupFile m_file_option;
4524   OptionGroupBoolean m_current_frame_option;
4525 };
4526 
4527 #pragma mark CommandObjectTargetSymbols
4528 
4529 //-------------------------------------------------------------------------
4530 // CommandObjectTargetSymbols
4531 //-------------------------------------------------------------------------
4532 
4533 class CommandObjectTargetSymbols : public CommandObjectMultiword {
4534 public:
4535   //------------------------------------------------------------------
4536   // Constructors and Destructors
4537   //------------------------------------------------------------------
4538   CommandObjectTargetSymbols(CommandInterpreter &interpreter)
4539       : CommandObjectMultiword(
4540             interpreter, "target symbols",
4541             "Commands for adding and managing debug symbol files.",
4542             "target symbols <sub-command> ...") {
4543     LoadSubCommand(
4544         "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
4545   }
4546 
4547   ~CommandObjectTargetSymbols() override = default;
4548 
4549 private:
4550   //------------------------------------------------------------------
4551   // For CommandObjectTargetModules only
4552   //------------------------------------------------------------------
4553   DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetSymbols);
4554 };
4555 
4556 #pragma mark CommandObjectTargetStopHookAdd
4557 
4558 //-------------------------------------------------------------------------
4559 // CommandObjectTargetStopHookAdd
4560 //-------------------------------------------------------------------------
4561 
4562 static constexpr OptionDefinition g_target_stop_hook_add_options[] = {
4563     // clang-format off
4564   { 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." },
4565   { 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." },
4566   { 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." },
4567   { 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." },
4568   { 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." },
4569   { 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." },
4570   { 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." },
4571   { 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." },
4572   { 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." },
4573   { LLDB_OPT_SET_2,   false, "classname",    'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeClassName,                                        "Specify the class within which the stop-hook is to be run." },
4574   { 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." },
4575     // clang-format on
4576 };
4577 
4578 class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
4579                                        public IOHandlerDelegateMultiline {
4580 public:
4581   class CommandOptions : public Options {
4582   public:
4583     CommandOptions()
4584         : Options(), m_line_start(0), m_line_end(UINT_MAX),
4585           m_func_name_type_mask(eFunctionNameTypeAuto),
4586           m_sym_ctx_specified(false), m_thread_specified(false),
4587           m_use_one_liner(false), m_one_liner() {}
4588 
4589     ~CommandOptions() override = default;
4590 
4591     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4592       return llvm::makeArrayRef(g_target_stop_hook_add_options);
4593     }
4594 
4595     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4596                           ExecutionContext *execution_context) override {
4597       Status error;
4598       const int short_option = m_getopt_table[option_idx].val;
4599 
4600       switch (short_option) {
4601       case 'c':
4602         m_class_name = option_arg;
4603         m_sym_ctx_specified = true;
4604         break;
4605 
4606       case 'e':
4607         if (option_arg.getAsInteger(0, m_line_end)) {
4608           error.SetErrorStringWithFormat("invalid end line number: \"%s\"",
4609                                          option_arg.str().c_str());
4610           break;
4611         }
4612         m_sym_ctx_specified = true;
4613         break;
4614 
4615       case 'l':
4616         if (option_arg.getAsInteger(0, m_line_start)) {
4617           error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
4618                                          option_arg.str().c_str());
4619           break;
4620         }
4621         m_sym_ctx_specified = true;
4622         break;
4623 
4624       case 'i':
4625         m_no_inlines = true;
4626         break;
4627 
4628       case 'n':
4629         m_function_name = option_arg;
4630         m_func_name_type_mask |= eFunctionNameTypeAuto;
4631         m_sym_ctx_specified = true;
4632         break;
4633 
4634       case 'f':
4635         m_file_name = option_arg;
4636         m_sym_ctx_specified = true;
4637         break;
4638 
4639       case 's':
4640         m_module_name = option_arg;
4641         m_sym_ctx_specified = true;
4642         break;
4643 
4644       case 't':
4645         if (option_arg.getAsInteger(0, m_thread_id))
4646           error.SetErrorStringWithFormat("invalid thread id string '%s'",
4647                                          option_arg.str().c_str());
4648         m_thread_specified = true;
4649         break;
4650 
4651       case 'T':
4652         m_thread_name = option_arg;
4653         m_thread_specified = true;
4654         break;
4655 
4656       case 'q':
4657         m_queue_name = option_arg;
4658         m_thread_specified = true;
4659         break;
4660 
4661       case 'x':
4662         if (option_arg.getAsInteger(0, m_thread_index))
4663           error.SetErrorStringWithFormat("invalid thread index string '%s'",
4664                                          option_arg.str().c_str());
4665         m_thread_specified = true;
4666         break;
4667 
4668       case 'o':
4669         m_use_one_liner = true;
4670         m_one_liner = option_arg;
4671         break;
4672 
4673       default:
4674         error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
4675         break;
4676       }
4677       return error;
4678     }
4679 
4680     void OptionParsingStarting(ExecutionContext *execution_context) override {
4681       m_class_name.clear();
4682       m_function_name.clear();
4683       m_line_start = 0;
4684       m_line_end = UINT_MAX;
4685       m_file_name.clear();
4686       m_module_name.clear();
4687       m_func_name_type_mask = eFunctionNameTypeAuto;
4688       m_thread_id = LLDB_INVALID_THREAD_ID;
4689       m_thread_index = UINT32_MAX;
4690       m_thread_name.clear();
4691       m_queue_name.clear();
4692 
4693       m_no_inlines = false;
4694       m_sym_ctx_specified = false;
4695       m_thread_specified = false;
4696 
4697       m_use_one_liner = false;
4698       m_one_liner.clear();
4699     }
4700 
4701     std::string m_class_name;
4702     std::string m_function_name;
4703     uint32_t m_line_start;
4704     uint32_t m_line_end;
4705     std::string m_file_name;
4706     std::string m_module_name;
4707     uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType.
4708     lldb::tid_t m_thread_id;
4709     uint32_t m_thread_index;
4710     std::string m_thread_name;
4711     std::string m_queue_name;
4712     bool m_sym_ctx_specified;
4713     bool m_no_inlines;
4714     bool m_thread_specified;
4715     // Instance variables to hold the values for one_liner options.
4716     bool m_use_one_liner;
4717     std::string m_one_liner;
4718   };
4719 
4720   CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
4721       : CommandObjectParsed(interpreter, "target stop-hook add",
4722                             "Add a hook to be executed when the target stops.",
4723                             "target stop-hook add"),
4724         IOHandlerDelegateMultiline("DONE",
4725                                    IOHandlerDelegate::Completion::LLDBCommand),
4726         m_options() {}
4727 
4728   ~CommandObjectTargetStopHookAdd() override = default;
4729 
4730   Options *GetOptions() override { return &m_options; }
4731 
4732 protected:
4733   void IOHandlerActivated(IOHandler &io_handler) override {
4734     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4735     if (output_sp) {
4736       output_sp->PutCString(
4737           "Enter your stop hook command(s).  Type 'DONE' to end.\n");
4738       output_sp->Flush();
4739     }
4740   }
4741 
4742   void IOHandlerInputComplete(IOHandler &io_handler,
4743                               std::string &line) override {
4744     if (m_stop_hook_sp) {
4745       if (line.empty()) {
4746         StreamFileSP error_sp(io_handler.GetErrorStreamFile());
4747         if (error_sp) {
4748           error_sp->Printf("error: stop hook #%" PRIu64
4749                            " aborted, no commands.\n",
4750                            m_stop_hook_sp->GetID());
4751           error_sp->Flush();
4752         }
4753         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
4754         if (target)
4755           target->RemoveStopHookByID(m_stop_hook_sp->GetID());
4756       } else {
4757         m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
4758         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4759         if (output_sp) {
4760           output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
4761                             m_stop_hook_sp->GetID());
4762           output_sp->Flush();
4763         }
4764       }
4765       m_stop_hook_sp.reset();
4766     }
4767     io_handler.SetIsDone(true);
4768   }
4769 
4770   bool DoExecute(Args &command, CommandReturnObject &result) override {
4771     m_stop_hook_sp.reset();
4772 
4773     Target *target = GetSelectedOrDummyTarget();
4774     if (target) {
4775       Target::StopHookSP new_hook_sp = target->CreateStopHook();
4776 
4777       //  First step, make the specifier.
4778       std::unique_ptr<SymbolContextSpecifier> specifier_ap;
4779       if (m_options.m_sym_ctx_specified) {
4780         specifier_ap.reset(new SymbolContextSpecifier(
4781             m_interpreter.GetDebugger().GetSelectedTarget()));
4782 
4783         if (!m_options.m_module_name.empty()) {
4784           specifier_ap->AddSpecification(
4785               m_options.m_module_name.c_str(),
4786               SymbolContextSpecifier::eModuleSpecified);
4787         }
4788 
4789         if (!m_options.m_class_name.empty()) {
4790           specifier_ap->AddSpecification(
4791               m_options.m_class_name.c_str(),
4792               SymbolContextSpecifier::eClassOrNamespaceSpecified);
4793         }
4794 
4795         if (!m_options.m_file_name.empty()) {
4796           specifier_ap->AddSpecification(
4797               m_options.m_file_name.c_str(),
4798               SymbolContextSpecifier::eFileSpecified);
4799         }
4800 
4801         if (m_options.m_line_start != 0) {
4802           specifier_ap->AddLineSpecification(
4803               m_options.m_line_start,
4804               SymbolContextSpecifier::eLineStartSpecified);
4805         }
4806 
4807         if (m_options.m_line_end != UINT_MAX) {
4808           specifier_ap->AddLineSpecification(
4809               m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
4810         }
4811 
4812         if (!m_options.m_function_name.empty()) {
4813           specifier_ap->AddSpecification(
4814               m_options.m_function_name.c_str(),
4815               SymbolContextSpecifier::eFunctionSpecified);
4816         }
4817       }
4818 
4819       if (specifier_ap)
4820         new_hook_sp->SetSpecifier(specifier_ap.release());
4821 
4822       // Next see if any of the thread options have been entered:
4823 
4824       if (m_options.m_thread_specified) {
4825         ThreadSpec *thread_spec = new ThreadSpec();
4826 
4827         if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
4828           thread_spec->SetTID(m_options.m_thread_id);
4829         }
4830 
4831         if (m_options.m_thread_index != UINT32_MAX)
4832           thread_spec->SetIndex(m_options.m_thread_index);
4833 
4834         if (!m_options.m_thread_name.empty())
4835           thread_spec->SetName(m_options.m_thread_name.c_str());
4836 
4837         if (!m_options.m_queue_name.empty())
4838           thread_spec->SetQueueName(m_options.m_queue_name.c_str());
4839 
4840         new_hook_sp->SetThreadSpecifier(thread_spec);
4841       }
4842       if (m_options.m_use_one_liner) {
4843         // Use one-liner.
4844         new_hook_sp->GetCommandPointer()->AppendString(
4845             m_options.m_one_liner.c_str());
4846         result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
4847                                        new_hook_sp->GetID());
4848       } else {
4849         m_stop_hook_sp = new_hook_sp;
4850         m_interpreter.GetLLDBCommandsFromIOHandler(
4851             "> ",     // Prompt
4852             *this,    // IOHandlerDelegate
4853             true,     // Run IOHandler in async mode
4854             nullptr); // Baton for the "io_handler" that will be passed back
4855                       // into our IOHandlerDelegate functions
4856       }
4857       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4858     } else {
4859       result.AppendError("invalid target\n");
4860       result.SetStatus(eReturnStatusFailed);
4861     }
4862 
4863     return result.Succeeded();
4864   }
4865 
4866 private:
4867   CommandOptions m_options;
4868   Target::StopHookSP m_stop_hook_sp;
4869 };
4870 
4871 #pragma mark CommandObjectTargetStopHookDelete
4872 
4873 //-------------------------------------------------------------------------
4874 // CommandObjectTargetStopHookDelete
4875 //-------------------------------------------------------------------------
4876 
4877 class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
4878 public:
4879   CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
4880       : CommandObjectParsed(interpreter, "target stop-hook delete",
4881                             "Delete a stop-hook.",
4882                             "target stop-hook delete [<idx>]") {}
4883 
4884   ~CommandObjectTargetStopHookDelete() override = default;
4885 
4886 protected:
4887   bool DoExecute(Args &command, CommandReturnObject &result) override {
4888     Target *target = GetSelectedOrDummyTarget();
4889     if (target) {
4890       // FIXME: see if we can use the breakpoint id style parser?
4891       size_t num_args = command.GetArgumentCount();
4892       if (num_args == 0) {
4893         if (!m_interpreter.Confirm("Delete all stop hooks?", true)) {
4894           result.SetStatus(eReturnStatusFailed);
4895           return false;
4896         } else {
4897           target->RemoveAllStopHooks();
4898         }
4899       } else {
4900         bool success;
4901         for (size_t i = 0; i < num_args; i++) {
4902           lldb::user_id_t user_id = StringConvert::ToUInt32(
4903               command.GetArgumentAtIndex(i), 0, 0, &success);
4904           if (!success) {
4905             result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4906                                          command.GetArgumentAtIndex(i));
4907             result.SetStatus(eReturnStatusFailed);
4908             return false;
4909           }
4910           success = target->RemoveStopHookByID(user_id);
4911           if (!success) {
4912             result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4913                                          command.GetArgumentAtIndex(i));
4914             result.SetStatus(eReturnStatusFailed);
4915             return false;
4916           }
4917         }
4918       }
4919       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4920     } else {
4921       result.AppendError("invalid target\n");
4922       result.SetStatus(eReturnStatusFailed);
4923     }
4924 
4925     return result.Succeeded();
4926   }
4927 };
4928 
4929 #pragma mark CommandObjectTargetStopHookEnableDisable
4930 
4931 //-------------------------------------------------------------------------
4932 // CommandObjectTargetStopHookEnableDisable
4933 //-------------------------------------------------------------------------
4934 
4935 class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
4936 public:
4937   CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
4938                                            bool enable, const char *name,
4939                                            const char *help, const char *syntax)
4940       : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
4941   }
4942 
4943   ~CommandObjectTargetStopHookEnableDisable() override = default;
4944 
4945 protected:
4946   bool DoExecute(Args &command, CommandReturnObject &result) override {
4947     Target *target = GetSelectedOrDummyTarget();
4948     if (target) {
4949       // FIXME: see if we can use the breakpoint id style parser?
4950       size_t num_args = command.GetArgumentCount();
4951       bool success;
4952 
4953       if (num_args == 0) {
4954         target->SetAllStopHooksActiveState(m_enable);
4955       } else {
4956         for (size_t i = 0; i < num_args; i++) {
4957           lldb::user_id_t user_id = StringConvert::ToUInt32(
4958               command.GetArgumentAtIndex(i), 0, 0, &success);
4959           if (!success) {
4960             result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4961                                          command.GetArgumentAtIndex(i));
4962             result.SetStatus(eReturnStatusFailed);
4963             return false;
4964           }
4965           success = target->SetStopHookActiveStateByID(user_id, m_enable);
4966           if (!success) {
4967             result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4968                                          command.GetArgumentAtIndex(i));
4969             result.SetStatus(eReturnStatusFailed);
4970             return false;
4971           }
4972         }
4973       }
4974       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4975     } else {
4976       result.AppendError("invalid target\n");
4977       result.SetStatus(eReturnStatusFailed);
4978     }
4979     return result.Succeeded();
4980   }
4981 
4982 private:
4983   bool m_enable;
4984 };
4985 
4986 #pragma mark CommandObjectTargetStopHookList
4987 
4988 //-------------------------------------------------------------------------
4989 // CommandObjectTargetStopHookList
4990 //-------------------------------------------------------------------------
4991 
4992 class CommandObjectTargetStopHookList : public CommandObjectParsed {
4993 public:
4994   CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
4995       : CommandObjectParsed(interpreter, "target stop-hook list",
4996                             "List all stop-hooks.",
4997                             "target stop-hook list [<type>]") {}
4998 
4999   ~CommandObjectTargetStopHookList() override = default;
5000 
5001 protected:
5002   bool DoExecute(Args &command, CommandReturnObject &result) override {
5003     Target *target = GetSelectedOrDummyTarget();
5004     if (!target) {
5005       result.AppendError("invalid target\n");
5006       result.SetStatus(eReturnStatusFailed);
5007       return result.Succeeded();
5008     }
5009 
5010     size_t num_hooks = target->GetNumStopHooks();
5011     if (num_hooks == 0) {
5012       result.GetOutputStream().PutCString("No stop hooks.\n");
5013     } else {
5014       for (size_t i = 0; i < num_hooks; i++) {
5015         Target::StopHookSP this_hook = target->GetStopHookAtIndex(i);
5016         if (i > 0)
5017           result.GetOutputStream().PutCString("\n");
5018         this_hook->GetDescription(&(result.GetOutputStream()),
5019                                   eDescriptionLevelFull);
5020       }
5021     }
5022     result.SetStatus(eReturnStatusSuccessFinishResult);
5023     return result.Succeeded();
5024   }
5025 };
5026 
5027 #pragma mark CommandObjectMultiwordTargetStopHooks
5028 
5029 //-------------------------------------------------------------------------
5030 // CommandObjectMultiwordTargetStopHooks
5031 //-------------------------------------------------------------------------
5032 
5033 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
5034 public:
5035   CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
5036       : CommandObjectMultiword(
5037             interpreter, "target stop-hook",
5038             "Commands for operating on debugger target stop-hooks.",
5039             "target stop-hook <subcommand> [<subcommand-options>]") {
5040     LoadSubCommand("add", CommandObjectSP(
5041                               new CommandObjectTargetStopHookAdd(interpreter)));
5042     LoadSubCommand(
5043         "delete",
5044         CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
5045     LoadSubCommand("disable",
5046                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
5047                        interpreter, false, "target stop-hook disable [<id>]",
5048                        "Disable a stop-hook.", "target stop-hook disable")));
5049     LoadSubCommand("enable",
5050                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
5051                        interpreter, true, "target stop-hook enable [<id>]",
5052                        "Enable a stop-hook.", "target stop-hook enable")));
5053     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList(
5054                                interpreter)));
5055   }
5056 
5057   ~CommandObjectMultiwordTargetStopHooks() override = default;
5058 };
5059 
5060 #pragma mark CommandObjectMultiwordTarget
5061 
5062 //-------------------------------------------------------------------------
5063 // CommandObjectMultiwordTarget
5064 //-------------------------------------------------------------------------
5065 
5066 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
5067     CommandInterpreter &interpreter)
5068     : CommandObjectMultiword(interpreter, "target",
5069                              "Commands for operating on debugger targets.",
5070                              "target <subcommand> [<subcommand-options>]") {
5071   LoadSubCommand("create",
5072                  CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
5073   LoadSubCommand("delete",
5074                  CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
5075   LoadSubCommand("list",
5076                  CommandObjectSP(new CommandObjectTargetList(interpreter)));
5077   LoadSubCommand("select",
5078                  CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
5079   LoadSubCommand(
5080       "stop-hook",
5081       CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
5082   LoadSubCommand("modules",
5083                  CommandObjectSP(new CommandObjectTargetModules(interpreter)));
5084   LoadSubCommand("symbols",
5085                  CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
5086   LoadSubCommand("variable",
5087                  CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
5088 }
5089 
5090 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;
5091