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