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