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