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