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