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