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