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