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