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