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