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