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