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