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