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