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