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/CommandInterpreter.h"
25 #include "lldb/Interpreter/CommandReturnObject.h"
26 #include "lldb/Interpreter/OptionArgParser.h"
27 #include "lldb/Interpreter/OptionGroupArchitecture.h"
28 #include "lldb/Interpreter/OptionGroupBoolean.h"
29 #include "lldb/Interpreter/OptionGroupFile.h"
30 #include "lldb/Interpreter/OptionGroupFormat.h"
31 #include "lldb/Interpreter/OptionGroupPlatform.h"
32 #include "lldb/Interpreter/OptionGroupString.h"
33 #include "lldb/Interpreter/OptionGroupUInt64.h"
34 #include "lldb/Interpreter/OptionGroupUUID.h"
35 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
36 #include "lldb/Interpreter/OptionGroupVariable.h"
37 #include "lldb/Interpreter/Options.h"
38 #include "lldb/Symbol/CompileUnit.h"
39 #include "lldb/Symbol/FuncUnwinders.h"
40 #include "lldb/Symbol/LineTable.h"
41 #include "lldb/Symbol/ObjectFile.h"
42 #include "lldb/Symbol/SymbolFile.h"
43 #include "lldb/Symbol/SymbolVendor.h"
44 #include "lldb/Symbol/UnwindPlan.h"
45 #include "lldb/Symbol/VariableList.h"
46 #include "lldb/Target/ABI.h"
47 #include "lldb/Target/Process.h"
48 #include "lldb/Target/RegisterContext.h"
49 #include "lldb/Target/SectionLoadList.h"
50 #include "lldb/Target/StackFrame.h"
51 #include "lldb/Target/Thread.h"
52 #include "lldb/Target/ThreadSpec.h"
53 #include "lldb/Utility/Args.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         if (objfile)
1392           objfile->Dump(&strm);
1393       }
1394     }
1395     strm.IndentLess();
1396   }
1397   return num_dumped;
1398 }
1399 
1400 static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
1401                              Module *module, SortOrder sort_order) {
1402   if (module) {
1403     SymbolVendor *sym_vendor = module->GetSymbolVendor();
1404     if (sym_vendor) {
1405       Symtab *symtab = sym_vendor->GetSymtab();
1406       if (symtab)
1407         symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
1408                      sort_order);
1409     }
1410   }
1411 }
1412 
1413 static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,
1414                                Module *module) {
1415   if (module) {
1416     SectionList *section_list = module->GetSectionList();
1417     if (section_list) {
1418       strm.Printf("Sections for '%s' (%s):\n",
1419                   module->GetSpecificationDescription().c_str(),
1420                   module->GetArchitecture().GetArchitectureName());
1421       strm.IndentMore();
1422       section_list->Dump(&strm,
1423                          interpreter.GetExecutionContext().GetTargetPtr(), true,
1424                          UINT32_MAX);
1425       strm.IndentLess();
1426     }
1427   }
1428 }
1429 
1430 static bool DumpModuleSymbolVendor(Stream &strm, Module *module) {
1431   if (module) {
1432     SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
1433     if (symbol_vendor) {
1434       symbol_vendor->Dump(&strm);
1435       return true;
1436     }
1437   }
1438   return false;
1439 }
1440 
1441 static void DumpAddress(ExecutionContextScope *exe_scope,
1442                         const Address &so_addr, bool verbose, Stream &strm) {
1443   strm.IndentMore();
1444   strm.Indent("    Address: ");
1445   so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
1446   strm.PutCString(" (");
1447   so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset);
1448   strm.PutCString(")\n");
1449   strm.Indent("    Summary: ");
1450   const uint32_t save_indent = strm.GetIndentLevel();
1451   strm.SetIndentLevel(save_indent + 13);
1452   so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription);
1453   strm.SetIndentLevel(save_indent);
1454   // Print out detailed address information when verbose is enabled
1455   if (verbose) {
1456     strm.EOL();
1457     so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext);
1458   }
1459   strm.IndentLess();
1460 }
1461 
1462 static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
1463                                   Module *module, uint32_t resolve_mask,
1464                                   lldb::addr_t raw_addr, lldb::addr_t offset,
1465                                   bool verbose) {
1466   if (module) {
1467     lldb::addr_t addr = raw_addr - offset;
1468     Address so_addr;
1469     SymbolContext sc;
1470     Target *target = interpreter.GetExecutionContext().GetTargetPtr();
1471     if (target && !target->GetSectionLoadList().IsEmpty()) {
1472       if (!target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
1473         return false;
1474       else if (so_addr.GetModule().get() != module)
1475         return false;
1476     } else {
1477       if (!module->ResolveFileAddress(addr, so_addr))
1478         return false;
1479     }
1480 
1481     ExecutionContextScope *exe_scope =
1482         interpreter.GetExecutionContext().GetBestExecutionContextScope();
1483     DumpAddress(exe_scope, so_addr, verbose, strm);
1484     //        strm.IndentMore();
1485     //        strm.Indent ("    Address: ");
1486     //        so_addr.Dump (&strm, exe_scope,
1487     //        Address::DumpStyleModuleWithFileAddress);
1488     //        strm.PutCString (" (");
1489     //        so_addr.Dump (&strm, exe_scope,
1490     //        Address::DumpStyleSectionNameOffset);
1491     //        strm.PutCString (")\n");
1492     //        strm.Indent ("    Summary: ");
1493     //        const uint32_t save_indent = strm.GetIndentLevel ();
1494     //        strm.SetIndentLevel (save_indent + 13);
1495     //        so_addr.Dump (&strm, exe_scope,
1496     //        Address::DumpStyleResolvedDescription);
1497     //        strm.SetIndentLevel (save_indent);
1498     //        // Print out detailed address information when verbose is enabled
1499     //        if (verbose)
1500     //        {
1501     //            strm.EOL();
1502     //            so_addr.Dump (&strm, exe_scope,
1503     //            Address::DumpStyleDetailedSymbolContext);
1504     //        }
1505     //        strm.IndentLess();
1506     return true;
1507   }
1508 
1509   return false;
1510 }
1511 
1512 static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
1513                                      Stream &strm, Module *module,
1514                                      const char *name, bool name_is_regex,
1515                                      bool verbose) {
1516   if (module) {
1517     SymbolContext sc;
1518 
1519     SymbolVendor *sym_vendor = module->GetSymbolVendor();
1520     if (sym_vendor) {
1521       Symtab *symtab = sym_vendor->GetSymtab();
1522       if (symtab) {
1523         std::vector<uint32_t> match_indexes;
1524         ConstString symbol_name(name);
1525         uint32_t num_matches = 0;
1526         if (name_is_regex) {
1527           RegularExpression name_regexp(symbol_name.GetStringRef());
1528           num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType(
1529               name_regexp, eSymbolTypeAny, match_indexes);
1530         } else {
1531           num_matches =
1532               symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes);
1533         }
1534 
1535         if (num_matches > 0) {
1536           strm.Indent();
1537           strm.Printf("%u symbols match %s'%s' in ", num_matches,
1538                       name_is_regex ? "the regular expression " : "", name);
1539           DumpFullpath(strm, &module->GetFileSpec(), 0);
1540           strm.PutCString(":\n");
1541           strm.IndentMore();
1542           for (uint32_t i = 0; i < num_matches; ++i) {
1543             Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
1544             if (symbol && symbol->ValueIsAddress()) {
1545               DumpAddress(interpreter.GetExecutionContext()
1546                               .GetBestExecutionContextScope(),
1547                           symbol->GetAddressRef(), verbose, strm);
1548             }
1549           }
1550           strm.IndentLess();
1551           return num_matches;
1552         }
1553       }
1554     }
1555   }
1556   return 0;
1557 }
1558 
1559 static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
1560                                   Stream &strm, SymbolContextList &sc_list,
1561                                   bool verbose) {
1562   strm.IndentMore();
1563 
1564   const uint32_t num_matches = sc_list.GetSize();
1565 
1566   for (uint32_t i = 0; i < num_matches; ++i) {
1567     SymbolContext sc;
1568     if (sc_list.GetContextAtIndex(i, sc)) {
1569       AddressRange range;
1570 
1571       sc.GetAddressRange(eSymbolContextEverything, 0, true, range);
1572 
1573       DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm);
1574     }
1575   }
1576   strm.IndentLess();
1577 }
1578 
1579 static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
1580                                      Stream &strm, Module *module,
1581                                      const char *name, bool name_is_regex,
1582                                      bool include_inlines, bool include_symbols,
1583                                      bool verbose) {
1584   if (module && name && name[0]) {
1585     SymbolContextList sc_list;
1586     const bool append = true;
1587     size_t num_matches = 0;
1588     if (name_is_regex) {
1589       RegularExpression function_name_regex((llvm::StringRef(name)));
1590       num_matches = module->FindFunctions(function_name_regex, include_symbols,
1591                                           include_inlines, append, sc_list);
1592     } else {
1593       ConstString function_name(name);
1594       num_matches = module->FindFunctions(
1595           function_name, nullptr, eFunctionNameTypeAuto, include_symbols,
1596           include_inlines, append, sc_list);
1597     }
1598 
1599     if (num_matches) {
1600       strm.Indent();
1601       strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1602                   num_matches > 1 ? "es" : "");
1603       DumpFullpath(strm, &module->GetFileSpec(), 0);
1604       strm.PutCString(":\n");
1605       DumpSymbolContextList(
1606           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1607           strm, sc_list, verbose);
1608     }
1609     return num_matches;
1610   }
1611   return 0;
1612 }
1613 
1614 static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
1615                                  Module *module, const char *name_cstr,
1616                                  bool name_is_regex) {
1617   if (module && name_cstr && name_cstr[0]) {
1618     TypeList type_list;
1619     const uint32_t max_num_matches = UINT32_MAX;
1620     size_t num_matches = 0;
1621     bool name_is_fully_qualified = false;
1622     SymbolContext sc;
1623 
1624     ConstString name(name_cstr);
1625     llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
1626     num_matches =
1627         module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches,
1628                           searched_symbol_files, type_list);
1629 
1630     if (num_matches) {
1631       strm.Indent();
1632       strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1633                   num_matches > 1 ? "es" : "");
1634       DumpFullpath(strm, &module->GetFileSpec(), 0);
1635       strm.PutCString(":\n");
1636       for (TypeSP type_sp : type_list.Types()) {
1637         if (type_sp) {
1638           // Resolve the clang type so that any forward references
1639           // to types that haven't yet been parsed will get parsed.
1640           type_sp->GetFullCompilerType();
1641           type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1642           // Print all typedef chains
1643           TypeSP typedef_type_sp(type_sp);
1644           TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1645           while (typedefed_type_sp) {
1646             strm.EOL();
1647             strm.Printf("     typedef '%s': ",
1648                         typedef_type_sp->GetName().GetCString());
1649             typedefed_type_sp->GetFullCompilerType();
1650             typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull,
1651                                               true);
1652             typedef_type_sp = typedefed_type_sp;
1653             typedefed_type_sp = typedef_type_sp->GetTypedefType();
1654           }
1655         }
1656         strm.EOL();
1657       }
1658     }
1659     return num_matches;
1660   }
1661   return 0;
1662 }
1663 
1664 static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
1665                              const SymbolContext &sym_ctx,
1666                              const char *name_cstr, bool name_is_regex) {
1667   if (!sym_ctx.module_sp)
1668     return 0;
1669 
1670   TypeList type_list;
1671   const uint32_t max_num_matches = UINT32_MAX;
1672   size_t num_matches = 1;
1673   bool name_is_fully_qualified = false;
1674 
1675   ConstString name(name_cstr);
1676   llvm::DenseSet<SymbolFile *> searched_symbol_files;
1677   num_matches = sym_ctx.module_sp->FindTypes(
1678       sym_ctx, name, name_is_fully_qualified, max_num_matches,
1679       searched_symbol_files, type_list);
1680 
1681   if (num_matches) {
1682     strm.Indent();
1683     strm.PutCString("Best match found in ");
1684     DumpFullpath(strm, &sym_ctx.module_sp->GetFileSpec(), 0);
1685     strm.PutCString(":\n");
1686 
1687     TypeSP type_sp(type_list.GetTypeAtIndex(0));
1688     if (type_sp) {
1689       // Resolve the clang type so that any forward references
1690       // to types that haven't yet been parsed will get parsed.
1691       type_sp->GetFullCompilerType();
1692       type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1693       // Print all typedef chains
1694       TypeSP typedef_type_sp(type_sp);
1695       TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1696       while (typedefed_type_sp) {
1697         strm.EOL();
1698         strm.Printf("     typedef '%s': ",
1699                     typedef_type_sp->GetName().GetCString());
1700         typedefed_type_sp->GetFullCompilerType();
1701         typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1702         typedef_type_sp = typedefed_type_sp;
1703         typedefed_type_sp = typedef_type_sp->GetTypedefType();
1704       }
1705     }
1706     strm.EOL();
1707   }
1708   return num_matches;
1709 }
1710 
1711 static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
1712                                           Stream &strm, Module *module,
1713                                           const FileSpec &file_spec,
1714                                           uint32_t line, bool check_inlines,
1715                                           bool verbose) {
1716   if (module && file_spec) {
1717     SymbolContextList sc_list;
1718     const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
1719         file_spec, line, check_inlines, eSymbolContextEverything, sc_list);
1720     if (num_matches > 0) {
1721       strm.Indent();
1722       strm.Printf("%u match%s found in ", num_matches,
1723                   num_matches > 1 ? "es" : "");
1724       strm << file_spec;
1725       if (line > 0)
1726         strm.Printf(":%u", line);
1727       strm << " in ";
1728       DumpFullpath(strm, &module->GetFileSpec(), 0);
1729       strm.PutCString(":\n");
1730       DumpSymbolContextList(
1731           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1732           strm, sc_list, verbose);
1733       return num_matches;
1734     }
1735   }
1736   return 0;
1737 }
1738 
1739 static size_t FindModulesByName(Target *target, const char *module_name,
1740                                 ModuleList &module_list,
1741                                 bool check_global_list) {
1742   FileSpec module_file_spec(module_name, false);
1743   ModuleSpec module_spec(module_file_spec);
1744 
1745   const size_t initial_size = module_list.GetSize();
1746 
1747   if (check_global_list) {
1748     // Check the global list
1749     std::lock_guard<std::recursive_mutex> guard(
1750         Module::GetAllocationModuleCollectionMutex());
1751     const size_t num_modules = Module::GetNumberAllocatedModules();
1752     ModuleSP module_sp;
1753     for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1754       Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
1755 
1756       if (module) {
1757         if (module->MatchesModuleSpec(module_spec)) {
1758           module_sp = module->shared_from_this();
1759           module_list.AppendIfNeeded(module_sp);
1760         }
1761       }
1762     }
1763   } else {
1764     if (target) {
1765       const size_t num_matches =
1766           target->GetImages().FindModules(module_spec, module_list);
1767 
1768       // Not found in our module list for our target, check the main
1769       // shared module list in case it is a extra file used somewhere
1770       // else
1771       if (num_matches == 0) {
1772         module_spec.GetArchitecture() = target->GetArchitecture();
1773         ModuleList::FindSharedModules(module_spec, module_list);
1774       }
1775     } else {
1776       ModuleList::FindSharedModules(module_spec, module_list);
1777     }
1778   }
1779 
1780   return module_list.GetSize() - initial_size;
1781 }
1782 
1783 #pragma mark CommandObjectTargetModulesModuleAutoComplete
1784 
1785 //----------------------------------------------------------------------
1786 // A base command object class that can auto complete with module file
1787 // paths
1788 //----------------------------------------------------------------------
1789 
1790 class CommandObjectTargetModulesModuleAutoComplete
1791     : public CommandObjectParsed {
1792 public:
1793   CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
1794                                                const char *name,
1795                                                const char *help,
1796                                                const char *syntax)
1797       : CommandObjectParsed(interpreter, name, help, syntax) {
1798     CommandArgumentEntry arg;
1799     CommandArgumentData file_arg;
1800 
1801     // Define the first (and only) variant of this arg.
1802     file_arg.arg_type = eArgTypeFilename;
1803     file_arg.arg_repetition = eArgRepeatStar;
1804 
1805     // There is only one variant this argument could be; put it into the
1806     // argument entry.
1807     arg.push_back(file_arg);
1808 
1809     // Push the data for the first argument into the m_arguments vector.
1810     m_arguments.push_back(arg);
1811   }
1812 
1813   ~CommandObjectTargetModulesModuleAutoComplete() override = default;
1814 
1815   int HandleArgumentCompletion(Args &input, int &cursor_index,
1816                                int &cursor_char_position,
1817                                OptionElementVector &opt_element_vector,
1818                                int match_start_point, int max_return_elements,
1819                                bool &word_complete,
1820                                StringList &matches) override {
1821     // Arguments are the standard module completer.
1822     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
1823     completion_str.erase(cursor_char_position);
1824 
1825     CommandCompletions::InvokeCommonCompletionCallbacks(
1826         GetCommandInterpreter(), CommandCompletions::eModuleCompletion,
1827         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
1828         word_complete, matches);
1829     return matches.GetSize();
1830   }
1831 };
1832 
1833 #pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1834 
1835 //----------------------------------------------------------------------
1836 // A base command object class that can auto complete with module source
1837 // file paths
1838 //----------------------------------------------------------------------
1839 
1840 class CommandObjectTargetModulesSourceFileAutoComplete
1841     : public CommandObjectParsed {
1842 public:
1843   CommandObjectTargetModulesSourceFileAutoComplete(
1844       CommandInterpreter &interpreter, const char *name, const char *help,
1845       const char *syntax, uint32_t flags)
1846       : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1847     CommandArgumentEntry arg;
1848     CommandArgumentData source_file_arg;
1849 
1850     // Define the first (and only) variant of this arg.
1851     source_file_arg.arg_type = eArgTypeSourceFile;
1852     source_file_arg.arg_repetition = eArgRepeatPlus;
1853 
1854     // There is only one variant this argument could be; put it into the
1855     // argument entry.
1856     arg.push_back(source_file_arg);
1857 
1858     // Push the data for the first argument into the m_arguments vector.
1859     m_arguments.push_back(arg);
1860   }
1861 
1862   ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
1863 
1864   int HandleArgumentCompletion(Args &input, int &cursor_index,
1865                                int &cursor_char_position,
1866                                OptionElementVector &opt_element_vector,
1867                                int match_start_point, int max_return_elements,
1868                                bool &word_complete,
1869                                StringList &matches) override {
1870     // Arguments are the standard source file completer.
1871     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
1872     completion_str.erase(cursor_char_position);
1873 
1874     CommandCompletions::InvokeCommonCompletionCallbacks(
1875         GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
1876         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
1877         word_complete, matches);
1878     return matches.GetSize();
1879   }
1880 };
1881 
1882 #pragma mark CommandObjectTargetModulesDumpObjfile
1883 
1884 class CommandObjectTargetModulesDumpObjfile
1885     : public CommandObjectTargetModulesModuleAutoComplete {
1886 public:
1887   CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
1888       : CommandObjectTargetModulesModuleAutoComplete(
1889             interpreter, "target modules dump objfile",
1890             "Dump the object file headers from one or more target modules.",
1891             nullptr) {}
1892 
1893   ~CommandObjectTargetModulesDumpObjfile() override = default;
1894 
1895 protected:
1896   bool DoExecute(Args &command, CommandReturnObject &result) override {
1897     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1898     if (target == nullptr) {
1899       result.AppendError("invalid target, create a debug target using the "
1900                          "'target create' command");
1901       result.SetStatus(eReturnStatusFailed);
1902       return false;
1903     }
1904 
1905     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1906     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1907     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1908 
1909     size_t num_dumped = 0;
1910     if (command.GetArgumentCount() == 0) {
1911       // Dump all headers for all modules images
1912       num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(),
1913                                             target->GetImages());
1914       if (num_dumped == 0) {
1915         result.AppendError("the target has no associated executable images");
1916         result.SetStatus(eReturnStatusFailed);
1917       }
1918     } else {
1919       // Find the modules that match the basename or full path.
1920       ModuleList module_list;
1921       const char *arg_cstr;
1922       for (int arg_idx = 0;
1923            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
1924            ++arg_idx) {
1925         size_t num_matched =
1926             FindModulesByName(target, arg_cstr, module_list, true);
1927         if (num_matched == 0) {
1928           result.AppendWarningWithFormat(
1929               "Unable to find an image that matches '%s'.\n", arg_cstr);
1930         }
1931       }
1932       // Dump all the modules we found.
1933       num_dumped =
1934           DumpModuleObjfileHeaders(result.GetOutputStream(), module_list);
1935     }
1936 
1937     if (num_dumped > 0) {
1938       result.SetStatus(eReturnStatusSuccessFinishResult);
1939     } else {
1940       result.AppendError("no matching executable images found");
1941       result.SetStatus(eReturnStatusFailed);
1942     }
1943     return result.Succeeded();
1944   }
1945 };
1946 
1947 #pragma mark CommandObjectTargetModulesDumpSymtab
1948 
1949 static OptionEnumValueElement g_sort_option_enumeration[4] = {
1950     {eSortOrderNone, "none",
1951      "No sorting, use the original symbol table order."},
1952     {eSortOrderByAddress, "address", "Sort output by symbol address."},
1953     {eSortOrderByName, "name", "Sort output by symbol name."},
1954     {0, nullptr, nullptr}};
1955 
1956 static OptionDefinition g_target_modules_dump_symtab_options[] = {
1957     // clang-format off
1958   { 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." }
1959     // clang-format on
1960 };
1961 
1962 class CommandObjectTargetModulesDumpSymtab
1963     : public CommandObjectTargetModulesModuleAutoComplete {
1964 public:
1965   CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
1966       : CommandObjectTargetModulesModuleAutoComplete(
1967             interpreter, "target modules dump symtab",
1968             "Dump the symbol table from one or more target modules.", nullptr),
1969         m_options() {}
1970 
1971   ~CommandObjectTargetModulesDumpSymtab() override = default;
1972 
1973   Options *GetOptions() override { return &m_options; }
1974 
1975   class CommandOptions : public Options {
1976   public:
1977     CommandOptions() : Options(), m_sort_order(eSortOrderNone) {}
1978 
1979     ~CommandOptions() override = default;
1980 
1981     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1982                           ExecutionContext *execution_context) override {
1983       Status error;
1984       const int short_option = m_getopt_table[option_idx].val;
1985 
1986       switch (short_option) {
1987       case 's':
1988         m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
1989             option_arg, GetDefinitions()[option_idx].enum_values,
1990             eSortOrderNone, error);
1991         break;
1992 
1993       default:
1994         error.SetErrorStringWithFormat("invalid short option character '%c'",
1995                                        short_option);
1996         break;
1997       }
1998       return error;
1999     }
2000 
2001     void OptionParsingStarting(ExecutionContext *execution_context) override {
2002       m_sort_order = eSortOrderNone;
2003     }
2004 
2005     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2006       return llvm::makeArrayRef(g_target_modules_dump_symtab_options);
2007     }
2008 
2009     SortOrder m_sort_order;
2010   };
2011 
2012 protected:
2013   bool DoExecute(Args &command, CommandReturnObject &result) override {
2014     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2015     if (target == nullptr) {
2016       result.AppendError("invalid target, create a debug target using the "
2017                          "'target create' command");
2018       result.SetStatus(eReturnStatusFailed);
2019       return false;
2020     } else {
2021       uint32_t num_dumped = 0;
2022 
2023       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2024       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2025       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2026 
2027       if (command.GetArgumentCount() == 0) {
2028         // Dump all sections for all modules images
2029         std::lock_guard<std::recursive_mutex> guard(
2030             target->GetImages().GetMutex());
2031         const size_t num_modules = target->GetImages().GetSize();
2032         if (num_modules > 0) {
2033           result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64
2034                                           " modules.\n",
2035                                           (uint64_t)num_modules);
2036           for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2037             if (num_dumped > 0) {
2038               result.GetOutputStream().EOL();
2039               result.GetOutputStream().EOL();
2040             }
2041             if (m_interpreter.WasInterrupted())
2042               break;
2043             num_dumped++;
2044             DumpModuleSymtab(
2045                 m_interpreter, result.GetOutputStream(),
2046                 target->GetImages().GetModulePointerAtIndexUnlocked(image_idx),
2047                 m_options.m_sort_order);
2048           }
2049         } else {
2050           result.AppendError("the target has no associated executable images");
2051           result.SetStatus(eReturnStatusFailed);
2052           return false;
2053         }
2054       } else {
2055         // Dump specified images (by basename or fullpath)
2056         const char *arg_cstr;
2057         for (int arg_idx = 0;
2058              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2059              ++arg_idx) {
2060           ModuleList module_list;
2061           const size_t num_matches =
2062               FindModulesByName(target, arg_cstr, module_list, true);
2063           if (num_matches > 0) {
2064             for (size_t i = 0; i < num_matches; ++i) {
2065               Module *module = module_list.GetModulePointerAtIndex(i);
2066               if (module) {
2067                 if (num_dumped > 0) {
2068                   result.GetOutputStream().EOL();
2069                   result.GetOutputStream().EOL();
2070                 }
2071                 if (m_interpreter.WasInterrupted())
2072                   break;
2073                 num_dumped++;
2074                 DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
2075                                  module, m_options.m_sort_order);
2076               }
2077             }
2078           } else
2079             result.AppendWarningWithFormat(
2080                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2081         }
2082       }
2083 
2084       if (num_dumped > 0)
2085         result.SetStatus(eReturnStatusSuccessFinishResult);
2086       else {
2087         result.AppendError("no matching executable images found");
2088         result.SetStatus(eReturnStatusFailed);
2089       }
2090     }
2091     return result.Succeeded();
2092   }
2093 
2094   CommandOptions m_options;
2095 };
2096 
2097 #pragma mark CommandObjectTargetModulesDumpSections
2098 
2099 //----------------------------------------------------------------------
2100 // Image section dumping command
2101 //----------------------------------------------------------------------
2102 
2103 class CommandObjectTargetModulesDumpSections
2104     : public CommandObjectTargetModulesModuleAutoComplete {
2105 public:
2106   CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter)
2107       : CommandObjectTargetModulesModuleAutoComplete(
2108             interpreter, "target modules dump sections",
2109             "Dump the sections from one or more target modules.",
2110             //"target modules dump sections [<file1> ...]")
2111             nullptr) {}
2112 
2113   ~CommandObjectTargetModulesDumpSections() override = default;
2114 
2115 protected:
2116   bool DoExecute(Args &command, CommandReturnObject &result) override {
2117     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2118     if (target == nullptr) {
2119       result.AppendError("invalid target, create a debug target using the "
2120                          "'target create' command");
2121       result.SetStatus(eReturnStatusFailed);
2122       return false;
2123     } else {
2124       uint32_t num_dumped = 0;
2125 
2126       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2127       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2128       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2129 
2130       if (command.GetArgumentCount() == 0) {
2131         // Dump all sections for all modules images
2132         const size_t num_modules = target->GetImages().GetSize();
2133         if (num_modules > 0) {
2134           result.GetOutputStream().Printf("Dumping sections for %" PRIu64
2135                                           " modules.\n",
2136                                           (uint64_t)num_modules);
2137           for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2138             if (m_interpreter.WasInterrupted())
2139               break;
2140             num_dumped++;
2141             DumpModuleSections(
2142                 m_interpreter, result.GetOutputStream(),
2143                 target->GetImages().GetModulePointerAtIndex(image_idx));
2144           }
2145         } else {
2146           result.AppendError("the target has no associated executable images");
2147           result.SetStatus(eReturnStatusFailed);
2148           return false;
2149         }
2150       } else {
2151         // Dump specified images (by basename or fullpath)
2152         const char *arg_cstr;
2153         for (int arg_idx = 0;
2154              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2155              ++arg_idx) {
2156           ModuleList module_list;
2157           const size_t num_matches =
2158               FindModulesByName(target, arg_cstr, module_list, true);
2159           if (num_matches > 0) {
2160             for (size_t i = 0; i < num_matches; ++i) {
2161               if (m_interpreter.WasInterrupted())
2162                 break;
2163               Module *module = module_list.GetModulePointerAtIndex(i);
2164               if (module) {
2165                 num_dumped++;
2166                 DumpModuleSections(m_interpreter, result.GetOutputStream(),
2167                                    module);
2168               }
2169             }
2170           } else {
2171             // Check the global list
2172             std::lock_guard<std::recursive_mutex> guard(
2173                 Module::GetAllocationModuleCollectionMutex());
2174 
2175             result.AppendWarningWithFormat(
2176                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2177           }
2178         }
2179       }
2180 
2181       if (num_dumped > 0)
2182         result.SetStatus(eReturnStatusSuccessFinishResult);
2183       else {
2184         result.AppendError("no matching executable images found");
2185         result.SetStatus(eReturnStatusFailed);
2186       }
2187     }
2188     return result.Succeeded();
2189   }
2190 };
2191 
2192 #pragma mark CommandObjectTargetModulesDumpSymfile
2193 
2194 //----------------------------------------------------------------------
2195 // Image debug symbol dumping command
2196 //----------------------------------------------------------------------
2197 
2198 class CommandObjectTargetModulesDumpSymfile
2199     : public CommandObjectTargetModulesModuleAutoComplete {
2200 public:
2201   CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter)
2202       : CommandObjectTargetModulesModuleAutoComplete(
2203             interpreter, "target modules dump symfile",
2204             "Dump the debug symbol file for one or more target modules.",
2205             //"target modules dump symfile [<file1> ...]")
2206             nullptr) {}
2207 
2208   ~CommandObjectTargetModulesDumpSymfile() override = default;
2209 
2210 protected:
2211   bool DoExecute(Args &command, CommandReturnObject &result) override {
2212     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2213     if (target == nullptr) {
2214       result.AppendError("invalid target, create a debug target using the "
2215                          "'target create' command");
2216       result.SetStatus(eReturnStatusFailed);
2217       return false;
2218     } else {
2219       uint32_t num_dumped = 0;
2220 
2221       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2222       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2223       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2224 
2225       if (command.GetArgumentCount() == 0) {
2226         // Dump all sections for all modules images
2227         const ModuleList &target_modules = target->GetImages();
2228         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2229         const size_t num_modules = target_modules.GetSize();
2230         if (num_modules > 0) {
2231           result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64
2232                                           " modules.\n",
2233                                           (uint64_t)num_modules);
2234           for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2235             if (m_interpreter.WasInterrupted())
2236               break;
2237             if (DumpModuleSymbolVendor(
2238                     result.GetOutputStream(),
2239                     target_modules.GetModulePointerAtIndexUnlocked(image_idx)))
2240               num_dumped++;
2241           }
2242         } else {
2243           result.AppendError("the target has no associated executable images");
2244           result.SetStatus(eReturnStatusFailed);
2245           return false;
2246         }
2247       } else {
2248         // Dump specified images (by basename or fullpath)
2249         const char *arg_cstr;
2250         for (int arg_idx = 0;
2251              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2252              ++arg_idx) {
2253           ModuleList module_list;
2254           const size_t num_matches =
2255               FindModulesByName(target, arg_cstr, module_list, true);
2256           if (num_matches > 0) {
2257             for (size_t i = 0; i < num_matches; ++i) {
2258               if (m_interpreter.WasInterrupted())
2259                 break;
2260               Module *module = module_list.GetModulePointerAtIndex(i);
2261               if (module) {
2262                 if (DumpModuleSymbolVendor(result.GetOutputStream(), module))
2263                   num_dumped++;
2264               }
2265             }
2266           } else
2267             result.AppendWarningWithFormat(
2268                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2269         }
2270       }
2271 
2272       if (num_dumped > 0)
2273         result.SetStatus(eReturnStatusSuccessFinishResult);
2274       else {
2275         result.AppendError("no matching executable images found");
2276         result.SetStatus(eReturnStatusFailed);
2277       }
2278     }
2279     return result.Succeeded();
2280   }
2281 };
2282 
2283 #pragma mark CommandObjectTargetModulesDumpLineTable
2284 
2285 //----------------------------------------------------------------------
2286 // Image debug line table dumping command
2287 //----------------------------------------------------------------------
2288 
2289 class CommandObjectTargetModulesDumpLineTable
2290     : public CommandObjectTargetModulesSourceFileAutoComplete {
2291 public:
2292   CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter)
2293       : CommandObjectTargetModulesSourceFileAutoComplete(
2294             interpreter, "target modules dump line-table",
2295             "Dump the line table for one or more compilation units.", nullptr,
2296             eCommandRequiresTarget) {}
2297 
2298   ~CommandObjectTargetModulesDumpLineTable() override = default;
2299 
2300 protected:
2301   bool DoExecute(Args &command, CommandReturnObject &result) override {
2302     Target *target = m_exe_ctx.GetTargetPtr();
2303     uint32_t total_num_dumped = 0;
2304 
2305     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2306     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2307     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2308 
2309     if (command.GetArgumentCount() == 0) {
2310       result.AppendError("file option must be specified.");
2311       result.SetStatus(eReturnStatusFailed);
2312       return result.Succeeded();
2313     } else {
2314       // Dump specified images (by basename or fullpath)
2315       const char *arg_cstr;
2316       for (int arg_idx = 0;
2317            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2318            ++arg_idx) {
2319         FileSpec file_spec(arg_cstr, false);
2320 
2321         const ModuleList &target_modules = target->GetImages();
2322         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2323         const size_t num_modules = target_modules.GetSize();
2324         if (num_modules > 0) {
2325           uint32_t num_dumped = 0;
2326           for (uint32_t i = 0; i < num_modules; ++i) {
2327             if (m_interpreter.WasInterrupted())
2328               break;
2329             if (DumpCompileUnitLineTable(
2330                     m_interpreter, result.GetOutputStream(),
2331                     target_modules.GetModulePointerAtIndexUnlocked(i),
2332                     file_spec, m_exe_ctx.GetProcessPtr() &&
2333                                    m_exe_ctx.GetProcessRef().IsAlive()))
2334               num_dumped++;
2335           }
2336           if (num_dumped == 0)
2337             result.AppendWarningWithFormat(
2338                 "No source filenames matched '%s'.\n", arg_cstr);
2339           else
2340             total_num_dumped += num_dumped;
2341         }
2342       }
2343     }
2344 
2345     if (total_num_dumped > 0)
2346       result.SetStatus(eReturnStatusSuccessFinishResult);
2347     else {
2348       result.AppendError("no source filenames matched any command arguments");
2349       result.SetStatus(eReturnStatusFailed);
2350     }
2351     return result.Succeeded();
2352   }
2353 };
2354 
2355 #pragma mark CommandObjectTargetModulesDump
2356 
2357 //----------------------------------------------------------------------
2358 // Dump multi-word command for target modules
2359 //----------------------------------------------------------------------
2360 
2361 class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2362 public:
2363   //------------------------------------------------------------------
2364   // Constructors and Destructors
2365   //------------------------------------------------------------------
2366   CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
2367       : CommandObjectMultiword(interpreter, "target modules dump",
2368                                "Commands for dumping information about one or "
2369                                "more target modules.",
2370                                "target modules dump "
2371                                "[headers|symtab|sections|symfile|line-table] "
2372                                "[<file1> <file2> ...]") {
2373     LoadSubCommand("objfile",
2374                    CommandObjectSP(
2375                        new CommandObjectTargetModulesDumpObjfile(interpreter)));
2376     LoadSubCommand(
2377         "symtab",
2378         CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter)));
2379     LoadSubCommand("sections",
2380                    CommandObjectSP(new CommandObjectTargetModulesDumpSections(
2381                        interpreter)));
2382     LoadSubCommand("symfile",
2383                    CommandObjectSP(
2384                        new CommandObjectTargetModulesDumpSymfile(interpreter)));
2385     LoadSubCommand("line-table",
2386                    CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
2387                        interpreter)));
2388   }
2389 
2390   ~CommandObjectTargetModulesDump() override = default;
2391 };
2392 
2393 class CommandObjectTargetModulesAdd : public CommandObjectParsed {
2394 public:
2395   CommandObjectTargetModulesAdd(CommandInterpreter &interpreter)
2396       : CommandObjectParsed(interpreter, "target modules add",
2397                             "Add a new module to the current target's modules.",
2398                             "target modules add [<module>]"),
2399         m_option_group(),
2400         m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
2401                       eArgTypeFilename, "Fullpath to a stand alone debug "
2402                                         "symbols file for when debug symbols "
2403                                         "are not in the executable.") {
2404     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2405                           LLDB_OPT_SET_1);
2406     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2407     m_option_group.Finalize();
2408   }
2409 
2410   ~CommandObjectTargetModulesAdd() override = default;
2411 
2412   Options *GetOptions() override { return &m_option_group; }
2413 
2414   int HandleArgumentCompletion(Args &input, int &cursor_index,
2415                                int &cursor_char_position,
2416                                OptionElementVector &opt_element_vector,
2417                                int match_start_point, int max_return_elements,
2418                                bool &word_complete,
2419                                StringList &matches) override {
2420     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
2421     completion_str.erase(cursor_char_position);
2422 
2423     CommandCompletions::InvokeCommonCompletionCallbacks(
2424         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
2425         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
2426         word_complete, matches);
2427     return matches.GetSize();
2428   }
2429 
2430 protected:
2431   OptionGroupOptions m_option_group;
2432   OptionGroupUUID m_uuid_option_group;
2433   OptionGroupFile m_symbol_file;
2434 
2435   bool DoExecute(Args &args, CommandReturnObject &result) override {
2436     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2437     if (target == nullptr) {
2438       result.AppendError("invalid target, create a debug target using the "
2439                          "'target create' command");
2440       result.SetStatus(eReturnStatusFailed);
2441       return false;
2442     } else {
2443       bool flush = false;
2444 
2445       const size_t argc = args.GetArgumentCount();
2446       if (argc == 0) {
2447         if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2448           // We are given a UUID only, go locate the file
2449           ModuleSpec module_spec;
2450           module_spec.GetUUID() =
2451               m_uuid_option_group.GetOptionValue().GetCurrentValue();
2452           if (m_symbol_file.GetOptionValue().OptionWasSet())
2453             module_spec.GetSymbolFileSpec() =
2454                 m_symbol_file.GetOptionValue().GetCurrentValue();
2455           if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
2456             ModuleSP module_sp(target->GetSharedModule(module_spec));
2457             if (module_sp) {
2458               result.SetStatus(eReturnStatusSuccessFinishResult);
2459               return true;
2460             } else {
2461               StreamString strm;
2462               module_spec.GetUUID().Dump(&strm);
2463               if (module_spec.GetFileSpec()) {
2464                 if (module_spec.GetSymbolFileSpec()) {
2465                   result.AppendErrorWithFormat(
2466                       "Unable to create the executable or symbol file with "
2467                       "UUID %s with path %s and symbol file %s",
2468                       strm.GetData(),
2469                       module_spec.GetFileSpec().GetPath().c_str(),
2470                       module_spec.GetSymbolFileSpec().GetPath().c_str());
2471                 } else {
2472                   result.AppendErrorWithFormat(
2473                       "Unable to create the executable or symbol file with "
2474                       "UUID %s with path %s",
2475                       strm.GetData(),
2476                       module_spec.GetFileSpec().GetPath().c_str());
2477                 }
2478               } else {
2479                 result.AppendErrorWithFormat("Unable to create the executable "
2480                                              "or symbol file with UUID %s",
2481                                              strm.GetData());
2482               }
2483               result.SetStatus(eReturnStatusFailed);
2484               return false;
2485             }
2486           } else {
2487             StreamString strm;
2488             module_spec.GetUUID().Dump(&strm);
2489             result.AppendErrorWithFormat(
2490                 "Unable to locate the executable or symbol file with UUID %s",
2491                 strm.GetData());
2492             result.SetStatus(eReturnStatusFailed);
2493             return false;
2494           }
2495         } else {
2496           result.AppendError(
2497               "one or more executable image paths must be specified");
2498           result.SetStatus(eReturnStatusFailed);
2499           return false;
2500         }
2501       } else {
2502         for (auto &entry : args.entries()) {
2503           if (entry.ref.empty())
2504             continue;
2505 
2506           FileSpec file_spec(entry.ref, true);
2507           if (file_spec.Exists()) {
2508             ModuleSpec module_spec(file_spec);
2509             if (m_uuid_option_group.GetOptionValue().OptionWasSet())
2510               module_spec.GetUUID() =
2511                   m_uuid_option_group.GetOptionValue().GetCurrentValue();
2512             if (m_symbol_file.GetOptionValue().OptionWasSet())
2513               module_spec.GetSymbolFileSpec() =
2514                   m_symbol_file.GetOptionValue().GetCurrentValue();
2515             if (!module_spec.GetArchitecture().IsValid())
2516               module_spec.GetArchitecture() = target->GetArchitecture();
2517             Status error;
2518             ModuleSP module_sp(target->GetSharedModule(module_spec, &error));
2519             if (!module_sp) {
2520               const char *error_cstr = error.AsCString();
2521               if (error_cstr)
2522                 result.AppendError(error_cstr);
2523               else
2524                 result.AppendErrorWithFormat("unsupported module: %s",
2525                                              entry.c_str());
2526               result.SetStatus(eReturnStatusFailed);
2527               return false;
2528             } else {
2529               flush = true;
2530             }
2531             result.SetStatus(eReturnStatusSuccessFinishResult);
2532           } else {
2533             std::string resolved_path = file_spec.GetPath();
2534             result.SetStatus(eReturnStatusFailed);
2535             if (resolved_path != entry.ref) {
2536               result.AppendErrorWithFormat(
2537                   "invalid module path '%s' with resolved path '%s'\n",
2538                   entry.ref.str().c_str(), resolved_path.c_str());
2539               break;
2540             }
2541             result.AppendErrorWithFormat("invalid module path '%s'\n",
2542                                          entry.c_str());
2543             break;
2544           }
2545         }
2546       }
2547 
2548       if (flush) {
2549         ProcessSP process = target->GetProcessSP();
2550         if (process)
2551           process->Flush();
2552       }
2553     }
2554 
2555     return result.Succeeded();
2556   }
2557 };
2558 
2559 class CommandObjectTargetModulesLoad
2560     : public CommandObjectTargetModulesModuleAutoComplete {
2561 public:
2562   CommandObjectTargetModulesLoad(CommandInterpreter &interpreter)
2563       : CommandObjectTargetModulesModuleAutoComplete(
2564             interpreter, "target modules load", "Set the load addresses for "
2565                                                 "one or more sections in a "
2566                                                 "target module.",
2567             "target modules load [--file <module> --uuid <uuid>] <sect-name> "
2568             "<address> [<sect-name> <address> ....]"),
2569         m_option_group(),
2570         m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName,
2571                       "Fullpath or basename for module to load.", ""),
2572         m_load_option(LLDB_OPT_SET_1, false, "load", 'l',
2573                       "Write file contents to the memory.", false, true),
2574         m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p',
2575                     "Set PC to the entry point."
2576                     " Only applicable with '--load' option.",
2577                     false, true),
2578         m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset,
2579                        "Set the load address for all sections to be the "
2580                        "virtual address in the file plus the offset.",
2581                        0) {
2582     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2583                           LLDB_OPT_SET_1);
2584     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2585     m_option_group.Append(&m_load_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2586     m_option_group.Append(&m_pc_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2587     m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2588     m_option_group.Finalize();
2589   }
2590 
2591   ~CommandObjectTargetModulesLoad() override = default;
2592 
2593   Options *GetOptions() override { return &m_option_group; }
2594 
2595 protected:
2596   bool DoExecute(Args &args, CommandReturnObject &result) override {
2597     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2598     const bool load = m_load_option.GetOptionValue().GetCurrentValue();
2599     const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();
2600     if (target == nullptr) {
2601       result.AppendError("invalid target, create a debug target using the "
2602                          "'target create' command");
2603       result.SetStatus(eReturnStatusFailed);
2604       return false;
2605     } else {
2606       const size_t argc = args.GetArgumentCount();
2607       ModuleSpec module_spec;
2608       bool search_using_module_spec = false;
2609 
2610       // Allow "load" option to work without --file or --uuid
2611       // option.
2612       if (load) {
2613         if (!m_file_option.GetOptionValue().OptionWasSet() &&
2614             !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2615           ModuleList &module_list = target->GetImages();
2616           if (module_list.GetSize() == 1) {
2617             search_using_module_spec = true;
2618             module_spec.GetFileSpec() =
2619                 module_list.GetModuleAtIndex(0)->GetFileSpec();
2620           }
2621         }
2622       }
2623 
2624       if (m_file_option.GetOptionValue().OptionWasSet()) {
2625         search_using_module_spec = true;
2626         const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
2627         const bool use_global_module_list = true;
2628         ModuleList module_list;
2629         const size_t num_matches = FindModulesByName(
2630             target, arg_cstr, module_list, use_global_module_list);
2631         if (num_matches == 1) {
2632           module_spec.GetFileSpec() =
2633               module_list.GetModuleAtIndex(0)->GetFileSpec();
2634         } else if (num_matches > 1) {
2635           search_using_module_spec = false;
2636           result.AppendErrorWithFormat(
2637               "more than 1 module matched by name '%s'\n", arg_cstr);
2638           result.SetStatus(eReturnStatusFailed);
2639         } else {
2640           search_using_module_spec = false;
2641           result.AppendErrorWithFormat("no object file for module '%s'\n",
2642                                        arg_cstr);
2643           result.SetStatus(eReturnStatusFailed);
2644         }
2645       }
2646 
2647       if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2648         search_using_module_spec = true;
2649         module_spec.GetUUID() =
2650             m_uuid_option_group.GetOptionValue().GetCurrentValue();
2651       }
2652 
2653       if (search_using_module_spec) {
2654         ModuleList matching_modules;
2655         const size_t num_matches =
2656             target->GetImages().FindModules(module_spec, matching_modules);
2657 
2658         char path[PATH_MAX];
2659         if (num_matches == 1) {
2660           Module *module = matching_modules.GetModulePointerAtIndex(0);
2661           if (module) {
2662             ObjectFile *objfile = module->GetObjectFile();
2663             if (objfile) {
2664               SectionList *section_list = module->GetSectionList();
2665               if (section_list) {
2666                 bool changed = false;
2667                 if (argc == 0) {
2668                   if (m_slide_option.GetOptionValue().OptionWasSet()) {
2669                     const addr_t slide =
2670                         m_slide_option.GetOptionValue().GetCurrentValue();
2671                     const bool slide_is_offset = true;
2672                     module->SetLoadAddress(*target, slide, slide_is_offset,
2673                                            changed);
2674                   } else {
2675                     result.AppendError("one or more section name + load "
2676                                        "address pair must be specified");
2677                     result.SetStatus(eReturnStatusFailed);
2678                     return false;
2679                   }
2680                 } else {
2681                   if (m_slide_option.GetOptionValue().OptionWasSet()) {
2682                     result.AppendError("The \"--slide <offset>\" option can't "
2683                                        "be used in conjunction with setting "
2684                                        "section load addresses.\n");
2685                     result.SetStatus(eReturnStatusFailed);
2686                     return false;
2687                   }
2688 
2689                   for (size_t i = 0; i < argc; i += 2) {
2690                     const char *sect_name = args.GetArgumentAtIndex(i);
2691                     const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1);
2692                     if (sect_name && load_addr_cstr) {
2693                       ConstString const_sect_name(sect_name);
2694                       bool success = false;
2695                       addr_t load_addr = StringConvert::ToUInt64(
2696                           load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success);
2697                       if (success) {
2698                         SectionSP section_sp(
2699                             section_list->FindSectionByName(const_sect_name));
2700                         if (section_sp) {
2701                           if (section_sp->IsThreadSpecific()) {
2702                             result.AppendErrorWithFormat(
2703                                 "thread specific sections are not yet "
2704                                 "supported (section '%s')\n",
2705                                 sect_name);
2706                             result.SetStatus(eReturnStatusFailed);
2707                             break;
2708                           } else {
2709                             if (target->GetSectionLoadList()
2710                                     .SetSectionLoadAddress(section_sp,
2711                                                            load_addr))
2712                               changed = true;
2713                             result.AppendMessageWithFormat(
2714                                 "section '%s' loaded at 0x%" PRIx64 "\n",
2715                                 sect_name, load_addr);
2716                           }
2717                         } else {
2718                           result.AppendErrorWithFormat("no section found that "
2719                                                        "matches the section "
2720                                                        "name '%s'\n",
2721                                                        sect_name);
2722                           result.SetStatus(eReturnStatusFailed);
2723                           break;
2724                         }
2725                       } else {
2726                         result.AppendErrorWithFormat(
2727                             "invalid load address string '%s'\n",
2728                             load_addr_cstr);
2729                         result.SetStatus(eReturnStatusFailed);
2730                         break;
2731                       }
2732                     } else {
2733                       if (sect_name)
2734                         result.AppendError("section names must be followed by "
2735                                            "a load address.\n");
2736                       else
2737                         result.AppendError("one or more section name + load "
2738                                            "address pair must be specified.\n");
2739                       result.SetStatus(eReturnStatusFailed);
2740                       break;
2741                     }
2742                   }
2743                 }
2744 
2745                 if (changed) {
2746                   target->ModulesDidLoad(matching_modules);
2747                   Process *process = m_exe_ctx.GetProcessPtr();
2748                   if (process)
2749                     process->Flush();
2750                 }
2751                 if (load) {
2752                   ProcessSP process = target->CalculateProcess();
2753                   Address file_entry = objfile->GetEntryPointAddress();
2754                   if (!process) {
2755                     result.AppendError("No process");
2756                     return false;
2757                   }
2758                   if (set_pc && !file_entry.IsValid()) {
2759                     result.AppendError("No entry address in object file");
2760                     return false;
2761                   }
2762                   std::vector<ObjectFile::LoadableData> loadables(
2763                       objfile->GetLoadableData(*target));
2764                   if (loadables.size() == 0) {
2765                     result.AppendError("No loadable sections");
2766                     return false;
2767                   }
2768                   Status error = process->WriteObjectFile(std::move(loadables));
2769                   if (error.Fail()) {
2770                     result.AppendError(error.AsCString());
2771                     return false;
2772                   }
2773                   if (set_pc) {
2774                     ThreadList &thread_list = process->GetThreadList();
2775                     ThreadSP curr_thread(thread_list.GetSelectedThread());
2776                     RegisterContextSP reg_context(
2777                         curr_thread->GetRegisterContext());
2778                     reg_context->SetPC(file_entry.GetLoadAddress(target));
2779                   }
2780                 }
2781               } else {
2782                 module->GetFileSpec().GetPath(path, sizeof(path));
2783                 result.AppendErrorWithFormat(
2784                     "no sections in object file '%s'\n", path);
2785                 result.SetStatus(eReturnStatusFailed);
2786               }
2787             } else {
2788               module->GetFileSpec().GetPath(path, sizeof(path));
2789               result.AppendErrorWithFormat("no object file for module '%s'\n",
2790                                            path);
2791               result.SetStatus(eReturnStatusFailed);
2792             }
2793           } else {
2794             FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
2795             if (module_spec_file) {
2796               module_spec_file->GetPath(path, sizeof(path));
2797               result.AppendErrorWithFormat("invalid module '%s'.\n", path);
2798             } else
2799               result.AppendError("no module spec");
2800             result.SetStatus(eReturnStatusFailed);
2801           }
2802         } else {
2803           std::string uuid_str;
2804 
2805           if (module_spec.GetFileSpec())
2806             module_spec.GetFileSpec().GetPath(path, sizeof(path));
2807           else
2808             path[0] = '\0';
2809 
2810           if (module_spec.GetUUIDPtr())
2811             uuid_str = module_spec.GetUUID().GetAsString();
2812           if (num_matches > 1) {
2813             result.AppendErrorWithFormat(
2814                 "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "",
2815                 path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2816             for (size_t i = 0; i < num_matches; ++i) {
2817               if (matching_modules.GetModulePointerAtIndex(i)
2818                       ->GetFileSpec()
2819                       .GetPath(path, sizeof(path)))
2820                 result.AppendMessageWithFormat("%s\n", path);
2821             }
2822           } else {
2823             result.AppendErrorWithFormat(
2824                 "no modules were found  that match%s%s%s%s.\n",
2825                 path[0] ? " file=" : "", path,
2826                 !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2827           }
2828           result.SetStatus(eReturnStatusFailed);
2829         }
2830       } else {
2831         result.AppendError("either the \"--file <module>\" or the \"--uuid "
2832                            "<uuid>\" option must be specified.\n");
2833         result.SetStatus(eReturnStatusFailed);
2834         return false;
2835       }
2836     }
2837     return result.Succeeded();
2838   }
2839 
2840   OptionGroupOptions m_option_group;
2841   OptionGroupUUID m_uuid_option_group;
2842   OptionGroupString m_file_option;
2843   OptionGroupBoolean m_load_option;
2844   OptionGroupBoolean m_pc_option;
2845   OptionGroupUInt64 m_slide_option;
2846 };
2847 
2848 //----------------------------------------------------------------------
2849 // List images with associated information
2850 //----------------------------------------------------------------------
2851 
2852 static OptionDefinition g_target_modules_list_options[] = {
2853     // clang-format off
2854   { LLDB_OPT_SET_1, false, "address",        'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Display the image at this address." },
2855   { LLDB_OPT_SET_1, false, "arch",           'A', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth,               "Display the architecture when listing images." },
2856   { LLDB_OPT_SET_1, false, "triple",         't', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth,               "Display the triple when listing images." },
2857   { 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." },
2858   { 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)." },
2859   { LLDB_OPT_SET_1, false, "uuid",           'u', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,                "Display the UUID when listing images." },
2860   { LLDB_OPT_SET_1, false, "fullpath",       'f', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth,               "Display the fullpath to the image object file." },
2861   { LLDB_OPT_SET_1, false, "directory",      'd', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth,               "Display the directory with optional width for the image object file." },
2862   { LLDB_OPT_SET_1, false, "basename",       'b', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth,               "Display the basename with optional width for the image object file." },
2863   { LLDB_OPT_SET_1, false, "symfile",        's', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth,               "Display the fullpath to the image symbol file with optional width." },
2864   { 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." },
2865   { LLDB_OPT_SET_1, false, "mod-time",       'm', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth,               "Display the modification time with optional width of the module." },
2866   { 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." },
2867   { LLDB_OPT_SET_1, false, "pointer",        'p', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeNone,                "Display the module pointer." },
2868   { 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." }
2869     // clang-format on
2870 };
2871 
2872 class CommandObjectTargetModulesList : public CommandObjectParsed {
2873 public:
2874   class CommandOptions : public Options {
2875   public:
2876     CommandOptions()
2877         : Options(), m_format_array(), m_use_global_module_list(false),
2878           m_module_addr(LLDB_INVALID_ADDRESS) {}
2879 
2880     ~CommandOptions() override = default;
2881 
2882     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2883                           ExecutionContext *execution_context) override {
2884       Status error;
2885 
2886       const int short_option = m_getopt_table[option_idx].val;
2887       if (short_option == 'g') {
2888         m_use_global_module_list = true;
2889       } else if (short_option == 'a') {
2890         m_module_addr = OptionArgParser::ToAddress(
2891             execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
2892       } else {
2893         unsigned long width = 0;
2894         option_arg.getAsInteger(0, width);
2895         m_format_array.push_back(std::make_pair(short_option, width));
2896       }
2897       return error;
2898     }
2899 
2900     void OptionParsingStarting(ExecutionContext *execution_context) override {
2901       m_format_array.clear();
2902       m_use_global_module_list = false;
2903       m_module_addr = LLDB_INVALID_ADDRESS;
2904     }
2905 
2906     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2907       return llvm::makeArrayRef(g_target_modules_list_options);
2908     }
2909 
2910     // Instance variables to hold the values for command options.
2911     typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
2912     FormatWidthCollection m_format_array;
2913     bool m_use_global_module_list;
2914     lldb::addr_t m_module_addr;
2915   };
2916 
2917   CommandObjectTargetModulesList(CommandInterpreter &interpreter)
2918       : CommandObjectParsed(
2919             interpreter, "target modules list",
2920             "List current executable and dependent shared library images.",
2921             "target modules list [<cmd-options>]"),
2922         m_options() {}
2923 
2924   ~CommandObjectTargetModulesList() override = default;
2925 
2926   Options *GetOptions() override { return &m_options; }
2927 
2928 protected:
2929   bool DoExecute(Args &command, CommandReturnObject &result) override {
2930     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2931     const bool use_global_module_list = m_options.m_use_global_module_list;
2932     // Define a local module list here to ensure it lives longer than any
2933     // "locker"
2934     // object which might lock its contents below (through the "module_list_ptr"
2935     // variable).
2936     ModuleList module_list;
2937     if (target == nullptr && !use_global_module_list) {
2938       result.AppendError("invalid target, create a debug target using the "
2939                          "'target create' command");
2940       result.SetStatus(eReturnStatusFailed);
2941       return false;
2942     } else {
2943       if (target) {
2944         uint32_t addr_byte_size =
2945             target->GetArchitecture().GetAddressByteSize();
2946         result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2947         result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2948       }
2949       // Dump all sections for all modules images
2950       Stream &strm = result.GetOutputStream();
2951 
2952       if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) {
2953         if (target) {
2954           Address module_address;
2955           if (module_address.SetLoadAddress(m_options.m_module_addr, target)) {
2956             ModuleSP module_sp(module_address.GetModule());
2957             if (module_sp) {
2958               PrintModule(target, module_sp.get(), 0, strm);
2959               result.SetStatus(eReturnStatusSuccessFinishResult);
2960             } else {
2961               result.AppendErrorWithFormat(
2962                   "Couldn't find module matching address: 0x%" PRIx64 ".",
2963                   m_options.m_module_addr);
2964               result.SetStatus(eReturnStatusFailed);
2965             }
2966           } else {
2967             result.AppendErrorWithFormat(
2968                 "Couldn't find module containing address: 0x%" PRIx64 ".",
2969                 m_options.m_module_addr);
2970             result.SetStatus(eReturnStatusFailed);
2971           }
2972         } else {
2973           result.AppendError(
2974               "Can only look up modules by address with a valid target.");
2975           result.SetStatus(eReturnStatusFailed);
2976         }
2977         return result.Succeeded();
2978       }
2979 
2980       size_t num_modules = 0;
2981 
2982       // This locker will be locked on the mutex in module_list_ptr if it is
2983       // non-nullptr.
2984       // Otherwise it will lock the AllocationModuleCollectionMutex when
2985       // accessing
2986       // the global module list directly.
2987       std::unique_lock<std::recursive_mutex> guard(
2988           Module::GetAllocationModuleCollectionMutex(), std::defer_lock);
2989 
2990       const ModuleList *module_list_ptr = nullptr;
2991       const size_t argc = command.GetArgumentCount();
2992       if (argc == 0) {
2993         if (use_global_module_list) {
2994           guard.lock();
2995           num_modules = Module::GetNumberAllocatedModules();
2996         } else {
2997           module_list_ptr = &target->GetImages();
2998         }
2999       } else {
3000         // TODO: Convert to entry based iteration.  Requires converting
3001         // FindModulesByName.
3002         for (size_t i = 0; i < argc; ++i) {
3003           // Dump specified images (by basename or fullpath)
3004           const char *arg_cstr = command.GetArgumentAtIndex(i);
3005           const size_t num_matches = FindModulesByName(
3006               target, arg_cstr, module_list, use_global_module_list);
3007           if (num_matches == 0) {
3008             if (argc == 1) {
3009               result.AppendErrorWithFormat("no modules found that match '%s'",
3010                                            arg_cstr);
3011               result.SetStatus(eReturnStatusFailed);
3012               return false;
3013             }
3014           }
3015         }
3016 
3017         module_list_ptr = &module_list;
3018       }
3019 
3020       std::unique_lock<std::recursive_mutex> lock;
3021       if (module_list_ptr != nullptr) {
3022         lock =
3023             std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex());
3024 
3025         num_modules = module_list_ptr->GetSize();
3026       }
3027 
3028       if (num_modules > 0) {
3029         for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
3030           ModuleSP module_sp;
3031           Module *module;
3032           if (module_list_ptr) {
3033             module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx);
3034             module = module_sp.get();
3035           } else {
3036             module = Module::GetAllocatedModuleAtIndex(image_idx);
3037             module_sp = module->shared_from_this();
3038           }
3039 
3040           const size_t indent = strm.Printf("[%3u] ", image_idx);
3041           PrintModule(target, module, indent, strm);
3042         }
3043         result.SetStatus(eReturnStatusSuccessFinishResult);
3044       } else {
3045         if (argc) {
3046           if (use_global_module_list)
3047             result.AppendError(
3048                 "the global module list has no matching modules");
3049           else
3050             result.AppendError("the target has no matching modules");
3051         } else {
3052           if (use_global_module_list)
3053             result.AppendError("the global module list is empty");
3054           else
3055             result.AppendError(
3056                 "the target has no associated executable images");
3057         }
3058         result.SetStatus(eReturnStatusFailed);
3059         return false;
3060       }
3061     }
3062     return result.Succeeded();
3063   }
3064 
3065   void PrintModule(Target *target, Module *module, int indent, Stream &strm) {
3066     if (module == nullptr) {
3067       strm.PutCString("Null module");
3068       return;
3069     }
3070 
3071     bool dump_object_name = false;
3072     if (m_options.m_format_array.empty()) {
3073       m_options.m_format_array.push_back(std::make_pair('u', 0));
3074       m_options.m_format_array.push_back(std::make_pair('h', 0));
3075       m_options.m_format_array.push_back(std::make_pair('f', 0));
3076       m_options.m_format_array.push_back(std::make_pair('S', 0));
3077     }
3078     const size_t num_entries = m_options.m_format_array.size();
3079     bool print_space = false;
3080     for (size_t i = 0; i < num_entries; ++i) {
3081       if (print_space)
3082         strm.PutChar(' ');
3083       print_space = true;
3084       const char format_char = m_options.m_format_array[i].first;
3085       uint32_t width = m_options.m_format_array[i].second;
3086       switch (format_char) {
3087       case 'A':
3088         DumpModuleArchitecture(strm, module, false, width);
3089         break;
3090 
3091       case 't':
3092         DumpModuleArchitecture(strm, module, true, width);
3093         break;
3094 
3095       case 'f':
3096         DumpFullpath(strm, &module->GetFileSpec(), width);
3097         dump_object_name = true;
3098         break;
3099 
3100       case 'd':
3101         DumpDirectory(strm, &module->GetFileSpec(), width);
3102         break;
3103 
3104       case 'b':
3105         DumpBasename(strm, &module->GetFileSpec(), width);
3106         dump_object_name = true;
3107         break;
3108 
3109       case 'h':
3110       case 'o':
3111         // Image header address
3112         {
3113           uint32_t addr_nibble_width =
3114               target ? (target->GetArchitecture().GetAddressByteSize() * 2)
3115                      : 16;
3116 
3117           ObjectFile *objfile = module->GetObjectFile();
3118           if (objfile) {
3119             Address header_addr(objfile->GetHeaderAddress());
3120             if (header_addr.IsValid()) {
3121               if (target && !target->GetSectionLoadList().IsEmpty()) {
3122                 lldb::addr_t header_load_addr =
3123                     header_addr.GetLoadAddress(target);
3124                 if (header_load_addr == LLDB_INVALID_ADDRESS) {
3125                   header_addr.Dump(&strm, target,
3126                                    Address::DumpStyleModuleWithFileAddress,
3127                                    Address::DumpStyleFileAddress);
3128                 } else {
3129                   if (format_char == 'o') {
3130                     // Show the offset of slide for the image
3131                     strm.Printf(
3132                         "0x%*.*" PRIx64, addr_nibble_width, addr_nibble_width,
3133                         header_load_addr - header_addr.GetFileAddress());
3134                   } else {
3135                     // Show the load address of the image
3136                     strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
3137                                 addr_nibble_width, header_load_addr);
3138                   }
3139                 }
3140                 break;
3141               }
3142               // The address was valid, but the image isn't loaded, output the
3143               // address in an appropriate format
3144               header_addr.Dump(&strm, target, Address::DumpStyleFileAddress);
3145               break;
3146             }
3147           }
3148           strm.Printf("%*s", addr_nibble_width + 2, "");
3149         }
3150         break;
3151 
3152       case 'r': {
3153         size_t ref_count = 0;
3154         ModuleSP module_sp(module->shared_from_this());
3155         if (module_sp) {
3156           // Take one away to make sure we don't count our local "module_sp"
3157           ref_count = module_sp.use_count() - 1;
3158         }
3159         if (width)
3160           strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count);
3161         else
3162           strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count);
3163       } break;
3164 
3165       case 's':
3166       case 'S': {
3167         const SymbolVendor *symbol_vendor = module->GetSymbolVendor();
3168         if (symbol_vendor) {
3169           const FileSpec symfile_spec = symbol_vendor->GetMainFileSpec();
3170           if (format_char == 'S') {
3171             // Dump symbol file only if different from module file
3172             if (!symfile_spec || symfile_spec == module->GetFileSpec()) {
3173               print_space = false;
3174               break;
3175             }
3176             // Add a newline and indent past the index
3177             strm.Printf("\n%*s", indent, "");
3178           }
3179           DumpFullpath(strm, &symfile_spec, width);
3180           dump_object_name = true;
3181           break;
3182         }
3183         strm.Printf("%.*s", width, "<NONE>");
3184       } break;
3185 
3186       case 'm':
3187         strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(),
3188                                               llvm::AlignStyle::Left, width));
3189         break;
3190 
3191       case 'p':
3192         strm.Printf("%p", static_cast<void *>(module));
3193         break;
3194 
3195       case 'u':
3196         DumpModuleUUID(strm, module);
3197         break;
3198 
3199       default:
3200         break;
3201       }
3202     }
3203     if (dump_object_name) {
3204       const char *object_name = module->GetObjectName().GetCString();
3205       if (object_name)
3206         strm.Printf("(%s)", object_name);
3207     }
3208     strm.EOL();
3209   }
3210 
3211   CommandOptions m_options;
3212 };
3213 
3214 #pragma mark CommandObjectTargetModulesShowUnwind
3215 
3216 //----------------------------------------------------------------------
3217 // Lookup unwind information in images
3218 //----------------------------------------------------------------------
3219 
3220 static OptionDefinition g_target_modules_show_unwind_options[] = {
3221     // clang-format off
3222   { LLDB_OPT_SET_1, false, "name",    'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName,        "Show unwind instructions for a function or symbol name." },
3223   { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" }
3224     // clang-format on
3225 };
3226 
3227 class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
3228 public:
3229   enum {
3230     eLookupTypeInvalid = -1,
3231     eLookupTypeAddress = 0,
3232     eLookupTypeSymbol,
3233     eLookupTypeFunction,
3234     eLookupTypeFunctionOrSymbol,
3235     kNumLookupTypes
3236   };
3237 
3238   class CommandOptions : public Options {
3239   public:
3240     CommandOptions()
3241         : Options(), m_type(eLookupTypeInvalid), m_str(),
3242           m_addr(LLDB_INVALID_ADDRESS) {}
3243 
3244     ~CommandOptions() override = default;
3245 
3246     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3247                           ExecutionContext *execution_context) override {
3248       Status error;
3249 
3250       const int short_option = m_getopt_table[option_idx].val;
3251 
3252       switch (short_option) {
3253       case 'a': {
3254         m_str = option_arg;
3255         m_type = eLookupTypeAddress;
3256         m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3257                                             LLDB_INVALID_ADDRESS, &error);
3258         if (m_addr == LLDB_INVALID_ADDRESS)
3259           error.SetErrorStringWithFormat("invalid address string '%s'",
3260                                          option_arg.str().c_str());
3261         break;
3262       }
3263 
3264       case 'n':
3265         m_str = option_arg;
3266         m_type = eLookupTypeFunctionOrSymbol;
3267         break;
3268 
3269       default:
3270         error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
3271         break;
3272       }
3273 
3274       return error;
3275     }
3276 
3277     void OptionParsingStarting(ExecutionContext *execution_context) override {
3278       m_type = eLookupTypeInvalid;
3279       m_str.clear();
3280       m_addr = LLDB_INVALID_ADDRESS;
3281     }
3282 
3283     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3284       return llvm::makeArrayRef(g_target_modules_show_unwind_options);
3285     }
3286 
3287     // Instance variables to hold the values for command options.
3288 
3289     int m_type;        // Should be a eLookupTypeXXX enum after parsing options
3290     std::string m_str; // Holds name lookup
3291     lldb::addr_t m_addr; // Holds the address to lookup
3292   };
3293 
3294   CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
3295       : CommandObjectParsed(
3296             interpreter, "target modules show-unwind",
3297             "Show synthesized unwind instructions for a function.", nullptr,
3298             eCommandRequiresTarget | eCommandRequiresProcess |
3299                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
3300         m_options() {}
3301 
3302   ~CommandObjectTargetModulesShowUnwind() override = default;
3303 
3304   Options *GetOptions() override { return &m_options; }
3305 
3306 protected:
3307   bool DoExecute(Args &command, CommandReturnObject &result) override {
3308     Target *target = m_exe_ctx.GetTargetPtr();
3309     Process *process = m_exe_ctx.GetProcessPtr();
3310     ABI *abi = nullptr;
3311     if (process)
3312       abi = process->GetABI().get();
3313 
3314     if (process == nullptr) {
3315       result.AppendError(
3316           "You must have a process running to use this command.");
3317       result.SetStatus(eReturnStatusFailed);
3318       return false;
3319     }
3320 
3321     ThreadList threads(process->GetThreadList());
3322     if (threads.GetSize() == 0) {
3323       result.AppendError("The process must be paused to use this command.");
3324       result.SetStatus(eReturnStatusFailed);
3325       return false;
3326     }
3327 
3328     ThreadSP thread(threads.GetThreadAtIndex(0));
3329     if (!thread) {
3330       result.AppendError("The process must be paused to use this command.");
3331       result.SetStatus(eReturnStatusFailed);
3332       return false;
3333     }
3334 
3335     SymbolContextList sc_list;
3336 
3337     if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
3338       ConstString function_name(m_options.m_str.c_str());
3339       target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto,
3340                                         true, false, true, sc_list);
3341     } else if (m_options.m_type == eLookupTypeAddress && target) {
3342       Address addr;
3343       if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr,
3344                                                           addr)) {
3345         SymbolContext sc;
3346         ModuleSP module_sp(addr.GetModule());
3347         module_sp->ResolveSymbolContextForAddress(addr,
3348                                                   eSymbolContextEverything, sc);
3349         if (sc.function || sc.symbol) {
3350           sc_list.Append(sc);
3351         }
3352       }
3353     } else {
3354       result.AppendError(
3355           "address-expression or function name option must be specified.");
3356       result.SetStatus(eReturnStatusFailed);
3357       return false;
3358     }
3359 
3360     size_t num_matches = sc_list.GetSize();
3361     if (num_matches == 0) {
3362       result.AppendErrorWithFormat("no unwind data found that matches '%s'.",
3363                                    m_options.m_str.c_str());
3364       result.SetStatus(eReturnStatusFailed);
3365       return false;
3366     }
3367 
3368     for (uint32_t idx = 0; idx < num_matches; idx++) {
3369       SymbolContext sc;
3370       sc_list.GetContextAtIndex(idx, sc);
3371       if (sc.symbol == nullptr && sc.function == nullptr)
3372         continue;
3373       if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr)
3374         continue;
3375       AddressRange range;
3376       if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
3377                               false, range))
3378         continue;
3379       if (!range.GetBaseAddress().IsValid())
3380         continue;
3381       ConstString funcname(sc.GetFunctionName());
3382       if (funcname.IsEmpty())
3383         continue;
3384       addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target);
3385       if (abi)
3386         start_addr = abi->FixCodeAddress(start_addr);
3387 
3388       FuncUnwindersSP func_unwinders_sp(
3389           sc.module_sp->GetObjectFile()
3390               ->GetUnwindTable()
3391               .GetUncachedFuncUnwindersContainingAddress(start_addr, sc));
3392       if (!func_unwinders_sp)
3393         continue;
3394 
3395       result.GetOutputStream().Printf(
3396           "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n",
3397           sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
3398           funcname.AsCString(), start_addr);
3399 
3400       UnwindPlanSP non_callsite_unwind_plan =
3401           func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread, -1);
3402       if (non_callsite_unwind_plan) {
3403         result.GetOutputStream().Printf(
3404             "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
3405             non_callsite_unwind_plan->GetSourceName().AsCString());
3406       }
3407       UnwindPlanSP callsite_unwind_plan =
3408           func_unwinders_sp->GetUnwindPlanAtCallSite(*target, -1);
3409       if (callsite_unwind_plan) {
3410         result.GetOutputStream().Printf(
3411             "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
3412             callsite_unwind_plan->GetSourceName().AsCString());
3413       }
3414       UnwindPlanSP fast_unwind_plan =
3415           func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
3416       if (fast_unwind_plan) {
3417         result.GetOutputStream().Printf(
3418             "Fast UnwindPlan is '%s'\n",
3419             fast_unwind_plan->GetSourceName().AsCString());
3420       }
3421 
3422       result.GetOutputStream().Printf("\n");
3423 
3424       UnwindPlanSP assembly_sp =
3425           func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread, 0);
3426       if (assembly_sp) {
3427         result.GetOutputStream().Printf(
3428             "Assembly language inspection UnwindPlan:\n");
3429         assembly_sp->Dump(result.GetOutputStream(), thread.get(),
3430                           LLDB_INVALID_ADDRESS);
3431         result.GetOutputStream().Printf("\n");
3432       }
3433 
3434       UnwindPlanSP ehframe_sp =
3435           func_unwinders_sp->GetEHFrameUnwindPlan(*target, 0);
3436       if (ehframe_sp) {
3437         result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
3438         ehframe_sp->Dump(result.GetOutputStream(), thread.get(),
3439                          LLDB_INVALID_ADDRESS);
3440         result.GetOutputStream().Printf("\n");
3441       }
3442 
3443       UnwindPlanSP ehframe_augmented_sp =
3444           func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread, 0);
3445       if (ehframe_augmented_sp) {
3446         result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
3447         ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3448                                    LLDB_INVALID_ADDRESS);
3449         result.GetOutputStream().Printf("\n");
3450       }
3451 
3452       if (UnwindPlanSP plan_sp =
3453               func_unwinders_sp->GetDebugFrameUnwindPlan(*target, 0)) {
3454         result.GetOutputStream().Printf("debug_frame UnwindPlan:\n");
3455         plan_sp->Dump(result.GetOutputStream(), thread.get(),
3456                       LLDB_INVALID_ADDRESS);
3457         result.GetOutputStream().Printf("\n");
3458       }
3459 
3460       if (UnwindPlanSP plan_sp =
3461               func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target,
3462                                                                   *thread, 0)) {
3463         result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n");
3464         plan_sp->Dump(result.GetOutputStream(), thread.get(),
3465                       LLDB_INVALID_ADDRESS);
3466         result.GetOutputStream().Printf("\n");
3467       }
3468 
3469       UnwindPlanSP arm_unwind_sp =
3470           func_unwinders_sp->GetArmUnwindUnwindPlan(*target, 0);
3471       if (arm_unwind_sp) {
3472         result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
3473         arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3474                             LLDB_INVALID_ADDRESS);
3475         result.GetOutputStream().Printf("\n");
3476       }
3477 
3478       UnwindPlanSP compact_unwind_sp =
3479           func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0);
3480       if (compact_unwind_sp) {
3481         result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
3482         compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3483                                 LLDB_INVALID_ADDRESS);
3484         result.GetOutputStream().Printf("\n");
3485       }
3486 
3487       if (fast_unwind_plan) {
3488         result.GetOutputStream().Printf("Fast UnwindPlan:\n");
3489         fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(),
3490                                LLDB_INVALID_ADDRESS);
3491         result.GetOutputStream().Printf("\n");
3492       }
3493 
3494       ABISP abi_sp = process->GetABI();
3495       if (abi_sp) {
3496         UnwindPlan arch_default(lldb::eRegisterKindGeneric);
3497         if (abi_sp->CreateDefaultUnwindPlan(arch_default)) {
3498           result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
3499           arch_default.Dump(result.GetOutputStream(), thread.get(),
3500                             LLDB_INVALID_ADDRESS);
3501           result.GetOutputStream().Printf("\n");
3502         }
3503 
3504         UnwindPlan arch_entry(lldb::eRegisterKindGeneric);
3505         if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) {
3506           result.GetOutputStream().Printf(
3507               "Arch default at entry point UnwindPlan:\n");
3508           arch_entry.Dump(result.GetOutputStream(), thread.get(),
3509                           LLDB_INVALID_ADDRESS);
3510           result.GetOutputStream().Printf("\n");
3511         }
3512       }
3513 
3514       result.GetOutputStream().Printf("\n");
3515     }
3516     return result.Succeeded();
3517   }
3518 
3519   CommandOptions m_options;
3520 };
3521 
3522 //----------------------------------------------------------------------
3523 // Lookup information in images
3524 //----------------------------------------------------------------------
3525 
3526 static OptionDefinition g_target_modules_lookup_options[] = {
3527     // clang-format off
3528   { LLDB_OPT_SET_1,                                  true,  "address",    'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." },
3529   { 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." },
3530   /* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */
3531   { 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." },
3532   { 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." },
3533   { 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." },
3534   { 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)." },
3535   { 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)." },
3536   { 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." },
3537   { 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." },
3538   { 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." },
3539   { LLDB_OPT_SET_ALL,                                false, "verbose",    'v', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,                "Enable verbose lookup information." },
3540   { 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." },
3541     // clang-format on
3542 };
3543 
3544 class CommandObjectTargetModulesLookup : public CommandObjectParsed {
3545 public:
3546   enum {
3547     eLookupTypeInvalid = -1,
3548     eLookupTypeAddress = 0,
3549     eLookupTypeSymbol,
3550     eLookupTypeFileLine, // Line is optional
3551     eLookupTypeFunction,
3552     eLookupTypeFunctionOrSymbol,
3553     eLookupTypeType,
3554     kNumLookupTypes
3555   };
3556 
3557   class CommandOptions : public Options {
3558   public:
3559     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
3560 
3561     ~CommandOptions() override = default;
3562 
3563     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3564                           ExecutionContext *execution_context) override {
3565       Status error;
3566 
3567       const int short_option = m_getopt_table[option_idx].val;
3568 
3569       switch (short_option) {
3570       case 'a': {
3571         m_type = eLookupTypeAddress;
3572         m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3573                                             LLDB_INVALID_ADDRESS, &error);
3574       } break;
3575 
3576       case 'o':
3577         if (option_arg.getAsInteger(0, m_offset))
3578           error.SetErrorStringWithFormat("invalid offset string '%s'",
3579                                          option_arg.str().c_str());
3580         break;
3581 
3582       case 's':
3583         m_str = option_arg;
3584         m_type = eLookupTypeSymbol;
3585         break;
3586 
3587       case 'f':
3588         m_file.SetFile(option_arg, false);
3589         m_type = eLookupTypeFileLine;
3590         break;
3591 
3592       case 'i':
3593         m_include_inlines = false;
3594         break;
3595 
3596       case 'l':
3597         if (option_arg.getAsInteger(0, m_line_number))
3598           error.SetErrorStringWithFormat("invalid line number string '%s'",
3599                                          option_arg.str().c_str());
3600         else if (m_line_number == 0)
3601           error.SetErrorString("zero is an invalid line number");
3602         m_type = eLookupTypeFileLine;
3603         break;
3604 
3605       case 'F':
3606         m_str = option_arg;
3607         m_type = eLookupTypeFunction;
3608         break;
3609 
3610       case 'n':
3611         m_str = option_arg;
3612         m_type = eLookupTypeFunctionOrSymbol;
3613         break;
3614 
3615       case 't':
3616         m_str = option_arg;
3617         m_type = eLookupTypeType;
3618         break;
3619 
3620       case 'v':
3621         m_verbose = 1;
3622         break;
3623 
3624       case 'A':
3625         m_print_all = true;
3626         break;
3627 
3628       case 'r':
3629         m_use_regex = true;
3630         break;
3631       }
3632 
3633       return error;
3634     }
3635 
3636     void OptionParsingStarting(ExecutionContext *execution_context) override {
3637       m_type = eLookupTypeInvalid;
3638       m_str.clear();
3639       m_file.Clear();
3640       m_addr = LLDB_INVALID_ADDRESS;
3641       m_offset = 0;
3642       m_line_number = 0;
3643       m_use_regex = false;
3644       m_include_inlines = true;
3645       m_verbose = false;
3646       m_print_all = false;
3647     }
3648 
3649     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3650       return llvm::makeArrayRef(g_target_modules_lookup_options);
3651     }
3652 
3653     int m_type;        // Should be a eLookupTypeXXX enum after parsing options
3654     std::string m_str; // Holds name lookup
3655     FileSpec m_file;   // Files for file lookups
3656     lldb::addr_t m_addr; // Holds the address to lookup
3657     lldb::addr_t
3658         m_offset; // Subtract this offset from m_addr before doing lookups.
3659     uint32_t m_line_number; // Line number for file+line lookups
3660     bool m_use_regex;       // Name lookups in m_str are regular expressions.
3661     bool m_include_inlines; // Check for inline entries when looking up by
3662                             // file/line.
3663     bool m_verbose;         // Enable verbose lookup info
3664     bool m_print_all; // Print all matches, even in cases where there's a best
3665                       // match.
3666   };
3667 
3668   CommandObjectTargetModulesLookup(CommandInterpreter &interpreter)
3669       : CommandObjectParsed(interpreter, "target modules lookup",
3670                             "Look up information within executable and "
3671                             "dependent shared library images.",
3672                             nullptr, eCommandRequiresTarget),
3673         m_options() {
3674     CommandArgumentEntry arg;
3675     CommandArgumentData file_arg;
3676 
3677     // Define the first (and only) variant of this arg.
3678     file_arg.arg_type = eArgTypeFilename;
3679     file_arg.arg_repetition = eArgRepeatStar;
3680 
3681     // There is only one variant this argument could be; put it into the
3682     // argument entry.
3683     arg.push_back(file_arg);
3684 
3685     // Push the data for the first argument into the m_arguments vector.
3686     m_arguments.push_back(arg);
3687   }
3688 
3689   ~CommandObjectTargetModulesLookup() override = default;
3690 
3691   Options *GetOptions() override { return &m_options; }
3692 
3693   bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result,
3694                   bool &syntax_error) {
3695     switch (m_options.m_type) {
3696     case eLookupTypeAddress:
3697     case eLookupTypeFileLine:
3698     case eLookupTypeFunction:
3699     case eLookupTypeFunctionOrSymbol:
3700     case eLookupTypeSymbol:
3701     default:
3702       return false;
3703     case eLookupTypeType:
3704       break;
3705     }
3706 
3707     StackFrameSP frame = m_exe_ctx.GetFrameSP();
3708 
3709     if (!frame)
3710       return false;
3711 
3712     const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule));
3713 
3714     if (!sym_ctx.module_sp)
3715       return false;
3716 
3717     switch (m_options.m_type) {
3718     default:
3719       return false;
3720     case eLookupTypeType:
3721       if (!m_options.m_str.empty()) {
3722         if (LookupTypeHere(m_interpreter, result.GetOutputStream(), sym_ctx,
3723                            m_options.m_str.c_str(), m_options.m_use_regex)) {
3724           result.SetStatus(eReturnStatusSuccessFinishResult);
3725           return true;
3726         }
3727       }
3728       break;
3729     }
3730 
3731     return true;
3732   }
3733 
3734   bool LookupInModule(CommandInterpreter &interpreter, Module *module,
3735                       CommandReturnObject &result, bool &syntax_error) {
3736     switch (m_options.m_type) {
3737     case eLookupTypeAddress:
3738       if (m_options.m_addr != LLDB_INVALID_ADDRESS) {
3739         if (LookupAddressInModule(
3740                 m_interpreter, result.GetOutputStream(), module,
3741                 eSymbolContextEverything |
3742                     (m_options.m_verbose
3743                          ? static_cast<int>(eSymbolContextVariable)
3744                          : 0),
3745                 m_options.m_addr, m_options.m_offset, m_options.m_verbose)) {
3746           result.SetStatus(eReturnStatusSuccessFinishResult);
3747           return true;
3748         }
3749       }
3750       break;
3751 
3752     case eLookupTypeSymbol:
3753       if (!m_options.m_str.empty()) {
3754         if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(),
3755                                  module, m_options.m_str.c_str(),
3756                                  m_options.m_use_regex, m_options.m_verbose)) {
3757           result.SetStatus(eReturnStatusSuccessFinishResult);
3758           return true;
3759         }
3760       }
3761       break;
3762 
3763     case eLookupTypeFileLine:
3764       if (m_options.m_file) {
3765         if (LookupFileAndLineInModule(
3766                 m_interpreter, result.GetOutputStream(), module,
3767                 m_options.m_file, m_options.m_line_number,
3768                 m_options.m_include_inlines, m_options.m_verbose)) {
3769           result.SetStatus(eReturnStatusSuccessFinishResult);
3770           return true;
3771         }
3772       }
3773       break;
3774 
3775     case eLookupTypeFunctionOrSymbol:
3776     case eLookupTypeFunction:
3777       if (!m_options.m_str.empty()) {
3778         if (LookupFunctionInModule(
3779                 m_interpreter, result.GetOutputStream(), module,
3780                 m_options.m_str.c_str(), m_options.m_use_regex,
3781                 m_options.m_include_inlines,
3782                 m_options.m_type ==
3783                     eLookupTypeFunctionOrSymbol, // include symbols
3784                 m_options.m_verbose)) {
3785           result.SetStatus(eReturnStatusSuccessFinishResult);
3786           return true;
3787         }
3788       }
3789       break;
3790 
3791     case eLookupTypeType:
3792       if (!m_options.m_str.empty()) {
3793         if (LookupTypeInModule(m_interpreter, result.GetOutputStream(), module,
3794                                m_options.m_str.c_str(),
3795                                m_options.m_use_regex)) {
3796           result.SetStatus(eReturnStatusSuccessFinishResult);
3797           return true;
3798         }
3799       }
3800       break;
3801 
3802     default:
3803       m_options.GenerateOptionUsage(
3804           result.GetErrorStream(), this,
3805           GetCommandInterpreter().GetDebugger().GetTerminalWidth());
3806       syntax_error = true;
3807       break;
3808     }
3809 
3810     result.SetStatus(eReturnStatusFailed);
3811     return false;
3812   }
3813 
3814 protected:
3815   bool DoExecute(Args &command, CommandReturnObject &result) override {
3816     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
3817     if (target == nullptr) {
3818       result.AppendError("invalid target, create a debug target using the "
3819                          "'target create' command");
3820       result.SetStatus(eReturnStatusFailed);
3821       return false;
3822     } else {
3823       bool syntax_error = false;
3824       uint32_t i;
3825       uint32_t num_successful_lookups = 0;
3826       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
3827       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3828       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3829       // Dump all sections for all modules images
3830 
3831       if (command.GetArgumentCount() == 0) {
3832         ModuleSP current_module;
3833 
3834         // Where it is possible to look in the current symbol context
3835         // first, try that.  If this search was successful and --all
3836         // was not passed, don't print anything else.
3837         if (LookupHere(m_interpreter, result, syntax_error)) {
3838           result.GetOutputStream().EOL();
3839           num_successful_lookups++;
3840           if (!m_options.m_print_all) {
3841             result.SetStatus(eReturnStatusSuccessFinishResult);
3842             return result.Succeeded();
3843           }
3844         }
3845 
3846         // Dump all sections for all other modules
3847 
3848         const ModuleList &target_modules = target->GetImages();
3849         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
3850         const size_t num_modules = target_modules.GetSize();
3851         if (num_modules > 0) {
3852           for (i = 0; i < num_modules && !syntax_error; ++i) {
3853             Module *module_pointer =
3854                 target_modules.GetModulePointerAtIndexUnlocked(i);
3855 
3856             if (module_pointer != current_module.get() &&
3857                 LookupInModule(
3858                     m_interpreter,
3859                     target_modules.GetModulePointerAtIndexUnlocked(i), result,
3860                     syntax_error)) {
3861               result.GetOutputStream().EOL();
3862               num_successful_lookups++;
3863             }
3864           }
3865         } else {
3866           result.AppendError("the target has no associated executable images");
3867           result.SetStatus(eReturnStatusFailed);
3868           return false;
3869         }
3870       } else {
3871         // Dump specified images (by basename or fullpath)
3872         const char *arg_cstr;
3873         for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr &&
3874                     !syntax_error;
3875              ++i) {
3876           ModuleList module_list;
3877           const size_t num_matches =
3878               FindModulesByName(target, arg_cstr, module_list, false);
3879           if (num_matches > 0) {
3880             for (size_t j = 0; j < num_matches; ++j) {
3881               Module *module = module_list.GetModulePointerAtIndex(j);
3882               if (module) {
3883                 if (LookupInModule(m_interpreter, module, result,
3884                                    syntax_error)) {
3885                   result.GetOutputStream().EOL();
3886                   num_successful_lookups++;
3887                 }
3888               }
3889             }
3890           } else
3891             result.AppendWarningWithFormat(
3892                 "Unable to find an image that matches '%s'.\n", arg_cstr);
3893         }
3894       }
3895 
3896       if (num_successful_lookups > 0)
3897         result.SetStatus(eReturnStatusSuccessFinishResult);
3898       else
3899         result.SetStatus(eReturnStatusFailed);
3900     }
3901     return result.Succeeded();
3902   }
3903 
3904   CommandOptions m_options;
3905 };
3906 
3907 #pragma mark CommandObjectMultiwordImageSearchPaths
3908 
3909 //-------------------------------------------------------------------------
3910 // CommandObjectMultiwordImageSearchPaths
3911 //-------------------------------------------------------------------------
3912 
3913 class CommandObjectTargetModulesImageSearchPaths
3914     : public CommandObjectMultiword {
3915 public:
3916   CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter)
3917       : CommandObjectMultiword(
3918             interpreter, "target modules search-paths",
3919             "Commands for managing module search paths for a target.",
3920             "target modules search-paths <subcommand> [<subcommand-options>]") {
3921     LoadSubCommand(
3922         "add", CommandObjectSP(
3923                    new CommandObjectTargetModulesSearchPathsAdd(interpreter)));
3924     LoadSubCommand(
3925         "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear(
3926                      interpreter)));
3927     LoadSubCommand(
3928         "insert",
3929         CommandObjectSP(
3930             new CommandObjectTargetModulesSearchPathsInsert(interpreter)));
3931     LoadSubCommand(
3932         "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList(
3933                     interpreter)));
3934     LoadSubCommand(
3935         "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery(
3936                      interpreter)));
3937   }
3938 
3939   ~CommandObjectTargetModulesImageSearchPaths() override = default;
3940 };
3941 
3942 #pragma mark CommandObjectTargetModules
3943 
3944 //-------------------------------------------------------------------------
3945 // CommandObjectTargetModules
3946 //-------------------------------------------------------------------------
3947 
3948 class CommandObjectTargetModules : public CommandObjectMultiword {
3949 public:
3950   //------------------------------------------------------------------
3951   // Constructors and Destructors
3952   //------------------------------------------------------------------
3953   CommandObjectTargetModules(CommandInterpreter &interpreter)
3954       : CommandObjectMultiword(interpreter, "target modules",
3955                                "Commands for accessing information for one or "
3956                                "more target modules.",
3957                                "target modules <sub-command> ...") {
3958     LoadSubCommand(
3959         "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter)));
3960     LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad(
3961                                interpreter)));
3962     LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump(
3963                                interpreter)));
3964     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList(
3965                                interpreter)));
3966     LoadSubCommand(
3967         "lookup",
3968         CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter)));
3969     LoadSubCommand(
3970         "search-paths",
3971         CommandObjectSP(
3972             new CommandObjectTargetModulesImageSearchPaths(interpreter)));
3973     LoadSubCommand(
3974         "show-unwind",
3975         CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter)));
3976   }
3977 
3978   ~CommandObjectTargetModules() override = default;
3979 
3980 private:
3981   //------------------------------------------------------------------
3982   // For CommandObjectTargetModules only
3983   //------------------------------------------------------------------
3984   DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetModules);
3985 };
3986 
3987 class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
3988 public:
3989   CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter)
3990       : CommandObjectParsed(
3991             interpreter, "target symbols add",
3992             "Add a debug symbol file to one of the target's current modules by "
3993             "specifying a path to a debug symbols file, or using the options "
3994             "to specify a module to download symbols for.",
3995             "target symbols add <cmd-options> [<symfile>]",
3996             eCommandRequiresTarget),
3997         m_option_group(),
3998         m_file_option(
3999             LLDB_OPT_SET_1, false, "shlib", 's',
4000             CommandCompletions::eModuleCompletion, eArgTypeShlibName,
4001             "Fullpath or basename for module to find debug symbols for."),
4002         m_current_frame_option(
4003             LLDB_OPT_SET_2, false, "frame", 'F',
4004             "Locate the debug symbols the currently selected frame.", false,
4005             true)
4006 
4007   {
4008     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
4009                           LLDB_OPT_SET_1);
4010     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
4011     m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2,
4012                           LLDB_OPT_SET_2);
4013     m_option_group.Finalize();
4014   }
4015 
4016   ~CommandObjectTargetSymbolsAdd() override = default;
4017 
4018   int HandleArgumentCompletion(Args &input, int &cursor_index,
4019                                int &cursor_char_position,
4020                                OptionElementVector &opt_element_vector,
4021                                int match_start_point, int max_return_elements,
4022                                bool &word_complete,
4023                                StringList &matches) override {
4024     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
4025     completion_str.erase(cursor_char_position);
4026 
4027     CommandCompletions::InvokeCommonCompletionCallbacks(
4028         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
4029         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
4030         word_complete, matches);
4031     return matches.GetSize();
4032   }
4033 
4034   Options *GetOptions() override { return &m_option_group; }
4035 
4036 protected:
4037   bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
4038                         CommandReturnObject &result) {
4039     const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
4040     if (symbol_fspec) {
4041       char symfile_path[PATH_MAX];
4042       symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));
4043 
4044       if (!module_spec.GetUUID().IsValid()) {
4045         if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
4046           module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename();
4047       }
4048       // We now have a module that represents a symbol file
4049       // that can be used for a module that might exist in the
4050       // current target, so we need to find that module in the
4051       // target
4052       ModuleList matching_module_list;
4053 
4054       size_t num_matches = 0;
4055       // First extract all module specs from the symbol file
4056       lldb_private::ModuleSpecList symfile_module_specs;
4057       if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
4058                                               0, 0, symfile_module_specs)) {
4059         // Now extract the module spec that matches the target architecture
4060         ModuleSpec target_arch_module_spec;
4061         ModuleSpec symfile_module_spec;
4062         target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
4063         if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
4064                                                         symfile_module_spec)) {
4065           // See if it has a UUID?
4066           if (symfile_module_spec.GetUUID().IsValid()) {
4067             // It has a UUID, look for this UUID in the target modules
4068             ModuleSpec symfile_uuid_module_spec;
4069             symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
4070             num_matches = target->GetImages().FindModules(
4071                 symfile_uuid_module_spec, matching_module_list);
4072           }
4073         }
4074 
4075         if (num_matches == 0) {
4076           // No matches yet, iterate through the module specs to find a UUID
4077           // value that
4078           // we can match up to an image in our target
4079           const size_t num_symfile_module_specs =
4080               symfile_module_specs.GetSize();
4081           for (size_t i = 0; i < num_symfile_module_specs && num_matches == 0;
4082                ++i) {
4083             if (symfile_module_specs.GetModuleSpecAtIndex(
4084                     i, symfile_module_spec)) {
4085               if (symfile_module_spec.GetUUID().IsValid()) {
4086                 // It has a UUID, look for this UUID in the target modules
4087                 ModuleSpec symfile_uuid_module_spec;
4088                 symfile_uuid_module_spec.GetUUID() =
4089                     symfile_module_spec.GetUUID();
4090                 num_matches = target->GetImages().FindModules(
4091                     symfile_uuid_module_spec, matching_module_list);
4092               }
4093             }
4094           }
4095         }
4096       }
4097 
4098       // Just try to match up the file by basename if we have no matches at this
4099       // point
4100       if (num_matches == 0)
4101         num_matches =
4102             target->GetImages().FindModules(module_spec, matching_module_list);
4103 
4104       while (num_matches == 0) {
4105         ConstString filename_no_extension(
4106             module_spec.GetFileSpec().GetFileNameStrippingExtension());
4107         // Empty string returned, lets bail
4108         if (!filename_no_extension)
4109           break;
4110 
4111         // Check if there was no extension to strip and the basename is the same
4112         if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
4113           break;
4114 
4115         // Replace basename with one less extension
4116         module_spec.GetFileSpec().GetFilename() = filename_no_extension;
4117 
4118         num_matches =
4119             target->GetImages().FindModules(module_spec, matching_module_list);
4120       }
4121 
4122       if (num_matches > 1) {
4123         result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
4124                                      "use the --uuid option to resolve the "
4125                                      "ambiguity.\n",
4126                                      symfile_path);
4127       } else if (num_matches == 1) {
4128         ModuleSP module_sp(matching_module_list.GetModuleAtIndex(0));
4129 
4130         // The module has not yet created its symbol vendor, we can just
4131         // give the existing target module the symfile path to use for
4132         // when it decides to create it!
4133         module_sp->SetSymbolFileFileSpec(symbol_fspec);
4134 
4135         SymbolVendor *symbol_vendor =
4136             module_sp->GetSymbolVendor(true, &result.GetErrorStream());
4137         if (symbol_vendor) {
4138           SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
4139 
4140           if (symbol_file) {
4141             ObjectFile *object_file = symbol_file->GetObjectFile();
4142 
4143             if (object_file && object_file->GetFileSpec() == symbol_fspec) {
4144               // Provide feedback that the symfile has been successfully added.
4145               const FileSpec &module_fs = module_sp->GetFileSpec();
4146               result.AppendMessageWithFormat(
4147                   "symbol file '%s' has been added to '%s'\n", symfile_path,
4148                   module_fs.GetPath().c_str());
4149 
4150               // Let clients know something changed in the module
4151               // if it is currently loaded
4152               ModuleList module_list;
4153               module_list.Append(module_sp);
4154               target->SymbolsDidLoad(module_list);
4155 
4156               // Make sure we load any scripting resources that may be embedded
4157               // in the debug info files in case the platform supports that.
4158               Status error;
4159               StreamString feedback_stream;
4160               module_sp->LoadScriptingResourceInTarget(target, error,
4161                                                        &feedback_stream);
4162               if (error.Fail() && error.AsCString())
4163                 result.AppendWarningWithFormat(
4164                     "unable to load scripting data for module %s - error "
4165                     "reported was %s",
4166                     module_sp->GetFileSpec()
4167                         .GetFileNameStrippingExtension()
4168                         .GetCString(),
4169                     error.AsCString());
4170               else if (feedback_stream.GetSize())
4171                 result.AppendWarningWithFormat("%s", feedback_stream.GetData());
4172 
4173               flush = true;
4174               result.SetStatus(eReturnStatusSuccessFinishResult);
4175               return true;
4176             }
4177           }
4178         }
4179         // Clear the symbol file spec if anything went wrong
4180         module_sp->SetSymbolFileFileSpec(FileSpec());
4181       }
4182 
4183       namespace fs = llvm::sys::fs;
4184       if (module_spec.GetUUID().IsValid()) {
4185         StreamString ss_symfile_uuid;
4186         module_spec.GetUUID().Dump(&ss_symfile_uuid);
4187         result.AppendErrorWithFormat(
4188             "symbol file '%s' (%s) does not match any existing module%s\n",
4189             symfile_path, ss_symfile_uuid.GetData(),
4190             !fs::is_regular_file(symbol_fspec.GetPath())
4191                 ? "\n       please specify the full path to the symbol file"
4192                 : "");
4193       } else {
4194         result.AppendErrorWithFormat(
4195             "symbol file '%s' does not match any existing module%s\n",
4196             symfile_path,
4197             !fs::is_regular_file(symbol_fspec.GetPath())
4198                 ? "\n       please specify the full path to the symbol file"
4199                 : "");
4200       }
4201     } else {
4202       result.AppendError(
4203           "one or more executable image paths must be specified");
4204     }
4205     result.SetStatus(eReturnStatusFailed);
4206     return false;
4207   }
4208 
4209   bool DoExecute(Args &args, CommandReturnObject &result) override {
4210     Target *target = m_exe_ctx.GetTargetPtr();
4211     result.SetStatus(eReturnStatusFailed);
4212     bool flush = false;
4213     ModuleSpec module_spec;
4214     const bool uuid_option_set =
4215         m_uuid_option_group.GetOptionValue().OptionWasSet();
4216     const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
4217     const bool frame_option_set =
4218         m_current_frame_option.GetOptionValue().OptionWasSet();
4219     const size_t argc = args.GetArgumentCount();
4220 
4221     if (argc == 0) {
4222       if (uuid_option_set || file_option_set || frame_option_set) {
4223         bool success = false;
4224         bool error_set = false;
4225         if (frame_option_set) {
4226           Process *process = m_exe_ctx.GetProcessPtr();
4227           if (process) {
4228             const StateType process_state = process->GetState();
4229             if (StateIsStoppedState(process_state, true)) {
4230               StackFrame *frame = m_exe_ctx.GetFramePtr();
4231               if (frame) {
4232                 ModuleSP frame_module_sp(
4233                     frame->GetSymbolContext(eSymbolContextModule).module_sp);
4234                 if (frame_module_sp) {
4235                   if (frame_module_sp->GetPlatformFileSpec().Exists()) {
4236                     module_spec.GetArchitecture() =
4237                         frame_module_sp->GetArchitecture();
4238                     module_spec.GetFileSpec() =
4239                         frame_module_sp->GetPlatformFileSpec();
4240                   }
4241                   module_spec.GetUUID() = frame_module_sp->GetUUID();
4242                   success = module_spec.GetUUID().IsValid() ||
4243                             module_spec.GetFileSpec();
4244                 } else {
4245                   result.AppendError("frame has no module");
4246                   error_set = true;
4247                 }
4248               } else {
4249                 result.AppendError("invalid current frame");
4250                 error_set = true;
4251               }
4252             } else {
4253               result.AppendErrorWithFormat("process is not stopped: %s",
4254                                            StateAsCString(process_state));
4255               error_set = true;
4256             }
4257           } else {
4258             result.AppendError(
4259                 "a process must exist in order to use the --frame option");
4260             error_set = true;
4261           }
4262         } else {
4263           if (uuid_option_set) {
4264             module_spec.GetUUID() =
4265                 m_uuid_option_group.GetOptionValue().GetCurrentValue();
4266             success |= module_spec.GetUUID().IsValid();
4267           } else if (file_option_set) {
4268             module_spec.GetFileSpec() =
4269                 m_file_option.GetOptionValue().GetCurrentValue();
4270             ModuleSP module_sp(
4271                 target->GetImages().FindFirstModule(module_spec));
4272             if (module_sp) {
4273               module_spec.GetFileSpec() = module_sp->GetFileSpec();
4274               module_spec.GetPlatformFileSpec() =
4275                   module_sp->GetPlatformFileSpec();
4276               module_spec.GetUUID() = module_sp->GetUUID();
4277               module_spec.GetArchitecture() = module_sp->GetArchitecture();
4278             } else {
4279               module_spec.GetArchitecture() = target->GetArchitecture();
4280             }
4281             success |= module_spec.GetUUID().IsValid() ||
4282                        module_spec.GetFileSpec().Exists();
4283           }
4284         }
4285 
4286         if (success) {
4287           if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
4288             if (module_spec.GetSymbolFileSpec())
4289               success = AddModuleSymbols(target, module_spec, flush, result);
4290           }
4291         }
4292 
4293         if (!success && !error_set) {
4294           StreamString error_strm;
4295           if (uuid_option_set) {
4296             error_strm.PutCString("unable to find debug symbols for UUID ");
4297             module_spec.GetUUID().Dump(&error_strm);
4298           } else if (file_option_set) {
4299             error_strm.PutCString(
4300                 "unable to find debug symbols for the executable file ");
4301             error_strm << module_spec.GetFileSpec();
4302           } else if (frame_option_set) {
4303             error_strm.PutCString(
4304                 "unable to find debug symbols for the current frame");
4305           }
4306           result.AppendError(error_strm.GetString());
4307         }
4308       } else {
4309         result.AppendError("one or more symbol file paths must be specified, "
4310                            "or options must be specified");
4311       }
4312     } else {
4313       if (uuid_option_set) {
4314         result.AppendError("specify either one or more paths to symbol files "
4315                            "or use the --uuid option without arguments");
4316       } else if (frame_option_set) {
4317         result.AppendError("specify either one or more paths to symbol files "
4318                            "or use the --frame option without arguments");
4319       } else if (file_option_set && argc > 1) {
4320         result.AppendError("specify at most one symbol file path when "
4321                            "--shlib option is set");
4322       } else {
4323         PlatformSP platform_sp(target->GetPlatform());
4324 
4325         for (auto &entry : args.entries()) {
4326           if (!entry.ref.empty()) {
4327             module_spec.GetSymbolFileSpec().SetFile(entry.ref, true);
4328             if (file_option_set) {
4329               module_spec.GetFileSpec() =
4330                   m_file_option.GetOptionValue().GetCurrentValue();
4331             }
4332             if (platform_sp) {
4333               FileSpec symfile_spec;
4334               if (platform_sp
4335                       ->ResolveSymbolFile(*target, module_spec, symfile_spec)
4336                       .Success())
4337                 module_spec.GetSymbolFileSpec() = symfile_spec;
4338             }
4339 
4340             ArchSpec arch;
4341             bool symfile_exists = module_spec.GetSymbolFileSpec().Exists();
4342 
4343             if (symfile_exists) {
4344               if (!AddModuleSymbols(target, module_spec, flush, result))
4345                 break;
4346             } else {
4347               std::string resolved_symfile_path =
4348                   module_spec.GetSymbolFileSpec().GetPath();
4349               if (resolved_symfile_path != entry.ref) {
4350                 result.AppendErrorWithFormat(
4351                     "invalid module path '%s' with resolved path '%s'\n",
4352                     entry.c_str(), resolved_symfile_path.c_str());
4353                 break;
4354               }
4355               result.AppendErrorWithFormat("invalid module path '%s'\n",
4356                                            entry.c_str());
4357               break;
4358             }
4359           }
4360         }
4361       }
4362     }
4363 
4364     if (flush) {
4365       Process *process = m_exe_ctx.GetProcessPtr();
4366       if (process)
4367         process->Flush();
4368     }
4369     return result.Succeeded();
4370   }
4371 
4372   OptionGroupOptions m_option_group;
4373   OptionGroupUUID m_uuid_option_group;
4374   OptionGroupFile m_file_option;
4375   OptionGroupBoolean m_current_frame_option;
4376 };
4377 
4378 #pragma mark CommandObjectTargetSymbols
4379 
4380 //-------------------------------------------------------------------------
4381 // CommandObjectTargetSymbols
4382 //-------------------------------------------------------------------------
4383 
4384 class CommandObjectTargetSymbols : public CommandObjectMultiword {
4385 public:
4386   //------------------------------------------------------------------
4387   // Constructors and Destructors
4388   //------------------------------------------------------------------
4389   CommandObjectTargetSymbols(CommandInterpreter &interpreter)
4390       : CommandObjectMultiword(
4391             interpreter, "target symbols",
4392             "Commands for adding and managing debug symbol files.",
4393             "target symbols <sub-command> ...") {
4394     LoadSubCommand(
4395         "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
4396   }
4397 
4398   ~CommandObjectTargetSymbols() override = default;
4399 
4400 private:
4401   //------------------------------------------------------------------
4402   // For CommandObjectTargetModules only
4403   //------------------------------------------------------------------
4404   DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetSymbols);
4405 };
4406 
4407 #pragma mark CommandObjectTargetStopHookAdd
4408 
4409 //-------------------------------------------------------------------------
4410 // CommandObjectTargetStopHookAdd
4411 //-------------------------------------------------------------------------
4412 
4413 static OptionDefinition g_target_stop_hook_add_options[] = {
4414     // clang-format off
4415   { 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." },
4416   { 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." },
4417   { 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." },
4418   { 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." },
4419   { 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." },
4420   { 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." },
4421   { 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." },
4422   { 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." },
4423   { 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." },
4424   { 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." },
4425   { 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." },
4426     // clang-format on
4427 };
4428 
4429 class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
4430                                        public IOHandlerDelegateMultiline {
4431 public:
4432   class CommandOptions : public Options {
4433   public:
4434     CommandOptions()
4435         : Options(), m_line_start(0), m_line_end(UINT_MAX),
4436           m_func_name_type_mask(eFunctionNameTypeAuto),
4437           m_sym_ctx_specified(false), m_thread_specified(false),
4438           m_use_one_liner(false), m_one_liner() {}
4439 
4440     ~CommandOptions() override = default;
4441 
4442     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4443       return llvm::makeArrayRef(g_target_stop_hook_add_options);
4444     }
4445 
4446     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4447                           ExecutionContext *execution_context) override {
4448       Status error;
4449       const int short_option = m_getopt_table[option_idx].val;
4450 
4451       switch (short_option) {
4452       case 'c':
4453         m_class_name = option_arg;
4454         m_sym_ctx_specified = true;
4455         break;
4456 
4457       case 'e':
4458         if (option_arg.getAsInteger(0, m_line_end)) {
4459           error.SetErrorStringWithFormat("invalid end line number: \"%s\"",
4460                                          option_arg.str().c_str());
4461           break;
4462         }
4463         m_sym_ctx_specified = true;
4464         break;
4465 
4466       case 'l':
4467         if (option_arg.getAsInteger(0, m_line_start)) {
4468           error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
4469                                          option_arg.str().c_str());
4470           break;
4471         }
4472         m_sym_ctx_specified = true;
4473         break;
4474 
4475       case 'i':
4476         m_no_inlines = true;
4477         break;
4478 
4479       case 'n':
4480         m_function_name = option_arg;
4481         m_func_name_type_mask |= eFunctionNameTypeAuto;
4482         m_sym_ctx_specified = true;
4483         break;
4484 
4485       case 'f':
4486         m_file_name = option_arg;
4487         m_sym_ctx_specified = true;
4488         break;
4489 
4490       case 's':
4491         m_module_name = option_arg;
4492         m_sym_ctx_specified = true;
4493         break;
4494 
4495       case 't':
4496         if (option_arg.getAsInteger(0, m_thread_id))
4497           error.SetErrorStringWithFormat("invalid thread id string '%s'",
4498                                          option_arg.str().c_str());
4499         m_thread_specified = true;
4500         break;
4501 
4502       case 'T':
4503         m_thread_name = option_arg;
4504         m_thread_specified = true;
4505         break;
4506 
4507       case 'q':
4508         m_queue_name = option_arg;
4509         m_thread_specified = true;
4510         break;
4511 
4512       case 'x':
4513         if (option_arg.getAsInteger(0, m_thread_index))
4514           error.SetErrorStringWithFormat("invalid thread index string '%s'",
4515                                          option_arg.str().c_str());
4516         m_thread_specified = true;
4517         break;
4518 
4519       case 'o':
4520         m_use_one_liner = true;
4521         m_one_liner = option_arg;
4522         break;
4523 
4524       default:
4525         error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
4526         break;
4527       }
4528       return error;
4529     }
4530 
4531     void OptionParsingStarting(ExecutionContext *execution_context) override {
4532       m_class_name.clear();
4533       m_function_name.clear();
4534       m_line_start = 0;
4535       m_line_end = UINT_MAX;
4536       m_file_name.clear();
4537       m_module_name.clear();
4538       m_func_name_type_mask = eFunctionNameTypeAuto;
4539       m_thread_id = LLDB_INVALID_THREAD_ID;
4540       m_thread_index = UINT32_MAX;
4541       m_thread_name.clear();
4542       m_queue_name.clear();
4543 
4544       m_no_inlines = false;
4545       m_sym_ctx_specified = false;
4546       m_thread_specified = false;
4547 
4548       m_use_one_liner = false;
4549       m_one_liner.clear();
4550     }
4551 
4552     std::string m_class_name;
4553     std::string m_function_name;
4554     uint32_t m_line_start;
4555     uint32_t m_line_end;
4556     std::string m_file_name;
4557     std::string m_module_name;
4558     uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType.
4559     lldb::tid_t m_thread_id;
4560     uint32_t m_thread_index;
4561     std::string m_thread_name;
4562     std::string m_queue_name;
4563     bool m_sym_ctx_specified;
4564     bool m_no_inlines;
4565     bool m_thread_specified;
4566     // Instance variables to hold the values for one_liner options.
4567     bool m_use_one_liner;
4568     std::string m_one_liner;
4569   };
4570 
4571   CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
4572       : CommandObjectParsed(interpreter, "target stop-hook add",
4573                             "Add a hook to be executed when the target stops.",
4574                             "target stop-hook add"),
4575         IOHandlerDelegateMultiline("DONE",
4576                                    IOHandlerDelegate::Completion::LLDBCommand),
4577         m_options() {}
4578 
4579   ~CommandObjectTargetStopHookAdd() override = default;
4580 
4581   Options *GetOptions() override { return &m_options; }
4582 
4583 protected:
4584   void IOHandlerActivated(IOHandler &io_handler) override {
4585     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4586     if (output_sp) {
4587       output_sp->PutCString(
4588           "Enter your stop hook command(s).  Type 'DONE' to end.\n");
4589       output_sp->Flush();
4590     }
4591   }
4592 
4593   void IOHandlerInputComplete(IOHandler &io_handler,
4594                               std::string &line) override {
4595     if (m_stop_hook_sp) {
4596       if (line.empty()) {
4597         StreamFileSP error_sp(io_handler.GetErrorStreamFile());
4598         if (error_sp) {
4599           error_sp->Printf("error: stop hook #%" PRIu64
4600                            " aborted, no commands.\n",
4601                            m_stop_hook_sp->GetID());
4602           error_sp->Flush();
4603         }
4604         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
4605         if (target)
4606           target->RemoveStopHookByID(m_stop_hook_sp->GetID());
4607       } else {
4608         m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
4609         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4610         if (output_sp) {
4611           output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
4612                             m_stop_hook_sp->GetID());
4613           output_sp->Flush();
4614         }
4615       }
4616       m_stop_hook_sp.reset();
4617     }
4618     io_handler.SetIsDone(true);
4619   }
4620 
4621   bool DoExecute(Args &command, CommandReturnObject &result) override {
4622     m_stop_hook_sp.reset();
4623 
4624     Target *target = GetSelectedOrDummyTarget();
4625     if (target) {
4626       Target::StopHookSP new_hook_sp = target->CreateStopHook();
4627 
4628       //  First step, make the specifier.
4629       std::unique_ptr<SymbolContextSpecifier> specifier_ap;
4630       if (m_options.m_sym_ctx_specified) {
4631         specifier_ap.reset(new SymbolContextSpecifier(
4632             m_interpreter.GetDebugger().GetSelectedTarget()));
4633 
4634         if (!m_options.m_module_name.empty()) {
4635           specifier_ap->AddSpecification(
4636               m_options.m_module_name.c_str(),
4637               SymbolContextSpecifier::eModuleSpecified);
4638         }
4639 
4640         if (!m_options.m_class_name.empty()) {
4641           specifier_ap->AddSpecification(
4642               m_options.m_class_name.c_str(),
4643               SymbolContextSpecifier::eClassOrNamespaceSpecified);
4644         }
4645 
4646         if (!m_options.m_file_name.empty()) {
4647           specifier_ap->AddSpecification(
4648               m_options.m_file_name.c_str(),
4649               SymbolContextSpecifier::eFileSpecified);
4650         }
4651 
4652         if (m_options.m_line_start != 0) {
4653           specifier_ap->AddLineSpecification(
4654               m_options.m_line_start,
4655               SymbolContextSpecifier::eLineStartSpecified);
4656         }
4657 
4658         if (m_options.m_line_end != UINT_MAX) {
4659           specifier_ap->AddLineSpecification(
4660               m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
4661         }
4662 
4663         if (!m_options.m_function_name.empty()) {
4664           specifier_ap->AddSpecification(
4665               m_options.m_function_name.c_str(),
4666               SymbolContextSpecifier::eFunctionSpecified);
4667         }
4668       }
4669 
4670       if (specifier_ap)
4671         new_hook_sp->SetSpecifier(specifier_ap.release());
4672 
4673       // Next see if any of the thread options have been entered:
4674 
4675       if (m_options.m_thread_specified) {
4676         ThreadSpec *thread_spec = new ThreadSpec();
4677 
4678         if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
4679           thread_spec->SetTID(m_options.m_thread_id);
4680         }
4681 
4682         if (m_options.m_thread_index != UINT32_MAX)
4683           thread_spec->SetIndex(m_options.m_thread_index);
4684 
4685         if (!m_options.m_thread_name.empty())
4686           thread_spec->SetName(m_options.m_thread_name.c_str());
4687 
4688         if (!m_options.m_queue_name.empty())
4689           thread_spec->SetQueueName(m_options.m_queue_name.c_str());
4690 
4691         new_hook_sp->SetThreadSpecifier(thread_spec);
4692       }
4693       if (m_options.m_use_one_liner) {
4694         // Use one-liner.
4695         new_hook_sp->GetCommandPointer()->AppendString(
4696             m_options.m_one_liner.c_str());
4697         result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
4698                                        new_hook_sp->GetID());
4699       } else {
4700         m_stop_hook_sp = new_hook_sp;
4701         m_interpreter.GetLLDBCommandsFromIOHandler(
4702             "> ",     // Prompt
4703             *this,    // IOHandlerDelegate
4704             true,     // Run IOHandler in async mode
4705             nullptr); // Baton for the "io_handler" that will be passed back
4706                       // into our IOHandlerDelegate functions
4707       }
4708       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4709     } else {
4710       result.AppendError("invalid target\n");
4711       result.SetStatus(eReturnStatusFailed);
4712     }
4713 
4714     return result.Succeeded();
4715   }
4716 
4717 private:
4718   CommandOptions m_options;
4719   Target::StopHookSP m_stop_hook_sp;
4720 };
4721 
4722 #pragma mark CommandObjectTargetStopHookDelete
4723 
4724 //-------------------------------------------------------------------------
4725 // CommandObjectTargetStopHookDelete
4726 //-------------------------------------------------------------------------
4727 
4728 class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
4729 public:
4730   CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
4731       : CommandObjectParsed(interpreter, "target stop-hook delete",
4732                             "Delete a stop-hook.",
4733                             "target stop-hook delete [<idx>]") {}
4734 
4735   ~CommandObjectTargetStopHookDelete() override = default;
4736 
4737 protected:
4738   bool DoExecute(Args &command, CommandReturnObject &result) override {
4739     Target *target = GetSelectedOrDummyTarget();
4740     if (target) {
4741       // FIXME: see if we can use the breakpoint id style parser?
4742       size_t num_args = command.GetArgumentCount();
4743       if (num_args == 0) {
4744         if (!m_interpreter.Confirm("Delete all stop hooks?", true)) {
4745           result.SetStatus(eReturnStatusFailed);
4746           return false;
4747         } else {
4748           target->RemoveAllStopHooks();
4749         }
4750       } else {
4751         bool success;
4752         for (size_t i = 0; i < num_args; i++) {
4753           lldb::user_id_t user_id = StringConvert::ToUInt32(
4754               command.GetArgumentAtIndex(i), 0, 0, &success);
4755           if (!success) {
4756             result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4757                                          command.GetArgumentAtIndex(i));
4758             result.SetStatus(eReturnStatusFailed);
4759             return false;
4760           }
4761           success = target->RemoveStopHookByID(user_id);
4762           if (!success) {
4763             result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4764                                          command.GetArgumentAtIndex(i));
4765             result.SetStatus(eReturnStatusFailed);
4766             return false;
4767           }
4768         }
4769       }
4770       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4771     } else {
4772       result.AppendError("invalid target\n");
4773       result.SetStatus(eReturnStatusFailed);
4774     }
4775 
4776     return result.Succeeded();
4777   }
4778 };
4779 
4780 #pragma mark CommandObjectTargetStopHookEnableDisable
4781 
4782 //-------------------------------------------------------------------------
4783 // CommandObjectTargetStopHookEnableDisable
4784 //-------------------------------------------------------------------------
4785 
4786 class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
4787 public:
4788   CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
4789                                            bool enable, const char *name,
4790                                            const char *help, const char *syntax)
4791       : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
4792   }
4793 
4794   ~CommandObjectTargetStopHookEnableDisable() override = default;
4795 
4796 protected:
4797   bool DoExecute(Args &command, CommandReturnObject &result) override {
4798     Target *target = GetSelectedOrDummyTarget();
4799     if (target) {
4800       // FIXME: see if we can use the breakpoint id style parser?
4801       size_t num_args = command.GetArgumentCount();
4802       bool success;
4803 
4804       if (num_args == 0) {
4805         target->SetAllStopHooksActiveState(m_enable);
4806       } else {
4807         for (size_t i = 0; i < num_args; i++) {
4808           lldb::user_id_t user_id = StringConvert::ToUInt32(
4809               command.GetArgumentAtIndex(i), 0, 0, &success);
4810           if (!success) {
4811             result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4812                                          command.GetArgumentAtIndex(i));
4813             result.SetStatus(eReturnStatusFailed);
4814             return false;
4815           }
4816           success = target->SetStopHookActiveStateByID(user_id, m_enable);
4817           if (!success) {
4818             result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4819                                          command.GetArgumentAtIndex(i));
4820             result.SetStatus(eReturnStatusFailed);
4821             return false;
4822           }
4823         }
4824       }
4825       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4826     } else {
4827       result.AppendError("invalid target\n");
4828       result.SetStatus(eReturnStatusFailed);
4829     }
4830     return result.Succeeded();
4831   }
4832 
4833 private:
4834   bool m_enable;
4835 };
4836 
4837 #pragma mark CommandObjectTargetStopHookList
4838 
4839 //-------------------------------------------------------------------------
4840 // CommandObjectTargetStopHookList
4841 //-------------------------------------------------------------------------
4842 
4843 class CommandObjectTargetStopHookList : public CommandObjectParsed {
4844 public:
4845   CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
4846       : CommandObjectParsed(interpreter, "target stop-hook list",
4847                             "List all stop-hooks.",
4848                             "target stop-hook list [<type>]") {}
4849 
4850   ~CommandObjectTargetStopHookList() override = default;
4851 
4852 protected:
4853   bool DoExecute(Args &command, CommandReturnObject &result) override {
4854     Target *target = GetSelectedOrDummyTarget();
4855     if (!target) {
4856       result.AppendError("invalid target\n");
4857       result.SetStatus(eReturnStatusFailed);
4858       return result.Succeeded();
4859     }
4860 
4861     size_t num_hooks = target->GetNumStopHooks();
4862     if (num_hooks == 0) {
4863       result.GetOutputStream().PutCString("No stop hooks.\n");
4864     } else {
4865       for (size_t i = 0; i < num_hooks; i++) {
4866         Target::StopHookSP this_hook = target->GetStopHookAtIndex(i);
4867         if (i > 0)
4868           result.GetOutputStream().PutCString("\n");
4869         this_hook->GetDescription(&(result.GetOutputStream()),
4870                                   eDescriptionLevelFull);
4871       }
4872     }
4873     result.SetStatus(eReturnStatusSuccessFinishResult);
4874     return result.Succeeded();
4875   }
4876 };
4877 
4878 #pragma mark CommandObjectMultiwordTargetStopHooks
4879 
4880 //-------------------------------------------------------------------------
4881 // CommandObjectMultiwordTargetStopHooks
4882 //-------------------------------------------------------------------------
4883 
4884 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
4885 public:
4886   CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
4887       : CommandObjectMultiword(
4888             interpreter, "target stop-hook",
4889             "Commands for operating on debugger target stop-hooks.",
4890             "target stop-hook <subcommand> [<subcommand-options>]") {
4891     LoadSubCommand("add", CommandObjectSP(
4892                               new CommandObjectTargetStopHookAdd(interpreter)));
4893     LoadSubCommand(
4894         "delete",
4895         CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
4896     LoadSubCommand("disable",
4897                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
4898                        interpreter, false, "target stop-hook disable [<id>]",
4899                        "Disable a stop-hook.", "target stop-hook disable")));
4900     LoadSubCommand("enable",
4901                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
4902                        interpreter, true, "target stop-hook enable [<id>]",
4903                        "Enable a stop-hook.", "target stop-hook enable")));
4904     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList(
4905                                interpreter)));
4906   }
4907 
4908   ~CommandObjectMultiwordTargetStopHooks() override = default;
4909 };
4910 
4911 #pragma mark CommandObjectMultiwordTarget
4912 
4913 //-------------------------------------------------------------------------
4914 // CommandObjectMultiwordTarget
4915 //-------------------------------------------------------------------------
4916 
4917 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
4918     CommandInterpreter &interpreter)
4919     : CommandObjectMultiword(interpreter, "target",
4920                              "Commands for operating on debugger targets.",
4921                              "target <subcommand> [<subcommand-options>]") {
4922   LoadSubCommand("create",
4923                  CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
4924   LoadSubCommand("delete",
4925                  CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
4926   LoadSubCommand("list",
4927                  CommandObjectSP(new CommandObjectTargetList(interpreter)));
4928   LoadSubCommand("select",
4929                  CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
4930   LoadSubCommand(
4931       "stop-hook",
4932       CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
4933   LoadSubCommand("modules",
4934                  CommandObjectSP(new CommandObjectTargetModules(interpreter)));
4935   LoadSubCommand("symbols",
4936                  CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
4937   LoadSubCommand("variable",
4938                  CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
4939 }
4940 
4941 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;
4942