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