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